summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-11-13 23:17:23 -0700
committerLinux Build Service Account <lnxbuild@localhost>2016-11-13 23:17:25 -0700
commit124459b203bf648a97d88f7d9977f6882d7a47ac (patch)
tree1183ce90dba3b2a8a6c4ceb18552d294d4eebd9f
parente46119845c16713bc5f42442d654df0961220361 (diff)
parentce1a7c8d7df37fd31e2eff42c26f95828fdecf6a (diff)
Promotion of kernel.lnx.4.4-161113.
CRs Change ID Subject -------------------------------------------------------------------------------------------------------------- ALSA: hda/realtek - Add support for ALC295/ALC3254 coresight: tmc: implementing TMC-ETR AUX space API team: don't call netdev_change_features under team->lock drm/amdkfd: unbind only existing processes 1086818 I07802c21c661fe18fb2fda70980b04f646408d7d msm: ADSPRPC: Use secure session device while freeing me serial: 8250_pci: fix divide error bug if baud rate is 0 I0395c86e01cd49c348fda8f93087d26f88557c91 ANDROID: cpu: send KOBJ_ONLINE event when enabling cpus coresight: tmc: modifying naming convention stm class: Select CONFIG_SRCU MIPS: KVM: Fix modular KVM under QEMU 1084723 Iffc4a829613f9aa939b1ed20d360d54bfc541f10 msm: vidc: Print secure info for a session ext4: clean up error handling when orphan list is corrup percpu: fix synchronization between chunk->map_extend_wo 1072607 I57297df9f2819e7d774dbb21302b55ede61a37b2 clk: qcom: gpucc: add and update clocks of GPUCC drm/vmwgfx: Enable SVGA_3D_CMD_DX_SET_PREDICATION coresight: adding path for STM device 1086946 If7deee97c09666b7d9513f79c0e278c430acfdfd Documentation: sched: Update frequency guidance explanat coresight: etb10: adjust read pointer only when needed xfs: skip stale inodes in xfs_iflush_cluster netfilter: x_tables: make sure e->next_offset covers rem perf evlist: Make perf_evlist__open() open evsels with t usb: quirks: Add no-lpm quirk for Acer C120 LED Projecto mcb: Fixed bar number assignment for the gdd PCI: Disable all BAR sizing for devices with non-complia Ia38e42a06dc184395f79c1ec1d306bf9775704d5 Revert "mmc: Add status IRQ and status callback function Ifc9d2c6fe27900f30e6407398f5b24222518bffc android: recommended.cfg: remove CONFIG_UID_STAT coresight: etm4x: moving etm_drvdata::enable to atomic f perf/core: Fix perf_event_open() vs. execve() race Ia773afb4b266f012336b99fc8cf87453839e078b BACKPORT: PM / sleep: Go direct_complete if driver has n arm64: move early boot code to the .init segment sched/loadavg: Fix loadavg artifacts on fully idle and o bpf: Use mount_nodev not mount_ns to mount the bpf files USB: serial: option: add even more ZTE device ids 1086881 I52d51c09d7ff316248542c84a1cd65a28e2283da spmi: pmic-arb: support show_resume_irq KVM: x86: mask CPUID(0xD,0x1).EAX against host value 1066021 Id898076926f658a1b8b27a3ccb848756b36de4ca ANDROID: binder: Clear binder and cookie when setting ha coresight: tmc: getting rid of multiple read access MIPS: Sync icache & dcache in set_pte_at drm/i915: Don't leave old junk in ilk active watermarks 1074681 Ie8d5231327fcc27ab2a28542e0d96687abb9aace usb: core: Replace msleep with usleep_range 1081084 I50a3ca4e09c6cd6edeb5c15478989e19926c6576 ARM: dts: msm: Enable VDD_APC CPR aging for msmcobalt v2 1077126 I1b1791eacbf7afffd101d56d0ae06fe237b8c076 usb: xhci: Clear event handler busy flag upon event ring MIPS: Fix watchpoint restoration kvm: arm64: Fix EC field in inject_abt64 can: fix handling of unmodifiable configuration options ANDROID: base-cfg: enable UID_CPUTIME 1076516 Ic7ac0b7ac19d19577d4d1223c8638f17ad9d78af msm: mdss: dp: add support for link retraining at lower PM / sleep: Handle failures in device_suspend_late() con tmpfs: fix regression hang in fallocate undo ext4: address UBSAN warning in mb_find_order_for_block() arm64: cover the .head.text section in the .text segment ARM: imx6ul: Fix Micrel PHY mask clk: at91: fix check of clk_register() returned value clk: bcm2835: divider value has to be 1 or more sparc64: Fix numa node distance initialization sunrpc: fix stripping of padded MIC tokens coresight: etm3x: set progbit to stop trace collection Ied22323af831575303abd548574918baa9852dd0 FROMLIST: wlcore: Disable filtering in AP role IB/mlx4: Properly initialize GRH TClass and FlowLabel in ALSA: hda/realtek: Add Lenovo L460 to docking unit fixup tty/serial: atmel: fix hardware handshake selection iio: accel: kxsd9: fix the usage of spi_w8r8() 1035111 I19fbc8c608acc623a68f9a686391a7ecd8437a4a debug-pagealloc: Panic on pagealloc corruption I8110a4fd649b8ac1ec9bfac00255c1214135e4b2 Revert "arm: dcc_tty: fix armv6 dcc tty build failure" ALSA: hda / realtek - add two more Thinkpad IDs (5050,50 xfs: handle dquot buffer readahead in log recovery corre USB: serial: keyspan: fix use-after-free in probe error 1073250 I142b35901e8ba7724d3ba74ae8c58be3bc8dc44a ASoC: Change info logs to debug bpf, perf: delay release of BPF prog after grace period net: Don't forget pr_fmt on net_dbg_ratelimited for CONF drivers/hwtracing: make coresight-etm-perf.c explicitly perf tools: add infrastructure for PMU specific configur 1087345 I8d3ec938d433fe9bdbb8c091873c07e75c49d632 qcom-charger: smblib: add support for pd current setting 1071199 I5cc37fc09145f31116efd5104144b32c791e0e27 smb-lib: rerun APSD when any HVDCP adapter is detected coresight: tmc: make sysFS and Perf mode mutually exclus ipv6: Skip XFRM lookup if dst_entry in socket cache is v 1088388 Ieb72bd3779c3b9a372b469f3f7f571fc22294099 defconfig: enable QCOM_IRQ_HELPER for 32bit msmcobalt an powerpc: Fix definition of SIAR and SDAR registers arm64: cpuinfo: Missing NULL terminator in compat_hwcap_ KEYS: potential uninitialized variable usb: misc: usbtest: fix pattern tests for scatterlists. coresight: etm4x: add tracer ID for A72 Maia processor. 1085592 I542b9fe014cff5a4b944eaab6034bfdb3e63a087 drivers: mfd: Fix 32-bit audio compile drm/vmwgfx: Work around mode set failure in 2D VMs coresight: moving struct cs_buffers to header file MIPS: Fix MSA ld_*/st_* asm macros to use PTR_ADDU mmc: mmc: Fix partition switch timeout for some eMMCs perf tools: making coresight PMU listable arm64: Rework valid_user_regs coresight: implementing 'cpu_id()' API 1074681 Id22104b9e5b63153731df9eb55759de9a86128c6 usb: host: xhci: Replace msleep with usleep_range 1036444 I84243578a1ef2f9948f0c9a8c1c00dc6a31eb579 ARM: dts: msm: Enable gpu-quirk-disable-lmloadkill for m coresight: tmc: keep track of memory width 1086028 I1d97d8ef831e3a91df47eebf22e1156d0a3712ae soc: qcom: pil: Using devm_ioremap for mapping restart r stm class: Remove a pointless line MIPS: ptrace: Fix FP context restoration FCSR regression usb: dwc2: fix regression on big-endian PowerPC/ARM syst iio: proximity: as3935: fix buffer stack trashing drm/mgag200: Black screen fix for G200e rev 4 USB: xhci: Add broken streams quirk for Frescologic devi arm64: kaslr: increase randomization granularity netfilter: xt_qtaguid: seq_printf fixes 1086513 I40220bcf960a10d7d6271e09b9f85107ed0c24af ARM: dts: msm: Add stub regulator devices for msmtriton Bluetooth: vhci: Fix race at creating hci device drm: atmel-hlcdc: actually disable scaling when no scali 1079523 Ie96470b93d879d2c175f18aef25f3e256cd0a322 ARM: dts: msm: Enable memory allocation for diag on falc 1066012 I66c15b066808f28bd27bfe50fd0e03ff45a09fca ANDROID: binder: Add strong ref checks 1047963 I34e8268a0defe335ca9d360e910655c2891cd572 msm: kgsl: Change device-type memory mapping to Normal-N powerpc/iommu: Remove the dependency on EEH struct in DD ring-buffer: Prevent overflow of size in ring_buffer_res 1086836 I15607dcb06564a603910709fafb9eba563bf102c coresight: set appropriate clock rate for coresight devi netfilter: x_tables: xt_compat_match_from_user doesn't n s390: fix test_fp_ctl inline assembly contraints kprobes/x86: Clear TF bit in fault on single-stepping I5a9ef58dca32306fac5a4c7f28cdaa36fa8ae078 usb: dual-role: make stub functions inline 1085143 I3d4c1c7587b367836a151c3c988f58790611acd1 msm: mdss: Add support for secure camera perf/ring_buffer: Document AUX API usage locking/ww_mutex: Report recursive ww_mutex locking earl tty: vt, return error when con_startup fails stm class: Fix stm device initialization order 1083537 Ia63f8baf02b0ceee0960e208b976d7b573c39d52 ASoC: msm: refactor machine driver for msmfalcon arm64: don't map TEXT_OFFSET bytes below the kernel if w coresight: Fix NULL pointer dereference in _coresight_bu 1080348 Ie316941535f62afd75eac21280061b489e9196c1 ARM: dts: msm: Fix BT current leakage in msmcobalt MTP a 1084297 I118f4254686caf498087847916b7710662ab31e7 ARM: dts: msm: Change LAB precharge time to 500us in pmi Input: uinput - handle compat ioctl for UI_SET_PHYS Revert "cpufreq: interactive: build fixes for 4.4" perf symbols: Check before overwriting build_id 1078904 I32abceba2d55c95bdb8e9b6463a39d29fb3bc7c7 soc: qcom: Initialize structure with default values I4a686d64b6de37decf60019be1718e1d820193e6 vfs: change d_canonical_path to take two paths af_unix: fix hard linked sockets on overlay perf inject: Hit all DSOs for AUX data in JIT and other Linux 4.4.14 scsi_lib: correctly retry failed zero length REQ_TYPE_FS 1062351 Ie6ff66e272005bc83b3bb6ea8c353d4eb9088048 msm: camera: sensor: Change initializer to 0 instead of udp: prevent skbs lingering in tunnel socket queues KVM: x86: fix OOPS after invalid KVM_SET_DEBUGREGS coresight: etm3x: unlocking tracers in default arch init serial: 8250_mid: recognize interrupt source in handler drm/vmwgfx: Delay pinning fbdev framebuffer until after perf/core: Disable the event on a truncated AUX record HID: elo: kill not flush the work coresight: etb10: splitting sysFS "status" entry stm class: dummy_stm: Create multiple devices pipe: limit the per-user amount of pages allocated in pi drm/vmwgfx: use vmw_cmd_dx_cid_check for query commands. mei: fix NULL dereferencing during FW initiated disconne 1084217 I6dfa20b8d8b0ae7ccc94119bf9cf14c5e11a1cf7 sched: prevent race between disable window statistics an Fix OpenSSH pty regression on close netfilter: x_tables: don't move to non-existent next rul sock_diag: do not broadcast raw socket destruction ext4: fix hang when processing corrupted orphaned inode rtlwifi: pci: use dev_kfree_skb_irq instead of kfree_skb Linux 4.4.16 stm class: Fix a race in unlinking ARM: mvebu: fix HW I/O coherency related deadlocks drm/radeon: fix asic initialization for virtualized envi parisc: Fix pagefault crash in unaligned __get_user() ca 980999 I01e5e8c9e0b03fa8b09f0ffd6857fe7e60a48091 diag: Add mutex protection while closing SMD Revert "usb: gadget: prevent change of Host MAC address stm class: Do not leak the chrdev in error path xen/events: Don't move disabled irqs 1064046 I0a7e36b7e1fef9d42a4c0fe33d69a4debf15af2f msm: kgsl: Allow mempools to configure from the device t 1067965 I3dbe4fe426111023b60eefd968c426be7d6057b9 qpnp-smb2: fix reverse boost when input is removed packet: Use symmetric hash for PACKET_FANOUT_HASH. 1086727 I0e6e600f72f9ef8864f9b775df88f674de9cb52c qpnp-fg-gen3: support configuring ESR FCC based on charg Bluetooth: vhci: purge unhandled skbs thermal: cpu_cooling: fix improper order during initiali bpf, inode: disallow userns mounts ASoC: ak4642: Enable cache usage to fix crashes on resum coresight: remove csdev's link from topology coresight: tmc: cleaning up header file 1049684 Iba53d4381d61f23ce1195a147493b0d292cd3723 msm: kgsl: Add speed bin read capabilities for A306a GPU locking/qspinlock: Fix spin_unlock_wait() some more drm/nouveau: fix for disabled fbdev emulation iio: Fix error handling in iio_trigger_attach_poll_func drm/vmwgfx: Fix error paths when mapping framebuffer 1087356 Ie09a65e7974e2412af4add3b6f1e0aa20ee4a34b qcom-charger: smblib: lower delay in OTG soft-start chec Revert "SELinux: build fix for 4.1" cs-etm: avoid casting variable xen/acpi: allow xen-acpi-processor driver to load on Xen MIPS: Fix sigreturn via VDSO on microMIPS kernel ovl: Copy up underlying inode's ->i_mode to overlay inod wext: Fix 32 bit iwpriv compatibility issue with 64 bit xen/balloon: Fix declared-but-not-defined warning 1064046 Ie6789e13be7316a0de43538b9e477920fa64c6bb ARM: dts: msm: Add GPU mempools properties for all msm drm/atomic: Verify connector->funcs != NULL when clearin powerpc/pseries: Fix PCI config address for DDW 1081490 I3f2f7108b21adc2672e7f15ca24667c1c80a9453 dma-mapping: use iommu_unmap for unmapping address coresight: etm3x: moving etm_readl/writel to header file of: fix autoloading due to broken modalias with no 'comp coresight: etm3x: changing default trace configuration drm/vmwgfx: Fix order of operation drm: add missing drm_mode_set_crtcinfo call Bluetooth: vhci: fix open_timeout vs. hdev race 1073238 I18b7cb311e793c820da10990c47f472f7a0d0944 ASoC: msmcobalt: Update ignore suspend for MAD_CPE out w 1058676 I8f35cdd154fbde49c95cdd0e5f7df4b9e4f897a5 msm: vidc: Initialize the dcvs load during perf mode swi 1086186 Id681fbf3c923027d3db875d506cbe3f971919a8d qseecom: remove entry from qseecom_registered_app_list perf auxtrace: Add perf_evlist pointer to *info_priv_siz drm/vmwgfx: Check pin count before attempting to move a 1053383 I77eae2675e92447287bad05280cf32fc3c5b0fdd ARM: dts: msm: Enable ACD on msmcobalt v2 arm64: kernel: use literal for relocated address of __se percpu: fix synchronization between synchronous map exte 1053383 I712074a913b5603708542b71f5947e5ad43c8a5d clk: msm: osm: add support for configuring ACD block powerpc/pseries: Add POWER8NVL support to ibm,client-arc 1085356 I2103773a17e7d9ee5acb3f21dc955e2da493b3b4 ASoC: wcd934x: Fix AANC click and pop in voice call MIPS: Handle highmem pages in __update_cache drm/amdgpu: Fix hdmi deep color support. 1083253 I8481c79a36931e3cda8d893a82938499f2645f2a msm: mdss: add multiple partial update support 1084699 I583fa51599a1cbbd029cb45c075429730d2e071b fg-memif: update IMA error handling and clear sequence netfilter: ip6_tables: simplify translate_compat_table a ALSA: hda - Add PCI ID for Kabylake staging: iio: accel: fix error check 1072607 Iac989d3c9312654b599d8299206e5478ca454861 ARM: dts: msm: Update clock gcc node for MSMfalcon/Trito mfd: intel-lpss: Save register context on suspend nfsd: check permissions when setting ACLs 1077224 I8518d349a7838f9600e32d5b2a5853f7f96f9008 msm: cpp: Vote for nominal ahb clock while loading firmw USB: serial: quatech2: fix use-after-free in probe error irqchip/gic-v3: Configure all interrupts as non-secure G 1086622 Ie09c8ae431cc7da4c8cd745d9c6d018e6a256158 ARM: dts: msm: Add IMEM pil entry for msmtriton remove directory incorrectly tries to set delete on clos 1064689 Ibb993839c1057fb62f43e99df3bee8328a4c702f msm: camera: Change CID array size to MAX_CID_CH_PARAM_E ubi: Make recover_peb power cut aware I5b622c7ab4c0cb9670f8903f259a99888f503c1a Revert "switch: switch class and GPIO drivers." writeback: use higher precision calculation in domain_di stm class: Use driver's packet callback return value coresight: etm4x: unlocking tracers in default arch init USB: leave LPM alone if possible when binding/unbinding 1087974 I67cf15fa918832ebab56cb999265d02880682c5e msm: kgsl: Declare iomem addresses as void USB: serial: io_edgeport: fix memory leaks in attach err iio:st_pressure: fix sampling gains (bring inline with A coresight: release reference taken by 'bus_find_device() 1083111 Ic695e5320d6acbe8d16e23851f752a7fa673f0da msm: kgsl: Enable retention for gpu core clock sfc: on MC reset, clear PIO buffer linkage in TXQs mnt: Account for MS_RDONLY in fs_fully_visible ALSA: hda - fix read before array start perf/core: Fix perf_sched_count derailment 1043997 Iad01cb10faa892897f180ad217b27a56c2da89b5 defconfig: Enabling config INET_DIAG_DESTROY Revert "gpiolib: Split GPIO flags parsing and GPIO confi drm: make drm_atomic_set_mode_prop_for_crtc() more relia media: v4l2-compat-ioctl32: fix missing reserved field c xt_qtaguid: Fix panic caused by processing non-full sock xfs: disallow rw remount on fs with unknown ro-compat fe mm: Export migrate_page_move_mapping and migrate_page_co USB: serial: mxuport: fix use-after-free in probe error switchdev: pass pointer to fib_info instead of copy mac80211_hwsim: Add missing check for HWSIM_ATTR_SIGNAL Btrfs: don't use src fd for printk Revert "drivers: power: use 'current' instead of 'get_cu 1045472 1084507 I413ded858df41496d26362602abf3eb40c3cc1ed mdss: Fix solid fill unpack pattern SIGNAL: Move generic copy_siginfo() to signal.h uapi glibc compat: fix compilation when !__USE_MISC in g Revert "net: activity_stats: Stop using obsolete create_ ALSA: ctl: Stop notification after disconnection 1084966 If0afc6b1209b03ae17472a17b34d9d403757bfd0 soc: qcom: Replace ARRAY_SIZE macro with strlen usb: gadget: f_fs: Fix EFAULT generation for async read Linux 4.4.13 arm64: relocatable: deal with physically misaligned kern drm/i915: Refresh cached DP port register value on resum 1079913 Ica6a60f3f5bd1fad624d01ea410e62dbed09dac8 qcom-charger: Add batch register access support for CC2 ovl: verify upper dentry before unlink and rename coresight: fixing indentation problem drm/nouveau/fbcon: fix out-of-bounds memory accesses 1083137 Ib6c18253f5d8be0f6eba4cfb741c4492b33a4c3f mdss: sde: Add register read/write debugfs for SDE rotat coresight: etm-perf: incorporating sink definition from I64bf3bd1ab2dc735321160642dc6bbfa996f8068 BACKPORT: selinux: restrict kernel module loading perf/x86/intel/pt: Generate PMI in the STOP region as we iio: proximity: as3935: correct IIO_CHAN_INFO_RAW output coresight: Add support for Juno platform 1083253 Ib0fb977d86d6293595b62e9f0476615d68b919ac msm: mdss: dsi: Add support dual roi partial update AX.25: Close socket connection on session completion ARM: fix PTRACE_SETVFPREGS on SMP systems affs: fix remount failure when there are no options chan powerpc: Use privileged SPR number for MMCR2 1008319 I986d8c36c839a1dee23761465ad331ffc31dd6ac crypto: msm: qce50: Prevent deadlock during timeout scsi: Add QEMU CD-ROM to VPD Inquiry Blacklist tty/vt/keyboard: fix OOB access in do_compute_shiftstate arm64: Implement ptep_set_access_flags() for hardware AF coresight: adding sink parameter to function coresight_b 1062239 Ifcf6073b5b778bcb535d26bc33990254ff48c406 msm: kgsl: Add MEMDESC_MAPPED back to for legacy mapping tcp: record TLP and ER timer stats in v6 stats coresight: etb10: implementing AUX API net_sched: fix pfifo_head_drop behavior vs backlog kbuild: move -Wunused-const-variable to W=1 warning leve 1086476 Ib078cf01871c50e6eec7002a38391d4c41d4d45a USB: gadget: mtp: Make mtp_tx_req_len as Tx transfer len BACKPORT: timer: convert timer_slack_ns from unsigned lo I9f50ec15b0e22e602d73b9f745fc8666f8925d09 fiq_debugger: Add option to apply uart overlay by FIQ_DE Iabdca0bbedfbff59e9c820c58636a68ef9683d9f fuse: Add support for d_canonical_path mmc: sdhci-pci: Remove MMC_CAP_BUS_WIDTH_TEST for Intel crypto: sun4i-ss - Replace spinlock_bh by spin_lock_irq{ usb: musb: Ensure rx reinit occurs for shared_fifo endpo 1066548 I7cf1e6ceb63d27ce08b2d17b97a9844d257464ce PM / devfreq: Restart previous governor if new governor coresight: no need to do the forced type conversion clk: bcm2835: Fix PLL poweron 1080507 I8d70ad663f3476e1c81cc2126b1229a3c7c80265 ASoC: wcd934x: Change SIDO reference to internal stm class: Remove unnecessary pointer increment 1086946 I1928c6cd0509952443a912ef54e0d72d5f75955d sched/hmp: Use improved information for frequency notifi 1085214 Ic57b1db8688ff634ed7d62279baa7c042d126550 ASoC: wcd934x: fix MAD enable sequence for ADC2 Linux 4.4.12 cs-etm: account for each trace buffer in the queue MIPS: Prevent "restoration" of MSA context in non-MSA ke drm/nouveau/disp/sor/gf119: select correct sor when poki KVM: irqfd: fix NULL pointer dereference in kvm_irq_map_ net: macb: fix default configuration for GMAC on AT91 powerpc/pseries: Fix IBM_ARCH_VEC_NRCORES_OFFSET since P xfs: xfs_iflush_cluster fails to abort on error ARCv2: Check for LL-SC livelock only if LLSC is enabled 1088210 Ia9caa30b88eccb99dfebe9179bb61b8c2abb5de4 NFC: Detection of NQ chip set and firmware version 1081543 I28c550058dd990c9c8cd368a2677097c7f057ccd msm: ipa: Add support to configure WAN RX desc size iio: hudmidity: hdc100x: fix incorrect shifting and scal 1086571 1088713 I6ca20cbd29b9a7bd45a78321ea0f65b74450e8c1 ARM: dts: msm: Add battery profile for FG in QRD interpo arm64: simplify kernel segment mapping granularity hwrng: exynos - Fix unbalanced PM runtime put on timeout coresight: etm4x: implementing the perf PMU API I38132efaabf52bea75dfd736ce734a1b9690e87e netfilter: xt_quota2: make quota2_log work well 1086733 I464d720abc138e8cd9ba8d7f1704cd91f4408bee qpnp-smb2: add support to configure charge inhibit ALSA: hda - Add PCI ID for Kabylake-H drm/ttm: Make ttm_bo_mem_compat available Revert "misc: uid_stat: Include linux/atomic.h instead o coresight: etm4x: adding config and traceid registers perf/core: Free AUX pages in unmap path tipc: check nl sock before parsing nested attributes 1046834 I89ab8f353bc04bc0a04d5f5a6993e8e8e5ebbd2e Revert "input: touchscreen: synaptics v1.1" coresight: etm3x: implementing perf_enable/disable() API MIPS: KVM: Fix timer IRQ race when writing CP0_Compare coresight: etm4x: implementing user/kernel mode tracing arm64: introduce mov_q macro to move a constant into a 6 ext4: silence UBSAN in ext4_mb_init() iio: proximity: as3935: remove triggered buffer processi mnt: fs_fully_visible test the proper mount for MNT_LOCK 1086328 Icd8aa9f935eb0096d1e13934ea556c74d7341093 Revert "defconfig: msm64: msm: Compile vidc driver as LK ath10k: fix debugfs pktlog_filter write ANDROID: usb: gadget: f_midi: set fi->f to NULL when fre perf session: Simplify tool stubs crypto: talitos - fix ahash algorithms registration Revert "drivers: switch: remove S_IWUSR from dev_attr" ALSA: echoaudio: Fix memory allocation ARM: mvebu: fix GPIO config on the Linksys boards perf tools: pushing driver configuration down to the ker fix d_walk()/non-delayed __d_free() race clk: qcom: msm8916: Fix crypto clock flags Revert "misc seq_printf fixes for 4.4" drm/dp/mst: Always clear proposed vcpi table for port. 1050455 Idd409e3e38cfb01b28fa24543112d6bb206314ff msm: msm_bus: limit max chars read by sscanf sparc: Fix system call tracing register handling. 1085449 Ie9eef135cdefc8d2a55f038cf9de5fc7f3656f64 ARM: dts: msm: Add interposer dts files for msmcobalt 1050304 I5ef7cf5c95d46a695f20a51214a2afabd6feb4b6 msm: ext_display: update hpd and notify logic ARCv2: LLSC: software backoff is NOT needed starting HS2 ALSA: hda: add AMD Stoney PCI ID with proper driver caps drm/core: Do not preserve framebuffer on rmfb, v4. kvm: Fix irq route entries exceeding KVM_MAX_IRQ_ROUTES xfs: Don't wrap growfs AGFL indexes drm/nouveau/gr/gf100-: update sm error decoding from gk2 Bridge: Fix ipv6 mc snooping if bridge has no ipv6 addre Ie7512259150e146d8e382dc64d40e8faaa438917 ANDROID: restrict access to perf events 1053383 I59aa3a6eb3ce3908e2814b5d45920cbc76ee8eee clk: msm: osm: add debugfs interface to write to ACD reg ACPI / osi: Fix an issue that acpi_osi=!* cannot disable cpuidle: Fix cpuidle_state_is_coupled() argument in cpui usb: f_mass_storage: test whether thread is running befo usb: quirks: Fix sorting 1083537 I72e0a15c8a283c68a3ed10cfd02a4e3d9526c312 ASoC: msm: Add support for INTx ports and clocks crypto: ccp - Fix AES XTS error for request sizes above I2dcd833b66c88a48de8978dce9d72ab78f9af549 Revert "net: socket ioctl to reset connections matching perf tools: new naming convention for openCSD iommu/amd: Fix unity mapping initialization race UPSTREAM: procfs: fixes pthread cross-thread naming if ! ath9k: Fix LED polarity for some Mini PCI AR9220 MB92 ca KVM: nVMX: VMX instructions: fix segment checks when L1 1080747 I20e12bc1597ad15cb3dc9c3ef18d81d039931e07 ARM: dts: msm: Correct camera dtsi place for msmcobalt s ALSA: hda/realtek - ALC256 speaker noise issue of: irq: fix of_irq_get[_byname]() kernel-doc serial: 8250_mid: use proper bar for DNV platform I2aa803ccffbcd2802a7287514da7648e6b364157 quick selinux support for tracefs 1073250 Iaee59cf2d668e9a324ecf1e1106f6daecc54d67b ASoC: msmcobalt: clean up bootup errors x86, build: copy ldlinux.c32 to image.iso ARM: dts: armada-38x: fix MBUS_ID for crypto SRAM on Arm 1086541 If17aa7a60832b71a94d75718da07158e1474ef31 ARM: dts: msm: Add QRD interposer dts file for msmcobalt I698cd0c4ee6894e8d0655d88f3ecf4826c28a645 arm64: add option to build Image-dtb Idb88b901e0209c2cccc9c0796689f780592d58f9 ANDROID: dm verity fec: fix RS block calculation 1085547 I4aa1b9876bf1afd9b895d89dc5c4323ba3a3f661 ARM: dts: msm: update ICNSS DT node for msmcobalt interp stm class: dummy_stm: Make nr_dummies parameter read-onl dell-rbtn: Ignore ACPI notifications if device is suspen 1086946 I3e4f5e39ec9ae7eeaba9a567efd245a7aec1b7ad sched/hmp: Remove capping when reporting load to the cpu 1086127 I2dd07bd967b7d4fb4878b6d65bd0f011c6b15bdd ASoC: pcm: change capture_active to unsigned int sit: correct IP protocol used in ipip6_err Revert "HID: steelseries: validate output report details iommu/vt-d: Enable QI on all IOMMUs before setting root MIPS: Flush highmem pages in __flush_dcache_page MIPS: Use copy_s.fmt rather than copy_u.fmt arm64: kernel: don't export local symbols from head.S ALSA: hda - Fix headphone noise on Dell XPS 13 9360 Ic72bcebbd925b142b09539466bf963188c83108a ANDROID: base-cfg: enable CONFIG_IP_NF_NAT MIPS: Reserve nosave data for hibernation uvc: Forward compat ioctls to their handlers directly staging: comedi: das1800: fix possible NULL dereference memcg: add RCU locking around css_for_each_descendant_pr MIPS: ath79: make bootconsole wait for both THRE and TEM drm/amdgpu: use drm_mode_vrefresh() rather than mode->vr rtlwifi: Fix logic error in enter/exit power-save mode netfilter: x_tables: check for bogus target offset 1077126 Ie89b06d821c1f968ecc30333654bc3a1466f74e3 sound: usb: Add support to handle QMI client disconnect Fix reconnect to not defer smb3 session reconnect long a stm class: Support devices with multiple instances 1084285 I750b2adfb00f12960f74bd552a5896f66ecaece6 qpnp-fg-gen3: expose a fake battery SOC for debug board coresight: etb10: moving to local atomic operations drivers/hwtracing: make coresight-* explicitly non-modul hpfs: fix remount failure when there are no options chan 1086715 Icbbe0d4ab74c6f9bf6f2278a11020a9bc6c41930 qpnp-fg-gen3: Fix empty SOC handling ARM: 8579/1: mm: Fix definition of pmd_mknotpresent 1080409 Ie8e7a8d390d49937e57e23ada953c117541f2f99 regulator: cprh-kbss-regulator: update temp sensor ID fo I5bbf1db90f28ea956383b4a5d91ad508eea656dc ARM64: Ignore Image-dtb from git point of view MIPS: Avoid using unwind_stack() with usermode 1072607 I11c6cc7f09b403a09bdf65a14f7b9d327c5d9613 defconfig: msm: Add support for GCC clocks 1088681 Ie98fe48c2f4fdd0244573229b77ee9823df9e214 core_ctl: Synchronize access to cluster cpu list ARM: dts: imx35: restore existing used clock enumeration xhci: Cleanup only when releasing primary hcd 1082940 If11ec8628705e347488de2f4096ea02b125fba13 defconfig: msm: Add MSMTRITON in msmfalcon defconfig coresight: checking for NULL string in coresight_name_ma netfilter: x_tables: fix unconditional helper serial: samsung: Reorder the sequence of clock control w NFS: Fix another OPEN_DOWNGRADE bug 1080409 I0c9a921b684109f5c6e719eb1fb58667377f2c89 ARM: dts: msm: update VDD_GFX CPR settings for msmcobalt coresight: introducing a global trace ID function 1050304 I970545bbf99ba89804016844f5b294a7e762e6e5 msm: mdss: hdcp1x: handle hpd for hdcp use-cases 1080409 Ibb35a3f475725af96276389f78abb790ea5b5b81 ARM: dts: msm: update VDD_APC CPR settings for msmcobalt Ibf258b355d17f54f49b777a8f6e0089e9b59a3a5 Revert "Recreate asm/mach/mmc.h include file" stm class: Prevent user-controllable allocations proc: prevent stacking filesystems on top fs/cifs: correctly to anonymous authentication for the N 1052835 Iad411dbba05326aa2bce82aff5e8140fd0a31a08 msm: camera: Change %p into %pK coresight: tmc: dump system memory content only when nee ath9k: Add a module parameter to invert LED polarity. coresight: etm4x: Check every parameter used by dma_xx_c ARM: dts: exynos: Add interrupt line to MAX8997 PMIC on netfilter: x_tables: do compat validation via translate_ bpf: try harder on clones when writing into skb 1086418 I241a49dd36746c083b410a58c8c899ee0e9390ad ASoC: wcd934x: Fix fake button press for headset inserti xfs: fix inode validity check in xfs_iflush_cluster coresight: associating path with session rather than tra 1073034 I676dfa5567b1d09427e3e7691045fabc71b53d43 msm: kgsl: Fix potential device NULL pointer dereference cs-etm: removing unecessary structure field coresight: etm4x: modify q_support type fs/cifs: correctly to anonymous authentication via NTLMS aacraid: Fix for KDUMP driver hang 1085266 I11551594e5115e71aa116cc7238953205a4118c3 msm: ipa: fix division by 0 for DMA pipes xfs: print name of verifier if it fails 1045956 I95cda7e33288df7099826b37c2f436c5a33792e8 ARM: dts: msm: update bus bandwidth vote for msmcobalt u 1085449 I7313a121440bf5a455401cf73bd5ef4d6c1506cb Documentation: edac: Add bindings for arm64 cpu erp rtlwifi: rtl8723be: Add antenna select module parameter MIPS: VDSO: Build with `-fno-strict-aliasing' coresight: removing gratuitous boot time log messages 1072607 I8b86ebbabe37bb86bd20eafe9501c4677f21a553 clk: qcom: gcc: Cleanup code for GCC clocks 1075305 Ie1d1540a87e96a33d3e5521cf933399a60d467ab msm: mdss: hdcp1x: fix hdcp 1x registration and reset coresight: tmc: adding sysFS management entries drm/i915/ilk: Don't disable SSC source if it's in use stm class: Guard output assignment against concurrency scripts/package/Makefile: rpmbuild add support of RPMOPT 1076959 Ic3e5e51dcf95722ce81ea5546b2df99a4661a176 msm: cpp: De-init bandwidth manager during error conditi netfilter: x_tables: add compat version of xt_check_entr ipmr/ip6mr: Initialize the last assert time of mfc entri 1079523 I687696dbedfa0ce7e6053d70291a7beb6f81f82e memshare: Pass device structure to ramdump driver PM / Runtime: Fix error path in pm_runtime_force_resume( drm/i915/fbdev: Fix num_connector references in intel_fb MIPS: math-emu: Fix jalr emulation when rd == $0 1088046 I91805ebc2dcee6f2c5baa5c6d6a7856bd472c431 smb-lib: add debug logging to parallel taper usb: gadget: udc: core: Fix argument of dev_err() in usb coresight: etm3x: consolidating initial config 1024199 I5dc3561d15fa50ac58646f96559cfd262020dda9 msm: kgsl: Ignore EAGAIN when programming perfcounter usb: xhci-plat: properly handle probe deferral for devm_ coresight: tmc: making prepare/unprepare functions gener sched: panic on corrupted stack end Iff384eb527327bf88543408e0257241c1fd99a43 Revert "ARM: Add 'card_present' state to mmc_platfrom_da ovl: verify upper dentry in ovl_remove_and_whiteout() locking/static_key: Fix concurrent static_key_slow_inc() arm64: Implement pmdp_set_access_flags() for hardware AF 1088681 I5c5f25eb9b1eaf0605b606a65e0ac86996fa5f27 sched/core: Fix migrate tasks bail-out condition l2tp: fix configuration passed to setup_udp_tunnel_sock( KVM: x86: fix ordering of cr0 initialization code in vmx nfsd: Extend the mutex holding region around in nfsd4_pr locking,qspinlock: Fix spin_is_locked() and spin_unlock_ coresight: etm3x: implementing user/kernel mode tracing ath10k: fix rx_channel during hw reconfigure netfilter: x_tables: introduce and use xt_copy_counters_ I0a7ebff331d259c59a5e03c81918cc1613c3a766 ANDROID: dm verity fec: limit error correction recursion irqchip/gic: Ensure ordering between read of INTACK and sched/fair: Fix cfs_rq avg tracking underflow netfilter: x_tables: add and use xt_check_entry_offsets 1080747 I7529a30af5d3c16a9c40ace5b5bb85e43cc28923 ARM: dts: msm: Add camera dtsi file for msmcobalt qrd sk File names with trailing period or space need special ca MIPS: Disable preemption during prctl(PR_SET_FP_MODE, .. 1001139 1088572 Ied206f10313495e23c262e9d17e9834781c9708a msm: pcie: change the log type for PCIe Synopsys MSI int coresight: etm3x: adding operation mode for etm_enable() crypto: caam - fix caam_jr_alloc() ret code sparc/PCI: Fix for panic while enabling SR-IOV MIPS: KVM: Fix timer IRQ race when freezing timer USB: serial: option: add more ZTE device ids 1076516 I967f13216859be4c147e03c7ea318958300b2886 msm: mdss: dp: process downstream port status change ALSA: hda/realtek - New codecs support for ALC234/ALC274 mfd: intel_soc_pmic_core: Terminate panel control GPIO l 1071199 I953d42418f90398bd4248f8b761cf63943ce5532 qpnp-smb2: force HVDCP to 5V before reboot perf test: Fix build of BPF and LLVM on older glibc libr I71fda54f5f863d13b1437b1f909e52dd375d002d fiq_debugger: Add fiq_debugger.disable option 1086449 Iedbae0d4738c7badf3d4faf60f43e8c8bdab51e1 defconfig: msm: update msmfalcon defconfigs sparc64: Fix return from trap window fill crashes. perf: Synchronously free aux pages in case of allocation netfilter: x_tables: assert minimum target size virtio_balloon: fix PFN format for virtio-1 netem: fix a use after free thunderbolt: Fix double free of drom buffer perf/core: adding PMU driver specific configuration 1050304 I284bc56aa94eef127c2bdd0f80aab7b0cf080342 msm: mdss: hdcp2p2: optimize aux message read and write coresight: removing bind/unbind options from sysfs drm/nouveau/disp/sor/gf119: both links use the same trai tmpfs: don't undo fallocate past its last page hwmon: (dell-smm) Cache fan_type() calls and change fan coresight: etm4x: splitting etmv4 default configuration ALSA: au88x0: Fix calculation in vortex_wtdma_bufshift() Revert "misc: uidstat: Adding uid stat driver to collect coresight: Fix a typo in Kconfig drm/amdgpu/gfx7: fix broken condition check 1021945 I0030b0008d6224cda3fdc1f80308a7e9bcfe4405 qseecom: whitelist support for kernel client and listene ALSA: pcm: Free chmap at PCM free callback, too ALSA: hda - Fix headset mic detection problem for one De stm class: Hide STM-specific options if STM is disabled perf evsel: Introduce disable() method coresight: etm4x: moving sysFS entries to a dedicated fi 1082850 Iedd78288f71ddcaa9fcb2f63bd3b73be2c0006dd ASoC: add 352800Hz into the pcm known rates bridge: Don't insert unnecessary local fdb entry on chan ALSA: dummy: Fix a use-after-free at closing clk: bcm2835: pll_off should only update CM_PLL_ANARST 1077493 I95b17de5bf17b62096d2c9d60633b6b30768752a ARM: dts: msm: switch to RPM control for regulators on M netfilter: x_tables: validate all offsets and sizes in a netfilter: x_tables: kill check_entry helper mm: use phys_addr_t for reserve_bootmem_region() argumen USB: serial: option: add support for Cinterion PH8 and A ath10k: fix firmware assert in monitor mode I3fd1aa7a54fe3a8d3ad5537cbc61386e52f41ea0 android: base-cfg: remove CONFIG_SWITCH stm class: Add heartbeat stm source device powerpc/tm: Always reclaim in start_thread() for exec() 1073673 I2907495b65e62d95a892741aed008048bb86aced msm: kgsl: use seq_file for mem_entry debugfs IB/srp: Fix a debug kernel crash QE-UART: add "fsl,t1040-ucc-uart" to of_device_id gcov: disable tree-loop-im to reduce stack usage 1081831 Ibeb5d34412d4333f9c7f21d2fc7df1d3b1d4e72e gpio: qpnp-pin: Fix reading the GPIO mode for GPIO_LV_MV sparc64: Fix sparc64_set_context stack handling. rtlwifi: btcoexist: Implement antenna selection stm class: Plug stm device's unlink callback nfsd4/rpc: move backchannel create logic into rpc code perf scripts: Add python scripts for CoreSight traces I108de88fa4baaef99a53c4e4c6a1d8c4b4804157 Revert "mm: vmscan: Add a debug file for shrinkers" 1050538 I9ecb0103d7a73eedb2e0d1db1d5613b18dd77e59 qcedev: Validate Source and Destination addresses 1084100 I381003f4542d1483004df4b24e2ffe6bd1571592 msm: mdss: Dynamic resolution switch with DSC on/off Revert "SELinux: Enable setting security contexts on roo ath5k: Change led pin configuration for compaq c700 lapt USB: serial: io_edgeport: fix memory leaks in probe erro usb: gadget: fix spinlock dead lock in gadgetfs netfilter: arp_tables: simplify translate_compat_table a coresight: "DEVICE_ATTR_RO" should defined as static. vfs: add d_real_inode() helper netfilter: x_tables: check standard target size too TTY: n_gsm, fix false positive WARN_ON coresight: coresight_unregister() function cleanup 1085750 Ibc9ce23d4ba15d0e3faa9db3e760965a7439aed8 drivers: soc: implement notify_tx_abort() IB/cm: Fix a recently introduced locking bug stm class: stm_heartbeat: Make nr_devs parameter read-on 1084618 I2c62cd56a0d801dc0b136863899d77454e4de605 ARM: dts: msm: Add remote debugger device configuration mac80211: fix fast_tx header alignment 1086622 I79acd047c7e414ed19a2f992f8ff801b63c8a2ad ARM: dts: msm: Add IMEM pil entry for msmfalcon stm class: Fix unbalanced module/device refcounting iio: humidity: hdc100x: correct humidity integration tim make nfs_atomic_open() call d_drop() on all ->open_conte crypto: ux500 - memmove the right size hpfs: implement the show_options method netfilter: x_tables: validate e->target_offset early iio:ad7266: Fix broken regulator error handling vxlan: Accept user specified MTU value when create new v perf/core: Don't leak event in the syscall error path 1059771 Icdf27dce5b3eb7cfc4a7686f044195db13a81a58 diag: Fix race condition while closing SMD cdc_ncm: workaround for EM7455 "silent" data interface ext4: fix oops on corrupted filesystem coresight: etm4x: splitting struct etmv4_drvdata mei: amthif: discard not read messages 1024407 Icb3781ca31dd8474cfca077c52593dc69d011127 regulator: qpnp-labibb: add support to configure PFM for I7cb6b641f72085e69b90dca11d2ea68adcd02390 android: base-cfg: enable CONFIG_QUOTA posix_acl: Add set_posix_acl drm/imx: Match imx-ipuv3-crtc components using device no Revert "hid-multitouch: Filter collections by applicatio Ic0f7c17e4889c5580d70b52d9a709a37165a5747 ANDROID: dm verity fec: add missing release from fec_kty 1082940 Icb3f24222fb922d5e5cf6b0dbf9894dd3dc85f8d crypto: msm: enable hw crypto driver for msmtriton ALSA: timer: Fix negative queue usage by racy accesses MIPS: Loongson-3: Reserve 32MB for RS780E integrated GPU I170754d659d0891c075f85211b5e3970b114f097 UPSTREAM: USB: usbfs: fix potential infoleak in devio EDAC, sb_edac: Fix rank lookup on Broadwell arm64: Fix typo in the pmdp_huge_get_and_clear() definit drm/fb_helper: Fix references to dev->mode_config.num_co xen: use same main loop for counting and remapping pages pinctrl: mediatek: fix dual-edge code defect 1080024 I6ce703565bbf7482f9458207e32b5a9e2e87775a defconfig: Enable android-verity and FEC in msmcortex drm/i915: Update ifdeffery for mutex->owner tuntap: correctly wake up process during uninit coresight: stm: adding driver for CoreSight STM componen 1050304 Ife18adde8349acb92b22e228d0bbc18edbf2c90e msm: mdss: hdcp2p2: fix deadlock during re-authenticatio perf: passing struct perf_event to function setup_aux() drm/i915: Update CDCLK_FREQ register on BDW after changi 1086946 I357772e10bf8958804d9cd0c78eda27139054b21 sched/hmp: Use GFP_KERNEL for top task memory allocation stm class: Fix link list locking aacraid: Relinquish CPU during timeout wait drm/vmwgfx: Add an option to change assumed FB bpp mfd: omap-usb-tll: Fix scheduling while atomic BUG mei: bus: call mei_cl_read_start under device lock btrfs: account for non-CoW'd blocks in btrfs_abort_trans 1077174 I669dc12a17b3102a7fd7f28e8c78843e3e3f9764 wil6210: validate wil_pmc_alloc parameters 1080409 Idb1aa513ca2a0265c9aab9c2529499e59da97167 ARM: dts: msm: update VDD_GFX CPR aging and loop paramet memory: omap-gpmc: Fix omap gpmc EXTRADELAY timing usb: musb: only restore devctl when session was set in b UBI: Fix static volume checks when Fastmap is used ext4: iterate over buffer heads correctly in move_extent xhci: Fix handling timeouted commands on hosts in weird coresight: add API to get sink from path arm64: kernel: perform relocation processing from ID map 1086719 I65027413ecb22a1e89e37a12f66c5abda6c3ba28 ARM: dts: msm: update the ESR pulse width in pmicobalt 1086715 I665a6f879af4e6b6e9f94b5464be7894d5ea67cb qpnp-fg-gen3: update empty voltage threshold and empty S MIPS: Fix uapi include in exported asm/siginfo.h Revert "Don't kill IPv4 sockets when killing IPv6 socket x86/amd_nb: Fix boot crash on non-AMD systems Revert "net: activity_stats: Add statistics for network ecryptfs: forbid opening files without mmap handler Ibda2d126f6d72fedf797a98796c3cde7bb03db76 UPSTREAM: ALSA: timer: Fix leak in SNDRV_TIMER_IOCTL_PAR ALSA: hda - Fix headset mic detection problem for Dell m stm class: Support devices that override software assign ipmi: Remove smi_msg from waiting_rcv_msgs list before h 1073673 I1ef3bd0da3f74fa41074021699b2226c48bde9c3 msm: kgsl: add egl_surface/egl_image usage count in debu 1085620 I5c900d2ee161fa692d66e3e66012398869715662 sched: Fix race condition with active balance ARM: sunxi/dt: make the CHIP inherit from allwinner,sun5 1074681 I31a83abc057c345f29d204a63e7571b880678e69 usb: core: Add support to skip extended bus resume delay mac80211: mesh: flush mesh paths unconditionally MIPS: Don't unwind to user mode with EVA sparc64: Take ctx_alloc_lock properly in hugetlb_setup() xen/x86: actually allocate legacy interrupts on PV guest powerpc/pseries/eeh: Handle RTAS delay requests in confi 1087108 Ia0b9a2a52a3b33b7b68409c19c460d717eb5c1e2 clk: qcom: Add support to initialize & handle dynamic up s390/bpf: reduce maximum program size to 64 KB perf tools: fixing Makefile problems 1085356 I5f381b1e0c0222b8ae81d923da0b86d742b3cccd ASoC: wcd9335: Fix AANC click and pop in voice call netfilter: x_tables: validate targets of jumps gpio: bcm-kona: fix bcm_kona_gpio_reset() warnings Revert "net: fix iterating over hashtable in tcp_nuke_ad 1076959 I8de2db02e6e073144bc5d8a9173313102c9a598f msm: soc: Avoid calling bus clear pdata tipc: fix nametable publication field in nl compat Revert "scsi: fix soft lockup in scsi_remove_target() on MIPS: Fix 64k page support for 32 bit kernels. arm64: Provide "model name" in /proc/cpuinfo for PER_LIN arm64: kernel: replace early 64-bit literal loads with m ANDROID: configs: remove unused configs MIPS: Build microMIPS VDSO for microMIPS kernels 1086932 Ibf9ac87dc605266a90f7364b6618297e66902b39 ARM: dts: msm: Add storage node for QRD interposer msmco 1082940 I9a82c4c7aff24f00bb544577b40221002b71e135 arm: qcom: Add support for msmtriton chipset scsi: fix race between simultaneous decrements of ->host 1085405 I1b8bf9762642e0af73d7ac7fa51c974b93fd4b31 ARM: dts: msm: Add ADC nodes for pmfalcon 1086995 Ibaab202c47a475623e197a13191b2fed638ce20b arm: dma-mapping: page align size before flush tlb net_sched: fix mirrored packets checksum tracing: Handle NULL formats in hold_module_trace_bprint ARM: dts: at91: fix typo in sama5d2 PIN_PD24 description iio:ad7266: Fix probe deferral for vref HID: hiddev: validate num_values for HIDIOCGUSAGES, HIDI ALSA: hda/realtek: Add T560 docking unit fixup USB: mos7720: delete parport ALSA: hda - Fix the headset mic jack detection on Dell m drm/amdkfd: destroy dbgmgr in notifier release arm64: mm: always take dirty state from new pte in ptep_ 1085631 I0eed467aec676dd6eba71bf08aa4a45ada90133b ASoC: msm: q6dspv2: wake up tasks when ADSP goes down dma-debug: avoid spinlock recursion when disabling dma-d coresight: etm-perf: new PMU driver for ETM tracers vxlan, gre, geneve: Set a large MTU on ovs-created tunne Ic72a87432e27844155467817600adc6cf0c2209c Revert "drivers: power: Add watchdog timer to catch driv coresight: Fix erroneous memset in tmc_read_unprepare_et crypto: user - re-add size check for CRYPTO_MSG_GETALG Id9a6d02bdd98bf495d26595cf2cc90e480746186 UPSTREAM: cdc_ncm: do not call usbnet_link_change from c Input: pwm-beeper - fix - scheduling while atomic coresight: etm3x: splitting struct etm_drvdata coresight: tmc: allocating memory when needed iio: light apds9960: Add the missing dev.parent powerpc/eeh: Don't report error in eeh_pe_reset_and_reco usb: dwc3: exynos: Fix deferred probing storm. usb: host: ehci-tegra: Grab the correct UTMI pads reset BACKPORT: proc: add /proc/<pid>/timerslack_ns interface mac80211: Fix mesh estab_plinks counting in STA removal coresight: tmc: implementing TMC-ETF AUX space API I2e4c27352894b9f1f4c808b8db3ae5f9284faec1 UPSTREAM: ALSA: timer: Fix leak in events via snd_timer_ 1088046 Ieee5a3acf5bbcd66ca1789a1011bd8c9461657ef smb138x-charger: expose CHARGE_TYPE in parallel psy MAINTAINERS: Add a git tree for the stm class powerpc/book3s64: Fix branching to OOL handlers in reloc arm64: mm: Mark .rodata as RO crypto: qat - make qat_asym_algs.o depend on asn1 header arm/arm64: KVM: Enforce Break-Before-Make on Stage-2 pag Revert "misc: uidstat: Remove use of obsolete create_pro iio: humidity: hdc100x: fix IIO_TEMP channel reporting sparc: Harden signal return frame checks. 53c700: fix BUG on untagged commands hwmon: (ads7828) Enable internal reference I13e73cfb2ad761c94762d0c8196df7725abdf5c5 BACKPORT: perf tools: Document the perf sysctls stm class: Fix unlocking braino in the error path clk: bcm2835: add locking to pll*_on/off methods pinctrl: exynos5440: Use off-stack memory for pinctrl_gp wait/ptrace: assume __WALL if the child is traced coresight: fixing lockdep error 1084136 Ib59cdd88557d917c85d8d33968efc295bcef2280 usb: gadget: Do not disconnect unregistered dev Linux 4.4.15 drm/i915: Revert DisplayPort fast link training feature 1046834 I1c0c57de3319c59c094b9e8d9192995312192354 Revert "input: touchscreen: Add synaptics v1 driver" coresight: etb10: adding operation mode for sink->enable net: alx: Work around the DMA RX overflow issue 1079523 Ia291140cd815589caca0eec5ab280961891ba064 ARM: dts: msm: Enable memory allocation for diag on coba USB: uas: Fix slave queue_depth not being set iommu/arm-smmu: Wire up map_sg for arm-smmu-v3 asix: Fix offset calculation in asix_rx_fixup() causing arm64: Ensure pmd_present() returns false after pmd_mkno ipv6: Fix mem leak in rt6i_pcpu stm class: Fix locking in unbinding policy path netfilter: ip_tables: simplify translate_compat_table ar 1086946 I14a8290c9fcc4174ec80560e9f9d7bcdb119761f sched/hmp: Fix memory leak when task fork fails perf tools: adding coresight etm PMU record capabilities coresight: tmc: clearly define number of transfers per b neigh: Explicitly declare RCU-bh read side critical sect Iff5bff4fc1042e85866df9faa01bce8d04335ab8 FROMLIST: security,perf: Allow further restriction of pe ALSA: hda - fix use-after-free after module unload usb: musb: Stop bulk endpoint while queue is rotated 1071971 Ibbf3d432709eadf0808e062726804be6b2a065ee regulator: labibb: configure LCD/AMOLED mode and SWIRE c perf/x86: Fix undefined shift on 32-bit kernels geneve: Relax MTU constraints coresight: moving coresight_simple_func() to header file crypto: qat - fix adf_ctl_drv.c:undefined reference to a ALSA: hda/realtek - add new pin definition in alc225 pin arm64: use 'segment' rather than 'chunk' to describe map KVM: MTRR: remove MSR 0x2f8 mmc: sdhci-acpi: Remove MMC_CAP_BUS_WIDTH_TEST for Intel 1088970 I5061c95855d462879c2f5237ded80131de4d215d msm_11ad: disbale L1 for 11ad device coresight: tmc: waiting for TMCReady bit before programm 1086836 I190cdb3f3dfe718f19c40f31e82eeb401f9ea37d coresight: tmc: fix mutex release 1086710 Ib04ab10998de2f57b05cd976c3e9c8a1e2f4c574 qpnp-fg-gen3: extend profile integrity word usage fs/cifs: correctly to anonymous authentication for the N perf/ring_buffer: Refuse to begin AUX transaction after HID: multitouch: enable palm rejection for Windows Preci mnt: If fs_fully_visible fails call put_filesystem. 747680 I2689d42402befd849aff05353196c7c0a4d32d56 ARM64: config: Add VPN support I13923fda9d314f48196c29e4354133dfe01f5abd UPSTREAM: mac80211: fix "warning: ‘target_metric’ may be USB: EHCI: declare hostpc register as zero-length array sparc64: Reduce TLB flushes during hugepte changes I0ca651ef2d854fff03cee070524fe1e3971b6d8f Revert "armv6 dcc tty driver" 1083528 Idc0f0de7f3196d5e456d62e871c8ccfcb576fb07 ARM: dts: msm: add PMFALCON/PM2FALCON devices for msmcob MIPS64: R6: R2 emulation bugfix 1087964 I34ed23bdbbaedc73cae777a7df8a7c04efb3c0a8 msm: kgsl: Correct the merciu size for a540 UBIFS: Implement ->migratepage() x86/entry/traps: Don't force in_interrupt() to return tr cs-etm: associating output packet with CPU they executed crypto: public_key: select CRYPTO_AKCIPHER 1083537 I0ff5b7ba83f2fec89562337ec63e062b50abc589 ASoC: msm8x16-wcd: update mbhc config type sparc64: Fix bootup regressions on some Kconfig combinat I00c612be2b8c22dd5afb65a739551df91cb324fc ANDROID: dm verity fec: initialize recursion level crypto: vmx - Increase priority of aes-cbc cipher powerpc/eeh: Restore initial state in eeh_pe_reset_and_r ARM: 8578/1: mm: ensure pmd_present only checks the vali ath10k: fix kernel panic, move arvifs list head init bef Revert "misc: uidstat: avoid create_stat() race and bloc usb: common: otg-fsm: add license to usb-otg-fsm ALSA: hda/realtek - Add support for new codecs ALC700/AL Revert "powerpc/eeh: Fix crash in eeh_add_device_early() MIPS: lib: Mark intrinsics notrace netlink: Fix dump skb leak/double free 1085620 I61486e8648af0dbb82595fe699e1bc158e837362 sched/core: Keep rq online after cpu isolation vxlan: Relax MTU constraints 1085143 Iadab43e9655a9e97cdc6661c17a73891cbc2a17f msm: mdss: Enable secure display and camera feature for 1086299 I88f73603b6d389a46f8e819d9b490091d5ba4fe9 sched: Ensure watchdog is enabled before disabling 1036444 I31008433f19924bb35560d3e35fe0665e73751d5 msm: kgsl: Add qcom,gpu-quirk-disable-lmloadkill MIPS: Fix siginfo.h to use strict posix types perf tools: tracepoint_error() can receive e=NULL, robus xt_qtaguid: Fix panic caused by synack processing coresight: Handle build path error base: make module_create_drivers_dir race-free coresight: tmc: re-implementing tmc_read_prepare/unprepa irqchip/gic-v3: Fix ICC_SGI1R_EL1.INTID decoding mask iio:ad7266: Fix support for optional regulators coresight: tmc: splitting driver in ETB/ETF and ETR comp ring-buffer: Use long for nr_pages to avoid overflow fai 1085748 I74a10da503622f7cd9ceb9a8b503b876e17abab4 ASoC: wcd934x: Update surge recovery for version 1.1 perf tools: decoding capailitity for CoreSight traces nfsd: Always lock state exclusively. 1077922 I34193ef71bed3fe23d9699964ce3d18529b26dc6 msm: mdss: fix 32-bit compilation issues for MDSS DP dri Revert "tcp: Fix IPV6 module build errors" 1085388 I11caee63b7d99f1a2c7f563cb5e1478c9e8ac90a ARM: dts: msm: Disable clock gating on msmcobalt s390/bpf: fix recache skb->data/hlen for skb_vlan_push/p coresight: etb10: fixing the right amount of words to re 1086116 If2309a590ad37547354c0917dd11a202daa9abe4 ARM: dts: msm: Disable lpm sleep modes for msmfalcon coresight: tmc: introducing new header file scsi: Add intermediate STARGET_REMOVE state to scsi_targ 1015476 I0bcbfadb0c1a22529863a5c4b8cc5c53a1028915 ASoC: msm: qdsp6v2: add support for tx app type config Revert "net: fix crash in tcp_nuke_addr()" stm class: dummy_stm: Add link callback for fault inject tty: vt: Fix soft lockup in fbcon cursor blink timer. usb: musb: host: correct cppi dma channel for isoch tran perf cpumap: Auto initialize cpu__max_{node,cpu} mmc: longer timeout for long read time quirk 1075694 Ib2680fb97fed1d297c9a96c95edb08dea620495b msm: kgsl: Enable limits management on A540v2 fs/cifs: correctly to anonymous authentication for the L 1073836 Ie780cec4de818c94a407461580f9d80de7e4ec84 msm: kgsl: Increase fault detection threshold value esp: Fix ESN generation under UDP encapsulation MIPS: ptrace: Prevent writes to read-only FCSR bits 1088681 Ib697476c93c60e3d213aaa8fff0a2bcc2985bfce timer: Don't wait for running timers when migrating duri cifs: dynamic allocation of ntlmssp blob netfilter: x_tables: don't reject valid target size on s hwmon: (dell-smm) Disallow fan_type() calls on broken ma hwmon: (dell-smm) Restrict fan control and serial number coresight: tmc: adding mode of operation for link/sinks MIPS: MSA: Fix a link error on `_init_msa_upper' with ol 1082413 Ie263acbb0dd9cab06b239e14526be13622bd282d ARM: dts: msm: Add camera node for msmcobalt QVR board If2bba3c9ffb4e57190583b0bb2524d3b2514b2a3 UPSTREAM: ALSA: timer: Fix leak in events via snd_timer_ coresight: Fix tmc_read_unprepare_etr coresight: moving PM runtime operations to core framewor drm/gma500: Fix possible out of bounds read cpuidle: Indicate when a device has been unregistered cpufreq: interactive: drop cpufreq_{get,put}_global_kobj 1085702 I2064d3c21863e50ee1a70e57f7915d04f2ba0407 cgroup: Disable IRQs while holding css_set_lock Ida2b2ef7cd86dd87300bfb4c2cdb6bfe2ee1650d sdcardfs: Truncate packages_gid.list on overflow 1071971 I182dddc29f3d7c7b449b56ac7fb84e74061cf3a4 regulator: qpnp-labibb: Rename properties to reflect the aacraid: Fix for aac_command_thread hang 1073250 Ic6671aede0742f46e8573340a497e9f19773e5d8 ASoC: wcd9xxx: clean up bootup errors coresight: configuring ETF in FIFO mode when acting as l coresight: etm3x: moving sysFS entries to dedicated file Change-Id: I14eacc3304b2ea7d4e95ae9fda9615b79030c368 CRs-Fixed: 1084507, 1085214, 1088681, 1087974, 1083137, 1085592, 1088572, 980999, 1086476, 1075694, 1080348, 1081543, 1073673, 1050455, 1087964, 1045956, 1084699, 1083528, 1084297, 1084100, 1081831, 1085356, 1083537, 1086622, 1085750, 1084217, 1086571, 1086818, 1079523, 1084723, 1083111, 1084285, 1076516, 1085620, 1085748, 1088210, 1086946, 1078904, 1084618, 1086541, 747680, 1082850, 1086418, 1047963, 1066548, 1086186, 1064046, 1024407, 1066021, 1049684, 1062351, 1088046, 1084966, 1086127, 1085631, 1075305, 1086328, 1077224, 1086719, 1086715, 1086710, 1081084, 1086932, 1077174, 1066012, 1086881, 1064689, 1035111, 1084136, 1080024, 1086727, 1073034, 1088970, 1085547, 1086028, 1062239, 1088388, 1086733, 1087356, 1080409, 1058676, 1086836, 1001139, 1079913, 1076959, 1081490, 1036444, 1073250, 1071971, 1073238, 1082413, 1015476, 1088713, 1086116, 1074681, 1008319, 1086299, 1046834, 1024199, 1083253, 1071199, 1085143, 1085702, 1087345, 1087108, 1085388, 1085266, 1050304, 1052835, 1082940, 1072607, 1077126, 1059771, 1085405, 1053383, 1021945, 1077493, 1050538, 1080747, 1067965, 1073836, 1043997, 1086995, 1086513, 1085449, 1077922, 1086449, 1045472, 1080507
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio-proximity-as39352
-rw-r--r--Documentation/ABI/testing/sysfs-class-stm10
-rw-r--r--Documentation/devicetree/bindings/arm/msm/qcom,osm.txt47
-rw-r--r--Documentation/devicetree/bindings/cache/arm64_cache_erp.txt34
-rw-r--r--Documentation/devicetree/bindings/clock/imx35-clock.txt1
-rw-r--r--Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt9
-rw-r--r--Documentation/devicetree/bindings/gpu/adreno.txt54
-rw-r--r--Documentation/devicetree/bindings/platform/msm/rmnet_ipa.txt2
-rw-r--r--Documentation/devicetree/bindings/platform/msm/rmnet_ipa3.txt2
-rw-r--r--Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt2
-rw-r--r--Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt9
-rw-r--r--Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt34
-rw-r--r--Documentation/devicetree/bindings/sound/qcom-audio-dev.txt257
-rw-r--r--Documentation/filesystems/proc.txt18
-rw-r--r--Documentation/scheduler/sched-hmp.txt290
-rw-r--r--Documentation/scsi/scsi_eh.txt8
-rw-r--r--Documentation/serial/tty.txt3
-rw-r--r--Documentation/sysctl/fs.txt23
-rw-r--r--Documentation/sysctl/kernel.txt1
-rw-r--r--MAINTAINERS5
-rw-r--r--Makefile9
-rw-r--r--android/configs/android-base.cfg9
-rw-r--r--android/configs/android-recommended.cfg2
-rw-r--r--arch/arc/Kconfig2
-rw-r--r--arch/arc/kernel/setup.c4
-rw-r--r--arch/arm/boot/dts/armada-385-linksys.dtsi10
-rw-r--r--arch/arm/boot/dts/armada-xp-linksys-mamba.dts4
-rw-r--r--arch/arm/boot/dts/exynos4210-trats.dts2
-rw-r--r--arch/arm/boot/dts/qcom/Makefile5
-rw-r--r--arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/apq8096-dragonboard.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/apq8096-sbc.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm2falcon-rpm-regulator.dtsi238
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmfalcon-rpm-regulator.dtsi298
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi179
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmi8994.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi12
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-cdp.dtsi8
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-dtp.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-fluid.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-gpu.dtsi34
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-liquid.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi6
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-mtp.dtsi8
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-qrd-vr1.dtsi369
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-skuk.dtsi327
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi12
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi37
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-cdp.dtsi592
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-mtp.dtsi613
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon.dtsi3090
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-interposer-pmfalcon.dtsi279
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi14
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-qrd.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi17
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2-interposer-msmfalcon.dtsi864
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-cdp.dts24
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-mtp.dts24
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dts23
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dtsi105
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon.dtsi18
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi179
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt.dtsi48
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-regulator.dtsi726
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-rumi.dts8
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon-sim.dts8
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon.dtsi55
-rw-r--r--arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi365
-rw-r--r--arch/arm/boot/dts/qcom/msmtriton.dtsi27
-rw-r--r--arch/arm/boot/dts/sama5d2-pinfunc.h4
-rw-r--r--arch/arm/boot/dts/sun5i-r8-chip.dts2
-rw-r--r--arch/arm/configs/msmcortex_defconfig1
-rw-r--r--arch/arm/configs/msmfalcon_defconfig3
-rw-r--r--arch/arm/include/asm/mach/mmc.h28
-rw-r--r--arch/arm/include/asm/pgtable-2level.h1
-rw-r--r--arch/arm/include/asm/pgtable-3level.h5
-rw-r--r--arch/arm/include/asm/pgtable.h1
-rw-r--r--arch/arm/kernel/ptrace.c2
-rw-r--r--arch/arm/kvm/mmu.c17
-rw-r--r--arch/arm/mach-imx/mach-imx6ul.c2
-rw-r--r--arch/arm/mach-mvebu/coherency.c22
-rw-r--r--arch/arm/mach-qcom/Kconfig32
-rw-r--r--arch/arm/mm/dma-mapping.c3
-rw-r--r--arch/arm64/Kconfig.debug2
-rw-r--r--arch/arm64/Makefile2
-rw-r--r--arch/arm64/boot/.gitignore1
-rw-r--r--arch/arm64/boot/Makefile3
-rw-r--r--arch/arm64/boot/dts/arm/juno.dts305
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig8
-rw-r--r--arch/arm64/configs/msmcortex_defconfig8
-rw-r--r--arch/arm64/configs/msmfalcon-perf_defconfig31
-rw-r--r--arch/arm64/configs/msmfalcon_defconfig30
-rw-r--r--arch/arm64/include/asm/assembler.h20
-rw-r--r--arch/arm64/include/asm/elf.h4
-rw-r--r--arch/arm64/include/asm/pgtable-hwdef.h1
-rw-r--r--arch/arm64/include/asm/pgtable.h25
-rw-r--r--arch/arm64/include/asm/ptrace.h33
-rw-r--r--arch/arm64/kernel/cpuinfo.c8
-rw-r--r--arch/arm64/kernel/efi-entry.S2
-rw-r--r--arch/arm64/kernel/head.S160
-rw-r--r--arch/arm64/kernel/image.h2
-rw-r--r--arch/arm64/kernel/kaslr.c6
-rw-r--r--arch/arm64/kernel/ptrace.c81
-rw-r--r--arch/arm64/kernel/signal.c4
-rw-r--r--arch/arm64/kernel/signal32.c2
-rw-r--r--arch/arm64/kernel/vmlinux.lds.S36
-rw-r--r--arch/arm64/kvm/inject_fault.c2
-rw-r--r--arch/arm64/mm/dma-mapping.c1
-rw-r--r--arch/arm64/mm/fault.c50
-rw-r--r--arch/arm64/mm/init.c4
-rw-r--r--arch/arm64/mm/mmu.c35
-rw-r--r--arch/mips/ath79/early_printk.c6
-rw-r--r--arch/mips/include/asm/asmmacro.h40
-rw-r--r--arch/mips/include/asm/cacheflush.h6
-rw-r--r--arch/mips/include/asm/kvm_host.h3
-rw-r--r--arch/mips/include/asm/msa.h13
-rw-r--r--arch/mips/include/asm/pgtable.h26
-rw-r--r--arch/mips/include/asm/processor.h2
-rw-r--r--arch/mips/include/asm/switch_to.h2
-rw-r--r--arch/mips/include/asm/watch.h10
-rw-r--r--arch/mips/include/uapi/asm/siginfo.h22
-rw-r--r--arch/mips/kernel/mips-r2-to-r6-emul.c105
-rw-r--r--arch/mips/kernel/pm.c2
-rw-r--r--arch/mips/kernel/process.c6
-rw-r--r--arch/mips/kernel/ptrace.c27
-rw-r--r--arch/mips/kernel/r4k_fpu.S10
-rw-r--r--arch/mips/kernel/setup.c3
-rw-r--r--arch/mips/kernel/signal.c15
-rw-r--r--arch/mips/kernel/traps.c8
-rw-r--r--arch/mips/kernel/watch.c5
-rw-r--r--arch/mips/kvm/emulate.c89
-rw-r--r--arch/mips/kvm/interrupt.h1
-rw-r--r--arch/mips/kvm/locore.S1
-rw-r--r--arch/mips/kvm/mips.c11
-rw-r--r--arch/mips/kvm/trap_emul.c2
-rw-r--r--arch/mips/lib/ashldi3.c2
-rw-r--r--arch/mips/lib/ashrdi3.c2
-rw-r--r--arch/mips/lib/bswapdi.c2
-rw-r--r--arch/mips/lib/bswapsi.c2
-rw-r--r--arch/mips/lib/cmpdi2.c2
-rw-r--r--arch/mips/lib/lshrdi3.c2
-rw-r--r--arch/mips/lib/ucmpdi2.c2
-rw-r--r--arch/mips/loongson64/loongson-3/numa.c6
-rw-r--r--arch/mips/math-emu/cp1emu.c8
-rw-r--r--arch/mips/mm/cache.c41
-rw-r--r--arch/mips/vdso/Makefile4
-rw-r--r--arch/parisc/kernel/unaligned.c10
-rw-r--r--arch/powerpc/include/asm/reg.h6
-rw-r--r--arch/powerpc/kernel/eeh.c2
-rw-r--r--arch/powerpc/kernel/eeh_driver.c26
-rw-r--r--arch/powerpc/kernel/exceptions-64s.S16
-rw-r--r--arch/powerpc/kernel/process.c10
-rw-r--r--arch/powerpc/kernel/prom_init.c3
-rw-r--r--arch/powerpc/platforms/pseries/eeh_pseries.c51
-rw-r--r--arch/powerpc/platforms/pseries/iommu.c24
-rw-r--r--arch/s390/include/asm/fpu/api.h2
-rw-r--r--arch/s390/net/bpf_jit.h4
-rw-r--r--arch/s390/net/bpf_jit_comp.c4
-rw-r--r--arch/sparc/include/asm/head_64.h4
-rw-r--r--arch/sparc/include/asm/pgtable_64.h43
-rw-r--r--arch/sparc/include/asm/tlbflush_64.h3
-rw-r--r--arch/sparc/include/asm/ttable.h8
-rw-r--r--arch/sparc/kernel/Makefile1
-rw-r--r--arch/sparc/kernel/cherrs.S14
-rw-r--r--arch/sparc/kernel/entry.S17
-rw-r--r--arch/sparc/kernel/fpu_traps.S11
-rw-r--r--arch/sparc/kernel/head_64.S24
-rw-r--r--arch/sparc/kernel/misctrap.S12
-rw-r--r--arch/sparc/kernel/pci.c17
-rw-r--r--arch/sparc/kernel/rtrap_64.S57
-rw-r--r--arch/sparc/kernel/signal32.c46
-rw-r--r--arch/sparc/kernel/signal_32.c41
-rw-r--r--arch/sparc/kernel/signal_64.c33
-rw-r--r--arch/sparc/kernel/sigutil_32.c9
-rw-r--r--arch/sparc/kernel/sigutil_64.c10
-rw-r--r--arch/sparc/kernel/spiterrs.S18
-rw-r--r--arch/sparc/kernel/syscalls.S36
-rw-r--r--arch/sparc/kernel/urtt_fill.S98
-rw-r--r--arch/sparc/kernel/utrap.S3
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S4
-rw-r--r--arch/sparc/kernel/winfixup.S3
-rw-r--r--arch/sparc/mm/hugetlbpage.c33
-rw-r--r--arch/sparc/mm/init_64.c37
-rw-r--r--arch/sparc/mm/tlb.c25
-rw-r--r--arch/sparc/mm/tsb.c32
-rw-r--r--arch/x86/boot/Makefile3
-rw-r--r--arch/x86/kernel/amd_nb.c4
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c2
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_pt.c2
-rw-r--r--arch/x86/kernel/kprobes/core.c12
-rw-r--r--arch/x86/kernel/traps.c20
-rw-r--r--arch/x86/kvm/cpuid.c1
-rw-r--r--arch/x86/kvm/mtrr.c2
-rw-r--r--arch/x86/kvm/vmx.c25
-rw-r--r--arch/x86/kvm/x86.c5
-rw-r--r--arch/x86/pci/xen.c7
-rw-r--r--arch/x86/xen/setup.c65
-rw-r--r--crypto/asymmetric_keys/Kconfig1
-rw-r--r--crypto/crypto_user.c1
-rw-r--r--drivers/acpi/osl.c16
-rw-r--r--drivers/android/binder.c31
-rw-r--r--drivers/ata/libata-eh.c2
-rw-r--r--drivers/base/dd.c3
-rw-r--r--drivers/base/module.c8
-rw-r--r--drivers/base/power/main.c85
-rw-r--r--drivers/base/power/power.h3
-rw-r--r--drivers/base/power/runtime.c9
-rw-r--r--drivers/bluetooth/hci_vhci.c28
-rw-r--r--drivers/char/Kconfig4
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/adsprpc.c2
-rw-r--r--drivers/char/dcc_tty.c326
-rw-r--r--drivers/char/diag/diagchar.h1
-rw-r--r--drivers/char/diag/diagchar_core.c1
-rw-r--r--drivers/char/diag/diagfwd_peripheral.c3
-rw-r--r--drivers/char/diag/diagfwd_socket.c8
-rw-r--r--drivers/char/hw_random/exynos-rng.c10
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c8
-rw-r--r--drivers/clk/at91/clk-h32mx.c2
-rw-r--r--drivers/clk/bcm/clk-bcm2835.c23
-rw-r--r--drivers/clk/imx/clk-imx35.c4
-rw-r--r--drivers/clk/msm/clock-osm.c451
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.c253
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.h24
-rw-r--r--drivers/clk/qcom/clk-pll.h9
-rw-r--r--drivers/clk/qcom/gcc-msm8916.c2
-rw-r--r--drivers/clk/qcom/gcc-msmfalcon.c15
-rw-r--r--drivers/clk/qcom/gpucc-msmfalcon.c14
-rw-r--r--drivers/clk/qcom/vdd-level-falcon.h42
-rw-r--r--drivers/cpufreq/cpufreq_interactive.c22
-rw-r--r--drivers/cpuidle/cpuidle.c4
-rw-r--r--drivers/crypto/Kconfig10
-rw-r--r--drivers/crypto/caam/jr.c2
-rw-r--r--drivers/crypto/ccp/ccp-crypto-aes-xts.c17
-rw-r--r--drivers/crypto/msm/qce50.c21
-rw-r--r--drivers/crypto/msm/qcedev.c68
-rw-r--r--drivers/crypto/qat/qat_common/Makefile1
-rw-r--r--drivers/crypto/qat/qat_common/adf_common_drv.h13
-rw-r--r--drivers/crypto/sunxi-ss/sun4i-ss-cipher.c10
-rw-r--r--drivers/crypto/talitos.c64
-rw-r--r--drivers/crypto/ux500/hash/hash_core.c4
-rw-r--r--drivers/crypto/vmx/aes_cbc.c2
-rw-r--r--drivers/crypto/vmx/aes_ctr.c2
-rw-r--r--drivers/devfreq/devfreq.c13
-rw-r--r--drivers/edac/sb_edac.c13
-rw-r--r--drivers/firmware/efi/libstub/arm64-stub.c15
-rw-r--r--drivers/gpio/gpio-bcm-kona.c4
-rw-r--r--drivers/gpio/gpiolib-legacy.c8
-rw-r--r--drivers/gpio/gpiolib.c52
-rw-r--r--drivers/gpio/qpnp-pin.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c70
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c2
-rw-r--r--drivers/gpu/drm/drm_atomic.c5
-rw-r--r--drivers/gpu/drm/drm_crtc.c62
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c8
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c5
-rw-r--r--drivers/gpu/drm/drm_modes.c2
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_shrinker.c2
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h2
-rw-r--r--drivers/gpu/drm/i915/intel_display.c50
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c36
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c6
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c2
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c8
-rw-r--r--drivers/gpu/drm/imx/ipuv3-crtc.c2
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c10
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c2
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fbcon.c7
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fbcon.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fbcon.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c37
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c21
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c25
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c12
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h1
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c10
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fb.c53
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c10
-rw-r--r--drivers/gpu/ipu-v3/ipu-common.c5
-rw-r--r--drivers/gpu/msm/a5xx_reg.h2
-rw-r--r--drivers/gpu/msm/adreno-gpulist.h2
-rw-r--r--drivers/gpu/msm/adreno.c15
-rw-r--r--drivers/gpu/msm/adreno.h2
-rw-r--r--drivers/gpu/msm/adreno_a3xx.c40
-rw-r--r--drivers/gpu/msm/adreno_a5xx.c26
-rw-r--r--drivers/gpu/msm/adreno_perfcounter.c32
-rw-r--r--drivers/gpu/msm/kgsl.c49
-rw-r--r--drivers/gpu/msm/kgsl.h3
-rw-r--r--drivers/gpu/msm/kgsl_debugfs.c93
-rw-r--r--drivers/gpu/msm/kgsl_mmu.c20
-rw-r--r--drivers/gpu/msm/kgsl_pool.c132
-rw-r--r--drivers/gpu/msm/kgsl_pool.h2
-rw-r--r--drivers/gpu/msm/kgsl_snapshot.c3
-rw-r--r--drivers/hid/hid-elo.c2
-rw-r--r--drivers/hid/hid-multitouch.c28
-rw-r--r--drivers/hid/hid-steelseries.c5
-rw-r--r--drivers/hid/usbhid/hiddev.c10
-rw-r--r--drivers/hwmon/ads7828.c10
-rw-r--r--drivers/hwmon/dell-smm-hwmon.c80
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x.c4
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc.c6
-rw-r--r--drivers/hwtracing/coresight/coresight-tpiu.c3
-rw-r--r--drivers/hwtracing/stm/Kconfig15
-rw-r--r--drivers/hwtracing/stm/Makefile2
-rw-r--r--drivers/hwtracing/stm/core.c203
-rw-r--r--drivers/hwtracing/stm/dummy_stm.c67
-rw-r--r--drivers/hwtracing/stm/heartbeat.c126
-rw-r--r--drivers/hwtracing/stm/policy.c27
-rw-r--r--drivers/hwtracing/stm/stm.h2
-rw-r--r--drivers/iio/accel/kxsd9.c4
-rw-r--r--drivers/iio/adc/ad7266.c7
-rw-r--r--drivers/iio/humidity/hdc100x.c20
-rw-r--r--drivers/iio/industrialio-trigger.c23
-rw-r--r--drivers/iio/light/apds9960.c1
-rw-r--r--drivers/iio/pressure/st_pressure_core.c80
-rw-r--r--drivers/iio/proximity/as3935.c17
-rw-r--r--drivers/infiniband/core/cm.c4
-rw-r--r--drivers/infiniband/hw/mlx4/ah.c2
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c2
-rw-r--r--drivers/input/misc/pwm-beeper.c69
-rw-r--r--drivers/input/misc/uinput.c6
-rw-r--r--drivers/iommu/amd_iommu_init.c14
-rw-r--r--drivers/iommu/arm-smmu-v3.c1
-rw-r--r--drivers/iommu/intel-iommu.c17
-rw-r--r--drivers/irqchip/irq-gic-v3.c19
-rw-r--r--drivers/irqchip/irq-gic.c8
-rw-r--r--drivers/mcb/mcb-parse.c2
-rw-r--r--drivers/media/platform/msm/camera_v2/common/cam_soc_api.c9
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp40.c2
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c4
-rw-r--r--drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c42
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c2
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c2
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c285
-rw-r--r--drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h11
-rw-r--r--drivers/media/platform/msm/vidc/msm_venc.c5
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_common.c14
-rw-r--r--drivers/media/usb/uvc/uvc_v4l2.c39
-rw-r--r--drivers/media/v4l2-core/v4l2-compat-ioctl32.c3
-rw-r--r--drivers/memory/omap-gpmc.c2
-rw-r--r--drivers/mfd/intel-lpss.c19
-rw-r--r--drivers/mfd/intel_soc_pmic_core.c1
-rw-r--r--drivers/mfd/omap-usb-tll.c13
-rw-r--r--drivers/mfd/wcd9xxx-utils.c23
-rw-r--r--drivers/misc/hdcp.c136
-rw-r--r--drivers/misc/mei/amthif.c4
-rw-r--r--drivers/misc/mei/bus.c15
-rw-r--r--drivers/misc/mei/client.c4
-rw-r--r--drivers/misc/mei/hbm.c3
-rw-r--r--drivers/misc/mei/interrupt.c6
-rw-r--r--drivers/misc/mei/mei_dev.h2
-rw-r--r--drivers/misc/qseecom.c333
-rw-r--r--drivers/misc/uid_stat.c153
-rw-r--r--drivers/mmc/card/block.c5
-rw-r--r--drivers/mmc/core/core.c2
-rw-r--r--drivers/mmc/core/mmc.c7
-rw-r--r--drivers/mmc/host/sdhci-acpi.c6
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c5
-rw-r--r--drivers/mtd/ubi/eba.c43
-rw-r--r--drivers/mtd/ubi/fastmap.c1
-rw-r--r--drivers/mtd/ubi/ubi.h2
-rw-r--r--drivers/net/can/dev.c56
-rw-r--r--drivers/net/can/m_can/m_can.c2
-rw-r--r--drivers/net/ethernet/atheros/alx/main.c7
-rw-r--r--drivers/net/ethernet/cadence/macb.c13
-rw-r--r--drivers/net/ethernet/cadence/macb.h2
-rw-r--r--drivers/net/ethernet/rocker/rocker.c4
-rw-r--r--drivers/net/ethernet/sfc/ef10.c16
-rw-r--r--drivers/net/geneve.c41
-rw-r--r--drivers/net/team/team.c9
-rw-r--r--drivers/net/tun.c6
-rw-r--r--drivers/net/usb/asix_common.c2
-rw-r--r--drivers/net/usb/cdc_ncm.c7
-rw-r--r--drivers/net/vxlan.c60
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c8
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c7
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c13
-rw-r--r--drivers/net/wireless/ath/ath5k/led.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c7
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c10
-rw-r--r--drivers/net/wireless/ath/wil6210/pmc.c55
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c9
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c27
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c5
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/wifi.h3
-rw-r--r--drivers/net/wireless/ti/wlcore/init.c5
-rw-r--r--drivers/nfc/nq-nci.c104
-rw-r--r--drivers/nfc/nq-nci.h9
-rw-r--r--drivers/of/irq.c19
-rw-r--r--drivers/pci/host/pci-msm.c2
-rw-r--r--drivers/pci/probe.c6
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.c5
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos5440.c15
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_dp.c32
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_i.h2
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c23
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_dp.c27
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_i.h2
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c25
-rw-r--r--drivers/platform/msm/msm_11ad/msm_11ad.c48
-rw-r--r--drivers/platform/x86/dell-rbtn.c56
-rw-r--r--drivers/power/qcom-charger/fg-core.h7
-rw-r--r--drivers/power/qcom-charger/fg-memif.c193
-rw-r--r--drivers/power/qcom-charger/fg-reg.h25
-rw-r--r--drivers/power/qcom-charger/qpnp-fg-gen3.c219
-rw-r--r--drivers/power/qcom-charger/qpnp-smb2.c58
-rw-r--r--drivers/power/qcom-charger/smb-lib.c181
-rw-r--r--drivers/power/qcom-charger/smb-lib.h11
-rw-r--r--drivers/power/qcom-charger/smb-reg.h4
-rw-r--r--drivers/power/qcom-charger/smb138x-charger.c4
-rw-r--r--drivers/regulator/cprh-kbss-regulator.c2
-rw-r--r--drivers/regulator/qpnp-labibb-regulator.c341
-rw-r--r--drivers/scsi/53c700.c4
-rw-r--r--drivers/scsi/aacraid/aacraid.h1
-rw-r--r--drivers/scsi/aacraid/comminit.c24
-rw-r--r--drivers/scsi/aacraid/commsup.c12
-rw-r--r--drivers/scsi/scsi_devinfo.c1
-rw-r--r--drivers/scsi/scsi_error.c4
-rw-r--r--drivers/scsi/scsi_lib.c7
-rw-r--r--drivers/scsi/scsi_scan.c1
-rw-r--r--drivers/scsi/scsi_sysfs.c6
-rw-r--r--drivers/soc/qcom/memshare/msm_memshare.c14
-rw-r--r--drivers/soc/qcom/msm_bus/msm_bus_dbg_voter.c4
-rw-r--r--drivers/soc/qcom/pil-q6v5-mss.c3
-rw-r--r--drivers/soc/qcom/qdsp6v2/apr_tal_glink.c51
-rw-r--r--drivers/soc/qcom/service-locator.c2
-rw-r--r--drivers/soc/qcom/service-notifier.c5
-rw-r--r--drivers/soc/qcom/sysmon.c6
-rw-r--r--drivers/spmi/spmi-pmic-arb.c51
-rw-r--r--drivers/staging/android/fiq_debugger/Kconfig9
-rw-r--r--drivers/staging/android/fiq_debugger/fiq_debugger.c36
-rw-r--r--drivers/staging/comedi/drivers/das1800.c22
-rw-r--r--drivers/staging/iio/accel/sca3000_core.c2
-rw-r--r--drivers/thermal/cpu_cooling.c16
-rw-r--r--drivers/thunderbolt/eeprom.c1
-rw-r--r--drivers/tty/n_gsm.c4
-rw-r--r--drivers/tty/n_hdlc.c4
-rw-r--r--drivers/tty/n_tty.c70
-rw-r--r--drivers/tty/pty.c4
-rw-r--r--drivers/tty/serial/8250/8250_mid.c35
-rw-r--r--drivers/tty/serial/8250/8250_pci.c3
-rw-r--r--drivers/tty/serial/atmel_serial.c14
-rw-r--r--drivers/tty/serial/samsung.c4
-rw-r--r--drivers/tty/serial/ucc_uart.c3
-rw-r--r--drivers/tty/tty_buffer.c34
-rw-r--r--drivers/tty/vt/keyboard.c30
-rw-r--r--drivers/tty/vt/vt.c6
-rw-r--r--drivers/usb/common/usb-otg-fsm.c2
-rw-r--r--drivers/usb/core/driver.c40
-rw-r--r--drivers/usb/core/hub.c11
-rw-r--r--drivers/usb/core/quirks.c23
-rw-r--r--drivers/usb/dwc2/core.h27
-rw-r--r--drivers/usb/dwc3/dwc3-exynos.c19
-rw-r--r--drivers/usb/gadget/configfs.c9
-rw-r--r--drivers/usb/gadget/function/f_fs.c2
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c36
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.h2
-rw-r--r--drivers/usb/gadget/function/f_midi.c1
-rw-r--r--drivers/usb/gadget/function/f_mtp.c8
-rw-r--r--drivers/usb/gadget/function/u_ether.c21
-rw-r--r--drivers/usb/gadget/legacy/acm_ms.c4
-rw-r--r--drivers/usb/gadget/legacy/inode.c17
-rw-r--r--drivers/usb/gadget/legacy/mass_storage.c4
-rw-r--r--drivers/usb/gadget/legacy/multi.c12
-rw-r--r--drivers/usb/gadget/legacy/nokia.c7
-rw-r--r--drivers/usb/gadget/udc/udc-core.c2
-rw-r--r--drivers/usb/host/ehci-tegra.c2
-rw-r--r--drivers/usb/host/xhci-hub.c4
-rw-r--r--drivers/usb/host/xhci-mem.c30
-rw-r--r--drivers/usb/host/xhci-pci.c5
-rw-r--r--drivers/usb/host/xhci-plat.c3
-rw-r--r--drivers/usb/host/xhci-ring.c30
-rw-r--r--drivers/usb/host/xhci.c27
-rw-r--r--drivers/usb/misc/usbtest.c4
-rw-r--r--drivers/usb/musb/musb_core.c3
-rw-r--r--drivers/usb/musb/musb_host.c23
-rw-r--r--drivers/usb/serial/io_edgeport.c56
-rw-r--r--drivers/usb/serial/keyspan.c4
-rw-r--r--drivers/usb/serial/mos7720.c1
-rw-r--r--drivers/usb/serial/mxuport.c10
-rw-r--r--drivers/usb/serial/option.c155
-rw-r--r--drivers/usb/serial/quatech2.c1
-rw-r--r--drivers/usb/storage/uas.c1
-rw-r--r--drivers/video/fbdev/msm/mdss.h13
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c308
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.h18
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_aux.c122
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c158
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_panel.c121
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_hdcp.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_hdcp_1x.c32
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c119
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h34
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c56
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_debug.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c18
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c114
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c309
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pipe.c17
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_util.c31
-rw-r--r--drivers/video/fbdev/msm/mdss_panel.h89
-rw-r--r--drivers/video/fbdev/msm/mdss_smmu.c37
-rw-r--r--drivers/video/fbdev/msm/mdss_smmu.h34
-rw-r--r--drivers/video/fbdev/msm/msm_ext_display.c284
-rw-r--r--drivers/virtio/virtio_balloon.c20
-rw-r--r--drivers/xen/balloon.c28
-rw-r--r--drivers/xen/events/events_base.c6
-rw-r--r--drivers/xen/xen-acpi-processor.c35
-rw-r--r--fs/affs/super.c5
-rw-r--r--fs/btrfs/ctree.c5
-rw-r--r--fs/btrfs/extent-tree.c2
-rw-r--r--fs/btrfs/ioctl.c2
-rw-r--r--fs/btrfs/super.c2
-rw-r--r--fs/btrfs/transaction.h2
-rw-r--r--fs/cifs/cifs_unicode.c33
-rw-r--r--fs/cifs/cifs_unicode.h2
-rw-r--r--fs/cifs/connect.c4
-rw-r--r--fs/cifs/ntlmssp.h2
-rw-r--r--fs/cifs/sess.c203
-rw-r--r--fs/cifs/smb2glob.h1
-rw-r--r--fs/cifs/smb2inode.c8
-rw-r--r--fs/cifs/smb2pdu.c53
-rw-r--r--fs/cifs/smb2proto.h2
-rw-r--r--fs/dcache.c4
-rw-r--r--fs/eventpoll.c2
-rw-r--r--fs/ext4/ialloc.c59
-rw-r--r--fs/ext4/mballoc.c10
-rw-r--r--fs/ext4/move_extent.c1
-rw-r--r--fs/ext4/namei.c2
-rw-r--r--fs/fuse/dev.c5
-rw-r--r--fs/fuse/dir.c45
-rw-r--r--fs/fuse/fuse_i.h3
-rw-r--r--fs/hpfs/super.c42
-rw-r--r--fs/namespace.c10
-rw-r--r--fs/nfs/dir.c2
-rw-r--r--fs/nfs/nfs4proc.c5
-rw-r--r--fs/nfsd/nfs2acl.c20
-rw-r--r--fs/nfsd/nfs3acl.c16
-rw-r--r--fs/nfsd/nfs4acl.c16
-rw-r--r--fs/nfsd/nfs4callback.c18
-rw-r--r--fs/nfsd/nfs4state.c50
-rw-r--r--fs/nfsd/state.h2
-rw-r--r--fs/notify/inotify/inotify_user.c2
-rw-r--r--fs/overlayfs/dir.c113
-rw-r--r--fs/overlayfs/inode.c3
-rw-r--r--fs/overlayfs/overlayfs.h1
-rw-r--r--fs/pipe.c47
-rw-r--r--fs/posix_acl.c41
-rw-r--r--fs/proc/base.c109
-rw-r--r--fs/sdcardfs/dentry.c6
-rw-r--r--fs/sdcardfs/packagelist.c15
-rw-r--r--fs/select.c8
-rw-r--r--fs/ubifs/file.c24
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c2
-rw-r--r--fs/xfs/libxfs/xfs_alloc_btree.c1
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.c1
-rw-r--r--fs/xfs/libxfs/xfs_attr_remote.c1
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.c1
-rw-r--r--fs/xfs/libxfs/xfs_da_btree.c1
-rw-r--r--fs/xfs/libxfs/xfs_dir2_block.c1
-rw-r--r--fs/xfs/libxfs/xfs_dir2_data.c2
-rw-r--r--fs/xfs/libxfs/xfs_dir2_leaf.c2
-rw-r--r--fs/xfs/libxfs/xfs_dir2_node.c1
-rw-r--r--fs/xfs/libxfs/xfs_dquot_buf.c37
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c1
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.c1
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.c4
-rw-r--r--fs/xfs/libxfs/xfs_quota_defs.h2
-rw-r--r--fs/xfs/libxfs/xfs_sb.c2
-rw-r--r--fs/xfs/libxfs/xfs_shared.h1
-rw-r--r--fs/xfs/libxfs/xfs_symlink_remote.c1
-rw-r--r--fs/xfs/xfs_buf.h1
-rw-r--r--fs/xfs/xfs_error.c4
-rw-r--r--fs/xfs/xfs_fsops.c4
-rw-r--r--fs/xfs/xfs_inode.c26
-rw-r--r--fs/xfs/xfs_log_recover.c9
-rw-r--r--fs/xfs/xfs_super.c10
-rw-r--r--include/asm-generic/qspinlock.h32
-rw-r--r--include/asm-generic/siginfo.h15
-rw-r--r--include/drm/ttm/ttm_bo_api.h14
-rw-r--r--include/linux/amba/bus.h9
-rw-r--r--include/linux/amba/mmci.h3
-rw-r--r--include/linux/bpf.h4
-rw-r--r--include/linux/can/dev.h22
-rw-r--r--include/linux/dcache.h14
-rw-r--r--include/linux/freezer.h2
-rw-r--r--include/linux/hdcp_qseecom.h4
-rw-r--r--include/linux/hrtimer.h12
-rw-r--r--include/linux/irqchip/arm-gic-v3.h2
-rw-r--r--include/linux/jump_label.h16
-rw-r--r--include/linux/mm.h2
-rw-r--r--include/linux/net.h3
-rw-r--r--include/linux/netfilter/x_tables.h12
-rw-r--r--include/linux/nfcinfo.h6
-rw-r--r--include/linux/perf_event.h11
-rw-r--r--include/linux/pipe_fs_i.h4
-rw-r--r--include/linux/pm.h1
-rw-r--r--include/linux/poll.h2
-rw-r--r--include/linux/sched.h17
-rw-r--r--include/linux/signal.h15
-rw-r--r--include/linux/skbuff.h27
-rw-r--r--include/linux/sock_diag.h6
-rw-r--r--include/linux/spmi.h15
-rw-r--r--include/linux/stm.h13
-rw-r--r--include/linux/sunrpc/clnt.h2
-rw-r--r--include/linux/tty.h2
-rw-r--r--include/linux/usb.h2
-rw-r--r--include/linux/usb/class-dual-role.h9
-rw-r--r--include/linux/usb/ehci_def.h4
-rw-r--r--include/net/ip_tunnels.h1
-rw-r--r--include/net/switchdev.h2
-rw-r--r--include/net/tcp.h2
-rw-r--r--include/scsi/scsi_device.h1
-rw-r--r--include/soc/qcom/qseecomi.h19
-rw-r--r--include/sound/apr_audio-v2.h53
-rw-r--r--include/sound/msm-dai-q6-v2.h11
-rw-r--r--include/sound/q6afe-v2.h16
-rw-r--r--include/sound/soc-dai.h2
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/uapi/linux/fuse.h1
-rw-r--r--include/uapi/linux/libc-compat.h2
-rw-r--r--include/uapi/linux/msm_mdp_ext.h7
-rw-r--r--include/uapi/linux/nfc/Kbuild2
-rw-r--r--include/uapi/linux/nfc/nfcinfo.h21
-rw-r--r--include/uapi/linux/perf_event.h1
-rw-r--r--include/uapi/media/msm_sde_rotator.h6
-rw-r--r--include/uapi/media/msmb_ispif.h3
-rw-r--r--include/video/imx-ipu-v3.h2
-rw-r--r--kernel/Documentation/firmware_updater/request_firmware.txt22
-rw-r--r--kernel/Documentation/firmware_updater/synaptics_fw_updaterbin666266 -> 0 bytes
-rw-r--r--kernel/Documentation/firmware_updater/synaptics_fw_updater.c753
-rw-r--r--kernel/Documentation/firmware_updater/synaptics_fw_updater_readme.txt41
-rw-r--r--kernel/arch/arm/configs/omap3_beagle_android_defconfig2419
-rw-r--r--kernel/arch/arm/configs/panda_defconfig331
-rw-r--r--kernel/arch/arm/mach-omap2/board-omap3beagle.c1038
-rw-r--r--kernel/arch/arm/mach-omap2/board-omap4panda.c1053
-rw-r--r--kernel/bpf/inode.c3
-rw-r--r--kernel/cgroup.c124
-rw-r--r--kernel/cpu.c7
-rw-r--r--kernel/drivers/input/touchscreen/Kconfig721
-rw-r--r--kernel/drivers/input/touchscreen/Makefile68
-rw-r--r--kernel/drivers/input/touchscreen/synaptics_fw_update.c1698
-rw-r--r--kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c2162
-rw-r--r--kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h286
-rw-r--r--kernel/drivers/input/touchscreen/synaptics_rmi_dev.c710
-rw-r--r--kernel/events/core.c194
-rw-r--r--kernel/events/internal.h1
-rw-r--r--kernel/events/ring_buffer.c94
-rw-r--r--kernel/exit.c29
-rw-r--r--kernel/fork.c1
-rw-r--r--kernel/include/linux/input/synaptics_dsx.h59
-rw-r--r--kernel/jump_label.c36
-rw-r--r--kernel/locking/mutex.c9
-rw-r--r--kernel/locking/qspinlock.c60
-rw-r--r--kernel/sched/core.c68
-rw-r--r--kernel/sched/core_ctl.c38
-rw-r--r--kernel/sched/fair.c60
-rw-r--r--kernel/sched/hmp.c68
-rw-r--r--kernel/sched/loadavg.c11
-rw-r--r--kernel/sys.c5
-rw-r--r--kernel/sysctl.c14
-rw-r--r--kernel/time/hrtimer.c15
-rw-r--r--kernel/time/timer.c28
-rw-r--r--kernel/trace/ring_buffer.c35
-rw-r--r--kernel/trace/trace_printk.c7
-rw-r--r--kernel/watchdog.c28
-rw-r--r--lib/dma-debug.c2
-rw-r--r--mm/debug-pagealloc.c1
-rw-r--r--mm/memcontrol.c3
-rw-r--r--mm/migrate.c2
-rw-r--r--mm/page-writeback.c21
-rw-r--r--mm/page_alloc.c2
-rw-r--r--mm/percpu.c73
-rw-r--r--mm/shmem.c8
-rw-r--r--mm/vmscan.c43
-rw-r--r--net/ax25/af_ax25.c3
-rw-r--r--net/ax25/ax25_ds_timer.c5
-rw-r--r--net/ax25/ax25_std_timer.c5
-rw-r--r--net/ax25/ax25_subr.c3
-rw-r--r--net/bridge/br_fdb.c2
-rw-r--r--net/bridge/br_multicast.c4
-rw-r--r--net/bridge/br_private.h23
-rw-r--r--net/core/filter.c18
-rw-r--r--net/core/flow_dissector.c43
-rw-r--r--net/core/neighbour.c6
-rw-r--r--net/core/skbuff.c18
-rw-r--r--net/ipv4/af_inet.c1
-rw-r--r--net/ipv4/devinet.c8
-rw-r--r--net/ipv4/esp4.c52
-rw-r--r--net/ipv4/ip_gre.c8
-rw-r--r--net/ipv4/ip_tunnel.c20
-rw-r--r--net/ipv4/ipmr.c4
-rw-r--r--net/ipv4/netfilter/arp_tables.c293
-rw-r--r--net/ipv4/netfilter/ip_tables.c318
-rw-r--r--net/ipv4/tcp.c125
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv6/af_inet6.c17
-rw-r--r--net/ipv6/ip6_fib.c1
-rw-r--r--net/ipv6/ip6_output.c11
-rw-r--r--net/ipv6/ip6mr.c1
-rw-r--r--net/ipv6/netfilter/ip6_tables.c311
-rw-r--r--net/ipv6/sit.c4
-rw-r--r--net/ipv6/tcp_ipv6.c4
-rw-r--r--net/ipv6/udp.c2
-rw-r--r--net/l2tp/l2tp_core.c2
-rw-r--r--net/mac80211/mesh.c11
-rw-r--r--net/mac80211/mesh_hwmp.c2
-rw-r--r--net/mac80211/sta_info.h2
-rw-r--r--net/netfilter/Kconfig1
-rw-r--r--net/netfilter/x_tables.c245
-rw-r--r--net/netfilter/xt_quota2.c22
-rw-r--r--net/netlink/af_netlink.c7
-rw-r--r--net/openvswitch/vport-vxlan.c2
-rw-r--r--net/packet/af_packet.c2
-rw-r--r--net/sched/act_csum.c8
-rw-r--r--net/sched/act_mirred.c2
-rw-r--r--net/sched/act_nat.c18
-rw-r--r--net/sched/sch_fifo.c4
-rw-r--r--net/sched/sch_netem.c12
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c4
-rw-r--r--net/sunrpc/clnt.c12
-rw-r--r--net/switchdev/switchdev.c6
-rw-r--r--net/tipc/netlink_compat.c2
-rw-r--r--net/tipc/socket.c3
-rw-r--r--net/unix/af_unix.c6
-rw-r--r--net/wireless/wext-core.c25
-rw-r--r--scripts/Makefile.extrawarn1
-rw-r--r--scripts/mod/file2alias.c2
-rw-r--r--scripts/package/Makefile4
-rw-r--r--security/selinux/hooks.c40
-rw-r--r--security/selinux/include/classmap.h2
-rw-r--r--sound/core/pcm.c6
-rw-r--r--sound/core/pcm_native.c2
-rw-r--r--sound/core/timer.c2
-rw-r--r--sound/drivers/dummy.c1
-rw-r--r--sound/pci/au88x0/au88x0_core.c5
-rw-r--r--sound/pci/echoaudio/echoaudio.c4
-rw-r--r--sound/pci/hda/hda_generic.c2
-rw-r--r--sound/pci/hda/hda_intel.c21
-rw-r--r--sound/pci/hda/patch_realtek.c126
-rw-r--r--sound/soc/codecs/ak4642.c3
-rw-r--r--sound/soc/codecs/msm8x16/msm8x16-wcd.c109
-rw-r--r--sound/soc/codecs/msm8x16/msm8x16-wcd.h27
-rw-r--r--sound/soc/codecs/wcd9335.c35
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c160
-rw-r--r--sound/soc/codecs/wcd9xxx-resmgr-v2.c74
-rw-r--r--sound/soc/codecs/wcd9xxx-resmgr-v2.h2
-rw-r--r--sound/soc/msm/Kconfig76
-rw-r--r--sound/soc/msm/Makefile15
-rw-r--r--sound/soc/msm/msm-audio-pinctrl.h5
-rw-r--r--sound/soc/msm/msm-dai-fe.c32
-rw-r--r--sound/soc/msm/msmcobalt.c17
-rw-r--r--sound/soc/msm/msmfalcon-common.c1768
-rw-r--r--sound/soc/msm/msmfalcon-common.h69
-rw-r--r--sound/soc/msm/msmfalcon-ext-dai-links.c1527
-rw-r--r--sound/soc/msm/msmfalcon-external.c1700
-rw-r--r--sound/soc/msm/msmfalcon-external.h44
-rw-r--r--sound/soc/msm/msmfalcon-internal.c2453
-rw-r--r--sound/soc/msm/msmfalcon-internal.h32
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c15
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c229
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c188
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c135
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c458
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h35
-rw-r--r--sound/soc/msm/qdsp6v2/q6afe.c14
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c2
-rw-r--r--sound/soc/msm/qdsp6v2/q6audio-v2.c84
-rw-r--r--sound/soc/soc-compress.c4
-rw-r--r--sound/soc/soc-pcm.c2
-rw-r--r--sound/usb/usb_audio_qmi_svc.c211
-rw-r--r--tools/perf/MANIFEST1
-rw-r--r--tools/perf/Makefile.perf3
-rw-r--r--tools/perf/arch/arm/util/Build2
-rw-r--r--tools/perf/arch/arm/util/auxtrace.c54
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c563
-rw-r--r--tools/perf/arch/arm/util/cs-etm.h23
-rw-r--r--tools/perf/arch/arm/util/pmu.c34
-rw-r--r--tools/perf/arch/arm64/util/Build4
-rw-r--r--tools/perf/arch/x86/util/intel-bts.c4
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c4
-rw-r--r--tools/perf/builtin-inject.c12
-rw-r--r--tools/perf/builtin-record.c9
-rw-r--r--tools/perf/builtin-script.c3
-rw-r--r--tools/perf/config/Makefile29
-rw-r--r--tools/perf/scripts/python/cs-trace-disasm.py124
-rw-r--r--tools/perf/scripts/python/cs-trace-ranges.py44
-rw-r--r--tools/perf/tests/bpf.c14
-rw-r--r--tools/perf/tests/llvm.c8
-rw-r--r--tools/perf/util/Build2
-rw-r--r--tools/perf/util/auxtrace.c10
-rw-r--r--tools/perf/util/auxtrace.h7
-rw-r--r--tools/perf/util/build-id.c2
-rw-r--r--tools/perf/util/build-id.h1
-rw-r--r--tools/perf/util/cpumap.c30
-rw-r--r--tools/perf/util/cpumap.h32
-rw-r--r--tools/perf/util/cs-etm-decoder/Build7
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder-stub.c91
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder.c503
-rw-r--r--tools/perf/util/cs-etm-decoder/cs-etm-decoder.h118
-rw-r--r--tools/perf/util/cs-etm.c1533
-rw-r--r--tools/perf/util/cs-etm.h84
-rw-r--r--tools/perf/util/evlist.c26
-rw-r--r--tools/perf/util/evlist.h3
-rw-r--r--tools/perf/util/evsel.c43
-rw-r--r--tools/perf/util/evsel.h8
-rw-r--r--tools/perf/util/machine.c35
-rw-r--r--tools/perf/util/parse-events.c67
-rw-r--r--tools/perf/util/parse-events.h3
-rw-r--r--tools/perf/util/parse-events.l12
-rw-r--r--tools/perf/util/parse-events.y11
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c2
-rw-r--r--tools/perf/util/session.c40
-rw-r--r--tools/perf/util/symbol-minimal.c2
-rw-r--r--tools/perf/util/symbol.c3
-rw-r--r--virt/kvm/irqchip.c2
-rw-r--r--virt/kvm/kvm_main.c2
838 files changed, 33050 insertions, 17650 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935 b/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935
index 6708c5e264aa..33e96f740639 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935
+++ b/Documentation/ABI/testing/sysfs-bus-iio-proximity-as3935
@@ -1,4 +1,4 @@
-What /sys/bus/iio/devices/iio:deviceX/in_proximity_raw
+What /sys/bus/iio/devices/iio:deviceX/in_proximity_input
Date: March 2014
KernelVersion: 3.15
Contact: Matt Ranostay <mranostay@gmail.com>
diff --git a/Documentation/ABI/testing/sysfs-class-stm b/Documentation/ABI/testing/sysfs-class-stm
index c9aa4f3fc9a7..77ed3da0f68e 100644
--- a/Documentation/ABI/testing/sysfs-class-stm
+++ b/Documentation/ABI/testing/sysfs-class-stm
@@ -12,3 +12,13 @@ KernelVersion: 4.3
Contact: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Description:
Shows the number of channels per master on this STM device.
+
+What: /sys/class/stm/<stm>/hw_override
+Date: March 2016
+KernelVersion: 4.7
+Contact: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Description:
+ Reads as 0 if master numbers in the STP stream produced by
+ this stm device will match the master numbers assigned by
+ the software or 1 if the stm hardware overrides software
+ assigned masters.
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt
index c4d651e36d02..782fb6c4124d 100644
--- a/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,osm.txt
@@ -18,13 +18,15 @@ Properties:
Definition: Addresses and sizes for the memory of the OSM controller,
cluster PLL management, and APCS common register regions.
Optionally, the address of the efuse registers used to
- determine the pwrcl or perfcl speed-bins.
+ determine the pwrcl or perfcl speed-bins and/or the ACD
+ register space to initialize prior to enabling OSM.
+
- reg-names
Usage: required
Value type: <stringlist>
Definition: Address names. Must be "osm", "pwrcl_pll", "perfcl_pll",
- "apcs_common" and "debug". Optionally, "pwrcl_efuse" or
- "perfcl_efuse".
+ "apcs_common", and "debug". Optionally, "pwrcl_efuse",
+ "perfcl_efuse", "pwrcl_acd", or "perfcl_acd".
Must be specified in the same order as the corresponding
addresses are specified in the reg property.
@@ -216,6 +218,45 @@ Properties:
override values to write to the OSM controller for each
of the two clusters. Each tuple must contain three elements.
+- qcom,acdtd-val
+ Usage: required if pwrcl_acd or perfcl_acd registers are specified
+ Value type: <prop-encoded-array>
+ Definition: Array which defines the values to program to the ACD
+ Tunable-Length Delay register for the power and performance
+ clusters.
+
+- qcom,acdcr-val
+ Usage: required if pwrcl_acd or perfcl_acd registers are specified
+ Value type: <prop-encoded-array>
+ Definition: Array which defines the values for the ACD control register
+ for the power and performance clusters.
+
+- qcom,acdsscr-val
+ Usage: required if pwrcl_acd or perfcl_acd registers are specified
+ Value type: <prop-encoded-array>
+ Definition: Array which defines the values for the ACD Soft Start Control
+ register for the power and performance clusters.
+
+- qcom,acdextint0-val
+ Usage: required if pwrcl_acd or perfcl_acd registers are specified
+ Value type: <prop-encoded-array>
+ Definition: Array which defines the initial values for the ACD
+ external interface configuration register for the power
+ and performance clusters.
+
+- qcom,acdextint1-val
+ Usage: required if pwrcl_acd or perfcl_acd registers are specified
+ Value type: <prop-encoded-array>
+ Definition: Array which defines the final values for the ACD
+ external interface configuration register for the power
+ and performance clusters.
+
+- qcom,acdautoxfer-val
+ Usage: required if pwrcl_acd or perfcl_acd registers are specified
+ Value type: <prop-encoded-array>
+ Definition: Array which defines the values for the ACD auto transfer
+ control register for the power and performance clusters.
+
- qcom,pwrcl-apcs-mem-acc-cfg
Usage: required if qcom,osm-no-tz is specified
Value type: <prop-encoded-array>
diff --git a/Documentation/devicetree/bindings/cache/arm64_cache_erp.txt b/Documentation/devicetree/bindings/cache/arm64_cache_erp.txt
new file mode 100644
index 000000000000..8b600be55787
--- /dev/null
+++ b/Documentation/devicetree/bindings/cache/arm64_cache_erp.txt
@@ -0,0 +1,34 @@
+* ARM Cortex A53 / A57 cache error reporting driver
+
+Required properties:
+- compatible: Should be "arm,arm64-cpu-erp"
+- interrupts: List of hardware interrupts that may indicate an error condition
+ in the CPU subsystem, or in the L1 / L2 caches. At least one interrupt entry
+ is required.
+- interrupt-names: Must contain one or more of the following IRQ types:
+ "pri-dbe-irq" - double-bit error interrupt for primary cluster
+ "sec-dbe-irq" - double-bit error interrupt for secondary cluster
+ "pri-ext-irq" - external bus error interrupt for primary cluster
+ "sec-ext-irq" - external bus error interrupt for secondary cluster
+ "cci-irq" - CCI error interrupt. If this property is present, having
+ the 'cci' reg-base defined using the 'reg' property is
+ recommended.
+ At least one irq entry is required.
+
+Optional properties:
+- reg: Should contain physical address of the CCI register space
+- reg-names: Should contain 'cci'. Must be present if 'reg' property is present
+- poll-delay-msec: Indicates how often the edac check callback should be called. Time in msec.
+
+Example:
+ cpu_cache_erp {
+ compatible = "arm,arm64-cpu-erp";
+ interrupt-names = "pri-dbe-irq",
+ "sec-dbe-irq",
+ "pri-ext-irq",
+ "sec-ext-irq";
+ interrupts = <0 92 0>,
+ <0 91 0>,
+ <0 96 0>,
+ <0 95 0>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/imx35-clock.txt b/Documentation/devicetree/bindings/clock/imx35-clock.txt
index a70356452a82..f49783213c56 100644
--- a/Documentation/devicetree/bindings/clock/imx35-clock.txt
+++ b/Documentation/devicetree/bindings/clock/imx35-clock.txt
@@ -94,6 +94,7 @@ clocks and IDs.
csi_sel 79
iim_gate 80
gpu2d_gate 81
+ ckli_gate 82
Examples:
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 68b8f09238e0..56ad8c361219 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -350,8 +350,13 @@ the fps window.
as below:
--> Reset GPIO value
--> Sleep value (in ms)
-- qcom,partial-update-enabled: Boolean used to enable partial
+- qcom,partial-update-enabled: String used to enable partial
panel update for command mode panels.
+ "none": partial update is disabled
+ "single_roi": default enable mode, only single roi is sent to panel
+ "dual_roi": two rois are merged into one big roi. Panel ddic should be able
+ to process two roi's along with the DCS command to send two rois.
+ disabled if property is not specified.
- qcom,mdss-dsi-horizontal-line-idle: List of width ranges (EC - SC) in pixels indicating
additional idle time in dsi clock cycles that is needed
to compensate for smaller line width.
@@ -632,7 +637,7 @@ Example:
qcom,mdss-tear-check-rd-ptr-trigger-intr = <1281>;
qcom,mdss-tear-check-frame-rate = <6000>;
qcom,mdss-dsi-reset-sequence = <1 2>, <0 10>, <1 10>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
qcom,dcs-cmd-by-left;
qcom,mdss-dsi-lp11-init;
qcom,mdss-dsi-init-delay-us = <100>;
diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt
index ca58f0da07ef..8a79626125d9 100644
--- a/Documentation/devicetree/bindings/gpu/adreno.txt
+++ b/Documentation/devicetree/bindings/gpu/adreno.txt
@@ -154,6 +154,26 @@ GPU Quirks:
detection logic
- qcom,gpu-quirk-dp2clockgating-disable:
Disable RB sampler data path clock gating optimization
+- qcom,gpu-quirk-lmloadkill-disable:
+ Use register setting to disable local memory(LM) feature
+ to avoid corner case error
+
+KGSL Memory Pools:
+- qcom,gpu-mempools: Container for sets of GPU mempools.Multiple sets
+ (pools) can be defined within qcom,gpu-mempools.
+ Each mempool defines a pool order, reserved pages,
+ allocation allowed.
+Properties:
+- compatible: Must be qcom,gpu-mempools.
+- qcom,mempool-max-pages: Max pages for all mempools, If not defined there is no limit.
+- qcom,gpu-mempool: Defines a set of mempools.
+
+Properties:
+- reg: Index of the pool (0 = lowest pool order).
+- qcom,mempool-page-size: Size of page.
+- qcom,mempool-reserved: Number of pages reserved at init time for a pool.
+- qcom,mempool-allocate: Allocate memory from the system memory when the
+ reserved pool exhausted.
The following properties are optional as collecting data via coresight might
not be supported for every chipset. The documentation for coresight
@@ -222,6 +242,40 @@ Example of A330 GPU in MSM8916:
coresight-child-list = <&funnel_in0>;
coresight-child-ports = <5>;
+ /* GPU Mempools */
+ qcom,gpu-mempools {
+ #address-cells= <1>;
+ #size-cells = <0>;
+ compatible = "qcom,gpu-mempools";
+
+ /* 4K Page Pool configuration */
+ qcom,gpu-mempool@0 {
+ reg = <0>;
+ qcom,mempool-page-size = <4096>;
+ qcom,mempool-reserved = <2048>;
+ qcom,mempool-allocate;
+ };
+ /* 8K Page Pool configuration */
+ qcom,gpu-mempool@1 {
+ reg = <1>;
+ qcom,mempool-page-size = <8192>;
+ qcom,mempool-reserved = <1024>;
+ qcom,mempool-allocate;
+ };
+ /* 64K Page Pool configuration */
+ qcom,gpu-mempool@2 {
+ reg = <2>;
+ qcom,mempool-page-size = <65536>;
+ qcom,mempool-reserved = <256>;
+ };
+ /* 1M Page Pool configuration */
+ qcom,gpu-mempool@3 {
+ reg = <3>;
+ qcom,mempool-page-size = <1048576>;
+ qcom,mempool-reserved = <32>;
+ };
+ };
+
/* Power levels */
qcom,gpu-pwrlevels-bins {
#address-cells = <1>;
diff --git a/Documentation/devicetree/bindings/platform/msm/rmnet_ipa.txt b/Documentation/devicetree/bindings/platform/msm/rmnet_ipa.txt
index 102b304f5fb3..d8934c01cc71 100644
--- a/Documentation/devicetree/bindings/platform/msm/rmnet_ipa.txt
+++ b/Documentation/devicetree/bindings/platform/msm/rmnet_ipa.txt
@@ -12,9 +12,11 @@ Optional:
regarding scatter-gather capability
- qcom,ipa-napi-enable: Boolean context flag to indicate whether
to enable napi framework or not
+- qcom,wan-rx-desc-size: size of WAN rx desc fifo ring, default is 256
Example:
qcom,rmnet-ipa {
compatible = "qcom,rmnet-ipa";
+ qcom,wan-rx-desc-size = <256>;
}
diff --git a/Documentation/devicetree/bindings/platform/msm/rmnet_ipa3.txt b/Documentation/devicetree/bindings/platform/msm/rmnet_ipa3.txt
index 7ee28664668b..e9575f150c5e 100644
--- a/Documentation/devicetree/bindings/platform/msm/rmnet_ipa3.txt
+++ b/Documentation/devicetree/bindings/platform/msm/rmnet_ipa3.txt
@@ -12,9 +12,11 @@ Optional:
regarding scatter-gather capability
- qcom,ipa-napi-enable: Boolean context flag to indicate whether
to enable napi framework or not
+- qcom,wan-rx-desc-size: size of WAN rx desc fifo ring, default is 256
Example:
qcom,rmnet-ipa3 {
compatible = "qcom,rmnet-ipa3";
+ qcom,wan-rx-desc-size = <256>;
}
diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt
index caabcd347a72..4f5e0a117b2d 100644
--- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt
+++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-fg-gen3.txt
@@ -55,7 +55,7 @@ First Level Node - FG Gen3 device
be notified via the power supply framework. The userspace
will read 0% soc and immediately shutdown. If this property
is not specified, then the default value used will be
- 3100mV.
+ 2800mV.
- qcom,fg-vbatt-low-thr
Usage: optional
diff --git a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt
index 82386ba9b082..7090426c68f8 100644
--- a/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt
+++ b/Documentation/devicetree/bindings/power/qcom-charger/qpnp-smb2.txt
@@ -129,6 +129,15 @@ Charger specific properties:
happen but the adapter won't be asked to switch to a higher
voltage point.
+- qcom,chg-inhibit-threshold-mv
+ Usage: optional
+ Value type: <u32>
+ Definition: Charge inhibit threshold in milli-volts. Charging will be
+ inhibited when the battery voltage is within this threshold
+ from Vfloat at charger insertion. If this is not specified
+ then charge inhibit will be disabled by default.
+ Allowed values are: 50, 100, 200, 300.
+
=============================================
Second Level Nodes - SMB2 Charger Peripherals
=============================================
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
index 7be400da0d62..0545f6b7b59a 100644
--- a/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
@@ -8,7 +8,7 @@ display panels, LCD or AMOLED.
Main node required properties:
- compatible: Must be "qcom,qpnp-labibb-regulator"
-- qpnp,qpnp-labibb-mode: A string used to specify the working mode of LAB/IBB
+- qcom,qpnp-labibb-mode: A string used to specify the working mode of LAB/IBB
regulators when bootloader does not turned on the
display panel. Could be "lcd" or "amoled".
"lcd" means using LAB and IBB regulators are
@@ -26,9 +26,9 @@ Main node optional properties:
in LAB and IBB modules. Make sure the
hardware has needed support before
enabling this property.
-- qpnp,swire-control: A bool property which indicates if the LAB/IBB is
+- qcom,swire-control: A bool property which indicates if the LAB/IBB is
controlled by the SWIRE interface. Enable only
- if qpnp,qpnp-labibb-mode = "amoled".
+ if qcom,qpnp-labibb-mode = "amoled".
- qcom,labibb-ttw-force-lab-on: A boolean property which forces LAB to be
always on during TTW mode.
- qcom,skip-2nd-swire-cmd: A boolean property which indicates if
@@ -82,8 +82,10 @@ LAB subnode required properties:
are 25, 50, 75 and 100.
- qcom,qpnp-lab-nfet-size: NFET size in percentage. Supported values
are 25, 50, 75 and 100.
-- qcom,qpnp-lab-max-precharge-time: Precharge time in us of LAB regulator.
+- qcom,qpnp-lab-max-precharge-time: Precharge time in uS for LAB regulator.
Supported values are 200, 300, 400 and 500.
+ Suggested values for LCD and AMOLED mode
+ are 500 and 300uS respectively.
- qcom,qpnp-lab-switching-clock-frequency: The PWM switching clock frequency in
kHz of Lab regulator, Supported values
are: 3200, 2740, 2400, 2130, 1920,
@@ -91,11 +93,22 @@ LAB subnode required properties:
1130, 1070, 1010, 960, 910.
- qcom,qpnp-lab-limit-maximum-current: The maximum inductor current limit in
mA of LAB regulator. Supported values
- are 200, 400, 600 and 800.
+ are 200, 400, 600, 800, 1000, 1200,
+ 1400 and 1600.
+- interrupts: Specify the interrupts as per the interrupt
+ encoding.
+ Currently "lab-vreg-ok" is required for
+ LCD mode in pmicobalt. For AMOLED mode,
+ "lab-vreg-ok" is required only when SWIRE
+ control is enabled and skipping 2nd SWIRE
+ pulse is required in pmi8952/8996.
+- interrupt-names: Interrupt names to match up 1-to-1 with
+ the interrupts specified in 'interrupts'
+ property.
LAB subnode optional properties:
-- qpnp,qpnp-lab-current-sense: If this property is specified, the LAB current
+- qcom,qpnp-lab-current-sense: If this property is specified, the LAB current
sense gain will be programmed for LAB regulator.
Otherwise, LAB current sense gain will be
default to "1x". A string is used to specify the
@@ -209,7 +222,7 @@ IBB subnode optional properties:
any value in the allowed limit.
- qcom,output-voltage-one-pulse The expected voltage (in mV) of VDISN signal
on the first SWIRE pulse. This property
- can be specified only if 'qpnp,swire-control'
+ can be specified only if 'qcom,swire-control'
is defined. The minimum and maximum values
are 1400mV and 7700mV.
@@ -219,7 +232,7 @@ Example:
compatible = "qcom,qpnp-labibb-regulator";
#address-cells = <1>;
#size-cells = <1>;
- qpnp,qpnp-labibb-mode = "lcd";
+ qcom,qpnp-labibb-mode = "lcd";
qcom,pmic-revid = <&pmi8994_revid>;
qcom,skip-2nd-swire-cmd;
@@ -227,7 +240,8 @@ Example:
reg = <0xde00 0x100>;
reg-names = "lab";
- interrupts = <0x3 0xde 0x0>;
+ interrupts = <0x3 0xde 0x0
+ IRQ_TYPE_EDGE_RISING>;
interrupt-names = "lab-vreg-ok";
regulator-name = "lab_reg";
@@ -247,7 +261,7 @@ Example:
qcom,qpnp-lab-full-pull-down;
qcom,qpnp-lab-pull-down-enable;
qcom,qpnp-lab-switching-clock-frequency = <1600>;
- qcom,qpnp-lab-limit-maximum-current = <800>;
+ qcom,qpnp-lab-limit-maximum-current = <1600>;
qcom,qpnp-lab-limit-max-current-enable;
qcom,qpnp-lab-ps-threshold = <40>;
qcom,qpnp-lab-ps-enable;
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 82befcbd24a3..c3d58ce2c864 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -1606,6 +1606,130 @@ Example:
asoc-wsa-codec-prefixes = "SpkrMono";
};
+* MSMFALCON ASoC Machine driver
+
+Required properties:
+- compatible : "qcom,msmfalcon-asoc-snd"
+- qcom,model : The user-visible name of this sound card.
+- qcom,msm-hs-micbias-type : This property is used to recognize the headset
+ micbias type, internal or external.
+- qcom,msm-mbhc-hphl-swh: This property is used to distinguish headset HPHL
+switch type on target typically the switch type will be normally open or
+normally close, value for this property 0 for normally close and 1 for
+normally open.
+- qcom,msm-mbhc-gnd-swh: This property is used to distinguish headset GND
+switch type on target typically the switch type will be normally open or
+normally close, value for this property 0 for normally close and 1 for
+normally open.
+- qcom,audio-routing : A list of the connections between audio components.
+- qcom,msm-gpios : Lists down all the gpio sets that are supported.
+- qcom,pinctrl-names : Lists all the possible combinations of the gpio sets
+mentioned in qcom,msm-gpios.
+- pinctrl-names : The combinations of gpio sets from above that are supported in
+the flavor.
+- pinctrl-# : Pinctrl states as mentioned in pinctrl-names.
+
+Optional properties:
+- qcom,cdc-us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
+- qcom,msm-micbias1-ext-cap : Boolean. Enable micbias1 external
+capacitor mode.
+- qcom,msm-micbias2-ext-cap : Boolean. Enable micbias2 external
+capacitor mode.
+- qcom,msm-spk-ext-pa : GPIO which enables external speaker pa.
+- qcom,msm-mclk-freq : This property is used to inform machine driver about
+mclk frequency needs to be configured for internal and external PA.
+- asoc-platform: This is phandle list containing the references to platform device
+ nodes that are used as part of the sound card dai-links.
+- asoc-platform-names: This property contains list of platform names. The order of
+ the platform names should match to that of the phandle order
+ given in "asoc-platform".
+- asoc-cpu: This is phandle list containing the references to cpu dai device nodes
+ that are used as part of the sound card dai-links.
+- asoc-cpu-names: This property contains list of cpu dai names. The order of the
+ cpu dai names should match to that of the phandle order given.
+- asoc-codec: This is phandle list containing the references to codec dai device
+ nodes that are used as part of the sound card dai-links.
+- asoc-codec-names: This property contains list of codec dai names. The order of the
+ codec dai names should match to that of the phandle order given
+ in "asoc-codec".
+- qcom,wsa-max-devs : Maximum number of WSA881x devices present in the target
+- qcom,wsa-devs : List of phandles for all possible WSA881x devices supported for the target
+- qcom,wsa-aux-dev-prefix : Name prefix with Left/Right configuration for WSA881x device
+
+Example:
+ sound {
+ compatible = "qcom,msmfalcon-asoc-snd";
+ qcom,model = "msmfalcon-snd-card";
+ qcom,msm-mclk-freq = <9600000>;
+ qcom,msm-mbhc-hphl-swh = <0>;
+ qcom,msm-mbhc-gnd-swh = <0>;
+ qcom,msm-hs-micbias-type = "internal";
+ qcom,msm-micbias1-ext-cap;
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "SPK_RX_BIAS", "MCLK",
+ "INT_LDO_H", "MCLK",
+ "MIC BIAS External", "Handset Mic",
+ "MIC BIAS Internal2", "Headset Mic",
+ "MIC BIAS External", "Secondary Mic",
+ "AMIC1", "MIC BIAS External",
+ "AMIC2", "MIC BIAS Internal2",
+ "AMIC3", "MIC BIAS External";
+ qcom,msm-gpios =
+ "int_pdm",
+ "us_eu_gpio";
+ qcom,pinctrl-names =
+ "all_off",
+ "int_pdm_act",
+ "us_eu_gpio_act",
+ "int_pdm_us_eu_gpio_act";
+ pinctrl-names =
+ "all_off",
+ "int_pdm_act",
+ "us_eu_gpio_act",
+ "int_pdm_us_eu_gpio_act";
+ pinctrl-0 = <&cdc_pdm_lines_sus &cdc_pdm_lines_2_sus &cross_conn_det_sus>;
+ pinctrl-1 = <&cdc_pdm_lines_act &cdc_pdm_lines_2_act &cross_conn_det_sus>;
+ pinctrl-2 = <&cdc_pdm_lines_sus &cdc_pdm_lines_2_sus &cross_conn_det_act>;
+ pinctrl-3 = <&cdc_pdm_lines_act &cdc_pdm_lines_2_act &cross_conn_det_act>;
+ qcom,cdc-us-euro-gpios = <&msm_gpio 63 0>;
+ asoc-platform = <&pcm0>, <&pcm1>, <&voip>, <&voice>,
+ <&loopback>, <&compress>, <&hostless>,
+ <&afe>, <&lsm>, <&routing>, <&lpa>;
+ asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+ "msm-voip-dsp", "msm-pcm-voice", "msm-pcm-loopback",
+ "msm-compress-dsp", "msm-pcm-hostless", "msm-pcm-afe",
+ "msm-lsm-client", "msm-pcm-routing", "msm-pcm-lpa";
+ asoc-cpu = <&dai_pri_auxpcm>, <&dai_hdmi>,
+ <&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>, <&dai_mi2s3>,
+ <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+ <&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>,
+ <&bt_sco_rx>, <&bt_sco_tx>, <&int_fm_rx>, <&int_fm_tx>,
+ <&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
+ <&incall_record_rx>, <&incall_record_tx>, <&incall_music_rx>,
+ <&incall_music_2_rx>;
+ asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-hdmi.8",
+ "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+ "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+ "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
+ "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+ "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+ "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+ "msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+ "msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293",
+ "msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
+ "msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
+ "msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
+ "msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770";
+ asoc-codec = <&stub_codec>;
+ asoc-codec-names = "msm-stub-codec.1";
+ qcom,wsa-max-devs = <2>;
+ qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>,
+ <&wsa881x_213>, <&wsa881x_214>;
+ qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrLeft",
+ "SpkrRight", "SpkrLeft";
+ };
+
* MSM8952 Slimbus ASoC Machine driver
Required properties:
@@ -2032,6 +2156,139 @@ Example:
asoc-codec-names = "msm-stub-codec.1";
};
+* MSMFALCON ASoC Slimbus Machine driver
+
+Required properties:
+- compatible : "qcom,msmfalcon-asoc-snd-tasha" for tasha codec,
+ "qcom,msmfalcon-asoc-snd-tavil" for tavil codec.
+- qcom,model : The user-visible name of this sound card.
+- qcom,msm-mclk-freq : MCLK frequency value for external codec
+- qcom,msm-gpios : Lists down all the gpio sets that are supported.
+- qcom,pinctrl-names : Lists all the possible combinations of the gpio sets
+mentioned in qcom,msm-gpios. Say we have 2^N combinations for N GPIOs,
+this would list all the 2^N combinations.
+- pinctrl-names : The combinations of gpio sets from above that are supported in
+the flavor. This can be sometimes same as qcom, pinctrl-names i.e with 2^N
+combinations or will have less incase if some combination is not supported.
+- pinctrl-# : Pinctrl states as mentioned in pinctrl-names.
+- qcom,audio-routing : A list of the connections between audio components.
+- asoc-platform: This is phandle list containing the references to platform device
+ nodes that are used as part of the sound card dai-links.
+- asoc-platform-names: This property contains list of platform names. The order of
+ the platform names should match to that of the phandle order
+ given in "asoc-platform".
+- asoc-cpu: This is phandle list containing the references to cpu dai device nodes
+ that are used as part of the sound card dai-links.
+- asoc-cpu-names: This property contains list of cpu dai names. The order of the
+ cpu dai names should match to that of the phandle order given
+ in "asoc-cpu". The cpu names are in the form of "%s.%d" form,
+ where the id (%d) field represents the back-end AFE port id that
+ this CPU dai is associated with.
+- asoc-codec: This is phandle list containing the references to codec dai device
+ nodes that are used as part of the sound card dai-links.
+- asoc-codec-names: This property contains list of codec dai names. The order of the
+ codec dai names should match to that of the phandle order given
+ in "asoc-codec".
+Optional properties:
+- qcom,cdc-us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
+- clock-names : clock name defined for external clock.
+- clocks : external clock defined for codec clock.
+- qcom,wsa-max-devs : Maximum number of WSA881x devices present in the target
+- qcom,wsa-devs : List of phandles for all possible WSA881x devices supported for the target
+- qcom,wsa-aux-dev-prefix : Name prefix with Left/Right configuration for WSA881x device
+
+Example:
+
+ sound-9335 {
+ compatible = "qcom,msmfalcon-asoc-snd-tasha";
+ qcom,model = "msmfalcon-tasha-snd-card";
+
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "AIF4 MAD", "MCLK",
+ "ultrasound amp", "LINEOUT1",
+ "ultrasound amp", "LINEOUT3",
+ "AMIC1", "MIC BIAS1 Internal1",
+ "MIC BIAS1 Internal1", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCLeft Headset Mic",
+ "DMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Digital Mic1",
+ "DMIC2", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Digital Mic2",
+ "DMIC3", "MIC BIAS3 External",
+ "MIC BIAS3 External", "Digital Mic3",
+ "DMIC4", "MIC BIAS3 External",
+ "MIC BIAS3 External", "Digital Mic4",
+ "DMIC5", "MIC BIAS4 External",
+ "MIC BIAS4 External", "Digital Mic5",
+ "DMIC6", "MIC BIAS4 External",
+ "MIC BIAS4 External", "Digital Mic6";
+
+ qcom,msm-mbhc-hphl-swh = <0>;
+ qcom,msm-mbhc-gnd-swh = <0>;
+ qcom,msm-mclk-freq = <9600000>;
+ qcom,msm-gpios =
+ "slim",
+ "us_eu_gpio";
+ qcom,pinctrl-names =
+ "all_off",
+ "slim_act",
+ "us_eu_gpio_act",
+ "slim_us_eu_gpio_act";
+ pinctrl-names =
+ "all_off",
+ "slim_act",
+ "us_eu_gpio_act",
+ "slim_us_eu_gpio_act";
+ pinctrl-0 = <&cdc_slim_lines_sus &cross_conn_det_sus>;
+ pinctrl-1 = <&cdc_slim_lines_act &cross_conn_det_sus>;
+ pinctrl-2 = <&cdc_slim_lines_sus &cross_conn_det_act>;
+ pinctrl-3 = <&cdc_slim_lines_act &cross_conn_det_act>;
+ qcom,cdc-us-euro-gpios = <&msm_gpio 63 0>;
+ asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+ <&loopback>, <&compress>, <&hostless>,
+ <&afe>, <&lsm>, <&routing>, <&cpe>, <&compr>;
+ asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+ "msm-pcm-dsp.2", "msm-voip-dsp",
+ "msm-pcm-voice", "msm-pcm-loopback",
+ "msm-compress-dsp", "msm-pcm-hostless",
+ "msm-pcm-afe", "msm-lsm-client",
+ "msm-pcm-routing", "msm-cpe-lsm",
+ "msm-compr-dsp";
+ asoc-cpu = <&dai_hdmi>,
+ <&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+ <&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>,
+ <&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>,
+ <&afe_pcm_rx>, <&afe_pcm_tx>, <&afe_proxy_rx>,
+ <&afe_proxy_tx>, <&incall_record_rx>,
+ <&incall_record_tx>, <&incall_music_rx>,
+ <&incall_music_2_rx>, <&sb_5_rx>;
+ asoc-cpu-names = "msm-dai-q6-hdmi.8",
+ "msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
+ "msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+ "msm-dai-q6-dev.16388", "msm-dai-q6-dev.16389",
+ "msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+ "msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+ "msm-dai-q6-dev.16395", "msm-dai-q6-dev.224",
+ "msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
+ "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
+ "msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773",
+ "msm-dai-q6-dev.32770", "msm-dai-q6-dev.16394";
+ asoc-codec = <&stub_codec>;
+ asoc-codec-names = "msm-stub-codec.1";
+ qcom,wsa-max-devs = <2>;
+ qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>,
+ <&wsa881x_213>, <&wsa881x_214>;
+ qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrLeft",
+ "SpkrRight", "SpkrLeft";
+ };
+
* MSMCOBALT ASoC Machine driver
Required properties:
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
index d00ead0b3012..04c02786f6bd 100644
--- a/Documentation/filesystems/proc.txt
+++ b/Documentation/filesystems/proc.txt
@@ -43,6 +43,7 @@ Table of Contents
3.7 /proc/<pid>/task/<tid>/children - Information about task children
3.8 /proc/<pid>/fdinfo/<fd> - Information about opened file
3.9 /proc/<pid>/map_files - Information about memory mapped files
+ 3.10 /proc/<pid>/timerslack_ns - Task timerslack value
4 Configuring procfs
4.1 Mount options
@@ -1876,6 +1877,23 @@ time one can open(2) mappings from the listings of two processes and
comparing their inode numbers to figure out which anonymous memory areas
are actually shared.
+3.10 /proc/<pid>/timerslack_ns - Task timerslack value
+---------------------------------------------------------
+This file provides the value of the task's timerslack value in nanoseconds.
+This value specifies a amount of time that normal timers may be deferred
+in order to coalesce timers and avoid unnecessary wakeups.
+
+This allows a task's interactivity vs power consumption trade off to be
+adjusted.
+
+Writing 0 to the file will set the tasks timerslack to the default value.
+
+Valid values are from 0 - ULLONG_MAX
+
+An application setting the value must have PTRACE_MODE_ATTACH_FSCREDS level
+permissions on the task specified to change its timerslack_ns value.
+
+
------------------------------------------------------------------------------
Configuring procfs
------------------------------------------------------------------------------
diff --git a/Documentation/scheduler/sched-hmp.txt b/Documentation/scheduler/sched-hmp.txt
index 298064bc44d7..091d49ea80cf 100644
--- a/Documentation/scheduler/sched-hmp.txt
+++ b/Documentation/scheduler/sched-hmp.txt
@@ -31,6 +31,7 @@ CONTENTS
6.1 Per-CPU Window-Based Stats
6.2 Per-task Window-Based Stats
6.3 Effect of various task events
+ 6.4 Tying it all together
7. Tunables
8. HMP Scheduler Trace Points
8.1 sched_enq_deq_task
@@ -872,11 +873,17 @@ both in what they mean and also how they are derived.
*** 6.1 Per-CPU Window-Based Stats
-In addition to the per-task window-based demand, the HMP scheduler
-extensions also track the aggregate demand seen on each CPU. This is
-done using the same windows that the task demand is tracked with
-(which is in turn set by the governor when frequency guidance is in
-use). There are four quantities maintained for each CPU by the HMP scheduler:
+The scheduler tracks two separate types of quantities on a per CPU basis.
+The first type has to deal with the aggregate load on a CPU and the second
+type deals with top-tasks on that same CPU. We will first proceed to explain
+what is maintained as part of each type of statistics and then provide the
+connection between these two types of statistics at the end.
+
+First lets describe the HMP scheduler extensions to track the aggregate load
+seen on each CPU. This is done using the same windows that the task demand
+is tracked with (which is in turn set by the governor when frequency guidance
+is in use). There are four quantities maintained for each CPU by the HMP
+scheduler for tracking CPU load:
curr_runnable_sum: aggregate demand from all tasks which executed during
the current (not yet completed) window
@@ -903,24 +910,86 @@ A 'new' task is defined as a task whose number of active windows since fork is
less than sysctl_sched_new_task_windows. An active window is defined as a window
where a task was observed to be runnable.
+Moving on the second type of statistics; top-tasks, the scheduler tracks a list
+of top tasks per CPU. A top-task is defined as the task that runs the most in a
+given window on that CPU. This includes task that ran on that CPU through out
+the window or were migrated to that CPU prior to window expiration. It does not
+include tasks that were migrated away from that CPU prior to window expiration.
+
+To track top tasks, we first realize that there is no strict need to maintain
+the task struct itself as long as we know the load exerted by the top task. We
+also realize that to maintain top tasks on every CPU we have to track the
+execution of every single task that runs during the window. The load associated
+with a task needs to be migrated when the task migrates from one CPU to another.
+When the top task migrates away, we need to locate the second top task and so
+on.
+
+Given the above realizations, we use hashmaps to track top task load both
+for the current and the previous window. This hashmap is implemented as an array
+of fixed size. The key of the hashmap is given by
+task_execution_time_in_a_window / array_size. The size of the array (number of
+buckets in the hashmap) dictate the load granularity of each bucket. The value
+stored in each bucket is a refcount of all the tasks that executed long enough
+to be in that bucket. This approach has a few benefits. Firstly, any top task
+stats update now take O(1) time. While task migration is also O(1), it does
+still involve going through up to the size of the array to find the second top
+task. We optimize this search by using bitmaps. The next set bit in the bitmap
+gives the position of the second top task in our hashamp.
+
+Secondly, and more importantly, not having to store the task struct itself
+saves a lot of memory usage in that 1) there is no need to retrieve task structs
+later causing cache misses and 2) we don't have to unnecessarily hold up task
+memory for up to 2 full windows by calling get_task_struct() after a task exits.
+
+Given the motivation above, here are a list of quantities tracked as part of
+per CPU task top-tasks management
+
+ top_tasks[NUM_TRACKED_WINDOWS] - Hashmap of top-task load for the current and
+ previous window
+
+ BITMAP_ARRAY(top_tasks_bitmap) - Two bitmaps for the current and previous
+ windows corresponding to the top-task
+ hashmap.
+
+ load_subs[NUM_TRACKED_WINDOWS] - An array of load subtractions to be carried
+ out form curr/prev_runnable_sums for each CPU
+ prior to reporting load to the governor. The
+ purpose for this will be explained later in
+ the section pertaining to the TASK_MIGRATE
+ event. The type struct load_subtractions,
+ stores the value of the subtraction along
+ with the window start value for the window
+ for which the subtraction has to take place.
+
+
+ curr_table - Indication of which index of the array points to the current
+ window.
+
+ curr_top - The top task on a CPU at any given moment in the current window
+
+ prev_top - The top task on a CPU in the previous window
+
+
*** 6.2 Per-task window-based stats
Corresponding to curr_runnable_sum and prev_runnable_sum, two counters are
maintained per-task
-curr_window - represents cpu demand of task in its most recently tracked
- window
-prev_window - represents cpu demand of task in the window prior to the one
- being tracked by curr_window
+curr_window_cpu - represents task's contribution to cpu busy time on
+ various CPUs in the current window
-The above counters are resued for nt_curr_runnable_sum and
-nt_prev_runnable_sum.
+prev_window_cpu - represents task's contribution to cpu busy time on
+ various CPUs in the previous window
+
+curr_window - represents the sum of all entries in curr_window_cpu
+
+prev_window - represents the sum of all entries in prev_window_cpu
"cpu demand" of a task includes its execution time and can also include its
wait time. 'SCHED_FREQ_ACCOUNT_WAIT_TIME' controls whether task's wait
-time is included in its 'curr_window' and 'prev_window' counters or not.
+time is included in its CPU load counters or not.
-Needless to say, curr_runnable_sum counter of a cpu is derived from curr_window
+Curr_runnable_sum counter of a cpu is derived from curr_window_cpu[cpu]
counter of various tasks that ran on it in its most recent window.
*** 6.3 Effect of various task events
@@ -931,11 +1000,17 @@ PICK_NEXT_TASK
This represents beginning of execution for a task. Provided the task
refers to a non-idle task, a portion of task's wait time that
corresponds to the current window being tracked on a cpu is added to
- task's curr_window counter, provided SCHED_FREQ_ACCOUNT_WAIT_TIME is
- set. The same quantum is also added to cpu's curr_runnable_sum counter.
- The remaining portion, which corresponds to task's wait time in previous
- window is added to task's prev_window and cpu's prev_runnable_sum
- counters.
+ task's curr_window_cpu and curr_window counter, provided
+ SCHED_FREQ_ACCOUNT_WAIT_TIME is set. The same quantum is also added to
+ cpu's curr_runnable_sum counter. The remaining portion, which
+ corresponds to task's wait time in previous window is added to task's
+ prev_window, prev_window_cpu and cpu's prev_runnable_sum counters.
+
+ CPUs top_tasks hashmap is updated if needed with the new information.
+ Any previous entries in the hashmap are deleted and newer entries are
+ created. The top_tasks_bitmap reflects the updated state of the
+ hashmap. If the top task for the current and/or previous window has
+ changed, curr_top and prev_top are updated accordingly.
PUT_PREV_TASK
This represents end of execution of a time-slice for a task, where the
@@ -943,9 +1018,16 @@ PUT_PREV_TASK
or (in case of task being idle with cpu having non-zero rq->nr_iowait
count and sched_io_is_busy =1), a portion of task's execution time, that
corresponds to current window being tracked on a cpu is added to task's
- curr_window_counter and also to cpu's curr_runnable_sum counter. Portion
- of task's execution that corresponds to the previous window is added to
- task's prev_window and cpu's prev_runnable_sum counters.
+ curr_window_cpu and curr_window counter and also to cpu's
+ curr_runnable_sum counter. Portion of task's execution that corresponds
+ to the previous window is added to task's prev_window, prev_window_cpu
+ and cpu's prev_runnable_sum counters.
+
+ CPUs top_tasks hashmap is updated if needed with the new information.
+ Any previous entries in the hashmap are deleted and newer entries are
+ created. The top_tasks_bitmap reflects the updated state of the
+ hashmap. If the top task for the current and/or previous window has
+ changed, curr_top and prev_top are updated accordingly.
TASK_UPDATE
This event is called on a cpu's currently running task and hence
@@ -955,34 +1037,128 @@ TASK_UPDATE
TASK_WAKE
This event signifies a task waking from sleep. Since many windows
- could have elapsed since the task went to sleep, its curr_window
- and prev_window are updated to reflect task's demand in the most
- recent and its previous window that is being tracked on a cpu.
+ could have elapsed since the task went to sleep, its
+ curr_window_cpu/curr_window and prev_window_cpu/prev_window are
+ updated to reflect task's demand in the most recent and its previous
+ window that is being tracked on a cpu. Updated stats will trigger
+ the same book-keeping for top-tasks as other events.
TASK_MIGRATE
This event signifies task migration across cpus. It is invoked on the
task prior to being moved. Thus at the time of this event, the task
can be considered to be in "waiting" state on src_cpu. In that way
this event reflects actions taken under PICK_NEXT_TASK (i.e its
- wait time is added to task's curr/prev_window counters as well
+ wait time is added to task's curr/prev_window/_cpu counters as well
as src_cpu's curr/prev_runnable_sum counters, provided
- SCHED_FREQ_ACCOUNT_WAIT_TIME is non-zero). After that update,
- src_cpu's curr_runnable_sum is reduced by task's curr_window value
- and dst_cpu's curr_runnable_sum is increased by task's curr_window
- value. Similarly, src_cpu's prev_runnable_sum is reduced by task's
- prev_window value and dst_cpu's prev_runnable_sum is increased by
- task's prev_window value.
+ SCHED_FREQ_ACCOUNT_WAIT_TIME is non-zero).
+
+ After that update, we make a distinction between intra-cluster and
+ inter-cluster migrations for further book-keeping.
+
+ For intra-cluster migrations, we simply remove the entry for the task
+ in the top_tasks hashmap from the source CPU and add the entry to the
+ destination CPU. The top_tasks_bitmap, curr_top and prev_top are
+ updated accordingly. We then find the second top-task top in our
+ top_tasks hashmap for both the current and previous window and set
+ curr_top and prev_top to their new values.
+
+ For inter-cluster migrations we have a much more complicated scheme.
+ Firstly we add to the destination CPU's curr/prev_runnable_sum
+ the tasks curr/prev_window. Note we add the sum and not the
+ contribution any individual CPU. This is because when a tasks migrates
+ across clusters, we need the new cluster to ramp up to the appropriate
+ frequency given the task's total execution summed up across all CPUs
+ in the previous cluster.
+
+ Secondly the src_cpu's curr/prev_runnable_sum are reduced by task's
+ curr/prev_window_cpu values.
+
+ Thirdly, we need to walk all the CPUs in the cluster and subtract from
+ each CPU's curr/prev_runnable_sum the task's respective
+ curr/prev_window_cpu values. However, subtracting load from each of
+ the source CPUs is not trivial, as it would require all runqueue
+ locks to be held. To get around this we introduce a deferred load
+ subtraction mechanism whereby subtracting load from each of the source
+ CPUs is deferred until an opportune moment. This opportune moment is
+ when the governor comes asking the scheduler for load. At that time, all
+ necessary runqueue locks are already held.
+
+ There are a few cases to consider when doing deferred subtraction. Since
+ we are not holding all runqueue locks other CPUs in the source cluster
+ can be in a different window than the source CPU where the task is
+ migrating from.
+
+ Case 1:
+ Other CPU in the source cluster is in the same window. No special
+ consideration.
+
+ Case 2:
+ Other CPU in the source cluster is ahead by 1 window. In this
+ case, we will be doing redundant updates to subtraction load for the
+ prev window. There is no way to avoid this redundant update though,
+ without holding the rq lock.
+
+ Case 3:
+ Other CPU in the source cluster is trailing by 1 window In this
+ case, we might end up overwriting old data for that CPU. But this is not
+ a problem as when the other CPU calls update_task_ravg() it will move to
+ the same window. This relies on maintaining synchronized windows between
+ CPUs, which is true today.
+
+ To achieve all the above, we simple add the task's curr/prev_window_cpu
+ contributions to the per CPU load_subtractions array. These load
+ subtractions are subtracted from the respective CPU's
+ curr/prev_runnable_sums before the governor queries CPU load. Once this
+ is complete, the scheduler sets all curr/prev_window_cpu contributions
+ of the task to 0 for all CPUs in the source cluster. The destination
+ CPUs's curr/prev_window_cpu is updated with the tasks curr/prev_window
+ sums.
+
+ Finally, we must deal with frequency aggregation. When frequency
+ aggregation is in effect, there is little point in dealing with per CPU
+ footprint since the load of all related tasks have to be reported on a
+ single CPU. Therefore when a task enters a related group we clear out
+ all per CPU contributions and add it to the task CPU's cpu_time struct.
+ From that point onwards we stop managing per CPU contributions upon
+ inter cluster migrations since that work is redundant. Finally when a
+ task exits a related group we must walk every CPU in reset all CPU
+ contributions. We then set the task CPU contribution to the respective
+ curr/prev sum values and add that sum to the task CPU rq runnable sum.
+
+ Top-task management is the same as in the case of intra-cluster
+ migrations.
IRQ_UPDATE
This event signifies end of execution of an interrupt handler. This
event results in update of cpu's busy time counters, curr_runnable_sum
- and prev_runnable_sum, provided cpu was idle.
- When sched_io_is_busy = 0, only the interrupt handling time is added
- to cpu's curr_runnable_sum and prev_runnable_sum counters. When
- sched_io_is_busy = 1, the event mirrors actions taken under
- TASK_UPDATED event i.e time since last accounting of idle task's cpu
- usage is added to cpu's curr_runnable_sum and prev_runnable_sum
- counters.
+ and prev_runnable_sum, provided cpu was idle. When sched_io_is_busy = 0,
+ only the interrupt handling time is added to cpu's curr_runnable_sum and
+ prev_runnable_sum counters. When sched_io_is_busy = 1, the event mirrors
+ actions taken under TASK_UPDATED event i.e time since last accounting
+ of idle task's cpu usage is added to cpu's curr_runnable_sum and
+ prev_runnable_sum counters. No update is needed for top-tasks in this
+ case.
+
+*** 6.4 Tying it all together
+
+Now the scheduler maintains two independent quantities for load reporing 1) CPU
+load as represented by prev_runnable_sum and 2) top-tasks. The reported load
+is governed by tunable sched_freq_reporting_policy. The default choice is
+FREQ_REPORT_MAX_CPU_LOAD_TOP_TASK. In other words:
+
+max(prev_runnable_sum, top_task load)
+
+Let's explain the rationale behind the choice. CPU load tracks the exact amount
+of execution observed on a CPU. This is close to the quantity that the vanilla
+governor used to track. It offers the advantages of no load over-reporting that
+our earlier load fixup mechanisms had deal with. It then also tackles the part
+picture problem by keeping of track of tasks that might be migrating across
+CPUs leaving a small footprint on each CPU. Since we maintain one top task per
+CPU, we can handle as many top tasks as the number of CPUs in a cluster. We
+might miss a few cases where the combined load of the top and non-top tasks on
+a CPU are more representative of the true load. However, those cases have been
+deemed to rare and have little impact on overall load/frequency behavior.
+
===========
7. TUNABLES
@@ -1238,6 +1414,18 @@ However LPM exit latency associated with an idle CPU outweigh the above
benefits on some targets. When this knob is turned on, the waker CPU is
selected if it has only 1 runnable task.
+*** 7.20 sched_freq_reporting_policy
+
+Appears at: /proc/sys/kernel/sched_freq_reporting_policy
+
+Default value: 0
+
+This dictates what the load reporting policy to the governor should be. The
+default value is FREQ_REPORT_MAX_CPU_LOAD_TOP_TASK. Other values include
+FREQ_REPORT_CPU_LOAD which only reports CPU load to the governor and
+FREQ_REPORT_TOP_TASK which only reports the load of the top task on a CPU
+to the governor.
+
=========================
8. HMP SCHEDULER TRACE POINTS
=========================
@@ -1318,7 +1506,7 @@ frequency of the CPU for real time task placement).
Logged when window-based stats are updated for a task. The update may happen
for a variety of reasons, see section 2.5, "Task Events."
-<idle>-0 [004] d.h4 12700.711513: sched_update_task_ravg: wc 12700711473496 ws 12700691772135 delta 19701361 event TASK_WAKE cpu 4 cur_freq 199200 cur_pid 0 task 13227 (powertop) ms 12640648272532 delta 60063200964 demand 13364423 sum 0 irqtime 0 cs 0 ps 495018 cur_window 0 prev_window 0
+rcu_preempt-7 [000] d..3 262857.738888: sched_update_task_ravg: wc 262857521127957 ws 262857490000000 delta 31127957 event PICK_NEXT_TASK cpu 0 cur_freq 291055 cur_pid 7 task 9309 (kworker/u16:0) ms 262857520627280 delta 500677 demand 282196 sum 156201 irqtime 0 pred_demand 267103 rq_cs 478718 rq_ps 0 cur_window 78433 (78433 0 0 0 0 0 0 0 ) prev_window 146430 (0 146430 0 0 0 0 0 0 ) nt_cs 0 nt_ps 0 active_wins 149 grp_cs 0 grp_ps 0, grp_nt_cs 0, grp_nt_ps: 0 curr_top 6 prev_top 2
- wc: wallclock, output of sched_clock(), monotonically increasing time since
boot (will roll over in 585 years) (ns)
@@ -1344,9 +1532,27 @@ for a variety of reasons, see section 2.5, "Task Events."
counter.
- ps: prev_runnable_sum of cpu (ns). See section 6.1 for more details of this
counter.
-- cur_window: cpu demand of task in its most recently tracked window (ns)
-- prev_window: cpu demand of task in the window prior to the one being tracked
- by cur_window
+- cur_window: cpu demand of task in its most recently tracked window summed up
+ across all CPUs (ns). This is followed by a list of contributions on each
+ individual CPU.
+- prev_window: cpu demand of task in its previous window summed up across
+ all CPUs (ns). This is followed by a list of contributions on each individual
+ CPU.
+- nt_cs: curr_runnable_sum of a cpu for new tasks only (ns).
+- nt_ps: prev_runnable_sum of a cpu for new tasks only (ns).
+- active_wins: No. of active windows since task statistics were initialized
+- grp_cs: curr_runnable_sum for colocated tasks. This is independent from
+ cs described above. The addition of these two fields give the total CPU
+ load for the most recent window
+- grp_ps: prev_runnable_sum for colocated tasks. This is independent from
+ ps described above. The addition of these two fields give the total CPU
+ load for the previous window.
+- grp_nt_cs: curr_runnable_sum of a cpu for grouped new tasks only (ns).
+- grp_nt_ps: prev_runnable_sum for a cpu for grouped new tasks only (ns).
+- curr_top: index of the top task in the top_tasks array in the current
+ window for a CPU.
+- prev_top: index of the top task in the top_tasks array in the previous
+ window for a CPU
*** 8.5 sched_update_history
diff --git a/Documentation/scsi/scsi_eh.txt b/Documentation/scsi/scsi_eh.txt
index 8638f61c8c9d..37eca00796ee 100644
--- a/Documentation/scsi/scsi_eh.txt
+++ b/Documentation/scsi/scsi_eh.txt
@@ -263,19 +263,23 @@ scmd->allowed.
3. scmd recovered
ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd
- - shost->host_failed--
- clear scmd->eh_eflags
- scsi_setup_cmd_retry()
- move from local eh_work_q to local eh_done_q
LOCKING: none
+ CONCURRENCY: at most one thread per separate eh_work_q to
+ keep queue manipulation lockless
4. EH completes
ACTION: scsi_eh_flush_done_q() retries scmds or notifies upper
- layer of failure.
+ layer of failure. May be called concurrently but must have
+ a no more than one thread per separate eh_work_q to
+ manipulate the queue locklessly
- scmd is removed from eh_done_q and scmd->eh_entry is cleared
- if retry is necessary, scmd is requeued using
scsi_queue_insert()
- otherwise, scsi_finish_command() is invoked for scmd
+ - zero shost->host_failed
LOCKING: queue or finish function performs appropriate locking
diff --git a/Documentation/serial/tty.txt b/Documentation/serial/tty.txt
index bc3842dc323a..e2dea3dc4307 100644
--- a/Documentation/serial/tty.txt
+++ b/Documentation/serial/tty.txt
@@ -213,9 +213,6 @@ TTY_IO_ERROR If set, causes all subsequent userspace read/write
TTY_OTHER_CLOSED Device is a pty and the other side has closed.
-TTY_OTHER_DONE Device is a pty and the other side has closed and
- all pending input processing has been completed.
-
TTY_NO_WRITE_SPLIT Prevent driver from splitting up writes into
smaller chunks.
diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt
index 88152f214f48..302b5ed616a6 100644
--- a/Documentation/sysctl/fs.txt
+++ b/Documentation/sysctl/fs.txt
@@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/fs:
- nr_open
- overflowuid
- overflowgid
+- pipe-user-pages-hard
+- pipe-user-pages-soft
- protected_hardlinks
- protected_symlinks
- suid_dumpable
@@ -159,6 +161,27 @@ The default is 65534.
==============================================================
+pipe-user-pages-hard:
+
+Maximum total number of pages a non-privileged user may allocate for pipes.
+Once this limit is reached, no new pipes may be allocated until usage goes
+below the limit again. When set to 0, no limit is applied, which is the default
+setting.
+
+==============================================================
+
+pipe-user-pages-soft:
+
+Maximum total number of pages a non-privileged user may allocate for pipes
+before the pipe size gets limited to a single page. Once this limit is reached,
+new pipes will be limited to a single page in size for this user in order to
+limit total memory usage, and trying to increase them using fcntl() will be
+denied until usage goes below the limit again. The default value allows to
+allocate up to 1024 pipes at their default size. When set to 0, no limit is
+applied.
+
+==============================================================
+
protected_hardlinks:
A long-standing class of security issues is the hardlink-based
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 03e6aafd5b94..2c5137a6fef6 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -60,6 +60,7 @@ show up in /proc/sys/kernel:
- panic_on_stackoverflow
- panic_on_unrecovered_nmi
- panic_on_warn
+- perf_cpu_time_max_percent
- perf_event_paranoid
- pid_max
- powersave-nap [ PPC only ]
diff --git a/MAINTAINERS b/MAINTAINERS
index ab65bbecb159..7875f7b71546 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1007,6 +1007,10 @@ F: drivers/hwtracing/coresight/*
F: Documentation/trace/coresight.txt
F: Documentation/devicetree/bindings/arm/coresight.txt
F: Documentation/ABI/testing/sysfs-bus-coresight-devices-*
+F: tools/perf/arch/arm/util/pmu.c
+F: tools/perf/arch/arm/util/auxtrace.c
+F: tools/perf/arch/arm/util/cs_etm.c
+F: tools/perf/arch/arm/util/cs_etm.h
ARM/CORGI MACHINE SUPPORT
M: Richard Purdie <rpurdie@rpsys.net>
@@ -9356,6 +9360,7 @@ F: drivers/mmc/host/dw_mmc*
SYSTEM TRACE MODULE CLASS
M: Alexander Shishkin <alexander.shishkin@linux.intel.com>
S: Maintained
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/ash/stm.git
F: Documentation/trace/stm.txt
F: drivers/hwtracing/stm/
F: include/linux/stm.h
diff --git a/Makefile b/Makefile
index 7d76ff290be4..66b873791ce0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 4
-SUBLEVEL = 11
+SUBLEVEL = 16
EXTRAVERSION =
NAME = Blurry Fish Butt
@@ -368,7 +368,7 @@ AFLAGS_MODULE =
LDFLAGS_MODULE =
CFLAGS_KERNEL =
AFLAGS_KERNEL =
-CFLAGS_GCOV = -fprofile-arcs -ftest-coverage
+CFLAGS_GCOV = -fprofile-arcs -ftest-coverage -fno-tree-loop-im
# Use USERINCLUDE when you must reference the UAPI directories only.
@@ -686,9 +686,10 @@ KBUILD_CFLAGS += $(call cc-option, -mno-global-merge,)
KBUILD_CFLAGS += $(call cc-option, -fcatch-undefined-behavior)
else
-# This warning generated too much noise in a regular build.
-# Use make W=1 to enable this warning (see scripts/Makefile.build)
+# These warnings generated too much noise in a regular build.
+# Use make W=1 to enable them (see scripts/Makefile.build)
KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable)
+KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable)
endif
ifdef CONFIG_FRAME_POINTER
diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg
index fa53af0c37ad..6496bb3961a2 100644
--- a/android/configs/android-base.cfg
+++ b/android/configs/android-base.cfg
@@ -37,7 +37,6 @@ CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
CONFIG_IP6_NF_TARGET_REJECT=y
-CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
CONFIG_IPV6=y
CONFIG_IPV6_MIP6=y
CONFIG_IPV6_MULTIPLE_TABLES=y
@@ -57,13 +56,13 @@ CONFIG_IP_NF_MANGLE=y
CONFIG_IP_NF_MATCH_AH=y
CONFIG_IP_NF_MATCH_ECN=y
CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_NAT=y
CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_SECURITY=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_IP_NF_TARGET_REJECT_SKERR=y
CONFIG_NET=y
CONFIG_NETDEVICES=y
CONFIG_NETFILTER=y
@@ -138,18 +137,20 @@ CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_MPPE=y
CONFIG_PREEMPT=y
-CONFIG_RESOURCE_COUNTERS=y
+CONFIG_PROFILING=y
+CONFIG_QUOTA=y
CONFIG_RTC_CLASS=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SETEND_EMULATION=y
CONFIG_STAGING=y
-CONFIG_SWITCH=y
CONFIG_SWP_EMULATION=y
CONFIG_SYNC=y
CONFIG_TUN=y
+CONFIG_UID_CPUTIME=y
CONFIG_UNIX=y
CONFIG_USB_GADGET=y
CONFIG_USB_CONFIGFS=y
diff --git a/android/configs/android-recommended.cfg b/android/configs/android-recommended.cfg
index e4c8aaade197..c3222a77ba24 100644
--- a/android/configs/android-recommended.cfg
+++ b/android/configs/android-recommended.cfg
@@ -110,7 +110,6 @@ CONFIG_TABLET_USB_AIPTEK=y
CONFIG_TABLET_USB_GTCO=y
CONFIG_TABLET_USB_HANWANG=y
CONFIG_TABLET_USB_KBTAB=y
-CONFIG_TABLET_USB_WACOM=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
@@ -119,7 +118,6 @@ CONFIG_TIMER_STATS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_UHID=y
-CONFIG_UID_STAT=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_HIDDEV=y
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 6312f607932f..2d785f5a3041 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -387,7 +387,7 @@ config ARC_HAS_LLSC
config ARC_STAR_9000923308
bool "Workaround for llock/scond livelock"
- default y
+ default n
depends on ISA_ARCV2 && SMP && ARC_HAS_LLSC
config ARC_HAS_SWAPE
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index e1b87444ea9a..05131805aa33 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -332,10 +332,6 @@ static void arc_chk_core_config(void)
pr_warn("CONFIG_ARC_FPU_SAVE_RESTORE needed for working apps\n");
else if (!cpu->extn.fpu_dp && fpu_enabled)
panic("FPU non-existent, disable CONFIG_ARC_FPU_SAVE_RESTORE\n");
-
- if (is_isa_arcv2() && IS_ENABLED(CONFIG_SMP) && cpu->isa.atomic &&
- !IS_ENABLED(CONFIG_ARC_STAR_9000923308))
- panic("llock/scond livelock workaround missing\n");
}
/*
diff --git a/arch/arm/boot/dts/armada-385-linksys.dtsi b/arch/arm/boot/dts/armada-385-linksys.dtsi
index 85d2c377c332..22f7a13e20b4 100644
--- a/arch/arm/boot/dts/armada-385-linksys.dtsi
+++ b/arch/arm/boot/dts/armada-385-linksys.dtsi
@@ -58,8 +58,8 @@
soc {
ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000
- MBUS_ID(0x09, 0x09) 0 0xf1100000 0x10000
- MBUS_ID(0x09, 0x05) 0 0xf1110000 0x10000>;
+ MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000
+ MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>;
internal-regs {
@@ -245,7 +245,7 @@
button@2 {
label = "Factory Reset Button";
linux,code = <KEY_RESTART>;
- gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
+ gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
};
};
@@ -260,7 +260,7 @@
};
sata {
- gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+ gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
default-state = "off";
};
};
@@ -313,7 +313,7 @@
&pinctrl {
keys_pin: keys-pin {
- marvell,pins = "mpp24", "mpp47";
+ marvell,pins = "mpp24", "mpp29";
marvell,function = "gpio";
};
diff --git a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
index b89e6cf1271a..7a461541ce50 100644
--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
+++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
@@ -304,13 +304,13 @@
button@1 {
label = "WPS";
linux,code = <KEY_WPS_BUTTON>;
- gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
+ gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
};
button@2 {
label = "Factory Reset Button";
linux,code = <KEY_RESTART>;
- gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+ gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
};
};
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index a50be640f1b0..59411e447fa0 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -298,6 +298,8 @@
compatible = "maxim,max8997-pmic";
reg = <0x66>;
+ interrupt-parent = <&gpx0>;
+ interrupts = <7 0>;
max8997,pmic-buck1-uses-gpio-dvs;
max8997,pmic-buck2-uses-gpio-dvs;
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index 9fa8763fb19d..7810842100cd 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -126,7 +126,10 @@ dtb-$(CONFIG_ARCH_MSMCOBALT) += msmcobalt-sim.dtb \
msmcobalt-v2.1-qrd.dtb \
apqcobalt-v2.1-mtp.dtb \
apqcobalt-v2.1-cdp.dtb \
- apqcobalt-v2.1-qrd.dtb
+ apqcobalt-v2.1-qrd.dtb \
+ msmcobalt-v2.1-interposer-msmfalcon-cdp.dtb \
+ msmcobalt-v2.1-interposer-msmfalcon-mtp.dtb \
+ msmcobalt-v2.1-interposer-msmfalcon-qrd.dtb
dtb-$(CONFIG_ARCH_MSMHAMSTER) += msmhamster-rumi.dtb
diff --git a/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi b/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi
index 9083c89802f3..70156b1f8493 100644
--- a/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi
+++ b/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi
@@ -361,7 +361,7 @@
&labibb {
status = "ok";
- qpnp,qpnp-labibb-mode = "lcd";
+ qcom,qpnp-labibb-mode = "lcd";
};
&ibb_regulator {
diff --git a/arch/arm/boot/dts/qcom/apq8096-dragonboard.dtsi b/arch/arm/boot/dts/qcom/apq8096-dragonboard.dtsi
index a2085945ac33..a7482bcce112 100644
--- a/arch/arm/boot/dts/qcom/apq8096-dragonboard.dtsi
+++ b/arch/arm/boot/dts/qcom/apq8096-dragonboard.dtsi
@@ -361,7 +361,7 @@
&labibb {
status = "ok";
- qpnp,qpnp-labibb-mode = "lcd";
+ qcom,qpnp-labibb-mode = "lcd";
};
&rpm_bus {
diff --git a/arch/arm/boot/dts/qcom/apq8096-sbc.dtsi b/arch/arm/boot/dts/qcom/apq8096-sbc.dtsi
index 4e7379d9e164..0ee28c2c427e 100644
--- a/arch/arm/boot/dts/qcom/apq8096-sbc.dtsi
+++ b/arch/arm/boot/dts/qcom/apq8096-sbc.dtsi
@@ -364,7 +364,7 @@
&labibb {
status = "ok";
- qpnp,qpnp-labibb-mode = "lcd";
+ qcom,qpnp-labibb-mode = "lcd";
};
&ibb_regulator {
diff --git a/arch/arm/boot/dts/qcom/msm-pm2falcon-rpm-regulator.dtsi b/arch/arm/boot/dts/qcom/msm-pm2falcon-rpm-regulator.dtsi
new file mode 100644
index 000000000000..f500079e6953
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm-pm2falcon-rpm-regulator.dtsi
@@ -0,0 +1,238 @@
+/* Copyright (c) 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.
+ */
+
+&rpm_bus {
+ rpm-regulator-smpb1 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "smpb";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <1>;
+ status = "disabled";
+
+ regulator-s1 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_s1";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpb2 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "smpb";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <1>;
+ status = "disabled";
+
+ regulator-s2 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_s2";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpb3 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "smpb";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <1>;
+ status = "disabled";
+
+ regulator-s3 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_s3";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpb5 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "smpb";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <1>;
+ status = "disabled";
+
+ regulator-s5 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_s5";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldob1 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldob";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l1 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l1";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldob2 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldob";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l2 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l2";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldob3 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldob";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l3 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l3";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldob4 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldob";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l4 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l4";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldob5 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldob";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l5 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l5";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldob6 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldob";
+ qcom,resource-id = <6>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l6 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l6";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldob7 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldob";
+ qcom,resource-id = <7>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l7 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l7";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldob8 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldob";
+ qcom,resource-id = <8>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l8 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l8";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldob9 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "rwsc";
+ qcom,resource-id = <9>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l9 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l9";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldob10 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "rwsm";
+ qcom,resource-id = <10>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l10 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l10";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-bobb {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "bobb";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <4>;
+ status = "disabled";
+
+ regulator-bob {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_bob";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm-pmfalcon-rpm-regulator.dtsi b/arch/arm/boot/dts/qcom/msm-pmfalcon-rpm-regulator.dtsi
new file mode 100644
index 000000000000..0b625bf04ef5
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm-pmfalcon-rpm-regulator.dtsi
@@ -0,0 +1,298 @@
+/* Copyright (c) 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.
+ */
+
+&rpm_bus {
+ rpm-regulator-smpa4 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <4>;
+ qcom,regulator-type = <1>;
+ status = "disabled";
+
+ regulator-s4 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_s4";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa5 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <1>;
+ status = "disabled";
+
+ regulator-s5 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_s5";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-smpa6 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "smpa";
+ qcom,resource-id = <6>;
+ qcom,regulator-type = <1>;
+ status = "disabled";
+
+ regulator-s6 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_s6";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa1 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <1>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l1 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l1";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa2 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <2>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l2 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l2";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa3 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <3>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l3 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l3";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa5 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <5>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l5 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l5";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa6 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <6>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l6 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l6";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa7 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <7>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l7 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l7";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa8 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <8>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l8 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l8";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa9 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <9>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l9 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l9";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa10 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <10>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l10 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l10";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa11 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <11>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l11 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l11";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa12 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <12>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l12 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l12";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa13 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <13>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l13 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l13";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa14 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <14>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l14 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l14";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa15 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <15>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l15 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l15";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa17 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <17>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l17 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l17";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+
+ rpm-regulator-ldoa19 {
+ compatible = "qcom,rpm-smd-regulator-resource";
+ qcom,resource-name = "ldoa";
+ qcom,resource-id = <19>;
+ qcom,regulator-type = <0>;
+ status = "disabled";
+
+ regulator-l19 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pmfalcon_l19";
+ qcom,set = <3>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi b/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi
index dec37881249c..b8fac8a183a2 100644
--- a/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi
@@ -158,6 +158,185 @@
interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>;
};
};
+
+ pmfalcon_vadc: vadc@3100 {
+ compatible = "qcom,qpnp-vadc-hc";
+ reg = <0x3100 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "eoc-int-en-set";
+ qcom,adc-bit-resolution = <15>;
+ qcom,adc-vdd-reference = <1875>;
+
+ chan@6 {
+ label = "die_temp";
+ reg = <6>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <3>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ qcom,cal-val = <0>;
+ };
+
+ chan@0 {
+ label = "ref_gnd";
+ reg = <0>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ qcom,cal-val = <0>;
+ };
+
+ chan@1 {
+ label = "ref_1250v";
+ reg = <1>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ qcom,cal-val = <0>;
+ };
+
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@85 {
+ label = "vcoin";
+ reg = <0x85>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4d {
+ label = "msm_therm";
+ reg = <0x4d>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@51 {
+ label = "quiet_therm";
+ reg = <0x51>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@1d {
+ label = "drax_temp";
+ reg = <0x1d>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <3>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ qcom,cal-val = <0>;
+ };
+ };
+
+ pmfalcon_adc_tm: vadc@3400 {
+ compatible = "qcom,qpnp-adc-tm-hc";
+ reg = <0x3400 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0x0 0x34 0x0 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "eoc-int-en-set";
+ qcom,adc-bit-resolution = <15>;
+ qcom,adc-vdd-reference = <1875>;
+ qcom,adc_tm-vadc = <&pmfalcon_vadc>;
+ qcom,decimation = <0>;
+ qcom,fast-avg-setup = <0>;
+
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,btm-channel-number = <0x60>;
+ };
+
+ chan@4d {
+ label = "msm_therm";
+ reg = <0x4d>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,btm-channel-number = <0x68>;
+ qcom,thermal-node;
+ };
+
+ chan@51 {
+ label = "quiet_therm";
+ reg = <0x51>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,btm-channel-number = <0x70>;
+ qcom,thermal-node;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,btm-channel-number = <0x78>;
+ qcom,thermal-node;
+ };
+ };
+
+ pmfalcon_rradc: rradc@4500 {
+ compatible = "qcom,rradc";
+ reg = <0x4500 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+ };
};
qcom,pmfalcon@1 {
diff --git a/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi
index bba70329c819..c46c0963ff56 100644
--- a/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmi8994.dtsi
@@ -497,7 +497,7 @@
qcom,qpnp-lab-pull-down-enable;
qcom,qpnp-lab-switching-clock-frequency =
<1600>;
- qcom,qpnp-lab-limit-maximum-current = <800>;
+ qcom,qpnp-lab-limit-maximum-current = <1600>;
qcom,qpnp-lab-limit-max-current-enable;
qcom,qpnp-lab-ps-threshold = <20>;
qcom,qpnp-lab-ps-enable;
diff --git a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi
index a5243aff4282..b88b0e28c948 100644
--- a/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmicobalt.dtsi
@@ -321,7 +321,7 @@
qcom,pmic-revid = <&pmicobalt_revid>;
io-channels = <&pmicobalt_rradc 0>;
io-channel-names = "rradc_batt_id";
- qcom,fg-esr-timer-awake = <64>;
+ qcom,fg-esr-timer-awake = <96>;
qcom,fg-esr-timer-asleep = <256>;
qcom,cycle-counter-en;
status = "okay";
@@ -334,7 +334,8 @@
<0x2 0x40 0x2 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x40 0x3 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x40 0x4 IRQ_TYPE_EDGE_BOTH>,
- <0x2 0x40 0x5 IRQ_TYPE_EDGE_BOTH>,
+ <0x2 0x40 0x5
+ IRQ_TYPE_EDGE_RISING>,
<0x2 0x40 0x6 IRQ_TYPE_EDGE_BOTH>,
<0x2 0x40 0x7 IRQ_TYPE_EDGE_BOTH>;
interrupt-names = "soc-update",
@@ -554,6 +555,9 @@
regulator-min-microvolt = <4600000>;
regulator-max-microvolt = <6000000>;
+ interrupts = <0x3 0xde 0x0
+ IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "lab-vreg-ok";
qcom,qpnp-lab-min-voltage = <4600000>;
qcom,qpnp-lab-step-size = <100000>;
qcom,qpnp-lab-slew-rate = <5000>;
@@ -568,13 +572,13 @@
qcom,qpnp-lab-pull-down-enable;
qcom,qpnp-lab-switching-clock-frequency =
<1600>;
- qcom,qpnp-lab-limit-maximum-current = <800>;
+ qcom,qpnp-lab-limit-maximum-current = <1600>;
qcom,qpnp-lab-limit-max-current-enable;
qcom,qpnp-lab-ps-threshold = <20>;
qcom,qpnp-lab-ps-enable;
qcom,qpnp-lab-nfet-size = <100>;
qcom,qpnp-lab-pfet-size = <100>;
- qcom,qpnp-lab-max-precharge-time = <300>;
+ qcom,qpnp-lab-max-precharge-time = <500>;
};
};
diff --git a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
index 40df8b7ff4de..48cf099b84a8 100644
--- a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
@@ -388,7 +388,7 @@
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,cont-splash-enabled;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <720 128 720 64 720 64>;
};
@@ -432,7 +432,7 @@
qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>;
qcom,cont-splash-enabled;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <4 4 2 2 20 20>;
};
diff --git a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi
index 30646dba1cd9..34e41c2bf28f 100644
--- a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi
@@ -376,7 +376,7 @@
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,cont-splash-enabled;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <720 128 720 64 720 64>;
};
diff --git a/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi
index 4855da387e21..165c7de039e5 100644
--- a/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-cdp.dtsi
@@ -387,7 +387,7 @@
&labibb {
status = "ok";
- qpnp,qpnp-labibb-mode = "lcd";
+ qcom,qpnp-labibb-mode = "lcd";
};
&dsi_dual_sharp_video {
@@ -409,7 +409,7 @@
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <720 128 720 64 720 64>;
};
@@ -432,7 +432,7 @@
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
/* panel supports slice height of 8/16/32/48/3840 */
qcom,panel-roi-alignment = <1080 8 1080 8 1080 8>;
};
@@ -480,7 +480,7 @@
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <4 2 4 2 20 20>;
};
diff --git a/arch/arm/boot/dts/qcom/msm8996-dtp.dtsi b/arch/arm/boot/dts/qcom/msm8996-dtp.dtsi
index 19d052791c9a..5c62766b1a26 100644
--- a/arch/arm/boot/dts/qcom/msm8996-dtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-dtp.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -452,7 +452,7 @@
&labibb {
status = "ok";
- qpnp,qpnp-labibb-mode = "lcd";
+ qcom,qpnp-labibb-mode = "lcd";
};
&mdss_mdp {
diff --git a/arch/arm/boot/dts/qcom/msm8996-fluid.dtsi b/arch/arm/boot/dts/qcom/msm8996-fluid.dtsi
index 824d31afb7d8..baecf4b8574e 100644
--- a/arch/arm/boot/dts/qcom/msm8996-fluid.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-fluid.dtsi
@@ -629,14 +629,14 @@
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
/* panel supports slice height of 8/16/32/48/3840 */
qcom,panel-roi-alignment = <1080 8 1080 8 1080 8>;
};
&labibb {
status = "ok";
- qpnp,qpnp-labibb-mode = "lcd";
+ qcom,qpnp-labibb-mode = "lcd";
};
&pmi8994_mpps {
diff --git a/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi b/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi
index 07423a601b35..215608959dc5 100644
--- a/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-gpu.dtsi
@@ -129,6 +129,40 @@
vddcx-supply = <&gdsc_gpu>;
vdd-supply = <&gdsc_gpu_gx>;
+ /* GPU Mempools */
+ qcom,gpu-mempools {
+ #address-cells= <1>;
+ #size-cells = <0>;
+ compatible = "qcom,gpu-mempools";
+
+ /* 4K Page Pool configuration */
+ qcom,gpu-mempool@0 {
+ reg = <0>;
+ qcom,mempool-page-size = <4096>;
+ qcom,mempool-reserved = <2048>;
+ qcom,mempool-allocate;
+ };
+ /* 8K Page Pool configuration */
+ qcom,gpu-mempool@1 {
+ reg = <1>;
+ qcom,mempool-page-size = <8192>;
+ qcom,mempool-reserved = <1024>;
+ qcom,mempool-allocate;
+ };
+ /* 64K Page Pool configuration */
+ qcom,gpu-mempool@2 {
+ reg = <2>;
+ qcom,mempool-page-size = <65536>;
+ qcom,mempool-reserved = <256>;
+ };
+ /* 1M Page Pool configuration */
+ qcom,gpu-mempool@3 {
+ reg = <3>;
+ qcom,mempool-page-size = <1048576>;
+ qcom,mempool-reserved = <32>;
+ };
+ };
+
/* Power levels */
qcom,gpu-pwrlevels {
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/qcom/msm8996-liquid.dtsi b/arch/arm/boot/dts/qcom/msm8996-liquid.dtsi
index 33397e3e4762..dae7306cdd07 100644
--- a/arch/arm/boot/dts/qcom/msm8996-liquid.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-liquid.dtsi
@@ -319,7 +319,7 @@
&labibb {
status = "ok";
- qpnp,qpnp-labibb-mode = "lcd";
+ qcom,qpnp-labibb-mode = "lcd";
};
&dsi_dual_jdi_4k_nofbc_video {
diff --git a/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi
index 3d534ff1550e..bd8aa7fe02f7 100644
--- a/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-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
@@ -343,7 +343,7 @@
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,cont-splash-enabled;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <720 128 720 64 720 64>;
};
@@ -387,7 +387,7 @@
qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>;
qcom,cont-splash-enabled;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <4 4 2 2 20 20>;
};
diff --git a/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi
index 96279288d336..27d3eea5bc20 100644
--- a/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi
@@ -368,7 +368,7 @@
&labibb {
status = "ok";
- qpnp,qpnp-labibb-mode = "lcd";
+ qcom,qpnp-labibb-mode = "lcd";
};
&dsi_dual_sharp_video {
@@ -397,7 +397,7 @@
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <720 128 720 64 720 64>;
};
@@ -420,7 +420,7 @@
qcom,mdss-dsi-bl-min-level = <1>;
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
/* panel supports slice height of 8/16/32/48/3840 */
qcom,panel-roi-alignment = <1080 8 1080 8 1080 8>;
};
@@ -468,7 +468,7 @@
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,5v-boost-gpio = <&pmi8994_gpios 8 0>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <4 4 2 2 20 20>;
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-qrd-vr1.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-qrd-vr1.dtsi
new file mode 100644
index 000000000000..0fb1a0425dd5
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-qrd-vr1.dtsi
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 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.
+ */
+
+&soc {
+ led_flash0: qcom,camera-flash@0 {
+ cell-index = <0>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-source = <&pmicobalt_flash0 &pmicobalt_flash1>;
+ qcom,switch-source = <&pmicobalt_switch0>;
+ status = "ok";
+ };
+
+ led_flash1: qcom,camera-flash@1 {
+ cell-index = <1>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-source = <&pmicobalt_flash2>;
+ qcom,switch-source = <&pmicobalt_switch1>;
+ status = "ok";
+ };
+};
+
+&tlmm{
+ cam_sensor_front_active: cam_sensor_front_active {
+ /* RESET */
+ mux {
+ pins = "gpio9";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio9";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_front_suspend: cam_sensor_front_suspend {
+ /* RESET */
+ mux {
+ pins = "gpio9";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio9";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_rear2_active: cam_sensor_rear2_active {
+ /* RESET, STANDBY */
+ mux {
+ pins = "gpio27","gpio8";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio27","gpio8";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_rear2_suspend: cam_sensor_rear2_suspend {
+ /* RESET, STANDBY */
+ mux {
+ pins = "gpio27","gpio8";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio27","gpio8";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+};
+
+
+&cci {
+ actuator0: qcom,actuator@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
+ actuator1: qcom,actuator@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
+ eeprom0: qcom,eeprom@0 {
+ cell-index = <0>;
+ reg = <0>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pmcobalt_lvs1>;
+ cam_vana-supply = <&pmicobalt_bob>;
+ cam_vdig-supply = <&pmcobalt_s3>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 3312000 1352000>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1352000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 30 0>,
+ <&pmcobalt_gpios 20 0>,
+ <&tlmm 29 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vdig = <2>;
+ qcom,gpio-vana = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_mmss clk_mclk0_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ eeprom1: qcom,eeprom@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,eeprom";
+ cam_vdig-supply = <&pmcobalt_lvs1>;
+ cam_vio-supply = <&pmcobalt_lvs1>;
+ cam_vana-supply = <&pmicobalt_bob>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-min-voltage = <0 0 3312000>;
+ qcom,cam-vreg-max-voltage = <0 0 3600000>;
+ qcom,cam-vreg-op-mode = <0 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 27 0>,
+ <&tlmm 8 0>;
+ qcom,gpio-standby = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_STANDBY1",
+ "CAM_VANA";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss clk_mclk1_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk1_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ eeprom2: qcom,eeprom@2 {
+ cell-index = <2>;
+ reg = <0x2>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pmcobalt_lvs1>;
+ cam_vana-supply = <&pmcobalt_l22>;
+ cam_vdig-supply = <&pmcobalt_s3>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 2864000 1352000>;
+ qcom,cam-vreg-max-voltage = <0 2864000 1352000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_front_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_active
+ &cam_sensor_front_suspend>;
+ gpios = <&tlmm 15 0>,
+ <&tlmm 9 0>,
+ <&pmcobalt_gpios 9 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vdig = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_VDIG";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss clk_mclk2_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@0 {
+ cell-index = <0>;
+ compatible = "qcom,camera";
+ reg = <0x0>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <270>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,actuator-src = <&actuator0>;
+ qcom,eeprom-src = <&eeprom0>;
+ cam_vio-supply = <&pmcobalt_lvs1>;
+ cam_vana-supply = <&pmicobalt_bob>;
+ cam_vdig-supply = <&pmcobalt_s3>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 3312000 1352000>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1352000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 30 0>,
+ <&pmcobalt_gpios 20 0>,
+ <&tlmm 29 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vdig = <2>;
+ qcom,gpio-vana = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_mmss clk_mclk0_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@1 {
+ cell-index = <1>;
+ compatible = "qcom,camera";
+ reg = <0x1>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <90>;
+ qcom,eeprom-src = <&eeprom1>;
+ cam_vio-supply = <&pmcobalt_lvs1>;
+ cam_vana-supply = <&pmicobalt_bob>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana";
+ qcom,cam-vreg-min-voltage = <0 3312000>;
+ qcom,cam-vreg-max-voltage = <0 3600000>;
+ qcom,cam-vreg-op-mode = <0 80000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 27 0>,
+ <&tlmm 8 0>;
+ qcom,gpio-standby = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_STANDBY1",
+ "CAM_VANA1";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss clk_mclk1_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk1_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@2 {
+ cell-index = <2>;
+ compatible = "qcom,camera";
+ reg = <0x02>;
+ qcom,csiphy-sd-index = <2>;
+ qcom,csid-sd-index = <2>;
+ qcom,mount-angle = <90>;
+ qcom,eeprom-src = <&eeprom2>;
+ qcom,led-flash-src = <&led_flash1>;
+ qcom,actuator-src = <&actuator1>;
+ cam_vio-supply = <&pmcobalt_lvs1>;
+ cam_vana-supply = <&pmcobalt_l22>;
+ cam_vdig-supply = <&pmcobalt_s3>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 2864000 1352000>;
+ qcom,cam-vreg-max-voltage = <0 2864000 1352000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_front_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_front_suspend>;
+ gpios = <&tlmm 15 0>,
+ <&tlmm 9 0>,
+ <&pmcobalt_gpios 9 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vdig = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_VDIG";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss clk_mclk2_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+};
+
+&pmcobalt_gpios {
+ gpio@c800 { /* GPIO 9 - CAMERA SENSOR 2 VDIG */
+ qcom,mode = <1>; /* Output */
+ qcom,pull = <5>; /* No Pull */
+ qcom,vin-sel = <0>; /* VIN1 GPIO_LV */
+ qcom,src-sel = <0>; /* GPIO */
+ qcom,invert = <0>; /* Invert */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "ok";
+ };
+
+ gpio@d300 { /* GPIO 20 - CAMERA SENSOR 0 VDIG */
+ qcom,mode = <1>; /* Output */
+ qcom,pull = <5>; /* No Pull */
+ qcom,vin-sel = <1>; /* VIN1 GPIO_MV */
+ qcom,src-sel = <0>; /* GPIO */
+ qcom,invert = <0>; /* Invert */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-skuk.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-skuk.dtsi
new file mode 100644
index 000000000000..a432f0710fe2
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-camera-sensor-skuk.dtsi
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 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.
+ */
+
+&soc {
+ led_flash0: qcom,camera-flash@0 {
+ cell-index = <0>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-source = <&pmicobalt_flash0 &pmicobalt_flash1>;
+ qcom,switch-source = <&pmicobalt_switch0>;
+ status = "ok";
+ };
+
+ led_flash1: qcom,camera-flash@1 {
+ cell-index = <1>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-source = <&pmicobalt_flash2>;
+ qcom,switch-source = <&pmicobalt_switch1>;
+ status = "ok";
+ };
+};
+
+&cci {
+ actuator0: qcom,actuator@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ gpios = <&tlmm 29 0>;
+ qcom,gpio-vaf = <0>;
+ qcom,gpio-req-tbl-num = <0>;
+ qcom,gpio-req-tbl-flags = <0>;
+ qcom,gpio-req-tbl-label = "CAM_VAF";
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_actuator_vaf_active>;
+ pinctrl-1 = <&cam_actuator_vaf_suspend>;
+ };
+
+ actuator1: qcom,actuator@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ gpios = <&tlmm 29 0>;
+ qcom,gpio-vaf = <0>;
+ qcom,gpio-req-tbl-num = <0>;
+ qcom,gpio-req-tbl-flags = <0>;
+ qcom,gpio-req-tbl-label = "CAM_VAF";
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_actuator_vaf_active>;
+ pinctrl-1 = <&cam_actuator_vaf_suspend>;
+ };
+
+ eeprom0: qcom,eeprom@0 {
+ cell-index = <0>;
+ reg = <0>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pmcobalt_lvs1>;
+ cam_vana-supply = <&pmicobalt_bob>;
+ cam_vdig-supply = <&pmcobalt_s3>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 3312000 1352000>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1352000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 30 0>,
+ <&pmcobalt_gpios 20 0>,
+ <&tlmm 29 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vdig = <2>;
+ qcom,gpio-vana = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_mmss clk_mclk0_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ eeprom1: qcom,eeprom@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,eeprom";
+ cam_vdig-supply = <&pmcobalt_lvs1>;
+ cam_vio-supply = <&pmcobalt_lvs1>;
+ cam_vana-supply = <&pmicobalt_bob>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-min-voltage = <0 0 3312000>;
+ qcom,cam-vreg-max-voltage = <0 0 3600000>;
+ qcom,cam-vreg-op-mode = <0 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 15 0>,
+ <&tlmm 9 0>,
+ <&tlmm 8 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1",
+ "CAM_VANA1";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss clk_mclk2_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ eeprom2: qcom,eeprom@2 {
+ cell-index = <2>;
+ reg = <0x2>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&pmcobalt_lvs1>;
+ cam_vana-supply = <&pmcobalt_l22>;
+ cam_vdig-supply = <&pmcobalt_s3>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage =
+ <0 2864000 1352000>;
+ qcom,cam-vreg-max-voltage =
+ <0 2864000 1352000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_front_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_front_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 28 0>,
+ <&pmcobalt_gpios 9 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vdig = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_VDIG";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss clk_mclk1_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk1_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@0 {
+ cell-index = <0>;
+ compatible = "qcom,camera";
+ reg = <0x0>;
+ qcom,special-support-sensors = "imx362_gt24c64a";
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <270>;
+ qcom,eeprom-src = <&eeprom0>;
+ cam_vio-supply = <&pmcobalt_lvs1>;
+ cam_vana-supply = <&pmicobalt_bob>;
+ cam_vdig-supply = <&pmcobalt_s3>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <0 3312000 1352000>;
+ qcom,cam-vreg-max-voltage = <0 3600000 1352000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 30 0>,
+ <&pmcobalt_gpios 20 0>,
+ <&tlmm 29 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vdig = <2>;
+ qcom,gpio-vana = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_VDIG",
+ "CAM_VANA";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_mmss clk_mclk0_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@1 {
+ cell-index = <1>;
+ compatible = "qcom,camera";
+ reg = <0x1>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <90>;
+ qcom,eeprom-src = <&eeprom1>;
+ cam_vdig-supply = <&pmcobalt_lvs1>;
+ cam_vio-supply = <&pmcobalt_lvs1>;
+ cam_vana-supply = <&pmicobalt_bob>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-min-voltage = <0 0 3312000>;
+ qcom,cam-vreg-max-voltage = <0 0 3600000>;
+ qcom,cam-vreg-op-mode = <0 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 15 0>,
+ <&tlmm 9 0>,
+ <&tlmm 8 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1",
+ "CAM_VANA1";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_mmss clk_mclk2_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@2 {
+ cell-index = <2>;
+ compatible = "qcom,camera";
+ reg = <0x02>;
+ qcom,csiphy-sd-index = <2>;
+ qcom,csid-sd-index = <2>;
+ qcom,mount-angle = <90>;
+ cam_vio-supply = <&pmcobalt_lvs1>;
+ cam_vana-supply = <&pmcobalt_l22>;
+ cam_vdig-supply = <&pmcobalt_s3>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage =
+ <0 2864000 1352000>;
+ qcom,cam-vreg-max-voltage =
+ <0 2864000 1352000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk2_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 15 0>,
+ <&tlmm 9 0>,
+ <&pmcobalt_gpios 9 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-vdig = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_VDIG";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_mmss clk_mclk2_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+};
+&pmcobalt_gpios {
+ gpio@c800 { /* GPIO 9 - CAMERA SENSOR 2 VDIG */
+ qcom,mode = <1>; /* Output */
+ qcom,pull = <5>; /* No Pull */
+ qcom,vin-sel = <0>; /* VIN1 GPIO_LV */
+ qcom,src-sel = <0>; /* GPIO */
+ qcom,invert = <0>; /* Invert */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "ok";
+ };
+
+ gpio@d300 { /* GPIO 20 - CAMERA SENSOR 0 VDIG */
+ qcom,mode = <1>; /* Output */
+ qcom,pull = <5>; /* No Pull */
+ qcom,vin-sel = <1>; /* VIN1 GPIO_MV */
+ qcom,src-sel = <0>; /* GPIO */
+ qcom,invert = <0>; /* Invert */
+ qcom,master-en = <1>; /* Enable GPIO */
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi
index 4822823aa63f..ca504a798659 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-cdp.dtsi
@@ -17,11 +17,11 @@
compatible = "qca,wcn3990";
qca,bt-vdd-io-supply = <&pmcobalt_s3>;
qca,bt-vdd-xtal-supply = <&pmcobalt_s5>;
- qca,bt-vdd-core-supply = <&pmcobalt_l7_pin_ctrl>;
- qca,bt-vdd-pa-supply = <&pmcobalt_l17_pin_ctrl>;
- qca,bt-vdd-ldo-supply = <&pmcobalt_l25_pin_ctrl>;
+ qca,bt-vdd-core-supply = <&pmcobalt_l7>;
+ qca,bt-vdd-pa-supply = <&pmcobalt_l17>;
+ qca,bt-vdd-ldo-supply = <&pmcobalt_l25>;
qca,bt-chip-pwd-supply = <&pmicobalt_bob_pin1>;
- clocks = <&clock_gcc clk_rf_clk2>;
+ clocks = <&clock_gcc clk_rf_clk2_pin>;
clock-names = "rf_clk2";
qca,bt-vdd-io-voltage-level = <1352000 1352000>;
@@ -299,7 +299,7 @@
&labibb {
status = "ok";
- qpnp,qpnp-labibb-mode = "lcd";
+ qcom,qpnp-labibb-mode = "lcd";
};
&pmicobalt_wled {
@@ -382,7 +382,7 @@
qcom,mdss-dsi-bl-max-level = <4095>;
qcom,5v-boost-gpio = <&tlmm 51 0>;
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
- qcom,partial-update-enabled;
+ qcom,partial-update-enabled = "single_roi";
qcom,panel-roi-alignment = <4 2 4 2 20 20>;
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
index e140074465ef..8739e8f22549 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-gpu.dtsi
@@ -77,6 +77,9 @@
qcom,tsens-name = "tsens_tz_sensor12";
+ /* Quirks */
+ qcom,gpu-quirk-lmloadkill-disable;
+
clocks = <&clock_gfx clk_gpucc_gfx3d_clk>,
<&clock_gcc clk_gcc_gpu_cfg_ahb_clk>,
<&clock_gpu clk_gpucc_rbbmtimer_clk>,
@@ -119,6 +122,40 @@
vddcx-supply = <&gdsc_gpu_cx>;
vdd-supply = <&gdsc_gpu_gx>;
+ /* GPU Mempools */
+ qcom,gpu-mempools {
+ #address-cells= <1>;
+ #size-cells = <0>;
+ compatible = "qcom,gpu-mempools";
+
+ /* 4K Page Pool configuration */
+ qcom,gpu-mempool@0 {
+ reg = <0>;
+ qcom,mempool-page-size = <4096>;
+ qcom,mempool-reserved = <2048>;
+ qcom,mempool-allocate;
+ };
+ /* 8K Page Pool configuration */
+ qcom,gpu-mempool@1 {
+ reg = <1>;
+ qcom,mempool-page-size = <8192>;
+ qcom,mempool-reserved = <1024>;
+ qcom,mempool-allocate;
+ };
+ /* 64K Page Pool configuration */
+ qcom,gpu-mempool@2 {
+ reg = <2>;
+ qcom,mempool-page-size = <65536>;
+ qcom,mempool-reserved = <256>;
+ };
+ /* 1M Page Pool configuration */
+ qcom,gpu-mempool@3 {
+ reg = <3>;
+ qcom,mempool-page-size = <1048576>;
+ qcom,mempool-reserved = <32>;
+ };
+ };
+
/* Power levels */
qcom,gpu-pwrlevels {
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-cdp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-cdp.dtsi
new file mode 100644
index 000000000000..4822823aa63f
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-cdp.dtsi
@@ -0,0 +1,592 @@
+/* Copyright (c) 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.
+ */
+
+#include "msmcobalt-pinctrl.dtsi"
+#include "msmcobalt-camera-sensor-cdp.dtsi"
+/ {
+ bluetooth: bt_wcn3990 {
+ compatible = "qca,wcn3990";
+ qca,bt-vdd-io-supply = <&pmcobalt_s3>;
+ qca,bt-vdd-xtal-supply = <&pmcobalt_s5>;
+ qca,bt-vdd-core-supply = <&pmcobalt_l7_pin_ctrl>;
+ qca,bt-vdd-pa-supply = <&pmcobalt_l17_pin_ctrl>;
+ qca,bt-vdd-ldo-supply = <&pmcobalt_l25_pin_ctrl>;
+ qca,bt-chip-pwd-supply = <&pmicobalt_bob_pin1>;
+ clocks = <&clock_gcc clk_rf_clk2>;
+ clock-names = "rf_clk2";
+
+ qca,bt-vdd-io-voltage-level = <1352000 1352000>;
+ qca,bt-vdd-xtal-voltage-level = <2040000 2040000>;
+ qca,bt-vdd-core-voltage-level = <1800000 1800000>;
+ qca,bt-vdd-pa-voltage-level = <1304000 1304000>;
+ qca,bt-vdd-ldo-voltage-level = <3312000 3312000>;
+ qca,bt-chip-pwd-voltage-level = <3600000 3600000>;
+
+ qca,bt-vdd-io-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-xtal-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-core-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-pa-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-ldo-current-level = <1>; /* LPM/PFM */
+ };
+};
+
+&blsp1_uart3_hs {
+ status = "ok";
+};
+
+&ufsphy1 {
+ vdda-phy-supply = <&pmcobalt_l1>;
+ vdda-pll-supply = <&pmcobalt_l2>;
+ vddp-ref-clk-supply = <&pmcobalt_l26>;
+ vdda-phy-max-microamp = <51400>;
+ vdda-pll-max-microamp = <14600>;
+ vddp-ref-clk-max-microamp = <100>;
+ vddp-ref-clk-always-on;
+ status = "ok";
+};
+
+&ufs1 {
+ vdd-hba-supply = <&gdsc_ufs>;
+ vdd-hba-fixed-regulator;
+ vcc-supply = <&pmcobalt_l20>;
+ vccq-supply = <&pmcobalt_l26>;
+ vccq2-supply = <&pmcobalt_s4>;
+ vcc-max-microamp = <750000>;
+ vccq-max-microamp = <560000>;
+ vccq2-max-microamp = <750000>;
+ status = "ok";
+};
+
+&ufs_ice {
+ status = "ok";
+};
+
+&sdhc_2 {
+ vdd-supply = <&pmcobalt_l21>;
+ qcom,vdd-voltage-level = <2950000 2960000>;
+ qcom,vdd-current-level = <200 800000>;
+
+ vdd-io-supply = <&pmcobalt_l13>;
+ qcom,vdd-io-voltage-level = <1808000 2960000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000
+ 50000000 100000000 200000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+ cd-gpios = <&tlmm 95 0x1>;
+
+ status = "ok";
+};
+
+&uartblsp2dm1 {
+ status = "ok";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart_console_active>;
+};
+
+&pmcobalt_gpios {
+ /* GPIO 5 for Home Key */
+ gpio@c400 {
+ status = "okay";
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,out-strength = <1>;
+ };
+
+ /* GPIO 6 for Vol+ Key */
+ gpio@c500 {
+ status = "okay";
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,out-strength = <1>;
+ };
+
+ /* GPIO 7 for Snapshot Key */
+ gpio@c600 {
+ status = "okay";
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,out-strength = <1>;
+ };
+
+ /* GPIO 8 for Focus Key */
+ gpio@c700 {
+ status = "okay";
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,out-strength = <1>;
+ };
+
+ gpio@cc00 { /* GPIO 13 */
+ qcom,mode = <1>;
+ qcom,output-type = <0>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <0>;
+ qcom,out-strength = <1>;
+ qcom,src-sel = <3>;
+ qcom,master-en = <1>;
+ status = "okay";
+ };
+
+ /* GPIO 21 (NFC_CLK_REQ) */
+ gpio@d400 {
+ qcom,mode = <0>;
+ qcom,vin-sel = <1>;
+ qcom,src-sel = <0>;
+ qcom,master-en = <1>;
+ status = "okay";
+ };
+};
+
+&i2c_5 {
+ status = "okay";
+ synaptics@20 {
+ compatible = "synaptics,dsx";
+ reg = <0x20>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <125 0x2008>;
+ vdd-supply = <&pmcobalt_l6>;
+ avdd-supply = <&pmcobalt_l28>;
+ synaptics,vdd-voltage = <1808000 1808000>;
+ synaptics,avdd-voltage = <3008000 3008000>;
+ synaptics,vdd-current = <40000>;
+ synaptics,avdd-current = <20000>;
+ pinctrl-names = "pmx_ts_active", "pmx_ts_suspend";
+ pinctrl-0 = <&ts_active>;
+ pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+ synaptics,display-coords = <0 0 1439 2559>;
+ synaptics,panel-coords = <0 0 1439 2559>;
+ synaptics,reset-gpio = <&tlmm 89 0x00>;
+ synaptics,irq-gpio = <&tlmm 125 0x2008>;
+ synaptics,disable-gpios;
+ synaptics,fw-name = "PR1702898-s3528t_60QHD_00400001.img";
+ };
+};
+
+&i2c_6 { /* BLSP1 QUP6 (NFC) */
+ status = "okay";
+ nq@28 {
+ compatible = "qcom,nq-nci";
+ reg = <0x28>;
+ qcom,nq-irq = <&tlmm 92 0x00>;
+ qcom,nq-ven = <&tlmm 12 0x00>;
+ qcom,nq-firm = <&tlmm 93 0x00>;
+ qcom,nq-clkreq = <&pmcobalt_gpios 21 0x00>;
+ qcom,nq-esepwr = <&tlmm 116 0x00>;
+ interrupt-parent = <&tlmm>;
+ qcom,clk-src = "BBCLK3";
+ interrupts = <92 0>;
+ interrupt-names = "nfc_irq";
+ pinctrl-names = "nfc_active", "nfc_suspend";
+ pinctrl-0 = <&nfc_int_active &nfc_enable_active>;
+ pinctrl-1 = <&nfc_int_suspend &nfc_enable_suspend>;
+ clocks = <&clock_gcc clk_ln_bb_clk3_pin>;
+ clock-names = "ref_clk";
+ };
+};
+
+&i2c_7 {
+ status = "okay";
+ qcom,smb138x@8 {
+ compatible = "qcom,i2c-pmic";
+ reg = <0x8>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x0 0xd1 0x0 IRQ_TYPE_LEVEL_LOW>;
+ interrupt_names = "smb138x";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ qcom,periph-map = <0x10 0x11 0x12 0x13 0x14 0x16 0x36>;
+
+ smb138x_tadc: qcom,tadc@3600 {
+ compatible = "qcom,tadc";
+ reg = <0x3600 0x100>;
+
+ interrupts = <0x36 0x0 IRQ_TYPE_EDGE_BOTH>;
+ interrupt-names = "eoc";
+
+ batt_therm {
+ qcom,rbias = <68100>;
+ qcom,rtherm-at-25degc = <68000>;
+ qcom,beta-coefficient = <3450>;
+ };
+
+ skin_temp {
+ qcom,rbias = <33000>;
+ qcom,rtherm-at-25degc = <68000>;
+ qcom,beta-coefficient = <3450>;
+ };
+
+ die_temp {
+ qcom,scale = <(-1032)>;
+ qcom,offset = <344125>;
+ };
+
+ batt_i {
+ qcom,channel = <3>;
+ qcom,scale = <20000000>;
+ };
+
+ batt_v {
+ qcom,scale = <5000000>;
+ };
+
+ input_i {
+ qcom,scale = <14285714>;
+ };
+
+ input_v {
+ qcom,scale = <25000000>;
+ };
+
+ otg_i {
+ qcom,scale = <5714286>;
+ };
+ };
+ };
+};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+ hw-config = "split_dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_dual_nt35597_video>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ qcom,platform-reset-gpio = <&tlmm 94 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,panel-mode-gpio = <&tlmm 91 0>;
+};
+
+&mdss_dsi1 {
+ qcom,dsi-pref-prim-pan = <&dsi_dual_nt35597_video>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ qcom,platform-reset-gpio = <&tlmm 94 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,panel-mode-gpio = <&tlmm 91 0>;
+};
+
+&labibb {
+ status = "ok";
+ qpnp,qpnp-labibb-mode = "lcd";
+};
+
+&pmicobalt_wled {
+ qcom,led-strings-list = [00 01];
+};
+
+&dsi_dual_nt35597_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_dual_nt35597_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_dual_nt35597_truly_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_dual_nt35597_truly_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_nt35597_dsc_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_nt35597_dsc_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_sharp_4k_dsc_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_sharp_4k_dsc_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_dual_jdi_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,5v-boost-gpio = <&tlmm 51 0>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_dual_jdi_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,5v-boost-gpio = <&tlmm 51 0>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,partial-update-enabled;
+ qcom,panel-roi-alignment = <4 2 4 2 20 20>;
+};
+
+&dsi_sharp_1080_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_jdi_1080_vid {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply_no_labibb>;
+ qcom,5v-boost-gpio = <&tlmm 51 0>;
+};
+
+&dsi_dual_sharp_1080_120hz_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&mdss_hdmi_tx {
+ pinctrl-names = "hdmi_hpd_active", "hdmi_ddc_active", "hdmi_cec_active",
+ "hdmi_active", "hdmi_sleep";
+ pinctrl-0 = <&mdss_hdmi_5v_active &mdss_hdmi_hpd_active
+ &mdss_hdmi_ddc_suspend &mdss_hdmi_cec_suspend>;
+ pinctrl-1 = <&mdss_hdmi_5v_active &mdss_hdmi_hpd_active
+ &mdss_hdmi_ddc_active &mdss_hdmi_cec_suspend>;
+ pinctrl-2 = <&mdss_hdmi_5v_active &mdss_hdmi_hpd_active
+ &mdss_hdmi_cec_active &mdss_hdmi_ddc_suspend>;
+ pinctrl-3 = <&mdss_hdmi_5v_active &mdss_hdmi_hpd_active
+ &mdss_hdmi_ddc_active &mdss_hdmi_cec_active>;
+ pinctrl-4 = <&mdss_hdmi_5v_suspend &mdss_hdmi_hpd_suspend
+ &mdss_hdmi_ddc_suspend &mdss_hdmi_cec_suspend>;
+};
+
+&mdss_dp_ctrl {
+ pinctrl-names = "mdss_dp_active", "mdss_dp_sleep";
+ pinctrl-0 = <&mdss_dp_aux_active &mdss_dp_usbplug_cc_active>;
+ pinctrl-1 = <&mdss_dp_aux_suspend &mdss_dp_usbplug_cc_suspend>;
+ qcom,aux-en-gpio = <&tlmm 77 0>;
+ qcom,aux-sel-gpio = <&tlmm 78 0>;
+ qcom,usbplug-cc-gpio = <&tlmm 38 0>;
+};
+
+&pmicobalt_charger {
+ qcom,batteryless-platform;
+};
+
+&pmicobalt_haptics {
+ status = "okay";
+};
+
+&pmcobalt_vadc {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@85 {
+ label = "vcoin";
+ reg = <0x85>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4d {
+ label = "msm_therm";
+ reg = <0x4d>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@51 {
+ label = "quiet_therm";
+ reg = <0x51>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+};
+
+&pmcobalt_adc_tm {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,btm-channel-number = <0x60>;
+ };
+
+ chan@4d {
+ label = "msm_therm";
+ reg = <0x4d>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,btm-channel-number = <0x68>;
+ qcom,thermal-node;
+ };
+
+ chan@51 {
+ label = "quiet_therm";
+ reg = <0x51>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,btm-channel-number = <0x70>;
+ qcom,thermal-node;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,btm-channel-number = <0x78>;
+ qcom,thermal-node;
+ };
+};
+
+&wil6210 {
+ status = "ok";
+};
+
+&soc {
+ gpio_keys {
+ compatible = "gpio-keys";
+ input-name = "gpio-keys";
+ status = "okay";
+
+ home {
+ label = "home";
+ gpios = <&pmcobalt_gpios 5 0x1>;
+ linux,input-type = <1>;
+ linux,code = <102>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+
+ };
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&pmcobalt_gpios 6 0x1>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ cam_snapshot {
+ label = "cam_snapshot";
+ gpios = <&pmcobalt_gpios 7 0x1>;
+ linux,input-type = <1>;
+ linux,code = <766>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ cam_focus {
+ label = "cam_focus";
+ gpios = <&pmcobalt_gpios 8 0x1>;
+ linux,input-type = <1>;
+ linux,code = <528>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-mtp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-mtp.dtsi
new file mode 100644
index 000000000000..b77bab712ecf
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon-mtp.dtsi
@@ -0,0 +1,613 @@
+/* Copyright (c) 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.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "msmcobalt-pinctrl.dtsi"
+#include "msmcobalt-camera-sensor-mtp.dtsi"
+/ {
+ bluetooth: bt_wcn3990 {
+ compatible = "qca,wcn3990";
+ qca,bt-vdd-io-supply = <&pmcobalt_s3>;
+ qca,bt-vdd-xtal-supply = <&pmcobalt_s5>;
+ qca,bt-vdd-core-supply = <&pmcobalt_l7_pin_ctrl>;
+ qca,bt-vdd-pa-supply = <&pmcobalt_l17_pin_ctrl>;
+ qca,bt-vdd-ldo-supply = <&pmcobalt_l25_pin_ctrl>;
+ qca,bt-chip-pwd-supply = <&pmicobalt_bob_pin1>;
+ clocks = <&clock_gcc clk_rf_clk2>;
+ clock-names = "rf_clk2";
+
+ qca,bt-vdd-io-voltage-level = <1352000 1352000>;
+ qca,bt-vdd-xtal-voltage-level = <2040000 2040000>;
+ qca,bt-vdd-core-voltage-level = <1800000 1800000>;
+ qca,bt-vdd-pa-voltage-level = <1304000 1304000>;
+ qca,bt-vdd-ldo-voltage-level = <3312000 3312000>;
+ qca,bt-chip-pwd-voltage-level = <3600000 3600000>;
+
+ qca,bt-vdd-io-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-xtal-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-core-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-pa-current-level = <1>; /* LPM/PFM */
+ qca,bt-vdd-ldo-current-level = <1>; /* LPM/PFM */
+ };
+};
+
+&blsp1_uart3_hs {
+ status = "ok";
+};
+
+&ufsphy1 {
+ vdda-phy-supply = <&pmcobalt_l1>;
+ vdda-pll-supply = <&pmcobalt_l2>;
+ vddp-ref-clk-supply = <&pmcobalt_l26>;
+ vdda-phy-max-microamp = <51400>;
+ vdda-pll-max-microamp = <14600>;
+ vddp-ref-clk-max-microamp = <100>;
+ vddp-ref-clk-always-on;
+ status = "ok";
+};
+
+&ufs1 {
+ vdd-hba-supply = <&gdsc_ufs>;
+ vdd-hba-fixed-regulator;
+ vcc-supply = <&pmcobalt_l20>;
+ vccq-supply = <&pmcobalt_l26>;
+ vccq2-supply = <&pmcobalt_s4>;
+ vcc-max-microamp = <750000>;
+ vccq-max-microamp = <560000>;
+ vccq2-max-microamp = <750000>;
+ status = "ok";
+};
+
+&ufs_ice {
+ status = "ok";
+};
+
+&sdhc_2 {
+ vdd-supply = <&pmcobalt_l21>;
+ qcom,vdd-voltage-level = <2950000 2960000>;
+ qcom,vdd-current-level = <200 800000>;
+
+ vdd-io-supply = <&pmcobalt_l13>;
+ qcom,vdd-io-voltage-level = <1808000 2960000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000
+ 50000000 100000000 200000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+ cd-gpios = <&tlmm 95 0x1>;
+
+ status = "ok";
+};
+
+&uartblsp2dm1 {
+ status = "ok";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart_console_active>;
+};
+
+&pmcobalt_gpios {
+ /* GPIO 6 for Vol+ Key */
+ gpio@c500 {
+ status = "okay";
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,out-strength = <1>;
+ };
+
+ /* GPIO 7 for Snapshot Key */
+ gpio@c600 {
+ status = "okay";
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,out-strength = <1>;
+ };
+
+ /* GPIO 8 for Focus Key */
+ gpio@c700 {
+ status = "okay";
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,out-strength = <1>;
+ };
+
+ gpio@cc00 { /* GPIO 13 */
+ qcom,mode = <1>;
+ qcom,output-type = <0>;
+ qcom,pull = <5>;
+ qcom,vin-sel = <0>;
+ qcom,out-strength = <1>;
+ qcom,src-sel = <3>;
+ qcom,master-en = <1>;
+ status = "okay";
+ };
+
+ /* GPIO 21 (NFC_CLK_REQ) */
+ gpio@d400 {
+ qcom,mode = <0>;
+ qcom,vin-sel = <1>;
+ qcom,src-sel = <0>;
+ qcom,master-en = <1>;
+ status = "okay";
+ };
+
+ /* GPIO 18 SMB138X */
+ gpio@d100 {
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,master-en = <1>;
+ status = "okay";
+ };
+};
+
+&i2c_5 {
+ status = "okay";
+ synaptics@20 {
+ compatible = "synaptics,dsx";
+ reg = <0x20>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <125 0x2008>;
+ vdd-supply = <&pmcobalt_l6>;
+ avdd-supply = <&pmcobalt_l28>;
+ synaptics,vdd-voltage = <1808000 1808000>;
+ synaptics,avdd-voltage = <3008000 3008000>;
+ synaptics,vdd-current = <40000>;
+ synaptics,avdd-current = <20000>;
+ pinctrl-names = "pmx_ts_active", "pmx_ts_suspend";
+ pinctrl-0 = <&ts_active>;
+ pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+ synaptics,display-coords = <0 0 1439 2559>;
+ synaptics,panel-coords = <0 0 1439 2559>;
+ synaptics,reset-gpio = <&tlmm 89 0x00>;
+ synaptics,irq-gpio = <&tlmm 125 0x2008>;
+ synaptics,disable-gpios;
+ synaptics,fw-name = "PR1702898-s3528t_60QHD_00400001.img";
+ };
+};
+
+&i2c_6 { /* BLSP1 QUP6 (NFC) */
+ status = "okay";
+ nq@28 {
+ compatible = "qcom,nq-nci";
+ reg = <0x28>;
+ qcom,nq-irq = <&tlmm 92 0x00>;
+ qcom,nq-ven = <&tlmm 12 0x00>;
+ qcom,nq-firm = <&tlmm 93 0x00>;
+ qcom,nq-clkreq = <&pmcobalt_gpios 21 0x00>;
+ qcom,nq-esepwr = <&tlmm 116 0x00>;
+ interrupt-parent = <&tlmm>;
+ qcom,clk-src = "BBCLK3";
+ interrupts = <92 0>;
+ interrupt-names = "nfc_irq";
+ pinctrl-names = "nfc_active", "nfc_suspend";
+ pinctrl-0 = <&nfc_int_active &nfc_enable_active>;
+ pinctrl-1 = <&nfc_int_suspend &nfc_enable_suspend>;
+ clocks = <&clock_gcc clk_ln_bb_clk3_pin>;
+ clock-names = "ref_clk";
+ };
+};
+
+&i2c_7 {
+ status = "okay";
+ qcom,smb138x@8 {
+ compatible = "qcom,i2c-pmic";
+ reg = <0x8>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-parent = <&spmi_bus>;
+ interrupts = <0x0 0xd1 0x0 IRQ_TYPE_LEVEL_LOW>;
+ interrupt_names = "smb138x";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ qcom,periph-map = <0x10 0x11 0x12 0x13 0x14 0x16 0x36>;
+
+ smb138x_revid: qcom,revid@100 {
+ compatible = "qcom,qpnp-revid";
+ reg = <0x100 0x100>;
+ };
+
+ smb138x_tadc: qcom,tadc@3600 {
+ compatible = "qcom,tadc";
+ reg = <0x3600 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+ interrupts = <0x36 0x0 IRQ_TYPE_EDGE_BOTH>;
+ interrupt-names = "eoc";
+
+ batt_temp@0 {
+ reg = <0>;
+ qcom,rbias = <68100>;
+ qcom,rtherm-at-25degc = <68000>;
+ qcom,beta-coefficient = <3450>;
+ };
+
+ skin_temp@1 {
+ reg = <1>;
+ qcom,rbias = <33000>;
+ qcom,rtherm-at-25degc = <68000>;
+ qcom,beta-coefficient = <3450>;
+ };
+
+ die_temp@2 {
+ reg = <2>;
+ qcom,scale = <(-1032)>;
+ qcom,offset = <344125>;
+ };
+
+ batt_i@3 {
+ reg = <3>;
+ qcom,channel = <3>;
+ qcom,scale = <20000000>;
+ };
+
+ batt_v@4 {
+ reg = <4>;
+ qcom,scale = <5000000>;
+ };
+
+ input_i@5 {
+ reg = <5>;
+ qcom,scale = <14285714>;
+ };
+
+ input_v@6 {
+ reg = <6>;
+ qcom,scale = <25000000>;
+ };
+
+ otg_i@7 {
+ reg = <7>;
+ qcom,scale = <5714286>;
+ };
+ };
+
+ smb138x_parallel_slave: qcom,smb138x-parallel-slave@1000 {
+ compatible = "qcom,smb138x-parallel-slave";
+ qcom,pmic-revid = <&smb138x_revid>;
+ reg = <0x1000 0x700>;
+
+ io-channels = <&smb138x_tadc 2>,
+ <&smb138x_tadc 12>,
+ <&smb138x_tadc 3>;
+ io-channel-names = "charger_temp",
+ "charger_temp_max",
+ "batt_i";
+ };
+ };
+};
+
+&mdss_hdmi_tx {
+ pinctrl-names = "hdmi_hpd_active", "hdmi_ddc_active", "hdmi_cec_active",
+ "hdmi_active", "hdmi_sleep";
+ pinctrl-0 = <&mdss_hdmi_5v_active &mdss_hdmi_hpd_active
+ &mdss_hdmi_ddc_suspend &mdss_hdmi_cec_suspend>;
+ pinctrl-1 = <&mdss_hdmi_5v_active &mdss_hdmi_hpd_active
+ &mdss_hdmi_ddc_active &mdss_hdmi_cec_suspend>;
+ pinctrl-2 = <&mdss_hdmi_5v_active &mdss_hdmi_hpd_active
+ &mdss_hdmi_cec_active &mdss_hdmi_ddc_suspend>;
+ pinctrl-3 = <&mdss_hdmi_5v_active &mdss_hdmi_hpd_active
+ &mdss_hdmi_ddc_active &mdss_hdmi_cec_active>;
+ pinctrl-4 = <&mdss_hdmi_5v_suspend &mdss_hdmi_hpd_suspend
+ &mdss_hdmi_ddc_suspend &mdss_hdmi_cec_suspend>;
+};
+
+&mdss_dp_ctrl {
+ pinctrl-names = "mdss_dp_active", "mdss_dp_sleep";
+ pinctrl-0 = <&mdss_dp_aux_active &mdss_dp_usbplug_cc_active>;
+ pinctrl-1 = <&mdss_dp_aux_suspend &mdss_dp_usbplug_cc_suspend>;
+ qcom,aux-en-gpio = <&tlmm 77 0>;
+ qcom,aux-sel-gpio = <&tlmm 78 0>;
+ qcom,usbplug-cc-gpio = <&tlmm 38 0>;
+};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+ hw-config = "split_dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_dual_nt35597_video>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ qcom,platform-reset-gpio = <&tlmm 94 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,panel-mode-gpio = <&tlmm 91 0>;
+};
+
+&mdss_dsi1 {
+ qcom,dsi-pref-prim-pan = <&dsi_dual_nt35597_video>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+ qcom,platform-reset-gpio = <&tlmm 94 0>;
+ qcom,platform-te-gpio = <&tlmm 10 0>;
+ qcom,panel-mode-gpio = <&tlmm 91 0>;
+};
+
+&labibb {
+ status = "ok";
+ qpnp,qpnp-labibb-mode = "lcd";
+};
+
+&pmicobalt_wled {
+ qcom,led-strings-list = [00 01];
+};
+
+&dsi_dual_nt35597_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_dual_nt35597_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_dual_nt35597_truly_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_dual_nt35597_truly_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_nt35597_dsc_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_nt35597_dsc_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_sharp_4k_dsc_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_sharp_4k_dsc_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_dual_jdi_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,5v-boost-gpio = <&tlmm 51 0>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_dual_jdi_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,5v-boost-gpio = <&tlmm 51 0>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_sharp_1080_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&dsi_jdi_1080_vid {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply_no_labibb>;
+ qcom,5v-boost-gpio = <&tlmm 51 0>;
+};
+
+&dsi_dual_sharp_1080_120hz_cmd {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&pmicobalt_haptics {
+ status = "okay";
+};
+
+&pmcobalt_vadc {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@85 {
+ label = "vcoin";
+ reg = <0x85>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@4d {
+ label = "msm_therm";
+ reg = <0x4d>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@51 {
+ label = "quiet_therm";
+ reg = <0x51>;
+ qcom,decimation = <2>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+};
+
+&pmcobalt_adc_tm {
+ chan@83 {
+ label = "vph_pwr";
+ reg = <0x83>;
+ qcom,pre-div-channel-scaling = <1>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,btm-channel-number = <0x60>;
+ };
+
+ chan@4d {
+ label = "msm_therm";
+ reg = <0x4d>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,btm-channel-number = <0x68>;
+ qcom,thermal-node;
+ };
+
+ chan@51 {
+ label = "quiet_therm";
+ reg = <0x51>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,btm-channel-number = <0x70>;
+ qcom,thermal-node;
+ };
+
+ chan@4c {
+ label = "xo_therm";
+ reg = <0x4c>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <4>;
+ qcom,hw-settle-time = <2>;
+ qcom,btm-channel-number = <0x78>;
+ qcom,thermal-node;
+ };
+};
+
+&wil6210 {
+ status = "ok";
+};
+
+&soc {
+ gpio_keys {
+ compatible = "gpio-keys";
+ input-name = "gpio-keys";
+ status = "okay";
+
+ vol_up {
+ label = "volume_up";
+ gpios = <&pmcobalt_gpios 6 0x1>;
+ linux,input-type = <1>;
+ linux,code = <115>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ cam_snapshot {
+ label = "cam_snapshot";
+ gpios = <&pmcobalt_gpios 7 0x1>;
+ linux,input-type = <1>;
+ linux,code = <766>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+
+ cam_focus {
+ label = "cam_focus";
+ gpios = <&pmcobalt_gpios 8 0x1>;
+ linux,input-type = <1>;
+ linux,code = <528>;
+ gpio-key,wakeup;
+ debounce-interval = <15>;
+ };
+ };
+};
+
+/{
+ mtp_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+ #include "fg-gen3-batterydata-itech-3000mah.dtsi"
+ #include "fg-gen3-batterydata-ascent-3450mah.dtsi"
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon.dtsi
new file mode 100644
index 000000000000..32f616e1dc7a
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-interposer-msmfalcon.dtsi
@@ -0,0 +1,3090 @@
+/* Copyright (c) 2015-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.
+ */
+
+#include "skeleton64.dtsi"
+#include <dt-bindings/clock/msm-clocks-cobalt.h>
+#include <dt-bindings/regulator/qcom,rpm-smd-regulator.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM COBALT";
+ compatible = "qcom,msmcobalt";
+ qcom,msm-id = <292 0x0>;
+ interrupt-parent = <&intc>;
+
+ aliases {
+ serial0 = &uartblsp2dm1;
+ pci-domain0 = &pcie0;
+ sdhc2 = &sdhc_2; /* SDC2 SD card slot */
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ chosen {
+ stdout-path = "serial0";
+ bootargs = "rcupdate.rcu_expedited=1";
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x0>;
+ qcom,limits-info = <&mitigation_profile0>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ enable-method = "psci";
+ efficiency = <1024>;
+ next-level-cache = <&L2_0>;
+ qcom,ea = <&ea0>;
+ L2_0: l2-cache {
+ compatible = "arm,arch-cache";
+ cache-level = <2>;
+ /* A53 L2 dump not supported */
+ qcom,dump-size = <0x0>;
+ };
+ L1_I_0: l1-icache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x9040>;
+ };
+ L1_D_0: l1-dcache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x9040>;
+ };
+ };
+
+ CPU1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x1>;
+ qcom,limits-info = <&mitigation_profile1>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ enable-method = "psci";
+ efficiency = <1024>;
+ next-level-cache = <&L2_0>;
+ qcom,ea = <&ea1>;
+ L1_I_1: l1-icache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x9040>;
+ };
+ L1_D_1: l1-dcache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x9040>;
+ };
+ };
+
+ CPU2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x2>;
+ qcom,limits-info = <&mitigation_profile2>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ enable-method = "psci";
+ efficiency = <1024>;
+ next-level-cache = <&L2_0>;
+ qcom,ea = <&ea2>;
+ L1_I_2: l1-icache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x9040>;
+ };
+ L1_D_2: l1-dcache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x9040>;
+ };
+ };
+
+ CPU3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x3>;
+ qcom,limits-info = <&mitigation_profile3>;
+ qcom,lmh-dcvs = <&lmh_dcvs0>;
+ enable-method = "psci";
+ efficiency = <1024>;
+ next-level-cache = <&L2_0>;
+ qcom,ea = <&ea3>;
+ L1_I_3: l1-icache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x9040>;
+ };
+ L1_D_3: l1-dcache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x9040>;
+ };
+ };
+
+ CPU4: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x100>;
+ qcom,limits-info = <&mitigation_profile4>;
+ qcom,lmh-dcvs = <&lmh_dcvs1>;
+ enable-method = "psci";
+ efficiency = <1536>;
+ next-level-cache = <&L2_1>;
+ qcom,ea = <&ea4>;
+ L2_1: l2-cache {
+ compatible = "arm,arch-cache";
+ cache-level = <2>;
+ };
+ L1_I_100: l1-icache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x12000>;
+ };
+ L1_D_100: l1-dcache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x12000>;
+ };
+ };
+
+ CPU5: cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x101>;
+ qcom,limits-info = <&mitigation_profile5>;
+ qcom,lmh-dcvs = <&lmh_dcvs1>;
+ enable-method = "psci";
+ efficiency = <1536>;
+ next-level-cache = <&L2_1>;
+ qcom,ea = <&ea5>;
+ L1_I_101: l1-icache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x12000>;
+ };
+ L1_D_101: l1-dcache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x12000>;
+ };
+ };
+
+ CPU6: cpu@102 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x102>;
+ qcom,limits-info = <&mitigation_profile6>;
+ qcom,lmh-dcvs = <&lmh_dcvs1>;
+ enable-method = "psci";
+ efficiency = <1536>;
+ next-level-cache = <&L2_1>;
+ qcom,ea = <&ea6>;
+ L1_I_102: l1-icache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x12000>;
+ };
+ L1_D_102: l1-dcache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x12000>;
+ };
+ };
+
+ CPU7: cpu@103 {
+ device_type = "cpu";
+ compatible = "arm,armv8";
+ reg = <0x0 0x103>;
+ qcom,limits-info = <&mitigation_profile7>;
+ qcom,lmh-dcvs = <&lmh_dcvs1>;
+ enable-method = "psci";
+ efficiency = <1536>;
+ next-level-cache = <&L2_1>;
+ qcom,ea = <&ea7>;
+ L1_I_103: l1-icache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x12000>;
+ };
+ L1_D_103: l1-dcache {
+ compatible = "arm,arch-cache";
+ qcom,dump-size = <0x12000>;
+ };
+ };
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&CPU0>;
+ };
+
+ core1 {
+ cpu = <&CPU1>;
+ };
+
+ core2 {
+ cpu = <&CPU2>;
+ };
+
+ core3 {
+ cpu = <&CPU3>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&CPU4>;
+ };
+
+ core1 {
+ cpu = <&CPU5>;
+ };
+
+ core2 {
+ cpu = <&CPU6>;
+ };
+
+ core3 {
+ cpu = <&CPU7>;
+ };
+ };
+ };
+ };
+
+ soc: soc { };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ removed_regions: removed_regions@85800000 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0 0x85800000 0 0x3700000>;
+ };
+
+ pil_slpi_mem: pil_slpi_region@93800000 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0 0x93800000 0 0xf00000>;
+ };
+
+ pil_video_mem: pil_video_region@93300000 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0 0x93300000 0 0x500000>;
+ };
+
+ pil_adsp_mem: pil_adsp_region@91900000 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0 0x91900000 0 0x1a00000>;
+ };
+
+ modem_mem: modem_region@8ac00000 {
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0 0x8ac00000 0 0x6d00000>;
+ };
+
+ spss_mem: spss_region@8ab00000 { /* for SPSS-PIL */
+ compatible = "removed-dma-pool";
+ no-map;
+ reg = <0 0x8ab00000 0 0x100000>;
+ };
+
+ adsp_mem: adsp_region {
+ compatible = "shared-dma-pool";
+ alloc-ranges = <0 0x00000000 0 0xffffffff>;
+ reusable;
+ alignment = <0 0x400000>;
+ size = <0 0x800000>;
+ };
+
+ qseecom_mem: qseecom_region {
+ compatible = "shared-dma-pool";
+ alloc-ranges = <0 0x00000000 0 0xffffffff>;
+ reusable;
+ alignment = <0 0x400000>;
+ size = <0 0x1400000>;
+ };
+
+ sp_mem: sp_region { /* SPSS-HLOS ION shared mem */
+ compatible = "shared-dma-pool";
+ alloc-ranges = <0 0x00000000 0 0xffffffff>; /* 32-bit */
+ reusable;
+ alignment = <0 0x100000>;
+ size = <0 0x800000>;
+ };
+
+ secure_display_memory: secure_region {
+ compatible = "shared-dma-pool";
+ alloc-ranges = <0 0x00000000 0 0xffffffff>;
+ reusable;
+ alignment = <0 0x200000>;
+ size = <0 0x5c00000>;
+ };
+
+ /* global autoconfigured region for contiguous allocations */
+ linux,cma {
+ compatible = "shared-dma-pool";
+ alloc-ranges = <0 0x00000000 0 0xffffffff>;
+ reusable;
+ alignment = <0 0x400000>;
+ size = <0 0x2000000>;
+ linux,cma-default;
+ };
+
+ cont_splash_mem: splash_region@9d600000 {
+ reg = <0x0 0x9d600000 0x0 0x02400000>;
+ label = "cont_splash_mem";
+ };
+ };
+};
+
+#include "msmcobalt-smp2p.dtsi"
+#include "msm-gdsc-cobalt.dtsi"
+
+&soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0 0xffffffff>;
+ compatible = "simple-bus";
+
+ intc: interrupt-controller@17a00000 {
+ compatible = "arm,gic-v3";
+ reg = <0x17a00000 0x10000>, /* GICD */
+ <0x17b00000 0x100000>; /* GICR * 8 */
+ #interrupt-cells = <3>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ interrupt-controller;
+ #redistributor-regions = <1>;
+ redistributor-stride = <0x0 0x20000>;
+ interrupts = <1 9 4>;
+
+ gic-its@0x17a20000{
+ compatible = "arm,gic-v3-its";
+ msi-contoller;
+ reg = <0x17a20000 0x20000>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <1 1 0xf08>,
+ <1 2 0xf08>,
+ <1 3 0xf08>,
+ <1 0 0xf08>;
+ clock-frequency = <19200000>;
+ };
+
+ restart@10ac000 {
+ compatible = "qcom,pshold";
+ reg = <0x10ac000 0x4>,
+ <0x1fd3000 0x4>;
+ reg-names = "pshold-base", "tcsr-boot-misc-detect";
+ };
+
+ spmi_bus: qcom,spmi@800f000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0x800f000 0x1000>,
+ <0x8400000 0x1000000>,
+ <0x9400000 0x1000000>,
+ <0xa400000 0x220000>,
+ <0x800a000 0x3000>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupt-names = "periph_irq";
+ interrupts = <GIC_SPI 326 IRQ_TYPE_NONE>;
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ cell-index = <0>;
+ };
+
+ qcom,sps {
+ compatible = "qcom,msm_sps_4k";
+ qcom,device-type = <3>;
+ qcom,pipe-attr-ee;
+ };
+
+ uartblsp1dm1: serial@0c170000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0xc170000 0x1000>;
+ interrupts = <0 108 0>;
+ status = "disabled";
+ clocks = <&clock_gcc clk_gcc_blsp1_uart2_apps_clk>,
+ <&clock_gcc clk_gcc_blsp1_ahb_clk>;
+ clock-names = "core", "iface";
+ };
+
+ uartblsp2dm1: serial@0c1b0000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0xc1b0000 0x1000>;
+ interrupts = <0 114 0>;
+ status = "disabled";
+ clocks = <&clock_gcc clk_gcc_blsp2_uart2_apps_clk>,
+ <&clock_gcc clk_gcc_blsp2_ahb_clk>;
+ clock-names = "core", "iface";
+ };
+
+ slim_aud: slim@171c0000 {
+ cell-index = <1>;
+ compatible = "qcom,slim-ngd";
+ reg = <0x171c0000 0x2C000>,
+ <0x17184000 0x32000>;
+ reg-names = "slimbus_physical", "slimbus_bam_physical";
+ interrupts = <0 163 0>, <0 164 0>;
+ interrupt-names = "slimbus_irq", "slimbus_bam_irq";
+ qcom,apps-ch-pipes = <0x00001f80>;
+ qcom,ea-pc = <0x210>;
+ };
+
+ slim_qca: slim@17240000 {
+ status = "ok";
+ cell-index = <3>;
+ compatible = "qcom,slim-ngd";
+ reg = <0x17240000 0x2C000>,
+ <0x17204000 0x26000>;
+ reg-names = "slimbus_physical", "slimbus_bam_physical";
+ interrupts = <0 291 0>, <0 292 0>;
+ interrupt-names = "slimbus_irq", "slimbus_bam_irq";
+
+ /* Slimbus Slave DT for WCN3990 */
+ btfmslim_codec: wcn3990 {
+ compatible = "qcom,btfmslim_slave";
+ elemental-addr = [00 01 20 02 17 02];
+ qcom,btfm-slim-ifd = "btfmslim_slave_ifd";
+ qcom,btfm-slim-ifd-elemental-addr = [00 00 20 02 17 02];
+ };
+ };
+
+ timer@17920000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ compatible = "arm,armv7-timer-mem";
+ reg = <0x17920000 0x1000>;
+ clock-frequency = <19200000>;
+
+ frame@17921000 {
+ frame-number = <0>;
+ interrupts = <0 8 0x4>,
+ <0 7 0x4>;
+ reg = <0x17921000 0x1000>,
+ <0x17922000 0x1000>;
+ };
+
+ frame@17923000 {
+ frame-number = <1>;
+ interrupts = <0 9 0x4>;
+ reg = <0x17923000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17924000 {
+ frame-number = <2>;
+ interrupts = <0 10 0x4>;
+ reg = <0x17924000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17925000 {
+ frame-number = <3>;
+ interrupts = <0 11 0x4>;
+ reg = <0x17925000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17926000 {
+ frame-number = <4>;
+ interrupts = <0 12 0x4>;
+ reg = <0x17926000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17927000 {
+ frame-number = <5>;
+ interrupts = <0 13 0x4>;
+ reg = <0x17927000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17928000 {
+ frame-number = <6>;
+ interrupts = <0 14 0x4>;
+ reg = <0x17928000 0x1000>;
+ status = "disabled";
+ };
+ };
+
+ cpubw: qcom,cpubw {
+ compatible = "qcom,devbw";
+ governor = "performance";
+ qcom,src-dst-ports = <1 512>;
+ qcom,active-only;
+ qcom,bw-tbl =
+ < 762 /* 100 MHz */ >,
+ < 1144 /* 150 MHz */ >,
+ < 1525 /* 200 MHz */ >,
+ < 2288 /* 300 MHz */ >,
+ < 3143 /* 412 MHz */ >,
+ < 4173 /* 547 MHz */ >,
+ < 5195 /* 681 MHz */ >,
+ < 5859 /* 768 MHz */ >,
+ < 7759 /* 1017 MHz */ >,
+ < 9887 /* 1296 MHz */ >,
+ < 11863 /* 1555 MHz */ >,
+ < 13763 /* 1804 MHz */ >;
+ };
+
+ bwmon: qcom,cpu-bwmon {
+ compatible = "qcom,bimc-bwmon3";
+ reg = <0x01008000 0x300>, <0x01001000 0x200>;
+ reg-names = "base", "global_base";
+ interrupts = <0 183 4>;
+ qcom,mport = <0>;
+ qcom,target-dev = <&cpubw>;
+ };
+
+ mincpubw: qcom,mincpubw {
+ compatible = "qcom,devbw";
+ governor = "powersave";
+ qcom,src-dst-ports = <1 512>;
+ qcom,active-only;
+ qcom,bw-tbl =
+ < 762 /* 100 MHz */ >,
+ < 1144 /* 150 MHz */ >,
+ < 1525 /* 200 MHz */ >,
+ < 2288 /* 300 MHz */ >,
+ < 3143 /* 412 MHz */ >,
+ < 4173 /* 547 MHz */ >,
+ < 5195 /* 681 MHz */ >,
+ < 5859 /* 768 MHz */ >,
+ < 7759 /* 1017 MHz */ >,
+ < 9887 /* 1296 MHz */ >,
+ < 11863 /* 1555 MHz */ >,
+ < 13763 /* 1804 MHz */ >;
+ };
+
+ memlat_cpu0: qcom,memlat-cpu0 {
+ compatible = "qcom,devbw";
+ governor = "powersave";
+ qcom,src-dst-ports = <1 512>;
+ qcom,active-only;
+ qcom,bw-tbl =
+ < 762 /* 100 MHz */ >,
+ < 1144 /* 150 MHz */ >,
+ < 1525 /* 200 MHz */ >,
+ < 2288 /* 300 MHz */ >,
+ < 3143 /* 412 MHz */ >,
+ < 4173 /* 547 MHz */ >,
+ < 5195 /* 681 MHz */ >,
+ < 5859 /* 768 MHz */ >,
+ < 7759 /* 1017 MHz */ >,
+ < 9887 /* 1296 MHz */ >,
+ < 11863 /* 1555 MHz */ >,
+ < 13763 /* 1804 MHz */ >;
+ };
+
+ memlat_cpu4: qcom,memlat-cpu4 {
+ compatible = "qcom,devbw";
+ governor = "powersave";
+ qcom,src-dst-ports = <1 512>;
+ qcom,active-only;
+ status = "ok";
+ qcom,bw-tbl =
+ < 762 /* 100 MHz */ >,
+ < 1144 /* 150 MHz */ >,
+ < 1525 /* 200 MHz */ >,
+ < 2288 /* 300 MHz */ >,
+ < 3143 /* 412 MHz */ >,
+ < 4173 /* 547 MHz */ >,
+ < 5195 /* 681 MHz */ >,
+ < 5859 /* 768 MHz */ >,
+ < 7759 /* 1017 MHz */ >,
+ < 9887 /* 1296 MHz */ >,
+ < 11863 /* 1555 MHz */ >,
+ < 13763 /* 1804 MHz */ >;
+ };
+
+ qcom,arm-memlat-mon-0 {
+ compatible = "qcom,arm-memlat-mon";
+ qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>;
+ qcom,target-dev = <&memlat_cpu0>;
+ qcom,core-dev-table =
+ < 300000 1525 >,
+ < 499200 3143 >,
+ < 1113600 4173 >,
+ < 1881600 5859 >;
+ };
+
+ qcom,arm-memlat-mon-4 {
+ compatible = "qcom,arm-memlat-mon";
+ qcom,cpulist = <&CPU4 &CPU5 &CPU6 &CPU7>;
+ qcom,target-dev = <&memlat_cpu4>;
+ qcom,core-dev-table =
+ < 300000 1525 >,
+ < 480000 3143 >,
+ < 900000 4173 >,
+ < 1017000 7759 >,
+ < 1296000 9887 >,
+ < 1555000 11863 >,
+ < 1804000 13763 >;
+ };
+
+ devfreq_cpufreq: devfreq-cpufreq {
+ mincpubw-cpufreq {
+ target-dev = <&mincpubw>;
+ cpu-to-dev-map-0 =
+ < 1881600 1525 >;
+ cpu-to-dev-map-4 =
+ < 2016000 1525 >,
+ < 2092800 5195 >;
+ };
+ };
+
+ msm_cpufreq: qcom,msm-cpufreq {
+ compatible = "qcom,msm-cpufreq";
+ clock-names = "cpu0_clk", "cpu1_clk", "cpu2_clk",
+ "cpu3_clk", "cpu4_clk", "cpu5_clk",
+ "cpu6_clk", "cpu7_clk";
+ clocks = <&clock_cpu clk_pwrcl_clk>,
+ <&clock_cpu clk_pwrcl_clk>,
+ <&clock_cpu clk_pwrcl_clk>,
+ <&clock_cpu clk_pwrcl_clk>,
+ <&clock_cpu clk_perfcl_clk>,
+ <&clock_cpu clk_perfcl_clk>,
+ <&clock_cpu clk_perfcl_clk>,
+ <&clock_cpu clk_perfcl_clk>;
+
+ qcom,governor-per-policy;
+
+ qcom,cpufreq-table-0 =
+ < 300000 >,
+ < 345600 >,
+ < 422400 >,
+ < 499200 >,
+ < 576000 >,
+ < 633600 >,
+ < 710400 >,
+ < 806400 >,
+ < 883200 >,
+ < 960000 >,
+ < 1036800 >,
+ < 1113600 >,
+ < 1190400 >,
+ < 1248000 >,
+ < 1324800 >,
+ < 1401600 >,
+ < 1478400 >,
+ < 1574400 >,
+ < 1651200 >,
+ < 1728000 >,
+ < 1804800 >,
+ < 1881600 >;
+
+ qcom,cpufreq-table-4 =
+ < 300000 >,
+ < 345600 >,
+ < 422400 >,
+ < 480000 >,
+ < 556800 >,
+ < 633600 >,
+ < 710400 >,
+ < 787200 >,
+ < 844800 >,
+ < 902400 >,
+ < 979200 >,
+ < 1056000 >,
+ < 1171200 >,
+ < 1248000 >,
+ < 1324800 >,
+ < 1401600 >,
+ < 1478400 >,
+ < 1536000 >,
+ < 1632000 >,
+ < 1708800 >,
+ < 1785600 >,
+ < 1862400 >,
+ < 1939200 >,
+ < 2016000 >,
+ < 2092800 >;
+ };
+
+ arm64-cpu-erp {
+ compatible = "arm,arm64-cpu-erp";
+ interrupts = <0 43 4>,
+ <0 44 4>,
+ <0 41 4>,
+ <0 42 4>;
+
+ interrupt-names = "pri-dbe-irq",
+ "sec-dbe-irq",
+ "pri-ext-irq",
+ "sec-ext-irq";
+
+ poll-delay-ms = <5000>;
+ };
+
+ clock_gcc: qcom,gcc@100000 {
+ compatible = "qcom,gcc-cobalt";
+ reg = <0x100000 0xb0000>;
+ reg-names = "cc_base";
+ vdd_dig-supply = <&pmcobalt_s1_level>;
+ vdd_dig_ao-supply = <&pmcobalt_s1_level_ao>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ clock_mmss: qcom,mmsscc@c8c0000 {
+ compatible = "qcom,mmsscc-cobalt";
+ reg = <0xc8c0000 0x40000>;
+ reg-names = "cc_base";
+ vdd_dig-supply = <&pmcobalt_s1_level>;
+ vdd_mmsscc_mx-supply = <&pmcobalt_s9_level>;
+ clock-names = "xo", "gpll0", "gpll0_div",
+ "pclk0_src", "pclk1_src",
+ "byte0_src", "byte1_src",
+ "dp_link_src", "dp_vco_div",
+ "extpclk_src";
+ clocks = <&clock_gcc clk_cxo_clk_src>,
+ <&clock_gcc clk_gcc_mmss_gpll0_clk>,
+ <&clock_gcc clk_gcc_mmss_gpll0_div_clk>,
+ <&mdss_dsi0_pll clk_dsi0pll_pclk_mux>,
+ <&mdss_dsi1_pll clk_dsi1pll_pclk_mux>,
+ <&mdss_dsi0_pll clk_dsi0pll_byteclk_mux>,
+ <&mdss_dsi1_pll clk_dsi1pll_byteclk_mux>,
+ <&mdss_dp_pll clk_dp_link_2x_clk_divsel_five>,
+ <&mdss_dp_pll clk_vco_divided_clk_src_mux>,
+ <&mdss_hdmi_pll clk_hdmi_vco_clk>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ clock_gpu: qcom,gpucc@5065000 {
+ compatible = "qcom,gpucc-cobalt";
+ reg = <0x5065000 0x9000>;
+ reg-names = "cc_base";
+ vdd_dig-supply = <&pmcobalt_s1_level>;
+ clock-names = "xo_ao", "gpll0";
+ clocks = <&clock_gcc clk_cxo_clk_src_ao>,
+ <&clock_gcc clk_gcc_gpu_gpll0_clk>;
+ #clock-cells = <1>;
+ };
+
+ clock_gfx: qcom,gfxcc@5065000 {
+ compatible = "qcom,gfxcc-cobalt";
+ reg = <0x5065000 0x9000>;
+ reg-names = "cc_base";
+ vdd_gpucc-supply = <&gfx_vreg>;
+ vdd_mx-supply = <&pmcobalt_s9_level>;
+ vdd_gpu_mx-supply = <&pmcobalt_s9_level>;
+ qcom,gfx3d_clk_src-opp-handle = <&msm_gpu>;
+ qcom,gfxfreq-speedbin0 =
+ < 0 0 0 >,
+ < 171000000 1 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 251000000 2 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 332000000 3 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 403000000 4 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 504000000 5 RPM_SMD_REGULATOR_LEVEL_NOM >,
+ < 650000000 6 RPM_SMD_REGULATOR_LEVEL_TURBO >;
+ qcom,gfxfreq-mx-speedbin0 =
+ < 0 0 >,
+ < 171000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 251000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 332000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 403000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 504000000 RPM_SMD_REGULATOR_LEVEL_NOM >,
+ < 650000000 RPM_SMD_REGULATOR_LEVEL_TURBO >;
+ #clock-cells = <1>;
+ };
+
+ clock_cpu: qcom,cpu-clock-cobalt@179c0000 {
+ compatible = "qcom,cpu-clock-osm-msmcobalt-v1";
+ reg = <0x179c0000 0x4000>,
+ <0x17916000 0x1000>,
+ <0x17816000 0x1000>,
+ <0x179d1000 0x1000>,
+ <0x00784130 0x8>,
+ <0x1791101c 0x8>;
+ reg-names = "osm", "pwrcl_pll", "perfcl_pll",
+ "apcs_common", "perfcl_efuse", "debug";
+
+ vdd-pwrcl-supply = <&apc0_pwrcl_vreg>;
+ vdd-perfcl-supply = <&apc1_perfcl_vreg>;
+
+ interrupts = <GIC_SPI 35 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 36 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "pwrcl-irq", "perfcl-irq";
+
+ qcom,pwrcl-speedbin0-v0 =
+ < 300000000 0x0004000f 0x01200020 0x1 1 >,
+ < 345600000 0x05040012 0x02200020 0x1 2 >,
+ < 422400000 0x05040016 0x02200020 0x1 3 >,
+ < 499200000 0x0504001a 0x02200020 0x1 4 >,
+ < 576000000 0x0504001e 0x03200020 0x1 5 >,
+ < 633600000 0x05040021 0x03200020 0x1 6 >,
+ < 710400000 0x05040025 0x03200020 0x1 7 >,
+ < 806400000 0x0504002a 0x04200020 0x1 8 >,
+ < 883200000 0x0404002e 0x04250025 0x1 9 >,
+ < 960000000 0x04040032 0x05280028 0x1 10 >,
+ < 1036800000 0x04040036 0x052b002b 0x2 11 >,
+ < 1113600000 0x0404003a 0x052e002e 0x2 12 >,
+ < 1190400000 0x0404003e 0x06320032 0x2 13 >,
+ < 1248000000 0x04040041 0x06340034 0x2 14 >,
+ < 1324800000 0x04040045 0x06370037 0x2 15 >,
+ < 1401600000 0x04040049 0x073a003a 0x2 16 >,
+ < 1478400000 0x0404004d 0x073e003e 0x2 17 >,
+ < 1574400000 0x04040052 0x08420042 0x2 18 >,
+ < 1651200000 0x04040056 0x08450045 0x2 19 >,
+ < 1728000000 0x0404005a 0x08480048 0x2 20 >,
+ < 1804800000 0x0404005e 0x094b004b 0x3 21 >,
+ < 1881600000 0x04040062 0x094e004e 0x3 22 >;
+
+ qcom,perfcl-speedbin0-v0 =
+ < 300000000 0x0004000f 0x01200020 0x1 1 >,
+ < 345600000 0x05040012 0x02200020 0x1 2 >,
+ < 422400000 0x05040016 0x02200020 0x1 3 >,
+ < 480000000 0x05040019 0x02200020 0x1 4 >,
+ < 556800000 0x0504001d 0x03200020 0x1 5 >,
+ < 633600000 0x05040021 0x03200020 0x1 6 >,
+ < 710400000 0x05040025 0x03200020 0x1 7 >,
+ < 787200000 0x05040029 0x04200020 0x1 8 >,
+ < 844800000 0x0404002c 0x04230023 0x1 9 >,
+ < 902400000 0x0404002f 0x04260026 0x1 10 >,
+ < 979200000 0x04040033 0x05290029 0x1 11 >,
+ < 1056000000 0x04040037 0x052c002c 0x1 12 >,
+ < 1171200000 0x0404003d 0x06310031 0x2 13 >,
+ < 1248000000 0x04040041 0x06340034 0x2 14 >,
+ < 1324800000 0x04040045 0x06370037 0x2 15 >,
+ < 1401600000 0x04040049 0x073a003a 0x2 16 >,
+ < 1478400000 0x0404004d 0x073e003e 0x2 17 >,
+ < 1536000000 0x04040050 0x07400040 0x2 18 >,
+ < 1632000000 0x04040055 0x08440044 0x2 19 >,
+ < 1708800000 0x04040059 0x08470047 0x2 20 >,
+ < 1785600000 0x0404005d 0x094a004a 0x2 21 >,
+ < 1862400000 0x04040061 0x094e004e 0x2 22 >,
+ < 1939200000 0x04040065 0x09510051 0x3 23 >,
+ < 2016000000 0x04040069 0x0a540054 0x3 24 >,
+ < 2092800000 0x0404006d 0x0a570057 0x3 25 >;
+
+ qcom,up-timer =
+ <1000 1000>;
+ qcom,down-timer =
+ <1000 1000>;
+ qcom,pc-override-index =
+ <0 0>;
+ qcom,set-ret-inactive;
+ qcom,enable-llm-freq-vote;
+ qcom,llm-freq-up-timer =
+ <327675 327675>;
+ qcom,llm-freq-down-timer =
+ <327675 327675>;
+ qcom,enable-llm-volt-vote;
+ qcom,llm-volt-up-timer =
+ <327675 327675>;
+ qcom,llm-volt-down-timer =
+ <327675 327675>;
+ qcom,cc-reads = <10>;
+ qcom,cc-delay = <5>;
+ qcom,cc-factor = <100>;
+ qcom,osm-clk-rate = <200000000>;
+ qcom,xo-clk-rate = <19200000>;
+
+ qcom,l-val-base =
+ <0x17916004 0x17816004>;
+ qcom,apcs-itm-present =
+ <0x179d143c 0x179d143c>;
+ qcom,apcs-pll-user-ctl =
+ <0x1791600c 0x1781600c>;
+ qcom,apcs-cfg-rcgr =
+ <0x17911054 0x17811054>;
+ qcom,apcs-cmd-rcgr =
+ <0x17911050 0x17811050>;
+ qcom,apm-mode-ctl =
+ <0x179d0004 0x179d0010>;
+ qcom,apm-ctrl-status =
+ <0x179d000c 0x179d0018>;
+ qcom,llm-sw-overr=
+ <0x8fff0036 0x8fff003a 0x0fff0036>,
+ <0x8fff003d 0x8fff0041 0x0fff003d>;
+
+ qcom,apm-threshold-voltage = <832000>;
+ qcom,boost-fsm-en;
+ qcom,safe-fsm-en;
+ qcom,ps-fsm-en;
+ qcom,droop-fsm-en;
+ qcom,wfx-fsm-en;
+ qcom,pc-fsm-en;
+
+ qcom,pwrcl-apcs-mem-acc-cfg =
+ <0x179d1360 0x179d1364 0x179d1364>;
+ qcom,perfcl-apcs-mem-acc-cfg =
+ <0x179d1368 0x179d136C 0x179d1370>;
+ qcom,pwrcl-apcs-mem-acc-val =
+ <0x00000000 0x80000000 0x80000000>,
+ <0x00000000 0x00000000 0x00000000>,
+ <0x00000000 0x00000001 0x00000001>;
+ qcom,perfcl-apcs-mem-acc-val =
+ <0x00000000 0x00000000 0x80000000>,
+ <0x00000000 0x00000000 0x00000000>,
+ <0x00000000 0x00000000 0x00000001>;
+
+ clock-names = "aux_clk", "xo_ao";
+ clocks = <&clock_gcc clk_hmss_gpll0_clk_src>,
+ <&clock_gcc clk_cxo_clk_src_ao>;
+ #clock-cells = <1>;
+ };
+
+ clock_debug: qcom,debugcc@162000 {
+ compatible = "qcom,cc-debug-cobalt";
+ reg = <0x162000 0x4>;
+ reg-names = "cc_base";
+ clock-names = "debug_gpu_clk", "debug_gfx_clk",
+ "debug_mmss_clk", "debug_cpu_clk";
+ clocks = <&clock_gpu clk_gpucc_gcc_dbg_clk>,
+ <&clock_gfx clk_gfxcc_dbg_clk>,
+ <&clock_mmss clk_mmss_debug_mux>,
+ <&clock_cpu clk_cpu_debug_mux>;
+ #clock-cells = <1>;
+ };
+
+ qcom,rmtfs_sharedmem@0 {
+ compatible = "qcom,sharedmem-uio";
+ reg = <0x0 0x00200000>;
+ reg-names = "rmtfs";
+ qcom,client-id = <0x00000001>;
+ };
+
+ qcom,msm_gsi {
+ compatible = "qcom,msm_gsi";
+ };
+
+ qcom,rmnet-ipa {
+ compatible = "qcom,rmnet-ipa3";
+ qcom,rmnet-ipa-ssr;
+ qcom,ipa-loaduC;
+ qcom,ipa-advertise-sg-support;
+ };
+
+ ipa_hw: qcom,ipa@01e00000 {
+ compatible = "qcom,ipa";
+ reg = <0x01e00000 0x34000>,
+ <0x01e84000 0x31fff>,
+ <0x01e04000 0x2c000>;
+ reg-names = "ipa-base", "bam-base", "gsi-base";
+ interrupts =
+ <0 333 0>,
+ <0 432 0>,
+ <0 432 0>;
+ interrupt-names = "ipa-irq", "bam-irq", "gsi-irq";
+ qcom,ipa-hw-ver = <11>; /* IPA core version = IPAv3.1 */
+ qcom,ipa-hw-mode = <0>; /* IPA hw type = Normal */
+ qcom,ee = <0>;
+ qcom,use-gsi;
+ qcom,use-ipa-tethering-bridge;
+ qcom,modem-cfg-emb-pipe-flt;
+ qcom,do-not-use-ch-gsi-20;
+ qcom,ipa-wdi2;
+ qcom,use-64-bit-dma-mask;
+ clocks = <&clock_gcc clk_ipa_clk>;
+ clock-names = "core_clk";
+ qcom,arm-smmu;
+ qcom,smmu-disable-htw;
+ qcom,smmu-s1-bypass;
+ qcom,msm-bus,name = "ipa";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,num-paths = <4>;
+ qcom,msm-bus,vectors-KBps =
+ /* No vote */
+ <90 512 0 0>,
+ <90 585 0 0>,
+ <1 676 0 0>,
+ /* SMMU smmu_aggre2_noc_clk */
+ <81 10065 0 0>,
+ /* SVS */
+ <90 512 80000 640000>,
+ <90 585 80000 640000>,
+ <1 676 80000 80000>,
+ /* SMMU smmu_aggre2_noc_clk */
+ <81 10065 0 16000>,
+ /* NOMINAL */
+ <90 512 206000 960000>,
+ <90 585 206000 960000>,
+ <1 676 206000 160000>,
+ /* SMMU smmu_aggre2_noc_clk */
+ <81 10065 0 16000>,
+ /* TURBO */
+ <90 512 206000 3600000>,
+ <90 585 206000 3600000>,
+ <1 676 206000 300000>,
+ /* SMMU smmu_aggre2_noc_clk */
+ <81 10065 0 16000>;
+ qcom,bus-vector-names = "MIN", "SVS", "NOMINAL", "TURBO";
+
+ /* IPA RAM mmap */
+ qcom,ipa-ram-mmap = <
+ 0x280 /* ofst_start; */
+ 0x0 /* nat_ofst; */
+ 0x0 /* nat_size; */
+ 0x288 /* v4_flt_hash_ofst; */
+ 0x78 /* v4_flt_hash_size; */
+ 0x4000 /* v4_flt_hash_size_ddr; */
+ 0x308 /* v4_flt_nhash_ofst; */
+ 0x78 /* v4_flt_nhash_size; */
+ 0x4000 /* v4_flt_nhash_size_ddr; */
+ 0x388 /* v6_flt_hash_ofst; */
+ 0x78 /* v6_flt_hash_size; */
+ 0x4000 /* v6_flt_hash_size_ddr; */
+ 0x408 /* v6_flt_nhash_ofst; */
+ 0x78 /* v6_flt_nhash_size; */
+ 0x4000 /* v6_flt_nhash_size_ddr; */
+ 0xf /* v4_rt_num_index; */
+ 0x0 /* v4_modem_rt_index_lo; */
+ 0x7 /* v4_modem_rt_index_hi; */
+ 0x8 /* v4_apps_rt_index_lo; */
+ 0xe /* v4_apps_rt_index_hi; */
+ 0x488 /* v4_rt_hash_ofst; */
+ 0x78 /* v4_rt_hash_size; */
+ 0x4000 /* v4_rt_hash_size_ddr; */
+ 0x508 /* v4_rt_nhash_ofst; */
+ 0x78 /* v4_rt_nhash_size; */
+ 0x4000 /* v4_rt_nhash_size_ddr; */
+ 0xf /* v6_rt_num_index; */
+ 0x0 /* v6_modem_rt_index_lo; */
+ 0x7 /* v6_modem_rt_index_hi; */
+ 0x8 /* v6_apps_rt_index_lo; */
+ 0xe /* v6_apps_rt_index_hi; */
+ 0x588 /* v6_rt_hash_ofst; */
+ 0x78 /* v6_rt_hash_size; */
+ 0x4000 /* v6_rt_hash_size_ddr; */
+ 0x608 /* v6_rt_nhash_ofst; */
+ 0x78 /* v6_rt_nhash_size; */
+ 0x4000 /* v6_rt_nhash_size_ddr; */
+ 0x688 /* modem_hdr_ofst; */
+ 0x140 /* modem_hdr_size; */
+ 0x7c8 /* apps_hdr_ofst; */
+ 0x0 /* apps_hdr_size; */
+ 0x800 /* apps_hdr_size_ddr; */
+ 0x7d0 /* modem_hdr_proc_ctx_ofst; */
+ 0x200 /* modem_hdr_proc_ctx_size; */
+ 0x9d0 /* apps_hdr_proc_ctx_ofst; */
+ 0x200 /* apps_hdr_proc_ctx_size; */
+ 0x0 /* apps_hdr_proc_ctx_size_ddr; */
+ 0x0 /* modem_comp_decomp_ofst; diff */
+ 0x0 /* modem_comp_decomp_size; diff */
+ 0xbd8 /* modem_ofst; */
+ 0x1424 /* modem_size; */
+ 0x1ffc /* apps_v4_flt_hash_ofst; */
+ 0x0 /* apps_v4_flt_hash_size; */
+ 0x1ffc /* apps_v4_flt_nhash_ofst; */
+ 0x0 /* apps_v4_flt_nhash_size; */
+ 0x1ffc /* apps_v6_flt_hash_ofst; */
+ 0x0 /* apps_v6_flt_hash_size; */
+ 0x1ffc /* apps_v6_flt_nhash_ofst; */
+ 0x0 /* apps_v6_flt_nhash_size; */
+ 0x80 /* uc_info_ofst; */
+ 0x200 /* uc_info_size; */
+ 0x2000 /* end_ofst; */
+ 0x1ffc /* apps_v4_rt_hash_ofst; */
+ 0x0 /* apps_v4_rt_hash_size; */
+ 0x1ffc /* apps_v4_rt_nhash_ofst; */
+ 0x0 /* apps_v4_rt_nhash_size; */
+ 0x1ffc /* apps_v6_rt_hash_ofst; */
+ 0x0 /* apps_v6_rt_hash_size; */
+ 0x1ffc /* apps_v6_rt_nhash_ofst; */
+ 0x0 /* apps_v6_rt_nhash_size; */
+ >;
+
+ /* smp2p gpio information */
+ qcom,smp2pgpio_map_ipa_1_out {
+ compatible = "qcom,smp2pgpio-map-ipa-1-out";
+ gpios = <&smp2pgpio_ipa_1_out 0 0>;
+ };
+
+ qcom,smp2pgpio_map_ipa_1_in {
+ compatible = "qcom,smp2pgpio-map-ipa-1-in";
+ gpios = <&smp2pgpio_ipa_1_in 0 0>;
+ };
+
+ ipa_smmu_ap: ipa_smmu_ap {
+ compatible = "qcom,ipa-smmu-ap-cb";
+ iommus = <&anoc2_smmu 0x18e0>;
+ qcom,iova-mapping = <0x10000000 0x40000000>;
+ };
+
+ ipa_smmu_wlan: ipa_smmu_wlan {
+ compatible = "qcom,ipa-smmu-wlan-cb";
+ iommus = <&anoc2_smmu 0x18e1>;
+ };
+
+ ipa_smmu_uc: ipa_smmu_uc {
+ compatible = "qcom,ipa-smmu-uc-cb";
+ iommus = <&anoc2_smmu 0x18e2>;
+ qcom,iova-mapping = <0x40000000 0x20000000>;
+ };
+ };
+
+ qcom,ipa_fws@1e08000 {
+ compatible = "qcom,pil-tz-generic";
+ qcom,pas-id = <0xF>;
+ qcom,firmware-name = "ipa_fws";
+ };
+
+ qcom,chd_silver {
+ compatible = "qcom,core-hang-detect";
+ label = "silver";
+ qcom,threshold-arr = <0x179880b0 0x179980b0
+ 0x179a80b0 0x179b80b0>;
+ qcom,config-arr = <0x179880b8 0x179980b8
+ 0x179a80b8 0x179b80b8>;
+ };
+
+ qcom,chd_gold {
+ compatible = "qcom,core-hang-detect";
+ label = "gold";
+ qcom,threshold-arr = <0x178880b0 0x178980b0
+ 0x178a80b0 0x178b80b0>;
+ qcom,config-arr = <0x178880b8 0x178980b8
+ 0x178a80b8 0x178b80b8>;
+ };
+
+ qcom,ipc-spinlock@1f40000 {
+ compatible = "qcom,ipc-spinlock-sfpb";
+ reg = <0x1f40000 0x8000>;
+ qcom,num-locks = <8>;
+ };
+
+ qcom,ghd {
+ compatible = "qcom,gladiator-hang-detect";
+ qcom,threshold-arr = <0x179d141c 0x179d1420
+ 0x179d1424 0x179d1428 0x179d142c 0x179d1430>;
+ qcom,config-reg = <0x179d1434>;
+ };
+
+ qcom,msm-gladiator-v2@17900000 {
+ compatible = "qcom,msm-gladiator-v2";
+ reg = <0x17900000 0xe000>;
+ reg-names = "gladiator_base";
+ interrupts = <0 22 0>;
+ clock-names = "atb_clk";
+ clocks = <&clock_gcc clk_qdss_clk>;
+ };
+
+ qcom,smem@86000000 {
+ compatible = "qcom,smem";
+ reg = <0x86000000 0x200000>,
+ <0x17911008 0x4>,
+ <0x778000 0x7000>,
+ <0x1fd4000 0x8>;
+ reg-names = "smem", "irq-reg-base", "aux-mem1",
+ "smem_targ_info_reg";
+ qcom,mpu-enabled;
+ };
+
+ qcom,msm-adsprpc-mem {
+ compatible = "qcom,msm-adsprpc-mem-region";
+ memory-region = <&adsp_mem>;
+ };
+
+ qcom,msm_fastrpc {
+ compatible = "qcom,msm-fastrpc-adsp";
+ qcom,fastrpc-glink;
+
+ qcom,msm_fastrpc_cpz_cb1 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&lpass_q6_smmu 2>;
+ qcom,secure-context-bank;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb1 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&lpass_q6_smmu 8>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb2 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&lpass_q6_smmu 9>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb3 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&lpass_q6_smmu 10>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb4 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&lpass_q6_smmu 11>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb6 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&lpass_q6_smmu 5>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb7 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&lpass_q6_smmu 6>;
+ dma-coherent;
+ };
+ qcom,msm_fastrpc_compute_cb8 {
+ compatible = "qcom,msm-fastrpc-compute-cb";
+ label = "adsprpc-smd";
+ iommus = <&lpass_q6_smmu 7>;
+ dma-coherent;
+ };
+ };
+
+ rpm_bus: qcom,rpm-smd {
+ compatible = "qcom,rpm-glink";
+ qcom,glink-edge = "rpm";
+ rpm-channel-name = "rpm_requests";
+ };
+
+ glink_mpss: qcom,glink-ssr-modem {
+ compatible = "qcom,glink_ssr";
+ label = "modem";
+ qcom,edge = "mpss";
+ qcom,notify-edges = <&glink_lpass>, <&glink_dsps>, <&glink_rpm>,
+ <&glink_spss>;
+ qcom,xprt = "smem";
+ };
+
+ glink_lpass: qcom,glink-ssr-adsp {
+ compatible = "qcom,glink_ssr";
+ label = "adsp";
+ qcom,edge = "lpass";
+ qcom,notify-edges = <&glink_mpss>, <&glink_dsps>, <&glink_rpm>,
+ <&glink_spss>;
+ qcom,xprt = "smem";
+ };
+
+ glink_dsps: qcom,glink-ssr-dsps {
+ compatible = "qcom,glink_ssr";
+ label = "slpi";
+ qcom,edge = "dsps";
+ qcom,notify-edges = <&glink_mpss>, <&glink_lpass>, <&glink_rpm>,
+ <&glink_spss>;
+ qcom,xprt = "smem";
+ };
+
+ glink_rpm: qcom,glink-ssr-rpm {
+ compatible = "qcom,glink_ssr";
+ label = "rpm";
+ qcom,edge = "rpm";
+ qcom,notify-edges = <&glink_lpass>, <&glink_mpss>,
+ <&glink_dsps>, <&glink_spss>;
+ qcom,xprt = "smem";
+ };
+
+ glink_spss: qcom,glink-ssr-spss {
+ compatible = "qcom,glink_ssr";
+ label = "spss";
+ qcom,edge = "spss";
+ qcom,notify-edges = <&glink_mpss>, <&glink_lpass>,
+ <&glink_dsps>, <&glink_rpm>;
+ qcom,xprt = "mailbox";
+ };
+
+ qcom,glink-smem-native-xprt-modem@86000000 {
+ compatible = "qcom,glink-smem-native-xprt";
+ reg = <0x86000000 0x200000>,
+ <0x17911008 0x4>;
+ reg-names = "smem", "irq-reg-base";
+ qcom,irq-mask = <0x8000>;
+ interrupts = <0 452 1>;
+ label = "mpss";
+ };
+
+ qcom,glink-smem-native-xprt-adsp@86000000 {
+ compatible = "qcom,glink-smem-native-xprt";
+ reg = <0x86000000 0x200000>,
+ <0x17911008 0x4>;
+ reg-names = "smem", "irq-reg-base";
+ qcom,irq-mask = <0x200>;
+ interrupts = <0 157 1>;
+ label = "lpass";
+ };
+
+ qcom,glink-smem-native-xprt-dsps@86000000 {
+ compatible = "qcom,glink-smem-native-xprt";
+ reg = <0x86000000 0x200000>,
+ <0x17911008 0x4>;
+ reg-names = "smem", "irq-reg-base";
+ qcom,irq-mask = <0x8000000>;
+ interrupts = <0 179 1>;
+ label = "dsps";
+ };
+
+ qcom,glink-smem-native-xprt-rpm@778000 {
+ compatible = "qcom,glink-rpm-native-xprt";
+ reg = <0x778000 0x7000>,
+ <0x17911008 0x4>;
+ reg-names = "msgram", "irq-reg-base";
+ qcom,irq-mask = <0x1>;
+ interrupts = <0 168 1>;
+ label = "rpm";
+ };
+
+ qcom,glink-mailbox-xprt-spss@1d05008 {
+ compatible = "qcom,glink-mailbox-xprt";
+ reg = <0x1d05008 0x8>,
+ <0x1d05010 0x4>,
+ <0x1d0501c 0x4>,
+ <0x1d06008 0x4>;
+ reg-names = "mbox-loc-addr", "mbox-loc-size", "irq-reg-base",
+ "irq-rx-reset";
+ qcom,irq-mask = <0x1>;
+ interrupts = <0 348 4>;
+ label = "spss";
+ qcom,tx-ring-size = <0x800>;
+ qcom,rx-ring-size = <0x800>;
+ };
+
+ glink_spi_xprt_wdsp: qcom,glink-spi-xprt-wdsp {
+ compatible = "qcom,glink-spi-xprt";
+ label = "wdsp";
+ qcom,remote-fifo-config = <&glink_fifo_wdsp>;
+ qcom,qos-config = <&glink_qos_wdsp>;
+ qcom,ramp-time = <0x10>,
+ <0x20>,
+ <0x30>,
+ <0x40>;
+ };
+
+ glink_fifo_wdsp: qcom,glink-fifo-config-wdsp {
+ compatible = "qcom,glink-fifo-config";
+ qcom,out-read-idx-reg = <0x12000>;
+ qcom,out-write-idx-reg = <0x12004>;
+ qcom,in-read-idx-reg = <0x1200C>;
+ qcom,in-write-idx-reg = <0x12010>;
+ };
+
+ glink_qos_wdsp: qcom,glink-qos-config-wdsp {
+ compatible = "qcom,glink-qos-config";
+ qcom,flow-info = <0x80 0x0>,
+ <0x70 0x1>,
+ <0x60 0x2>,
+ <0x50 0x3>;
+ qcom,mtu-size = <0x800>;
+ qcom,tput-stats-cycle = <0xa>;
+ };
+
+ qcom,glink_pkt {
+ compatible = "qcom,glinkpkt";
+
+ qcom,glinkpkt-at-mdm0 {
+ qcom,glinkpkt-transport = "smem";
+ qcom,glinkpkt-edge = "mpss";
+ qcom,glinkpkt-ch-name = "DS";
+ qcom,glinkpkt-dev-name = "at_mdm0";
+ };
+
+ qcom,glinkpkt-loopback_cntl {
+ qcom,glinkpkt-transport = "lloop";
+ qcom,glinkpkt-edge = "local";
+ qcom,glinkpkt-ch-name = "LOCAL_LOOPBACK_CLNT";
+ qcom,glinkpkt-dev-name = "glink_pkt_loopback_ctrl";
+ };
+
+ qcom,glinkpkt-loopback_data {
+ qcom,glinkpkt-transport = "lloop";
+ qcom,glinkpkt-edge = "local";
+ qcom,glinkpkt-ch-name = "glink_pkt_lloop_CLNT";
+ qcom,glinkpkt-dev-name = "glink_pkt_loopback";
+ };
+
+ qcom,glinkpkt-apr-apps2 {
+ qcom,glinkpkt-transport = "smem";
+ qcom,glinkpkt-edge = "adsp";
+ qcom,glinkpkt-ch-name = "apr_apps2";
+ qcom,glinkpkt-dev-name = "apr_apps2";
+ };
+
+ qcom,glinkpkt-data40-cntl {
+ qcom,glinkpkt-transport = "smem";
+ qcom,glinkpkt-edge = "mpss";
+ qcom,glinkpkt-ch-name = "DATA40_CNTL";
+ qcom,glinkpkt-dev-name = "smdcntl8";
+ };
+
+ qcom,glinkpkt-data1 {
+ qcom,glinkpkt-transport = "smem";
+ qcom,glinkpkt-edge = "mpss";
+ qcom,glinkpkt-ch-name = "DATA1";
+ qcom,glinkpkt-dev-name = "smd7";
+ };
+
+ qcom,glinkpkt-data4 {
+ qcom,glinkpkt-transport = "smem";
+ qcom,glinkpkt-edge = "mpss";
+ qcom,glinkpkt-ch-name = "DATA4";
+ qcom,glinkpkt-dev-name = "smd8";
+ };
+
+ qcom,glinkpkt-data11 {
+ qcom,glinkpkt-transport = "smem";
+ qcom,glinkpkt-edge = "mpss";
+ qcom,glinkpkt-ch-name = "DATA11";
+ qcom,glinkpkt-dev-name = "smd11";
+ };
+ };
+
+ pcie0: qcom,pcie@01c00000 {
+ compatible = "qcom,pci-msm";
+ cell-index = <0>;
+
+ reg = <0x1c00000 0x2000>,
+ <0x1c06000 0x1000>,
+ <0x1b000000 0xf1d>,
+ <0x1b000f20 0xa8>,
+ <0x1b100000 0x100000>,
+ <0x1b200000 0x100000>,
+ <0x1b300000 0xd00000>;
+
+ reg-names = "parf", "phy", "dm_core", "elbi",
+ "conf", "io", "bars";
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x01000000 0x0 0x1b200000 0x1b200000 0x0 0x100000>,
+ <0x02000000 0x0 0x1b300000 0x1b300000 0x0 0xd00000>;
+ interrupt-parent = <&pcie0>;
+ interrupts = <0 1 2 3 4 5>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0xffffffff>;
+ interrupt-map = <0 0 0 0 &intc 0 0 405 0
+ 0 0 0 1 &intc 0 0 135 0
+ 0 0 0 2 &intc 0 0 136 0
+ 0 0 0 3 &intc 0 0 138 0
+ 0 0 0 4 &intc 0 0 139 0
+ 0 0 0 5 &intc 0 0 278 0>;
+
+ interrupt-names = "int_msi", "int_a", "int_b", "int_c",
+ "int_d", "int_global_int";
+
+ qcom,phy-sequence = <0x804 0x01 0x00
+ 0x034 0x14 0x00
+ 0x138 0x30 0x00
+ 0x048 0x0f 0x00
+ 0x15c 0x06 0x00
+ 0x090 0x01 0x00
+ 0x088 0x20 0x00
+ 0x0f0 0x00 0x00
+ 0x0f8 0x01 0x00
+ 0x0f4 0xc9 0x00
+ 0x11c 0xff 0x00
+ 0x120 0x3f 0x00
+ 0x164 0x01 0x00
+ 0x154 0x00 0x00
+ 0x148 0x0a 0x00
+ 0x05C 0x19 0x00
+ 0x038 0x90 0x00
+ 0x0b0 0x82 0x00
+ 0x0c0 0x03 0x00
+ 0x0bc 0x55 0x00
+ 0x0b8 0x55 0x00
+ 0x0a0 0x00 0x00
+ 0x09c 0x0d 0x00
+ 0x098 0x04 0x00
+ 0x13c 0x00 0x00
+ 0x060 0x08 0x00
+ 0x068 0x16 0x00
+ 0x070 0x34 0x00
+ 0x15c 0x06 0x00
+ 0x138 0x33 0x00
+ 0x03c 0x02 0x00
+ 0x040 0x0e 0x00
+ 0x080 0x04 0x00
+ 0x0dc 0x00 0x00
+ 0x0d8 0x3f 0x00
+ 0x00c 0x09 0x00
+ 0x010 0x01 0x00
+ 0x01c 0x40 0x00
+ 0x020 0x01 0x00
+ 0x014 0x02 0x00
+ 0x018 0x00 0x00
+ 0x024 0x7e 0x00
+ 0x028 0x15 0x00
+ 0x244 0x02 0x00
+ 0x2a4 0x12 0x00
+ 0x260 0x10 0x00
+ 0x28c 0x06 0x00
+ 0x504 0x03 0x00
+ 0x500 0x1c 0x00
+ 0x50c 0x14 0x00
+ 0x4d4 0x0a 0x00
+ 0x4d8 0x04 0x00
+ 0x4dc 0x1a 0x00
+ 0x434 0x4b 0x00
+ 0x414 0x04 0x00
+ 0x40c 0x04 0x00
+ 0x4f8 0x00 0x00
+ 0x4fc 0x80 0x00
+ 0x51c 0x40 0x00
+ 0x444 0x71 0x00
+ 0x43c 0x40 0x00
+ 0x854 0x04 0x00
+ 0x62c 0x52 0x00
+ 0x9ac 0x00 0x00
+ 0x8a0 0x01 0x00
+ 0x9e0 0x00 0x00
+ 0x9dc 0x01 0x00
+ 0x9a8 0x00 0x00
+ 0x8a4 0x01 0x00
+ 0x8a8 0x73 0x00
+ 0x9d8 0x99 0x00
+ 0x9b0 0x03 0x00
+ 0x804 0x03 0x00
+ 0x800 0x00 0x00
+ 0x808 0x03 0x00>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie0_clkreq_default
+ &pcie0_perst_default
+ &pcie0_wake_default>;
+
+ perst-gpio = <&tlmm 35 0>;
+ wake-gpio = <&tlmm 37 0>;
+
+ gdsc-vdd-supply = <&gdsc_pcie_0>;
+ vreg-1.8-supply = <&pmcobalt_l2>;
+ vreg-0.9-supply = <&pmcobalt_l1>;
+ vreg-cx-supply = <&pmcobalt_s1_level>;
+
+ qcom,vreg-1.8-voltage-level = <1200000 1200000 24000>;
+ qcom,vreg-0.9-voltage-level = <880000 880000 24000>;
+ qcom,vreg-cx-voltage-level = <RPM_SMD_REGULATOR_LEVEL_BINNING
+ RPM_SMD_REGULATOR_LEVEL_SVS 0>;
+
+ qcom,ep-latency = <10>;
+
+ qcom,ep-wakeirq;
+
+ linux,pci-domain = <0>;
+
+ qcom,pcie-phy-ver = <0x20>;
+ qcom,use-19p2mhz-aux-clk;
+
+ iommus = <&anoc1_smmu>;
+ qcom,smmu-exist;
+ qcom,smmu-sid-base = <0x1480>;
+
+ qcom,msm-bus,name = "pcie0";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <45 512 0 0>,
+ <45 512 500 800>;
+
+ clocks = <&clock_gcc clk_gcc_pcie_0_pipe_clk>,
+ <&clock_gcc clk_ln_bb_clk1>,
+ <&clock_gcc clk_gcc_pcie_0_aux_clk>,
+ <&clock_gcc clk_gcc_pcie_0_cfg_ahb_clk>,
+ <&clock_gcc clk_gcc_pcie_0_mstr_axi_clk>,
+ <&clock_gcc clk_gcc_pcie_0_slv_axi_clk>,
+ <&clock_gcc clk_gcc_pcie_clkref_clk>;
+
+ clock-names = "pcie_0_pipe_clk", "pcie_0_ref_clk_src",
+ "pcie_0_aux_clk", "pcie_0_cfg_ahb_clk",
+ "pcie_0_mstr_axi_clk", "pcie_0_slv_axi_clk",
+ "pcie_0_ldo";
+
+ max-clock-frequency-hz = <0>, <0>, <19200000>,
+ <0>, <0>, <0>, <0>, <0>, <0>,
+ <0>, <0>, <0>, <0>, <0>, <0>,
+ <0>, <0>;
+
+ resets = <&clock_gcc PCIE_PHY_BCR>,
+ <&clock_gcc PCIE_0_PHY_BCR>,
+ <&clock_gcc PCIE_0_PHY_BCR>;
+
+ reset-names = "pcie_phy_reset",
+ "pcie_0_phy_reset",
+ "pcie_0_phy_pipe_reset";
+ };
+
+ qcom,ipc_router {
+ compatible = "qcom,ipc_router";
+ qcom,node-id = <1>;
+ };
+
+ qcom,ipc_router_modem_xprt {
+ compatible = "qcom,ipc_router_glink_xprt";
+ qcom,ch-name = "IPCRTR";
+ qcom,xprt-remote = "mpss";
+ qcom,glink-xprt = "smem";
+ qcom,xprt-linkid = <1>;
+ qcom,xprt-version = <1>;
+ qcom,fragmented-data;
+ };
+
+ qcom,ipc_router_q6_xprt {
+ compatible = "qcom,ipc_router_glink_xprt";
+ qcom,ch-name = "IPCRTR";
+ qcom,xprt-remote = "lpass";
+ qcom,glink-xprt = "smem";
+ qcom,xprt-linkid = <1>;
+ qcom,xprt-version = <1>;
+ qcom,fragmented-data;
+ };
+
+ qcom,ipc_router_dsps_xprt {
+ compatible = "qcom,ipc_router_glink_xprt";
+ qcom,ch-name = "IPCRTR";
+ qcom,xprt-remote = "dsps";
+ qcom,glink-xprt = "smem";
+ qcom,xprt-linkid = <1>;
+ qcom,xprt-version = <1>;
+ qcom,fragmented-data;
+ };
+
+ qcom,spcom {
+ compatible = "qcom,spcom";
+
+ /* predefined channels, remote side is server */
+ qcom,spcom-ch-names = "sp_kernel" , "sp_ssr";
+ status = "ok";
+ };
+
+ spss_utils: qcom,spss_utils {
+ compatible = "qcom,spss-utils";
+ /* spss test fuse physical address */
+ qcom,spss-fuse-addr = <0x007841c4 0x4>;
+ qcom,spss-fuse-bit = <27>;
+ qcom,spss-test-firmware-name = "spss"; /* default name */
+ qcom,spss-prod-firmware-name = "spss1p"; /* 8 chars max */
+ status = "ok";
+ };
+
+ sdhc_2: sdhci@c0a4900 {
+ compatible = "qcom,sdhci-msm";
+ reg = <0xc0a4900 0x314>, <0xc0a4000 0x800>;
+ reg-names = "hc_mem", "core_mem";
+
+ interrupts = <0 125 0>, <0 221 0>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clock-names = "iface_clk", "core_clk";
+ clocks = <&clock_gcc clk_gcc_sdcc2_ahb_clk>,
+ <&clock_gcc clk_gcc_sdcc2_apps_clk>;
+
+ qcom,large-address-bus;
+ qcom,bus-width = <4>;
+ qcom,cpu-dma-latency-us = <701>;
+
+ qcom,devfreq,freq-table = <52000000 200000000>;
+
+ qcom,msm-bus,name = "sdhc2";
+ qcom,msm-bus,num-cases = <8>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
+ <81 512 1600 3200>, /* 400 KB/s*/
+ <81 512 80000 160000>, /* 20 MB/s */
+ <81 512 100000 200000>, /* 25 MB/s */
+ <81 512 200000 400000>, /* 50 MB/s */
+ <81 512 400000 800000>, /* 100 MB/s */
+ <81 512 800000 800000>, /* 200 MB/s */
+ <81 512 2048000 4096000>; /* Max. bandwidth */
+ qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+ 100000000 200000000 4294967295>;
+
+ status = "disabled";
+ };
+
+ ufsphy1: ufsphy@1da7000 {
+ compatible = "qcom,ufs-phy-qmp-v3";
+ reg = <0x1da7000 0xda8>;
+ reg-names = "phy_mem";
+ #phy-cells = <0>;
+ clock-names = "ref_clk_src",
+ "ref_clk",
+ "ref_aux_clk";
+ clocks = <&clock_gcc clk_ln_bb_clk1>,
+ <&clock_gcc clk_gcc_ufs_clkref_clk>,
+ <&clock_gcc clk_gcc_ufs_phy_aux_hw_ctl_clk>;
+ status = "disabled";
+ };
+
+ ufs_ice: ufsice@1db0000 {
+ compatible = "qcom,ice";
+ reg = <0x1db0000 0x8000>;
+ qcom,enable-ice-clk;
+ clock-names = "ufs_core_clk",
+ "bus_clk",
+ "iface_clk",
+ "ice_core_clk";
+ clocks = <&clock_gcc clk_gcc_ufs_axi_clk>,
+ <&clock_gcc clk_gcc_aggre1_ufs_axi_clk>,
+ <&clock_gcc clk_gcc_ufs_ahb_clk>,
+ <&clock_gcc clk_gcc_ufs_ice_core_clk>;
+ qcom,op-freq-hz = <0>,
+ <0>,
+ <0>,
+ <300000000>;
+ vdd-hba-supply = <&gdsc_ufs>;
+ qcom,msm-bus,name = "ufs_ice_noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <1 650 0 0>, /* No vote */
+ <1 650 1000 0>; /* Max. bandwidth */
+ qcom,bus-vector-names = "MIN",
+ "MAX";
+ qcom,instance-type = "ufs";
+ status = "disabled";
+ };
+
+ ufs1: ufshc@1da4000 {
+ compatible = "qcom,ufshc";
+ reg = <0x1da4000 0x2500>;
+ interrupts = <0 265 0>;
+ phys = <&ufsphy1>;
+ phy-names = "ufsphy";
+ ufs-qcom-crypto = <&ufs_ice>;
+
+ clock-names =
+ "core_clk",
+ "bus_aggr_clk",
+ "iface_clk",
+ "core_clk_unipro",
+ "core_clk_ice",
+ "ref_clk",
+ "tx_lane0_sync_clk",
+ "rx_lane0_sync_clk";
+ clocks =
+ <&clock_gcc clk_gcc_ufs_axi_hw_ctl_clk>,
+ <&clock_gcc clk_gcc_aggre1_ufs_axi_hw_ctl_clk>,
+ <&clock_gcc clk_gcc_ufs_ahb_clk>,
+ <&clock_gcc clk_gcc_ufs_unipro_core_hw_ctl_clk>,
+ <&clock_gcc clk_gcc_ufs_ice_core_hw_ctl_clk>,
+ <&clock_gcc clk_ln_bb_clk1>,
+ <&clock_gcc clk_gcc_ufs_tx_symbol_0_clk>,
+ <&clock_gcc clk_gcc_ufs_rx_symbol_0_clk>;
+ freq-table-hz =
+ <50000000 200000000>,
+ <0 0>,
+ <0 0>,
+ <37500000 150000000>,
+ <75000000 300000000>,
+ <0 0>,
+ <0 0>,
+ <0 0>;
+
+ lanes-per-direction = <1>;
+
+ qcom,msm-bus,name = "ufs1";
+ qcom,msm-bus,num-cases = <22>;
+ qcom,msm-bus,num-paths = <2>;
+ qcom,msm-bus,vectors-KBps =
+ <95 512 0 0>, <1 650 0 0>, /* No vote */
+ <95 512 922 0>, <1 650 1000 0>, /* PWM G1 */
+ <95 512 1844 0>, <1 650 1000 0>, /* PWM G2 */
+ <95 512 3688 0>, <1 650 1000 0>, /* PWM G3 */
+ <95 512 7376 0>, <1 650 1000 0>, /* PWM G4 */
+ <95 512 1844 0>, <1 650 1000 0>, /* PWM G1 L2 */
+ <95 512 3688 0>, <1 650 1000 0>, /* PWM G2 L2 */
+ <95 512 7376 0>, <1 650 1000 0>, /* PWM G3 L2 */
+ <95 512 14752 0>, <1 650 1000 0>, /* PWM G4 L2 */
+ <95 512 127796 0>, <1 650 1000 0>, /* HS G1 RA */
+ <95 512 255591 0>, <1 650 1000 0>, /* HS G2 RA */
+ <95 512 511181 0>, <1 650 1000 0>, /* HS G3 RA */
+ <95 512 255591 0>, <1 650 1000 0>, /* HS G1 RA L2 */
+ <95 512 511181 0>, <1 650 1000 0>, /* HS G2 RA L2 */
+ <95 512 1022362 0>, <1 650 1000 0>, /* HS G3 RA L2 */
+ <95 512 149422 0>, <1 650 1000 0>, /* HS G1 RB */
+ <95 512 298189 0>, <1 650 1000 0>, /* HS G2 RB */
+ <95 512 596378 0>, <1 650 1000 0>, /* HS G3 RB */
+ <95 512 298189 0>, <1 650 1000 0>, /* HS G1 RB L2 */
+ <95 512 596378 0>, <1 650 1000 0>, /* HS G2 RB L2 */
+ <95 512 1192756 0>, <1 650 1000 0>, /* HS G3 RB L2 */
+ <95 512 4096000 0>, <1 650 1000 0>; /* Max. bandwidth */
+ qcom,bus-vector-names = "MIN",
+ "PWM_G1_L1", "PWM_G2_L1", "PWM_G3_L1", "PWM_G4_L1",
+ "PWM_G1_L2", "PWM_G2_L2", "PWM_G3_L2", "PWM_G4_L2",
+ "HS_RA_G1_L1", "HS_RA_G2_L1", "HS_RA_G3_L1",
+ "HS_RA_G1_L2", "HS_RA_G2_L2", "HS_RA_G3_L2",
+ "HS_RB_G1_L1", "HS_RB_G2_L1", "HS_RB_G3_L1",
+ "HS_RB_G1_L2", "HS_RB_G2_L2", "HS_RB_G3_L2",
+ "MAX";
+
+ /* PM QoS */
+ qcom,pm-qos-cpu-groups = <0x0F 0xF0>;
+ qcom,pm-qos-cpu-group-latency-us = <70 70>;
+ qcom,pm-qos-default-cpu = <0>;
+
+ resets = <&clock_gcc UFS_BCR>;
+ reset-names = "core_reset";
+
+ status = "disabled";
+ };
+
+ usb3: ssusb@a800000 {
+ compatible = "qcom,dwc-usb3-msm";
+ reg = <0x0a800000 0xf8c00>,
+ <0x0c016000 0x400>;
+ reg-names = "core_base", "ahb2phy_base";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ interrupts = <0 347 0>, <0 243 0>, <0 180 0>;
+ interrupt-names = "hs_phy_irq", "ss_phy_irq", "pwr_event_irq";
+
+ USB3_GDSC-supply = <&gdsc_usb30>;
+ qcom,usb-dbm = <&dbm_1p5>;
+ qcom,msm-bus,name = "usb3";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <61 512 0 0>,
+ <61 512 240000 800000>;
+
+ qcom,dwc-usb3-msm-tx-fifo-size = <21288>;
+ extcon = <&pmicobalt_pdphy>;
+
+ clocks = <&clock_gcc clk_gcc_usb30_master_clk>,
+ <&clock_gcc clk_gcc_cfg_noc_usb3_axi_clk>,
+ <&clock_gcc clk_gcc_aggre1_usb3_axi_clk>,
+ <&clock_gcc clk_gcc_usb30_mock_utmi_clk>,
+ <&clock_gcc clk_gcc_usb30_sleep_clk>,
+ <&clock_gcc clk_cxo_dwc3_clk>;
+
+ clock-names = "core_clk", "iface_clk", "bus_aggr_clk",
+ "utmi_clk", "sleep_clk", "xo";
+
+ qcom,core-clk-rate = <120000000>;
+
+ resets = <&clock_gcc USB_30_BCR>;
+ reset-names = "core_reset";
+
+ dwc3@a800000 {
+ compatible = "snps,dwc3";
+ reg = <0x0a800000 0xcd00>;
+ interrupt-parent = <&intc>;
+ interrupts = <0 131 0>;
+ usb-phy = <&qusb_phy0>, <&ssphy>;
+ tx-fifo-resize;
+ snps,nominal-elastic-buffer;
+ snps,hird_thresh = <0x10>;
+ snps,num-gsi-evt-buffs = <0x3>;
+ };
+
+ qcom,usbbam@a904000 {
+ compatible = "qcom,usb-bam-msm";
+ reg = <0xa904000 0x17000>;
+ interrupt-parent = <&intc>;
+ interrupts = <0 132 0>;
+
+ qcom,bam-type = <0>;
+ qcom,usb-bam-fifo-baseaddr = <0x146bb000>;
+ qcom,usb-bam-num-pipes = <8>;
+ qcom,ignore-core-reset-ack;
+ qcom,disable-clk-gating;
+ qcom,usb-bam-override-threshold = <0x4001>;
+ qcom,usb-bam-max-mbps-highspeed = <400>;
+ qcom,usb-bam-max-mbps-superspeed = <3600>;
+ qcom,reset-bam-on-connect;
+
+ qcom,pipe0 {
+ label = "ssusb-qdss-in-0";
+ qcom,usb-bam-mem-type = <2>;
+ qcom,dir = <1>;
+ qcom,pipe-num = <0>;
+ qcom,peer-bam = <0>;
+ qcom,peer-bam-physical-address = <0x6064000>;
+ qcom,src-bam-pipe-index = <0>;
+ qcom,dst-bam-pipe-index = <0>;
+ qcom,data-fifo-offset = <0x0>;
+ qcom,data-fifo-size = <0x1800>;
+ qcom,descriptor-fifo-offset = <0x1800>;
+ qcom,descriptor-fifo-size = <0x800>;
+ };
+ };
+ };
+
+ qusb_phy0: qusb@c012000 {
+ compatible = "qcom,qusb2phy-v2";
+ reg = <0x0c012000 0x2a8>,
+ <0x01fcb24c 0x4>;
+ reg-names = "qusb_phy_base",
+ "tcsr_clamp_dig_n_1p8";
+ vdd-supply = <&pmcobalt_l1>;
+ vdda18-supply = <&pmcobalt_l12>;
+ vdda33-supply = <&pmcobalt_l24>;
+ qcom,vdd-voltage-level = <0 880000 880000>;
+ qcom,qusb-phy-init-seq =
+ /* <value reg_offset> */
+ <0x80 0x0
+ 0x13 0x04
+ 0x7c 0x18c
+ 0x80 0x2c
+ 0x0a 0x184
+ 0x00 0x240>;
+ phy_type= "utmi";
+
+ clocks = <&clock_gcc clk_ln_bb_clk1>,
+ <&clock_gcc clk_gcc_rx1_usb2_clkref_clk>;
+ clock-names = "ref_clk_src", "ref_clk";
+
+ resets = <&clock_gcc QUSB2PHY_PRIM_BCR>;
+ reset-names = "phy_reset";
+ };
+
+ ssphy: ssphy@c010000 {
+ compatible = "qcom,usb-ssphy-qmp-v2";
+ reg = <0x0c010000 0xe0c>,
+ <0x01fcb244 0x4>,
+ <0x01fcb248 0x4>;
+ reg-names = "qmp_phy_base",
+ "vls_clamp_reg",
+ "tcsr_usb3_dp_phymode";
+ vdd-supply = <&pmcobalt_l1>;
+ core-supply = <&pmcobalt_l2>;
+ qcom,vdd-voltage-level = <0 880000 880000>;
+ qcom,vbus-valid-override;
+ qcom,qmp-phy-init-seq =
+ /* <reg_offset, value, delay> */
+ <0x138 0x30 0x00
+ 0x034 0x04 0x01
+ 0x080 0x14 0x00
+ 0x03c 0x06 0x00
+ 0x08c 0x08 0x00
+ 0x15c 0x06 0x00
+ 0x164 0x01 0x00
+ 0x13c 0x80 0x00
+ 0x0b0 0x82 0x00
+ 0x0b8 0xab 0x00
+ 0x0bc 0xea 0x00
+ 0x0c0 0x02 0x00
+ 0x060 0x06 0x00
+ 0x068 0x16 0x00
+ 0x070 0x36 0x00
+ 0x0dc 0x00 0x00
+ 0x0d8 0x3f 0x00
+ 0x0f8 0x01 0x00
+ 0x0f4 0xc9 0x00
+ 0x148 0x0a 0x00
+ 0x0a0 0x00 0x00
+ 0x09c 0x34 0x00
+ 0x098 0x15 0x00
+ 0x090 0x04 0x00
+ 0x154 0x00 0x00
+ 0x094 0x00 0x00
+ 0x0f0 0x00 0x00
+ 0x00c 0x0a 0x00
+ 0x048 0x07 0x00
+ 0x0d0 0x80 0x00
+ 0x184 0x01 0x00
+ 0x010 0x01 0x00
+ 0x01c 0x31 0x00
+ 0x020 0x01 0x00
+ 0x014 0x00 0x00
+ 0x018 0x00 0x00
+ 0x024 0x85 0x00
+ 0x028 0x07 0x00
+ 0x430 0x0b 0x00
+ 0x4d4 0x0f 0x00
+ 0x4d8 0x4e 0x00
+ 0x4dc 0x18 0x00
+ 0x4f8 0x07 0x00
+ 0x4fc 0x80 0x00
+ 0x504 0x43 0x00
+ 0x50c 0x1c 0x00
+ 0x434 0x75 0x00
+ 0x43c 0x00 0x00
+ 0x440 0x00 0x00
+ 0x444 0x80 0x00
+ 0x408 0x0a 0x00
+ 0x414 0x06 0x00
+ 0x500 0x00 0x00
+ 0x4c0 0x03 0x00
+ 0x564 0x05 0x00
+ 0x830 0x0b 0x00
+ 0x8d4 0x0f 0x00
+ 0x8d8 0x4e 0x00
+ 0x8dc 0x18 0x00
+ 0x8f8 0x07 0x00
+ 0x8fc 0x80 0x00
+ 0x904 0x43 0x00
+ 0x90c 0x1c 0x00
+ 0x834 0x75 0x00
+ 0x83c 0x00 0x00
+ 0x840 0x00 0x00
+ 0x844 0x80 0x00
+ 0x808 0x0a 0x00
+ 0x814 0x06 0x00
+ 0x900 0x00 0x00
+ 0x8c0 0x03 0x00
+ 0x964 0x05 0x00
+ 0x260 0x10 0x00
+ 0x2a4 0x12 0x00
+ 0x28c 0x16 0x00
+ 0x244 0x00 0x00
+ 0x660 0x10 0x00
+ 0x6a4 0x12 0x00
+ 0x68c 0x16 0x00
+ 0x644 0x00 0x00
+ 0xcc8 0x83 0x00
+ 0xccc 0x09 0x00
+ 0xcd0 0xa2 0x00
+ 0xcd4 0x40 0x00
+ 0xcc4 0x02 0x00
+ 0xc80 0xd1 0x00
+ 0xc84 0x1f 0x00
+ 0xc88 0x47 0x00
+ 0xc64 0x1b 0x00
+ 0xc0c 0x9f 0x00
+ 0xc10 0x9f 0x00
+ 0xc14 0xb7 0x00
+ 0xc18 0x4e 0x00
+ 0xc1c 0x65 0x00
+ 0xc20 0x6b 0x00
+ 0xc24 0x15 0x00
+ 0xc28 0x0d 0x00
+ 0xc2c 0x15 0x00
+ 0xc30 0x0d 0x00
+ 0xc34 0x15 0x00
+ 0xc38 0x0d 0x00
+ 0xc3c 0x15 0x00
+ 0xc40 0x0d 0x00
+ 0xc44 0x15 0x00
+ 0xc48 0x0d 0x00
+ 0xc4c 0x15 0x00
+ 0xc50 0x0d 0x00
+ 0xc5c 0x02 0x00
+ 0xca0 0x04 0x00
+ 0xc8c 0x44 0x00
+ 0xc70 0xe7 0x00
+ 0xc74 0x03 0x00
+ 0xc78 0x40 0x00
+ 0xc7c 0x00 0x00
+ 0xdd8 0x8a 0x00
+ 0xcb8 0x75 0x00
+ 0xcb0 0x86 0x00
+ 0xcbc 0x13 0x00
+ 0xffffffff 0xffffffff 0x00>;
+
+ qcom,qmp-phy-reg-offset =
+ <0xd74 /* USB3_PHY_PCS_STATUS */
+ 0xcd8 /* USB3_PHY_AUTONOMOUS_MODE_CTRL */
+ 0xcdc /* USB3_PHY_LFPS_RXTERM_IRQ_CLEAR */
+ 0xc04 /* USB3_PHY_POWER_DOWN_CONTROL */
+ 0xc00 /* USB3_PHY_SW_RESET */
+ 0xc08 /* USB3_PHY_START */
+ 0xa00>; /* USB3PHY_PCS_MISC_TYPEC_CTRL */
+
+ clocks = <&clock_gcc clk_gcc_usb3_phy_aux_clk>,
+ <&clock_gcc clk_gcc_usb3_phy_pipe_clk>,
+ <&clock_gcc clk_ln_bb_clk1>,
+ <&clock_gcc clk_gcc_usb3_clkref_clk>;
+
+ clock-names = "aux_clk", "pipe_clk", "ref_clk_src",
+ "ref_clk";
+
+ resets = <&clock_gcc USB3_PHY_BCR>,
+ <&clock_gcc USB3PHY_PHY_BCR>;
+ reset-names = "phy_reset", "phy_phy_reset";
+ };
+
+ usb_audio_qmi_dev {
+ compatible = "qcom,usb-audio-qmi-dev";
+ iommus = <&lpass_q6_smmu 12>;
+ qcom,usb-audio-stream-id = <12>;
+ qcom,usb-audio-intr-num = <2>;
+ };
+
+ dbm_1p5: dbm@a8f8000 {
+ compatible = "qcom,usb-dbm-1p5";
+ reg = <0xa8f8000 0x300>;
+ qcom,reset-ep-after-lpm-resume;
+ };
+
+ usb_nop_phy: usb_nop_phy {
+ compatible = "usb-nop-xceiv";
+ };
+
+ qcom,lpass@17300000 {
+ compatible = "qcom,pil-tz-generic";
+ reg = <0x17300000 0x00100>;
+ interrupts = <0 162 1>;
+
+ vdd_cx-supply = <&pmcobalt_s1_level>;
+ qcom,proxy-reg-names = "vdd_cx";
+ qcom,vdd_cx-uV-uA = <RPM_SMD_REGULATOR_LEVEL_TURBO 100000>;
+
+ clocks = <&clock_gcc clk_cxo_pil_lpass_clk>;
+ clock-names = "xo";
+ qcom,proxy-clock-names = "xo";
+
+ qcom,pas-id = <1>;
+ qcom,proxy-timeout-ms = <10000>;
+ qcom,smem-id = <423>;
+ qcom,sysmon-id = <1>;
+ status = "ok";
+ qcom,ssctl-instance-id = <0x14>;
+ qcom,firmware-name = "adsp";
+ memory-region = <&pil_adsp_mem>;
+
+ /* GPIO inputs from lpass */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_2_in 0 0>;
+ qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_2_in 2 0>;
+ qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_2_in 1 0>;
+ qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_2_in 3 0>;
+
+ /* GPIO output to lpass */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>;
+ };
+
+ pil_modem: qcom,mss@4080000 {
+ compatible = "qcom,pil-q6v55-mss";
+ reg = <0x4080000 0x100>,
+ <0x1f63000 0x008>,
+ <0x1f65000 0x008>,
+ <0x1f64000 0x008>,
+ <0x4180000 0x020>,
+ <0x00179000 0x004>;
+ reg-names = "qdsp6_base", "halt_q6", "halt_modem",
+ "halt_nc", "rmb_base", "restart_reg";
+
+ clocks = <&clock_gcc clk_cxo_clk_src>,
+ <&clock_gcc clk_gcc_mss_cfg_ahb_clk>,
+ <&clock_gcc clk_gcc_bimc_mss_q6_axi_clk>,
+ <&clock_gcc clk_gcc_boot_rom_ahb_clk>,
+ <&clock_gcc clk_gpll0_out_msscc>,
+ <&clock_gcc clk_gcc_mss_snoc_axi_clk>,
+ <&clock_gcc clk_gcc_mss_mnoc_bimc_axi_clk>,
+ <&clock_gcc clk_qdss_clk>;
+ clock-names = "xo", "iface_clk", "bus_clk",
+ "mem_clk", "gpll0_mss_clk", "snoc_axi_clk",
+ "mnoc_axi_clk", "qdss_clk";
+ qcom,proxy-clock-names = "xo", "qdss_clk";
+ qcom,active-clock-names = "iface_clk", "bus_clk", "mem_clk",
+ "gpll0_mss_clk", "snoc_axi_clk",
+ "mnoc_axi_clk";
+
+ interrupts = <0 448 1>;
+ vdd_cx-supply = <&pmcobalt_s1_level>;
+ vdd_cx-voltage = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ vdd_mx-supply = <&pmcobalt_s9_level>;
+ vdd_mx-uV = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,firmware-name = "modem";
+ qcom,pil-self-auth;
+ qcom,sysmon-id = <0>;
+ qcom,ssctl-instance-id = <0x12>;
+ qcom,override-acc;
+ qcom,qdsp6v62-1-2;
+ status = "ok";
+ memory-region = <&modem_mem>;
+ qcom,mem-protect-id = <0xF>;
+
+ /* GPIO inputs from mss */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+ qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>;
+ qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
+ qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_1_in 3 0>;
+ qcom,gpio-shutdown-ack = <&smp2pgpio_ssr_smp2p_1_in 7 0>;
+
+ /* GPIO output to mss */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
+ };
+
+ tsens0: tsens@10aa000 {
+ compatible = "qcom,msmcobalt-tsens";
+ reg = <0x10aa000 0x2000>;
+ reg-names = "tsens_physical";
+ interrupts = <0 458 0>, <0 445 0>;
+ interrupt-names = "tsens-upper-lower", "tsens-critical";
+ qcom,client-id = <0 1 2 3 4 7 8 9 10 11 12 13>;
+ qcom,sensor-id = <0 1 2 3 4 7 8 9 10 11 12 13>;
+ qcom,sensors = <12>;
+ };
+
+ tsens1: tsens@10ad000 {
+ compatible = "qcom,msmcobalt-tsens";
+ reg = <0x10ad000 0x2000>;
+ reg-names = "tsens_physical";
+ interrupts = <0 184 0>, <0 430 0>;
+ interrupt-names = "tsens-upper-lower", "tsens-critical";
+ qcom,client-id = <14 15 16 17 18 19 20 21>;
+ qcom,sensor-id = <0 1 3 4 5 6 7 2>;
+ qcom,sensors = <8>;
+ };
+
+ qcom,sensor-information {
+ compatible = "qcom,sensor-information";
+ sensor_information0: qcom,sensor-information-0 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor0";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information1: qcom,sensor-information-1 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor1";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information2: qcom,sensor-information-2 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor2";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information3: qcom,sensor-information-3 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor3";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information4: qcom,sensor-information-4 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor4";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information7: qcom,sensor-information-7 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor7";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information8: qcom,sensor-information-8 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor8";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information9: qcom,sensor-information-9 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor9";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information10: qcom,sensor-information-10 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor10";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information11: qcom,sensor-information-11 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor11";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information12: qcom,sensor-information-12 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor12";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information13: qcom,sensor-information-13 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor13";
+ qcom,scaling-factor = <10>;
+ qcom,alias-name = "gpu";
+ };
+ sensor_information14: qcom,sensor-information-14 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor14";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information15: qcom,sensor-information-15 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor15";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information16: qcom,sensor-information-16 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor16";
+ qcom,alias-name = "pop_mem";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information17: qcom,sensor-information-17 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor17";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information18: qcom,sensor-information-18 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor18";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information19: qcom,sensor-information-19 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor19";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information20: qcom,sensor-information-20 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor20";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information21: qcom,sensor-information-21 {
+ qcom,sensor-type = "tsens";
+ qcom,sensor-name = "tsens_tz_sensor21";
+ qcom,scaling-factor = <10>;
+ };
+ sensor_information22: qcom,sensor-information-22 {
+ qcom,sensor-type = "alarm";
+ qcom,sensor-name = "pm8994_tz";
+ qcom,scaling-factor = <1000>;
+ };
+ sensor_information23: qcom,sensor-information-23 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "msm_therm";
+ };
+ sensor_information24: qcom,sensor-information-24 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "emmc_therm";
+ };
+ sensor_information25: qcom,sensor-information-25 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "pa_therm0";
+ };
+ sensor_information26: qcom,sensor-information-26 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "pa_therm1";
+ };
+ sensor_information27: qcom,sensor-information-27 {
+ qcom,sensor-type = "adc";
+ qcom,sensor-name = "quiet_therm";
+ };
+ sensor_information28: qcom,sensor-information-28 {
+ qcom,sensor-type = "llm";
+ qcom,sensor-name = "limits_sensor-01";
+ };
+ sensor_information29: qcom,sensor-information-29 {
+ qcom,sensor-type = "llm";
+ qcom,sensor-name = "limits_sensor-02";
+ };
+ };
+
+ qcom_seecom: qseecom@86600000 {
+ compatible = "qcom,qseecom";
+ reg = <0x86600000 0x2200000>;
+ reg-names = "secapp-region";
+ qcom,hlos-num-ce-hw-instances = <1>;
+ qcom,hlos-ce-hw-instance = <0>;
+ qcom,qsee-ce-hw-instance = <0>;
+ qcom,disk-encrypt-pipe-pair = <2>;
+ qcom,support-fde;
+ qcom,no-clock-support;
+ qcom,appsbl-qseecom-support;
+ qcom,commonlib64-loaded-by-uefi;
+ qcom,msm-bus,name = "qseecom-noc";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <55 512 0 0>,
+ <55 512 0 0>,
+ <55 512 120000 1200000>,
+ <55 512 393600 3936000>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ clocks = <&clock_gcc clk_ce1_clk>,
+ <&clock_gcc clk_qseecom_ce1_clk>,
+ <&clock_gcc clk_gcc_ce1_ahb_m_clk>,
+ <&clock_gcc clk_gcc_ce1_axi_m_clk>;
+ qcom,ce-opp-freq = <171430000>;
+ qcom,qsee-reentrancy-support = <2>;
+ };
+
+ qcom_tzlog: tz-log@146BF720 {
+ compatible = "qcom,tz-log";
+ reg = <0x146BF720 0x3000>;
+ qcom,hyplog-enabled;
+ hyplog-address-offset = <0x410>; /* 0x066BFB30 */
+ hyplog-size-offset = <0x414>; /* 0x066BFB34 */
+ };
+
+ qcom_crypto: qcrypto@1DE0000 {
+ compatible = "qcom,qcrypto";
+ reg = <0x1DE0000 0x20000>,
+ <0x1DC4000 0x24000>;
+ reg-names = "crypto-base","crypto-bam-base";
+ interrupts = <0 206 0>;
+ qcom,bam-pipe-pair = <2>;
+ qcom,ce-hw-instance = <0>;
+ qcom,ce-device = <0>;
+ qcom,bam-ee = <0>;
+ qcom,ce-hw-shared;
+ qcom,clk-mgmt-sus-res;
+ qcom,msm-bus,name = "qcrypto-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <55 512 0 0>,
+ <55 512 3936000 393600>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ clocks = <&clock_gcc clk_qcrypto_ce1_clk>,
+ <&clock_gcc clk_qcrypto_ce1_clk>,
+ <&clock_gcc clk_gcc_ce1_ahb_m_clk>,
+ <&clock_gcc clk_gcc_ce1_axi_m_clk>;
+ qcom,ce-opp-freq = <171430000>;
+ qcom,use-sw-aes-cbc-ecb-ctr-algo;
+ qcom,use-sw-aes-xts-algo;
+ qcom,use-sw-aes-ccm-algo;
+ qcom,use-sw-ahash-algo;
+ qcom,use-sw-aead-algo;
+ qcom,use-sw-hmac-algo;
+ };
+
+ qcom_cedev: qcedev@1DE0000{
+ compatible = "qcom,qcedev";
+ reg = <0x1DE0000 0x20000>,
+ <0x1DC4000 0x24000>;
+ reg-names = "crypto-base","crypto-bam-base";
+ interrupts = <0 206 0>;
+ qcom,bam-pipe-pair = <1>;
+ qcom,ce-hw-instance = <0>;
+ qcom,ce-device = <0>;
+ qcom,ce-hw-shared;
+ qcom,bam-ee = <0>;
+ qcom,msm-bus,name = "qcedev-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <55 512 0 0>,
+ <55 512 3936000 393600>;
+ clock-names = "core_clk_src", "core_clk",
+ "iface_clk", "bus_clk";
+ clocks = <&clock_gcc clk_qcedev_ce1_clk>,
+ <&clock_gcc clk_qcedev_ce1_clk>,
+ <&clock_gcc clk_gcc_ce1_ahb_m_clk>,
+ <&clock_gcc clk_gcc_ce1_axi_m_clk>;
+ qcom,ce-opp-freq = <171430000>;
+ };
+
+ qcom_rng: qrng@793000 {
+ compatible = "qcom,msm-rng";
+ reg = <0x793000 0x1000>;
+ qcom,msm-rng-iface-clk;
+ qcom,no-qrng-config;
+ qcom,msm-bus,name = "msm-rng-noc";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <1 618 0 0>, /* No vote */
+ <1 618 0 800>; /* 100 MB/s */
+ clocks = <&clock_gcc clk_gcc_prng_ahb_clk>;
+ clock-names = "iface_clk";
+ };
+
+ mitigation_profile0: qcom,limit_info-0 {
+ qcom,temperature-sensor = <&sensor_information1>;
+ qcom,hotplug-mitigation-enable;
+ };
+
+ mitigation_profile1: qcom,limit_info-1 {
+ qcom,temperature-sensor = <&sensor_information2>;
+ qcom,hotplug-mitigation-enable;
+ };
+
+ mitigation_profile2: qcom,limit_info-2 {
+ qcom,temperature-sensor = <&sensor_information3>;
+ qcom,hotplug-mitigation-enable;
+ };
+
+ mitigation_profile3: qcom,limit_info-3 {
+ qcom,temperature-sensor = <&sensor_information4>;
+ qcom,hotplug-mitigation-enable;
+ };
+
+ mitigation_profile4: qcom,limit_info-4 {
+ qcom,temperature-sensor = <&sensor_information7>;
+ qcom,hotplug-mitigation-enable;
+ };
+
+ mitigation_profile5: qcom,limit_info-5 {
+ qcom,temperature-sensor = <&sensor_information8>;
+ qcom,hotplug-mitigation-enable;
+ };
+
+ mitigation_profile6: qcom,limit_info-6 {
+ qcom,temperature-sensor = <&sensor_information9>;
+ qcom,hotplug-mitigation-enable;
+ };
+
+ mitigation_profile7: qcom,limit_info-7 {
+ qcom,temperature-sensor = <&sensor_information10>;
+ qcom,hotplug-mitigation-enable;
+ };
+
+ qcom,lmh {
+ compatible = "qcom,lmh_v1";
+ interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ qcom,msm-thermal {
+ compatible = "qcom,msm-thermal";
+ qcom,sensor-id = <1>;
+ qcom,poll-ms = <100>;
+ qcom,therm-reset-temp = <115>;
+ qcom,core-limit-temp = <70>;
+ qcom,core-temp-hysteresis = <10>;
+ qcom,hotplug-temp = <105>;
+ qcom,hotplug-temp-hysteresis = <20>;
+ qcom,online-hotplug-core;
+ qcom,synchronous-cluster-id = <0 1>;
+ qcom,synchronous-cluster-map = <0 4 &CPU0 &CPU1 &CPU2 &CPU3>,
+ <1 4 &CPU4 &CPU5 &CPU6 &CPU7>;
+ clock-names = "osm";
+ clocks = <&clock_cpu clk_pwrcl_clk>;
+
+ qcom,vdd-restriction-temp = <5>;
+ qcom,vdd-restriction-temp-hysteresis = <10>;
+
+ vdd-dig-supply = <&pmcobalt_s1_floor_level>;
+ vdd-gfx-supply = <&gfx_vreg>;
+
+ qcom,vdd-dig-rstr{
+ qcom,vdd-rstr-reg = "vdd-dig";
+ qcom,levels = <RPM_SMD_REGULATOR_LEVEL_NOM
+ RPM_SMD_REGULATOR_LEVEL_TURBO
+ RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ /* Nominal, Super Turbo, Super Turbo */
+ qcom,min-level = <RPM_SMD_REGULATOR_LEVEL_NONE>;
+ /* No Request */
+ };
+
+ qcom,vdd-gfx-rstr{
+ qcom,vdd-rstr-reg = "vdd-gfx";
+ qcom,levels = <5 6 6>; /* Nominal, Turbo, Turbo */
+ qcom,min-level = <1>; /* No Request */
+ };
+
+ msm_thermal_freq: qcom,vdd-apps-rstr{
+ qcom,vdd-rstr-reg = "vdd-apps";
+ qcom,levels = <1248000>;
+ qcom,freq-req;
+ };
+ };
+
+ qcom,bcl {
+ compatible = "qcom,bcl";
+ qcom,bcl-enable;
+ qcom,bcl-framework-interface;
+ qcom,bcl-freq-control-list = <&CPU4 &CPU5 &CPU6 &CPU7>;
+ qcom,bcl-hotplug-list = <&CPU4 &CPU5 &CPU6 &CPU7>;
+ qcom,bcl-soc-hotplug-list = <&CPU4 &CPU5 &CPU6 &CPU7>;
+ qcom,ibat-monitor {
+ qcom,low-threshold-uamp = <3400000>;
+ qcom,high-threshold-uamp = <4200000>;
+ qcom,mitigation-freq-khz = <576000>;
+ qcom,vph-high-threshold-uv = <3500000>;
+ qcom,vph-low-threshold-uv = <3300000>;
+ qcom,soc-low-threshold = <10>;
+ qcom,thermal-handle = <&msm_thermal_freq>;
+ };
+ };
+
+ qcom,ssc@5c00000 {
+ compatible = "qcom,pil-tz-generic";
+ reg = <0x5c00000 0x4000>;
+ interrupts = <0 390 1>;
+
+ vdd_cx-supply = <&pmcobalt_l27_level>;
+ vdd_px-supply = <&pmcobalt_lvs2>;
+ qcom,vdd_cx-uV-uA = <RPM_SMD_REGULATOR_LEVEL_TURBO 0>;
+ qcom,proxy-reg-names = "vdd_cx", "vdd_px";
+ qcom,keep-proxy-regs-on;
+
+ clocks = <&clock_gcc clk_cxo_pil_ssc_clk>,
+ <&clock_gcc clk_aggre2_noc_clk>;
+ clock-names = "xo", "aggre2";
+ qcom,proxy-clock-names = "xo", "aggre2";
+
+ qcom,pas-id = <12>;
+ qcom,proxy-timeout-ms = <10000>;
+ qcom,smem-id = <424>;
+ qcom,sysmon-id = <3>;
+ qcom,ssctl-instance-id = <0x16>;
+ qcom,firmware-name = "slpi";
+ status = "ok";
+ memory-region = <&pil_slpi_mem>;
+
+ /* GPIO inputs from ssc */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_3_in 0 0>;
+ qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_3_in 2 0>;
+ qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_3_in 1 0>;
+ qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_3_in 3 0>;
+
+ /* GPIO output to ssc */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_3_out 0 0>;
+ };
+
+ qcom,venus@cce0000 {
+ compatible = "qcom,pil-tz-generic";
+ reg = <0xcce0000 0x4000>;
+
+ vdd-supply = <&gdsc_venus>;
+ qcom,proxy-reg-names = "vdd";
+
+ clocks = <&clock_mmss clk_mmss_video_core_clk>,
+ <&clock_mmss clk_mmss_mnoc_ahb_clk>,
+ <&clock_mmss clk_mmss_video_ahb_clk>,
+ <&clock_gcc clk_mmssnoc_axi_clk>,
+ <&clock_mmss clk_mmss_video_axi_clk>,
+ <&clock_mmss clk_mmss_video_maxi_clk>;
+ clock-names = "core_clk", "mnoc_ahb_clk", "iface_clk",
+ "noc_axi_clk", "bus_clk", "maxi_clk";
+ qcom,proxy-clock-names = "core_clk","mnoc_ahb_clk",
+ "iface_clk", "noc_axi_clk", "bus_clk", "maxi_clk";
+
+ qcom,pas-id = <9>;
+ qcom,msm-bus,name = "pil-venus";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <63 512 0 0>,
+ <63 512 0 304000>;
+ qcom,proxy-timeout-ms = <100>;
+ qcom,firmware-name = "venus";
+ memory-region = <&pil_video_mem>;
+ status = "ok";
+ };
+
+ wdog: qcom,wdt@17817000 {
+ compatible = "qcom,msm-watchdog";
+ reg = <0x17817000 0x1000>;
+ reg-names = "wdt-base";
+ interrupts = <0 3 0>, <0 4 0>;
+ qcom,bark-time = <11000>;
+ qcom,pet-time = <10000>;
+ qcom,ipi-ping;
+ qcom,wakeup-enable;
+ qcom,scandump-size = <0x40000>;
+ };
+
+ qcom,spss@1d00000 {
+ compatible = "qcom,pil-tz-generic";
+ reg = <0x1d0101c 0x4>,
+ <0x1d01024 0x4>,
+ <0x1d01028 0x4>,
+ <0x1d0103c 0x4>,
+ <0x1d02030 0x4>;
+ reg-names = "sp2soc_irq_status", "sp2soc_irq_clr",
+ "sp2soc_irq_mask", "rmb_err", "rmb_err_spare2";
+ interrupts = <0 352 1>;
+
+ vdd_cx-supply = <&pmcobalt_s1_level>;
+ qcom,proxy-reg-names = "vdd_cx";
+ qcom,vdd_cx-uV-uA = <RPM_SMD_REGULATOR_LEVEL_TURBO 100000>;
+
+ clocks = <&clock_gcc clk_cxo_pil_spss_clk>;
+ clock-names = "xo";
+ qcom,proxy-clock-names = "xo";
+ qcom,pil-generic-irq-handler;
+ status = "ok";
+
+ qcom,pas-id = <14>;
+ qcom,proxy-timeout-ms = <10000>;
+ qcom,firmware-name = "spss";
+ memory-region = <&spss_mem>;
+ qcom,spss-scsr-bits = <24 25>;
+ };
+
+ qcom,msm-rtb {
+ compatible = "qcom,msm-rtb";
+ qcom,rtb-size = <0x100000>;
+ };
+
+ qcom,mpm2-sleep-counter@10a3000 {
+ compatible = "qcom,mpm2-sleep-counter";
+ reg = <0x010a3000 0x1000>;
+ clock-frequency = <32768>;
+ };
+
+ qcom,msm-imem@146bf000 {
+ compatible = "qcom,msm-imem";
+ reg = <0x146bf000 0x1000>;
+ ranges = <0x0 0x146bf000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ mem_dump_table@10 {
+ compatible = "qcom,msm-imem-mem_dump_table";
+ reg = <0x10 8>;
+ };
+
+ dload_type@18 {
+ compatible = "qcom,msm-imem-dload-type";
+ reg = <0x18 4>;
+ };
+
+ restart_reason@65c {
+ compatible = "qcom,msm-imem-restart_reason";
+ reg = <0x65c 4>;
+ };
+
+ boot_stats@6b0 {
+ compatible = "qcom,msm-imem-boot_stats";
+ reg = <0x6b0 32>;
+ };
+
+ pil@94c {
+ compatible = "qcom,msm-imem-pil";
+ reg = <0x94c 200>;
+ };
+
+ diag_dload@c8 {
+ compatible = "qcom,msm-imem-diag-dload";
+ reg = <0xc8 200>;
+ };
+ };
+
+ cpu_pmu: cpu-pmu {
+ compatible = "arm,armv8-pmuv3";
+ qcom,irq-is-percpu;
+ interrupts = <1 6 4>;
+ };
+
+ cpuss_dump {
+ compatible = "qcom,cpuss-dump";
+ qcom,l1_i_cache0 {
+ qcom,dump-node = <&L1_I_0>;
+ qcom,dump-id = <0x60>;
+ };
+ qcom,l1_i_cache1 {
+ qcom,dump-node = <&L1_I_1>;
+ qcom,dump-id = <0x61>;
+ };
+ qcom,l1_i_cache2 {
+ qcom,dump-node = <&L1_I_2>;
+ qcom,dump-id = <0x62>;
+ };
+ qcom,l1_i_cache3 {
+ qcom,dump-node = <&L1_I_3>;
+ qcom,dump-id = <0x63>;
+ };
+ qcom,l1_i_cache100 {
+ qcom,dump-node = <&L1_I_100>;
+ qcom,dump-id = <0x64>;
+ };
+ qcom,l1_i_cache101 {
+ qcom,dump-node = <&L1_I_101>;
+ qcom,dump-id = <0x65>;
+ };
+ qcom,l1_i_cache102 {
+ qcom,dump-node = <&L1_I_102>;
+ qcom,dump-id = <0x66>;
+ };
+ qcom,l1_i_cache103 {
+ qcom,dump-node = <&L1_I_103>;
+ qcom,dump-id = <0x67>;
+ };
+ qcom,l1_d_cache0 {
+ qcom,dump-node = <&L1_D_0>;
+ qcom,dump-id = <0x80>;
+ };
+ qcom,l1_d_cache1 {
+ qcom,dump-node = <&L1_D_1>;
+ qcom,dump-id = <0x81>;
+ };
+ qcom,l1_d_cache2 {
+ qcom,dump-node = <&L1_D_2>;
+ qcom,dump-id = <0x82>;
+ };
+ qcom,l1_d_cache3 {
+ qcom,dump-node = <&L1_D_3>;
+ qcom,dump-id = <0x83>;
+ };
+ qcom,l1_d_cache100 {
+ qcom,dump-node = <&L1_D_100>;
+ qcom,dump-id = <0x84>;
+ };
+ qcom,l1_d_cache101 {
+ qcom,dump-node = <&L1_D_101>;
+ qcom,dump-id = <0x85>;
+ };
+ qcom,l1_d_cache102 {
+ qcom,dump-node = <&L1_D_102>;
+ qcom,dump-id = <0x86>;
+ };
+ qcom,l1_d_cache103 {
+ qcom,dump-node = <&L1_D_103>;
+ qcom,dump-id = <0x87>;
+ };
+ };
+
+ qcom,msm-ssc-sensors {
+ compatible = "qcom,msm-ssc-sensors";
+ status = "ok";
+ };
+
+ dcc: dcc@10b3000 {
+ compatible = "qcom,dcc";
+ reg = <0x10b3000 0x1000>,
+ <0x10b4000 0x2000>;
+ reg-names = "dcc-base", "dcc-ram-base";
+
+ clocks = <&clock_gcc clk_gcc_dcc_ahb_clk>;
+ clock-names = "dcc_clk";
+ };
+
+ qcom,msm-core@780000 {
+ compatible = "qcom,apss-core-ea";
+ reg = <0x780000 0x1000>;
+ qcom,low-hyst-temp = <10>;
+ qcom,high-hyst-temp = <5>;
+ qcom,polling-interval = <50>;
+
+ ea0: ea0 {
+ sensor = <&sensor_information1>;
+ };
+
+ ea1: ea1 {
+ sensor = <&sensor_information2>;
+ };
+
+ ea2: ea2 {
+ sensor = <&sensor_information3>;
+ };
+
+ ea3: ea3 {
+ sensor = <&sensor_information4>;
+ };
+
+ ea4: ea4 {
+ sensor = <&sensor_information7>;
+ };
+
+ ea5: ea5 {
+ sensor = <&sensor_information8>;
+ };
+
+ ea6: ea6 {
+ sensor = <&sensor_information9>;
+ };
+
+ ea7: ea7 {
+ sensor = <&sensor_information10>;
+ };
+
+ };
+
+ qcom,icnss@18800000 {
+ status = "disabled";
+ compatible = "qcom,icnss";
+ reg = <0x18800000 0x800000>,
+ <0x10AC000 0x20>,
+ <0xa0000000 0x10000000>,
+ <0xb0000000 0x10000>;
+ reg-names = "membase", "mpm_config",
+ "smmu_iova_base", "smmu_iova_ipa";
+ interrupts = <0 413 0 /* CE0 */ >,
+ <0 414 0 /* CE1 */ >,
+ <0 415 0 /* CE2 */ >,
+ <0 416 0 /* CE3 */ >,
+ <0 417 0 /* CE4 */ >,
+ <0 418 0 /* CE5 */ >,
+ <0 420 0 /* CE6 */ >,
+ <0 421 0 /* CE7 */ >,
+ <0 422 0 /* CE8 */ >,
+ <0 423 0 /* CE9 */ >,
+ <0 424 0 /* CE10 */ >,
+ <0 425 0 /* CE11 */ >;
+ qcom,wlan-msa-memory = <0x100000>;
+ };
+
+ tspp: msm_tspp@0c1e7000 {
+ compatible = "qcom,msm_tspp";
+ reg = <0x0c1e7000 0x200>, /* MSM_TSIF0_PHYS */
+ <0x0c1e8000 0x200>, /* MSM_TSIF1_PHYS */
+ <0x0c1e9000 0x1000>, /* MSM_TSPP_PHYS */
+ <0x0c1c4000 0x23000>; /* MSM_TSPP_BAM_PHYS */
+ reg-names = "MSM_TSIF0_PHYS",
+ "MSM_TSIF1_PHYS",
+ "MSM_TSPP_PHYS",
+ "MSM_TSPP_BAM_PHYS";
+ interrupts = <0 121 0>, /* TSIF_TSPP_IRQ */
+ <0 119 0>, /* TSIF0_IRQ */
+ <0 120 0>, /* TSIF1_IRQ */
+ <0 122 0>; /* TSIF_BAM_IRQ */
+ interrupt-names = "TSIF_TSPP_IRQ",
+ "TSIF0_IRQ",
+ "TSIF1_IRQ",
+ "TSIF_BAM_IRQ";
+
+ clock-names = "iface_clk", "ref_clk";
+ clocks = <&clock_gcc clk_gcc_tsif_ahb_clk>,
+ <&clock_gcc clk_gcc_tsif_ref_clk>;
+
+ qcom,msm-bus,name = "tsif";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <82 512 0 0>, /* No vote */
+ <82 512 12288 24576>;
+ /* Max. bandwidth, 2xTSIF, each max of 96Mbps */
+
+ pinctrl-names = "disabled",
+ "tsif0-mode1", "tsif0-mode2",
+ "tsif1-mode1", "tsif1-mode2",
+ "dual-tsif-mode1", "dual-tsif-mode2";
+
+ pinctrl-0 = <>; /* disabled */
+ pinctrl-1 = <&tsif0_signals_active>; /* tsif0-mode1 */
+ pinctrl-2 = <&tsif0_signals_active
+ &tsif0_sync_active>; /* tsif0-mode2 */
+ pinctrl-3 = <&tsif1_signals_active>; /* tsif1-mode1 */
+ pinctrl-4 = <&tsif1_signals_active
+ &tsif1_sync_active>; /* tsif1-mode2 */
+ pinctrl-5 = <&tsif0_signals_active
+ &tsif1_signals_active>; /* dual-tsif-mode1 */
+ pinctrl-6 = <&tsif0_signals_active
+ &tsif0_sync_active
+ &tsif1_signals_active
+ &tsif1_sync_active>; /* dual-tsif-mode2 */
+ };
+
+ wil6210: qcom,wil6210 {
+ compatible = "qcom,wil6210";
+ qcom,pcie-parent = <&pcie0>;
+ qcom,wigig-en = <&tlmm 80 0>;
+ qcom,msm-bus,name = "wil6210";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <45 512 0 0>,
+ <45 512 600000 800000>; /* ~4.6Gbps (MCS12) */
+ qcom,use-ext-supply;
+ vdd-supply= <&pmcobalt_s7>;
+ vddio-supply= <&pmcobalt_s5>;
+ qcom,use-ext-clocks;
+ clocks = <&clock_gcc clk_rf_clk3>,
+ <&clock_gcc clk_rf_clk3_pin>;
+ clock-names = "rf_clk3_clk", "rf_clk3_pin_clk";
+ qcom,smmu-support;
+ status = "disabled";
+ };
+
+ qcom,qsee_ipc_irq_bridge {
+ compatible = "qcom,qsee-ipc-irq-bridge";
+
+ qcom,qsee-ipc-irq-spss {
+ qcom,rx-irq-clr = <0x1d08008 0x4>;
+ qcom,rx-irq-clr-mask = <0x1>;
+ qcom,dev-name = "qsee_ipc_irq_spss";
+ interrupts = <0 349 4>;
+ label = "spss";
+ };
+ };
+};
+
+&clock_cpu {
+ lmh_dcvs0: qcom,limits-dcvs@0 {
+ compatible = "qcom,msm-hw-limits";
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ lmh_dcvs1: qcom,limits-dcvs@1 {
+ compatible = "qcom,msm-hw-limits";
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ };
+};
+
+&gdsc_usb30 {
+ status = "ok";
+};
+
+&gdsc_pcie_0 {
+ status = "ok";
+};
+
+&gdsc_ufs {
+ status = "ok";
+};
+
+&gdsc_bimc_smmu {
+ clock-names = "bus_clk";
+ clocks = <&clock_mmss clk_mmss_bimc_smmu_axi_clk>;
+ proxy-supply = <&gdsc_bimc_smmu>;
+ qcom,proxy-consumer-enable;
+ status = "ok";
+};
+
+&gdsc_hlos1_vote_lpass_adsp {
+ status = "ok";
+};
+
+&gdsc_hlos1_vote_lpass_core {
+ status = "ok";
+};
+
+&gdsc_venus {
+ status = "ok";
+};
+
+&gdsc_venus_core0 {
+ status = "ok";
+ qcom,support-hw-trigger;
+};
+
+&gdsc_venus_core1 {
+ status = "ok";
+ qcom,support-hw-trigger;
+};
+
+&gdsc_camss_top {
+ status = "ok";
+};
+
+&gdsc_vfe0 {
+ parent-supply = <&gdsc_camss_top>;
+ status = "ok";
+};
+
+&gdsc_vfe1 {
+ parent-supply = <&gdsc_camss_top>;
+ status = "ok";
+};
+
+&gdsc_cpp {
+ parent-supply = <&gdsc_camss_top>;
+ status = "ok";
+};
+
+&gdsc_mdss {
+ proxy-supply = <&gdsc_mdss>;
+ qcom,proxy-consumer-enable;
+ status = "ok";
+};
+
+&gdsc_gpu_gx {
+ clock-names = "core_root_clk";
+ clocks = <&clock_gfx clk_gfx3d_clk_src>;
+ qcom,force-enable-root-clk;
+ parent-supply = <&gfx_vreg>;
+ status = "ok";
+};
+
+&gdsc_gpu_cx {
+ status = "ok";
+};
+
+#include "msm-pmcobalt.dtsi"
+#include "msm-pmicobalt.dtsi"
+#include "msm-pm8005.dtsi"
+#include "msm-pmcobalt-rpm-regulator.dtsi"
+#include "msmcobalt-regulator.dtsi"
+
+#include "msmcobalt-pm.dtsi"
+#include "msm-arm-smmu-cobalt.dtsi"
+#include "msm-arm-smmu-impl-defs-cobalt.dtsi"
+#include "msmcobalt-ion.dtsi"
+#include "msmcobalt-camera.dtsi"
+#include "msmcobalt-vidc.dtsi"
+#include "msmcobalt-coresight.dtsi"
+#include "msmcobalt-bus.dtsi"
+#include "msmcobalt-gpu.dtsi"
+#include "msmcobalt-pinctrl.dtsi"
+#include "msm-audio-lpass.dtsi"
+#include "msmcobalt-mdss.dtsi"
+#include "msmcobalt-mdss-pll.dtsi"
+#include "msmcobalt-blsp.dtsi"
+#include "msmcobalt-audio.dtsi"
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-interposer-pmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-interposer-pmfalcon.dtsi
new file mode 100644
index 000000000000..274281f7c982
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-interposer-pmfalcon.dtsi
@@ -0,0 +1,279 @@
+/* Copyright (c) 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.
+ */
+
+&clock_audio {
+ /delete-property/qcom,audio-ref-clk-gpio;
+};
+
+&slim_aud {
+ tasha_codec {
+ /delete-property/cdc-vdd-buck-supply;
+ /delete-property/cdc-buck-sido-supply;
+ /delete-property/cdc-vdd-tx-h-supply;
+ /delete-property/cdc-vdd-rx-h-supply;
+ /delete-property/cdc-vddpx-1-supply;
+ };
+
+ tavil_codec {
+ /delete-property/cdc-vdd-buck-supply;
+ /delete-property/cdc-buck-sido-supply;
+ /delete-property/cdc-vdd-tx-h-supply;
+ /delete-property/cdc-vdd-rx-h-supply;
+ /delete-property/cdc-vddpx-1-supply;
+ };
+};
+
+
+&led_flash0 {
+ /delete-property/qcom,flash-source;
+ /delete-property/qcom,torch-source;
+ /delete-property/qcom,switch-source;
+};
+
+&led_flash1 {
+ /delete-property/qcom,flash-source;
+ /delete-property/qcom,torch-source;
+ /delete-property/qcom,switch-source;
+};
+
+&eeprom0 {
+ /delete-property/cam_vio-supply;
+ /delete-property/cam_vana-supply;
+ /delete-property/cam_vdig-supply;
+ /delete-property/gpios;
+};
+
+&eeprom1 {
+ /delete-property/cam_vio-supply;
+ /delete-property/cam_vana-supply;
+ /delete-property/cam_vdig-supply;
+};
+
+&eeprom2 {
+ /delete-property/cam_vio-supply;
+ /delete-property/cam_vana-supply;
+ /delete-property/cam_vdig-supply;
+ /delete-property/gpios;
+};
+
+&cci {
+ /delete-node/qcom,camera@0;
+ /delete-node/qcom,camera@1;
+ /delete-node/qcom,camera@2;
+
+};
+
+&bluetooth {
+ /delete-property/qca,bt-vdd-io-supply;
+ /delete-property/qca,bt-vdd-xtal-supply;
+ /delete-property/qca,bt-vdd-core-supply;
+ /delete-property/qca,bt-vdd-pa-supply;
+ /delete-property/qca,bt-vdd-ldo-supply;
+ /delete-property/qca,bt-chip-pwd-supply;
+};
+
+&ufsphy1 {
+ /delete-property/vdda-phy-supply;
+ /delete-property/vdda-pll-supply;
+ /delete-property/vddp-ref-clk-supply;
+};
+
+&ufs1 {
+ /delete-property/vcc-supply;
+ /delete-property/vccq-supply;
+ /delete-property/vccq2-supply;
+};
+
+&sdhc_2 {
+ /delete-property/vdd-supply;
+ /delete-property/vdd-io-supply;
+};
+
+&i2c_5 {
+ /delete-node/synaptics@20;
+};
+
+&i2c_6 {
+ /delete-node/nq@28;
+};
+
+&i2c_7 {
+ /delete-node/qcom,smb138x@8;
+};
+
+&clock_gcc {
+ /delete-property/vdd_dig-supply;
+ /delete-property/vdd_dig_ao-supply;
+};
+
+&clock_mmss {
+ /delete-property/vdd_dig-supply;
+ /delete-property/vdd_mmsscc_mx-supply;
+};
+
+&clock_gpu {
+ /delete-property/vdd_dig-supply;
+};
+
+&clock_gfx {
+ /delete-property/vdd_mx-supply;
+ /delete-property/vdd_gpu_mx-supply;
+};
+
+&pcie0 {
+ /delete-property/vreg-1.8-supply;
+ /delete-property/vreg-0.9-supply;
+ /delete-property/vreg-cx-supply;
+};
+
+&qusb_phy0 {
+ /delete-property/vdd-supply;
+ /delete-property/vdda18-supply;
+ /delete-property/vdda33-supply;
+};
+
+&ssphy {
+ /delete-property/vdd-supply;
+ /delete-property/core-supply;
+};
+
+&usb3 {
+ /delete-property/extcon;
+};
+
+&mdss_dsi {
+ /delete-property/vdda-1p2-supply;
+ /delete-property/vdda-0p9-supply;
+};
+
+&mdss_dsi0 {
+ /delete-property/wqhd-vddio-supply;
+ /delete-property/lab-supply;
+ /delete-property/ibb-supply;
+};
+
+&mdss_dsi1 {
+ /delete-property/wqhd-vddio-supply;
+ /delete-property/lab-supply;
+ /delete-property/ibb-supply;
+};
+
+&mdss_dp_ctrl {
+ /delete-property/vdda-1p2-supply;
+ /delete-property/vdda-0p9-supply;
+ /delete-property/qcom,dp-usbpd-detection;
+};
+
+&mdss_hdmi_pll {
+ /delete-property/vdda-pll-supply;
+ /delete-property/vdda-phy-supply;
+};
+
+&apc0_cpr {
+ /* disable aging and closed-loop */
+ /delete-property/vdd-supply;
+ /delete-property/qcom,cpr-enable;
+ /delete-property/qcom,cpr-hw-closed-loop;
+ /delete-property/qcom,cpr-aging-ref-voltage;
+};
+
+&apc0_pwrcl_vreg {
+ /delete-property/qcom,cpr-aging-max-voltage-adjustment;
+ /delete-property/qcom,cpr-aging-ref-corner;
+ /delete-property/qcom,cpr-aging-ro-scaling-factor;
+ /delete-property/qcom,allow-aging-voltage-adjustment;
+ /delete-property/qcom,allow-aging-open-loop-voltage-adjustment;
+};
+
+&apc1_cpr {
+ /* disable aging and closed-loop */
+ /delete-property/vdd-supply;
+ /delete-property/qcom,cpr-enable;
+ /delete-property/qcom,cpr-hw-closed-loop;
+ /delete-property/qcom,cpr-aging-ref-voltage;
+};
+
+&apc1_perfcl_vreg {
+ /delete-property/qcom,cpr-aging-max-voltage-adjustment;
+ /delete-property/qcom,cpr-aging-ref-corner;
+ /delete-property/qcom,cpr-aging-ro-scaling-factor;
+ /delete-property/qcom,allow-aging-voltage-adjustment;
+ /delete-property/qcom,allow-aging-open-loop-voltage-adjustment;
+};
+
+&gfx_cpr {
+ reg = <0x05061000 0x4000>,
+ <0x00784000 0x1000>;
+ reg-names = "cpr_ctrl", "fuse_base";
+
+ /* disable aging and closed-loop */
+ /delete-property/vdd-supply;
+ /delete-property/qcom,cpr-enable;
+ /delete-property/qcom,cpr-aging-ref-voltage;
+ /delete-property/qcom,cpr-aging-allowed-reg-mask;
+ /delete-property/qcom,cpr-aging-allowed-reg-value;
+};
+
+&gfx_vreg {
+ /delete-property/qcom,cpr-aging-max-voltage-adjustment;
+ /delete-property/qcom,cpr-aging-ref-corner;
+ /delete-property/qcom,cpr-aging-ro-scaling-factor;
+ /delete-property/qcom,allow-aging-voltage-adjustment;
+ /delete-property/qcom,allow-aging-open-loop-voltage-adjustment;
+};
+
+&soc {
+ /delete-node/qcom,csid@ca30000;
+ /delete-node/qcom,csid@ca30400;
+ /delete-node/qcom,csid@ca30800;
+ /delete-node/qcom,csid@ca30c00;
+ /delete-node/gpio_keys;
+ /delete-node/qcom,lpass@17300000;
+ /delete-node/qcom,mss@4080000;
+ /delete-node/qcom,bcl;
+ /delete-node/qcom,msm-thermal;
+ /delete-node/qcom,ssc@5c00000;
+ /delete-node/qcom,spss@1d00000;
+ /delete-node/qcom,wil6210;
+ /delete-node/qcom,rpm-smd;
+ /delete-node/qcom,spmi@800f000;
+
+ rpm_bus: qcom,rpm-smd {
+ compatible = "qcom,rpm-glink";
+ qcom,glink-edge = "rpm";
+ rpm-channel-name = "rpm_requests";
+ };
+
+ spmi_bus: qcom,spmi@800f000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0x800f000 0x1000>,
+ <0x8400000 0x1000000>,
+ <0x9400000 0x1000000>,
+ <0xa400000 0x220000>,
+ <0x800a000 0x3000>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupt-names = "periph_irq";
+ interrupts = <GIC_SPI 326 IRQ_TYPE_NONE>;
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ cell-index = <0>;
+ };
+};
+
+#include "msm-pmfalcon.dtsi"
+#include "msm-pm2falcon.dtsi"
+#include "msmfalcon-regulator.dtsi"
+
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
index 81f53f1512fd..75de2d70028a 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-mtp.dtsi
@@ -18,11 +18,11 @@
compatible = "qca,wcn3990";
qca,bt-vdd-io-supply = <&pmcobalt_s3>;
qca,bt-vdd-xtal-supply = <&pmcobalt_s5>;
- qca,bt-vdd-core-supply = <&pmcobalt_l7_pin_ctrl>;
- qca,bt-vdd-pa-supply = <&pmcobalt_l17_pin_ctrl>;
- qca,bt-vdd-ldo-supply = <&pmcobalt_l25_pin_ctrl>;
+ qca,bt-vdd-core-supply = <&pmcobalt_l7>;
+ qca,bt-vdd-pa-supply = <&pmcobalt_l17>;
+ qca,bt-vdd-ldo-supply = <&pmcobalt_l25>;
qca,bt-chip-pwd-supply = <&pmicobalt_bob_pin1>;
- clocks = <&clock_gcc clk_rf_clk2>;
+ clocks = <&clock_gcc clk_rf_clk2_pin>;
clock-names = "rf_clk2";
qca,bt-vdd-io-voltage-level = <1352000 1352000>;
@@ -362,7 +362,7 @@
&labibb {
status = "ok";
- qpnp,qpnp-labibb-mode = "lcd";
+ qcom,qpnp-labibb-mode = "lcd";
};
&pmicobalt_wled {
@@ -469,6 +469,10 @@
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
};
+&mem_client_3_size {
+ qcom,peripheral-size = <0x500000>;
+};
+
&pmicobalt_haptics {
status = "okay";
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dtsi
index 58471f6d0fd1..1db1fc5cec46 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-qrd-skuk.dtsi
@@ -13,6 +13,7 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include "msmcobalt-pinctrl.dtsi"
#include "msmcobalt-audio.dtsi"
+#include "msmcobalt-camera-sensor-skuk.dtsi"
&blsp1_uart3_hs {
status = "ok";
@@ -184,7 +185,7 @@
&labibb {
status = "ok";
- qpnp,qpnp-labibb-mode = "lcd";
+ qcom,qpnp-labibb-mode = "lcd";
};
&dsi_dual_jdi_a407_cmd {
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi
index f0607ac3a34a..5b8585a33de6 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-qrd-vr1.dtsi
@@ -12,6 +12,7 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include "msmcobalt-pinctrl.dtsi"
+#include "msmcobalt-camera-sensor-qrd-vr1.dtsi"
&blsp1_uart3_hs {
status = "ok";
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-qrd.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-qrd.dtsi
index 682ea8a260ef..6483453ec5fa 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-qrd.dtsi
@@ -260,7 +260,7 @@
&labibb {
status = "ok";
- qpnp,qpnp-labibb-mode = "lcd";
+ qcom,qpnp-labibb-mode = "lcd";
};
&pmicobalt_wled {
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
index bb72cf3a0d2c..1ba5905bcc36 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-regulator.dtsi
@@ -590,8 +590,9 @@
qcom,cpr-idle-cycles = <15>;
qcom,cpr-up-down-delay-time = <3000>;
qcom,cpr-step-quot-init-min = <11>;
- qcom,cpr-step-quot-init-max = <13>;
+ qcom,cpr-step-quot-init-max = <12>;
qcom,cpr-count-mode = <0>; /* All at once */
+ qcom,cpr-count-repeat = <1>;
qcom,cpr-down-error-step-limit = <1>;
qcom,cpr-up-error-step-limit = <1>;
qcom,cpr-corner-switch-delay-time = <209>;
@@ -618,7 +619,7 @@
thread@0 {
qcom,cpr-thread-id = <0>;
qcom,cpr-consecutive-up = <0>;
- qcom,cpr-consecutive-down = <0>;
+ qcom,cpr-consecutive-down = <2>;
qcom,cpr-up-threshold = <2>;
qcom,cpr-down-threshold = <2>;
@@ -740,7 +741,7 @@
qcom,cpr-aging-max-voltage-adjustment = <15000>;
qcom,cpr-aging-ref-corner = <22>;
- qcom,cpr-aging-ro-scaling-factor = <2950>;
+ qcom,cpr-aging-ro-scaling-factor = <1620>;
qcom,allow-aging-voltage-adjustment = <0>;
qcom,allow-aging-open-loop-voltage-adjustment =
<1>;
@@ -761,9 +762,10 @@
qcom,cpr-loop-time = <5000000>;
qcom,cpr-idle-cycles = <15>;
qcom,cpr-up-down-delay-time = <3000>;
- qcom,cpr-step-quot-init-min = <11>;
- qcom,cpr-step-quot-init-max = <13>;
+ qcom,cpr-step-quot-init-min = <9>;
+ qcom,cpr-step-quot-init-max = <14>;
qcom,cpr-count-mode = <0>; /* All at once */
+ qcom,cpr-count-repeat = <1>;
qcom,cpr-down-error-step-limit = <1>;
qcom,cpr-up-error-step-limit = <1>;
qcom,cpr-corner-switch-delay-time = <209>;
@@ -790,7 +792,7 @@
thread@0 {
qcom,cpr-thread-id = <0>;
qcom,cpr-consecutive-up = <0>;
- qcom,cpr-consecutive-down = <0>;
+ qcom,cpr-consecutive-down = <2>;
qcom,cpr-up-threshold = <2>;
qcom,cpr-down-threshold = <2>;
@@ -932,7 +934,7 @@
qcom,cpr-aging-max-voltage-adjustment = <15000>;
qcom,cpr-aging-ref-corner = <25>;
- qcom,cpr-aging-ro-scaling-factor = <2950>;
+ qcom,cpr-aging-ro-scaling-factor = <1700>;
qcom,allow-aging-voltage-adjustment = <0>;
qcom,allow-aging-open-loop-voltage-adjustment =
<1>;
@@ -959,6 +961,7 @@
qcom,cpr-step-quot-init-min = <8>;
qcom,cpr-step-quot-init-max = <12>;
qcom,cpr-count-mode = <0>; /* All-at-once min */
+ qcom,cpr-count-repeat = <1>;
vdd-supply = <&pm8005_s1>;
qcom,voltage-step = <4000>;
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2-interposer-msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2-interposer-msmfalcon.dtsi
new file mode 100644
index 000000000000..02cc86212301
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2-interposer-msmfalcon.dtsi
@@ -0,0 +1,864 @@
+/* Copyright (c) 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.
+ */
+
+/*
+ * As a general rule, only version-specific property overrides should be placed
+ * inside this file. Common device definitions should be placed inside the
+ * msmcobalt.dtsi file.
+ */
+
+#include "msmcobalt-interposer-msmfalcon.dtsi"
+#include "msmcobalt-v2-camera.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSMCOBALT v2";
+ qcom,msm-id = <292 0x20000>;
+};
+
+&clock_cpu {
+ compatible = "qcom,cpu-clock-osm-msmcobalt-v2";
+ /delete-property/ qcom,llm-sw-overr;
+ qcom,pwrcl-speedbin0-v0 =
+ < 300000000 0x0004000f 0x01200020 0x1 1 >,
+ < 364800000 0x05040013 0x01200020 0x1 2 >,
+ < 441600000 0x05040017 0x02200020 0x1 3 >,
+ < 518400000 0x0504001b 0x02200020 0x1 4 >,
+ < 595200000 0x0504001f 0x02200020 0x1 5 >,
+ < 672000000 0x05040023 0x03200020 0x1 6 >,
+ < 748800000 0x05040027 0x03200020 0x1 7 >,
+ < 825600000 0x0404002b 0x03220022 0x1 8 >,
+ < 883200000 0x0404002e 0x04250025 0x1 9 >,
+ < 960000000 0x04040032 0x04280028 0x1 10 >,
+ < 1036800000 0x04040036 0x042b002b 0x1 11 >,
+ < 1094400000 0x04040039 0x052e002e 0x2 12 >,
+ < 1171200000 0x0404003d 0x05310031 0x2 13 >,
+ < 1248000000 0x04040041 0x05340034 0x2 14 >,
+ < 1324800000 0x04040045 0x06370037 0x2 15 >,
+ < 1401600000 0x04040049 0x063a003a 0x2 16 >,
+ < 1478400000 0x0404004d 0x073e003e 0x2 17 >,
+ < 1555200000 0x04040051 0x07410041 0x2 18 >,
+ < 1670400000 0x04040057 0x08460046 0x2 19 >,
+ < 1747200000 0x0404005b 0x08490049 0x2 20 >,
+ < 1824000000 0x0404005f 0x084c004c 0x3 21 >,
+ < 1900800000 0x04040063 0x094f004f 0x3 22 >;
+
+ qcom,perfcl-speedbin0-v0 =
+ < 300000000 0x0004000f 0x01200020 0x1 1 >,
+ < 345600000 0x05040012 0x01200020 0x1 2 >,
+ < 422400000 0x05040016 0x02200020 0x1 3 >,
+ < 499200000 0x0504001a 0x02200020 0x1 4 >,
+ < 576000000 0x0504001e 0x02200020 0x1 5 >,
+ < 652800000 0x05040022 0x03200020 0x1 6 >,
+ < 729600000 0x05040026 0x03200020 0x1 7 >,
+ < 806400000 0x0504002a 0x03220022 0x1 8 >,
+ < 902400000 0x0404002f 0x04260026 0x1 9 >,
+ < 979200000 0x04040033 0x04290029 0x1 10 >,
+ < 1056000000 0x04040037 0x052c002c 0x1 11 >,
+ < 1132800000 0x0404003b 0x052f002f 0x1 12 >,
+ < 1190400000 0x0404003e 0x05320032 0x2 13 >,
+ < 1267200000 0x04040042 0x06350035 0x2 14 >,
+ < 1344000000 0x04040046 0x06380038 0x2 15 >,
+ < 1420800000 0x0404004a 0x063b003b 0x2 16 >,
+ < 1497600000 0x0404004e 0x073e003e 0x2 17 >,
+ < 1574400000 0x04040052 0x07420042 0x2 18 >,
+ < 1651200000 0x04040056 0x07450045 0x2 19 >,
+ < 1728000000 0x0404005a 0x08480048 0x2 20 >,
+ < 1804800000 0x0404005e 0x084b004b 0x2 21 >,
+ < 1881600000 0x04040062 0x094e004e 0x2 22 >,
+ < 1958400000 0x04040066 0x09520052 0x2 23 >,
+ < 2035200000 0x0404006a 0x09550055 0x3 24 >,
+ < 2112000000 0x0404006e 0x0a580058 0x3 25 >,
+ < 2188800000 0x04040072 0x0a5b005b 0x3 26 >,
+ < 2265600000 0x04040076 0x0a5e005e 0x3 27 >,
+ < 2342400000 0x0404007a 0x0a620062 0x3 28 >,
+ < 2419200000 0x0404007e 0x0a650065 0x3 29 >,
+ < 2496000000 0x04040082 0x0a680068 0x3 30 >;
+
+ qcom,perfcl-speedbin1-v0 =
+ < 300000000 0x0004000f 0x01200020 0x1 1 >,
+ < 345600000 0x05040012 0x01200020 0x1 2 >,
+ < 422400000 0x05040016 0x02200020 0x1 3 >,
+ < 499200000 0x0504001a 0x02200020 0x1 4 >,
+ < 576000000 0x0504001e 0x02200020 0x1 5 >,
+ < 652800000 0x05040022 0x03200020 0x1 6 >,
+ < 729600000 0x05040026 0x03200020 0x1 7 >,
+ < 806400000 0x0504002a 0x03220022 0x1 8 >,
+ < 902400000 0x0404002f 0x04260026 0x1 9 >,
+ < 979200000 0x04040033 0x04290029 0x1 10 >,
+ < 1056000000 0x04040037 0x052c002c 0x1 11 >,
+ < 1132800000 0x0404003b 0x052f002f 0x1 12 >,
+ < 1190400000 0x0404003e 0x05320032 0x2 13 >,
+ < 1267200000 0x04040042 0x06350035 0x2 14 >,
+ < 1344000000 0x04040046 0x06380038 0x2 15 >,
+ < 1420800000 0x0404004a 0x063b003b 0x2 16 >,
+ < 1497600000 0x0404004e 0x073e003e 0x2 17 >,
+ < 1574400000 0x04040052 0x07420042 0x2 18 >,
+ < 1651200000 0x04040056 0x07450045 0x2 19 >,
+ < 1728000000 0x0404005a 0x08480048 0x2 20 >,
+ < 1804800000 0x0404005e 0x084b004b 0x2 21 >,
+ < 1881600000 0x04040062 0x094e004e 0x2 22 >,
+ < 1958400000 0x04040066 0x09520052 0x2 23 >,
+ < 2035200000 0x0404006a 0x09550055 0x3 24 >,
+ < 2112000000 0x0404006e 0x0a580058 0x3 25 >,
+ < 2208000000 0x04040073 0x0a5c005c 0x3 26 >,
+ < 2304000000 0x04010078 0x0a5c005c 0x3 26 >;
+};
+
+&msm_cpufreq {
+ qcom,cpufreq-table-0 =
+ < 300000 >,
+ < 364800 >,
+ < 441600 >,
+ < 518400 >,
+ < 595200 >,
+ < 672000 >,
+ < 748800 >,
+ < 825600 >,
+ < 883200 >,
+ < 960000 >,
+ < 1036800 >,
+ < 1094400 >,
+ < 1171200 >,
+ < 1248000 >,
+ < 1324800 >,
+ < 1401600 >,
+ < 1478400 >,
+ < 1555200 >,
+ < 1670400 >,
+ < 1747200 >,
+ < 1824000 >,
+ < 1900800 >;
+
+ qcom,cpufreq-table-4 =
+ < 300000 >,
+ < 345600 >,
+ < 422400 >,
+ < 499200 >,
+ < 576000 >,
+ < 652800 >,
+ < 729600 >,
+ < 806400 >,
+ < 902400 >,
+ < 979200 >,
+ < 1056000 >,
+ < 1132800 >,
+ < 1190400 >,
+ < 1267200 >,
+ < 1344000 >,
+ < 1420800 >,
+ < 1497600 >,
+ < 1574400 >,
+ < 1651200 >,
+ < 1728000 >,
+ < 1804800 >,
+ < 1881600 >,
+ < 1958400 >,
+ < 2035200 >,
+ < 2112000 >,
+ < 2188800 >,
+ < 2265600 >,
+ < 2342400 >,
+ < 2419200 >,
+ < 2496000 >;
+};
+
+&bwmon {
+ compatible = "qcom,bimc-bwmon4";
+ qcom,hw-timer-hz = <19200000>;
+};
+
+&devfreq_cpufreq {
+ mincpubw-cpufreq {
+ cpu-to-dev-map-0 =
+ < 1900800 1525 >;
+ cpu-to-dev-map-4 =
+ < 2112000 1525 >,
+ < 2496000 5195 >;
+ };
+};
+
+&clock_gcc {
+ compatible = "qcom,gcc-cobalt-v2";
+};
+
+&clock_mmss {
+ compatible = "qcom,mmsscc-cobalt-v2";
+};
+
+&clock_gpu {
+ compatible = "qcom,gpucc-cobalt-v2";
+};
+
+&clock_gfx {
+ compatible = "qcom,gfxcc-cobalt-v2";
+ qcom,gfxfreq-speedbin0 =
+ < 0 0 0 >,
+ < 180000000 1 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 257000000 2 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 342000000 3 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 414000000 4 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 515000000 5 RPM_SMD_REGULATOR_LEVEL_NOM >,
+ < 596000000 6 RPM_SMD_REGULATOR_LEVEL_NOM >,
+ < 670000000 7 RPM_SMD_REGULATOR_LEVEL_TURBO >;
+ qcom,gfxfreq-mx-speedbin0 =
+ < 0 0 >,
+ < 180000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 257000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 342000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 414000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 515000000 RPM_SMD_REGULATOR_LEVEL_NOM >,
+ < 596000000 RPM_SMD_REGULATOR_LEVEL_NOM >,
+ < 670000000 RPM_SMD_REGULATOR_LEVEL_TURBO >;
+};
+
+&mdss_mdp {
+ qcom,vbif-settings = <0x00d0 0x00002020>;
+ qcom,max-bandwidth-low-kbps = <9400000>;
+ qcom,max-bandwidth-high-kbps = <9400000>;
+ qcom,max-bandwidth-per-pipe-kbps = <4700000>;
+};
+
+&pmcobalt_s10 {
+ regulator-min-microvolt = <568000>;
+ regulator-max-microvolt = <1056000>;
+};
+
+&pmcobalt_s13 {
+ regulator-min-microvolt = <568000>;
+ regulator-max-microvolt = <1056000>;
+};
+
+&apc0_cpr {
+ compatible = "qcom,cprh-msmcobalt-v2-kbss-regulator";
+ qcom,cpr-corner-switch-delay-time = <1042>;
+ qcom,cpr-aging-ref-voltage = <1056000>;
+};
+
+&apc0_pwrcl_vreg {
+ regulator-max-microvolt = <23>;
+
+ qcom,cpr-fuse-combos = <16>;
+ qcom,cpr-speed-bins = <2>;
+ qcom,cpr-speed-bin-corners = <22 22>;
+ qcom,cpr-corners =
+ /* Speed bin 0 */
+ <22 22 22 22 22 22 22 22>,
+ /* Speed bin 1 */
+ <22 22 22 22 22 22 22 22>;
+
+ qcom,cpr-corner-fmax-map =
+ /* Speed bin 0 */
+ <8 11 18 22>,
+ /* Speed bin 1 */
+ <8 11 18 22>;
+
+ qcom,cpr-voltage-ceiling =
+ /* Speed bin 0 */
+ <828000 828000 828000 828000 828000
+ 828000 828000 828000 828000 828000
+ 828000 900000 900000 900000 900000
+ 900000 900000 900000 952000 952000
+ 1056000 1056000>,
+ /* Speed bin 1 */
+ <828000 828000 828000 828000 828000
+ 828000 828000 828000 828000 828000
+ 828000 900000 900000 900000 900000
+ 900000 900000 900000 952000 952000
+ 1056000 1056000>;
+
+ qcom,cpr-voltage-floor =
+ /* Speed bin 0 */
+ <568000 568000 568000 568000 568000
+ 568000 568000 568000 568000 568000
+ 568000 632000 632000 632000 632000
+ 632000 632000 632000 712000 712000
+ 772000 772000>,
+ /* Speed bin 1 */
+ <568000 568000 568000 568000 568000
+ 568000 568000 568000 568000 568000
+ 568000 632000 632000 632000 632000
+ 632000 632000 632000 712000 712000
+ 772000 772000>;
+
+ qcom,cpr-floor-to-ceiling-max-range =
+ /* Speed bin 0 */
+ <55000 55000 55000 55000
+ 55000 55000 55000 55000
+ 55000 55000 55000 65000
+ 65000 65000 65000 65000
+ 65000 65000 65000 65000
+ 65000 65000>,
+ /* Speed bin 1 */
+ <55000 55000 55000 55000
+ 55000 55000 55000 55000
+ 55000 55000 55000 65000
+ 65000 65000 65000 65000
+ 65000 65000 65000 65000
+ 65000 65000>;
+
+ qcom,corner-frequencies =
+ /* Speed bin 0 */
+ <300000000 364800000 441600000
+ 518400000 595200000 672000000
+ 748800000 825600000 883200000
+ 960000000 1036800000 1094400000
+ 1171200000 1248000000 1324800000
+ 1401600000 1478400000 1555200000
+ 1670400000 1747200000 1824000000
+ 1900800000>,
+ /* Speed bin 1 */
+ <300000000 364800000 441600000
+ 518400000 595200000 672000000
+ 748800000 825600000 883200000
+ 960000000 1036800000 1094400000
+ 1171200000 1248000000 1324800000
+ 1401600000 1478400000 1555200000
+ 1670400000 1747200000 1824000000
+ 1900800000>;
+
+ qcom,cpr-ro-scaling-factor =
+ <2595 2794 2577 2762 2471 2674 2199
+ 2553 3189 3255 3192 2962 3054 2982
+ 2042 2945>,
+ <2595 2794 2577 2762 2471 2674 2199
+ 2553 3189 3255 3192 2962 3054 2982
+ 2042 2945>,
+ <2391 2550 2483 2638 2382 2564 2259
+ 2555 2766 3041 2988 2935 2873 2688
+ 2013 2784>,
+ <2066 2153 2300 2434 2220 2386 2288
+ 2465 2028 2511 2487 2734 2554 2117
+ 1892 2377>;
+
+ qcom,cpr-open-loop-voltage-fuse-adjustment =
+ /* Speed bin 0 */
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>,
+ /* Speed bin 1 */
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>,
+ <40000 24000 0 30000>;
+
+ qcom,cpr-closed-loop-voltage-fuse-adjustment =
+ /* Speed bin 0 */
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>,
+ /* Speed bin 1 */
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>,
+ <20000 26000 0 30000>;
+
+ qcom,allow-voltage-interpolation;
+ qcom,allow-quotient-interpolation;
+ qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+
+ qcom,cpr-aging-ref-corner = <22 22>;
+ qcom,cpr-aging-ro-scaling-factor = <2950>;
+ qcom,allow-aging-voltage-adjustment = <0>;
+};
+
+&apc1_cpr {
+ compatible = "qcom,cprh-msmcobalt-v2-kbss-regulator";
+ qcom,cpr-corner-switch-delay-time = <1042>;
+ qcom,cpr-aging-ref-voltage = <1056000>;
+};
+
+&apc1_perfcl_vreg {
+ regulator-max-microvolt = <31>;
+
+ qcom,cpr-fuse-combos = <16>;
+ qcom,cpr-speed-bins = <2>;
+ qcom,cpr-speed-bin-corners = <30 26>;
+ qcom,cpr-corners =
+ /* Speed bin 0 */
+ <30 30 30 30 30 30 30 30>,
+ /* Speed bin 1 */
+ <26 26 26 26 26 26 26 26>;
+
+ qcom,cpr-corner-fmax-map =
+ /* Speed bin 0 */
+ <8 12 20 30>,
+ /* Speed bin 1 */
+ <8 12 20 26>;
+
+ qcom,cpr-voltage-ceiling =
+ /* Speed bin 0 */
+ <828000 828000 828000 828000 828000
+ 828000 828000 828000 828000 828000
+ 828000 828000 900000 900000 900000
+ 900000 900000 900000 900000 900000
+ 952000 952000 952000 1056000 1056000
+ 1056000 1056000 1056000 1056000 1056000>,
+ /* Speed bin 1 */
+ <828000 828000 828000 828000 828000
+ 828000 828000 828000 828000 828000
+ 828000 828000 900000 900000 900000
+ 900000 900000 900000 900000 900000
+ 952000 952000 952000 1056000 1056000
+ 1056000>;
+
+ qcom,cpr-voltage-floor =
+ /* Speed bin 0 */
+ <568000 568000 568000 568000 568000
+ 568000 568000 568000 568000 568000
+ 568000 568000 632000 632000 632000
+ 632000 632000 632000 632000 632000
+ 712000 712000 712000 772000 772000
+ 772000 772000 772000 772000 772000>,
+ /* Speed bin 1 */
+ <568000 568000 568000 568000 568000
+ 568000 568000 568000 568000 568000
+ 568000 568000 632000 632000 632000
+ 632000 632000 632000 632000 632000
+ 712000 712000 712000 772000 772000
+ 772000>;
+
+ qcom,cpr-floor-to-ceiling-max-range =
+ /* Speed bin 0 */
+ <55000 55000 55000 55000
+ 55000 55000 55000 55000
+ 55000 55000 55000 55000
+ 65000 65000 65000 65000
+ 65000 65000 65000 65000
+ 65000 65000 65000 65000
+ 65000 65000 65000 65000
+ 65000 65000>,
+ /* Speed bin 1 */
+ <55000 55000 55000 55000
+ 55000 55000 55000 55000
+ 55000 55000 55000 55000
+ 65000 65000 65000 65000
+ 65000 65000 65000 65000
+ 65000 65000 65000 65000
+ 65000 65000>;
+
+ qcom,corner-frequencies =
+ /* Speed bin 0 */
+ <300000000 345600000 422400000
+ 499200000 576000000 652800000
+ 729600000 806400000 902400000
+ 979200000 1056000000 1132800000
+ 1190400000 1267200000 1344000000
+ 1420800000 1497600000 1574400000
+ 1651200000 1728000000 1804800000
+ 1881600000 1958400000 2035200000
+ 2112000000 2188800000 2265600000
+ 2342400000 2419200000 2496000000>,
+ /* Speed bin 1 */
+ <300000000 345600000 422400000
+ 499200000 576000000 652800000
+ 729600000 806400000 902400000
+ 979200000 1056000000 1132800000
+ 1190400000 1267200000 1344000000
+ 1420800000 1497600000 1574400000
+ 1651200000 1728000000 1804800000
+ 1881600000 1958400000 2035200000
+ 2112000000 2208000000>;
+
+ qcom,cpr-ro-scaling-factor =
+ <2857 3057 2828 2952 2699 2798 2446
+ 2631 2629 2578 2244 3344 3289 3137
+ 3164 2655>,
+ <2857 3057 2828 2952 2699 2798 2446
+ 2631 2629 2578 2244 3344 3289 3137
+ 3164 2655>,
+ <2603 2755 2676 2777 2573 2685 2465
+ 2610 2312 2423 2243 3104 3022 3036
+ 2740 2303>,
+ <1901 2016 2096 2228 2034 2161 2077
+ 2188 1565 1870 1925 2235 2205 2413
+ 1762 1478>;
+
+ qcom,cpr-open-loop-voltage-fuse-adjustment =
+ /* Speed bin 0 */
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ /* Speed bin 1 */
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>,
+ <8000 0 0 52000>;
+
+ qcom,cpr-closed-loop-voltage-fuse-adjustment =
+ /* Speed bin 0 */
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ /* Speed bin 1 */
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>,
+ <0 0 0 50000>;
+
+ qcom,allow-voltage-interpolation;
+ qcom,allow-quotient-interpolation;
+ qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+
+ qcom,cpr-aging-ref-corner = <30 26>;
+ qcom,cpr-aging-ro-scaling-factor = <2950>;
+ qcom,allow-aging-voltage-adjustment = <0>;
+};
+
+&pm8005_s1 {
+ regulator-min-microvolt = <516000>;
+ regulator-max-microvolt = <1088000>;
+};
+
+&gfx_cpr {
+ compatible = "qcom,cpr4-msmcobalt-v2-mmss-regulator";
+ qcom,cpr-aging-ref-voltage = <1024000>;
+};
+
+&gfx_vreg {
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <8>;
+
+ qcom,cpr-fuse-corners = <4>;
+ qcom,cpr-fuse-combos = <8>;
+ qcom,cpr-corners = <8>;
+
+ qcom,cpr-corner-fmax-map = <1 3 5 8>;
+
+ qcom,cpr-voltage-ceiling =
+ <656000 716000 772000 880000 908000 948000 1016000 1088000>,
+ <660000 724000 772000 832000 916000 968000 1024000 1024000>,
+ <660000 724000 772000 832000 916000 968000 1024000 1024000>,
+ <660000 724000 772000 832000 916000 968000 1024000 1024000>,
+ <660000 724000 772000 832000 916000 968000 1024000 1024000>,
+ <660000 724000 772000 832000 916000 968000 1024000 1024000>,
+ <660000 724000 772000 832000 916000 968000 1024000 1024000>,
+ <660000 724000 772000 832000 916000 968000 1024000 1024000>;
+
+ qcom,cpr-voltage-floor =
+ <516000 516000 532000 584000 632000 672000 712000 756000>;
+
+ qcom,mem-acc-voltage = <1 1 1 2 2 2 2 2>;
+
+ qcom,corner-frequencies =
+ <180000000 257000000 342000000 414000000
+ 515000000 596000000 670000000 710000000>;
+
+ qcom,cpr-target-quotients =
+ < 0 0 0 0 331 357 0 0
+ 0 0 0 0 0 0 115 0>,
+ < 0 0 0 0 467 500 0 0
+ 0 0 0 0 0 0 199 0>,
+ < 0 0 0 0 628 665 0 0
+ 0 0 0 0 0 0 290 0>,
+ < 0 0 0 0 762 805 0 0
+ 0 0 0 0 0 0 397 0>,
+ < 0 0 0 0 964 1013 0 0
+ 0 0 1143 0 1138 1055 0 0>,
+ < 0 0 0 0 0 0 0 0
+ 0 0 1306 0 1289 1168 0 0>,
+ < 0 0 0 0 0 0 0 0
+ 0 0 1468 0 1429 1256 0 0>,
+ < 0 0 0 0 0 0 0 0
+ 0 0 1627 0 1578 1353 0 0>;
+
+ qcom,cpr-ro-scaling-factor =
+ < 0 0 0 0 2377 2571 0 0
+ 0 0 2168 0 2209 1849 1997 0>,
+ < 0 0 0 0 2377 2571 0 0
+ 0 0 2168 0 2209 1849 1997 0>,
+ < 0 0 0 0 2377 2571 0 0
+ 0 0 2168 0 2209 1849 1997 0>,
+ < 0 0 0 0 2377 2571 0 0
+ 0 0 2168 0 2209 1849 1997 0>,
+ < 0 0 0 0 2377 2571 0 0
+ 0 0 2168 0 2209 1849 1997 0>,
+ < 0 0 0 0 2377 2571 0 0
+ 0 0 2168 0 2209 1849 1997 0>,
+ < 0 0 0 0 2377 2571 0 0
+ 0 0 2168 0 2209 1849 1997 0>,
+ < 0 0 0 0 2377 2571 0 0
+ 0 0 2168 0 2209 1849 1997 0>;
+
+ qcom,cpr-open-loop-voltage-fuse-adjustment =
+ < 100000 0 0 0>,
+ < 100000 0 0 0>,
+ < 85000 (-15000) (-15000) (-15000)>,
+ < 85000 (-15000) (-15000) (-15000)>,
+ < 85000 (-15000) (-15000) (-15000)>,
+ < 85000 (-15000) (-15000) (-15000)>,
+ < 85000 (-15000) (-15000) (-15000)>,
+ < 85000 (-15000) (-15000) (-15000)>;
+
+ qcom,cpr-closed-loop-voltage-adjustment =
+ < 96000 18000 4000 0
+ 0 13000 9000 0>,
+ < 96000 18000 4000 0
+ 0 13000 9000 0>,
+ < 81000 3000 (-11000) (-15000)
+ (-15000) (-2000) (-6000) (-15000)>,
+ < 81000 3000 (-11000) (-15000)
+ (-15000) (-2000) (-6000) (-15000)>,
+ < 81000 3000 (-11000) (-15000)
+ (-15000) (-2000) (-6000) (-15000)>,
+ < 81000 3000 (-11000) (-15000)
+ (-15000) (-2000) (-6000) (-15000)>,
+ < 81000 3000 (-11000) (-15000)
+ (-15000) (-2000) (-6000) (-15000)>,
+ < 81000 3000 (-11000) (-15000)
+ (-15000) (-2000) (-6000) (-15000)>;
+
+ qcom,cpr-floor-to-ceiling-max-range =
+ <50000 50000 50000 50000 50000 50000 70000 70000>;
+
+ qcom,cpr-fused-closed-loop-voltage-adjustment-map =
+ <0 0 1 2 3 0 0 4>;
+
+ qcom,allow-voltage-interpolation;
+ qcom,cpr-scaled-open-loop-voltage-as-ceiling;
+
+ qcom,cpr-aging-max-voltage-adjustment = <15000>;
+ qcom,cpr-aging-ref-corner = <8>;
+ qcom,cpr-aging-ro-scaling-factor = <2950>;
+ qcom,allow-aging-voltage-adjustment = <0 0 1 1 1 1 1 1>;
+};
+
+&qusb_phy0 {
+ reg = <0x0c012000 0x2a8>,
+ <0x01fcb24c 0x4>,
+ <0x00784238 0x4>;
+ reg-names = "qusb_phy_base",
+ "tcsr_clamp_dig_n_1p8",
+ "efuse_addr";
+ qcom,efuse-bit-pos = <16>;
+ qcom,efuse-num-bits = <4>;
+ qcom,qusb-phy-init-seq =
+ /* <value reg_offset> */
+ <0x13 0x04 /* analog_controls_two */
+ 0x7c 0x18c /* pll_clock_inverter */
+ 0x80 0x2c /* pll_cmode */
+ 0x0a 0x184 /* pll_lock_delay */
+ 0xa5 0x23c /* tune1 */
+ 0x09 0x240 /* tune2 */
+ 0x19 0xb4>; /* digital_timers_two */
+};
+
+&msm_vidc {
+ qcom,load-freq-tbl =
+ /* Encoders */
+ <1105920 533000000 0x55555555>, /* 4kx2304@30 */ /*TURBO*/
+ <1036800 444000000 0x55555555>, /* 720p@240, 1080p@120,1440p@60,
+ * UHD@30 */ /*NOMINAL*/
+ < 829440 355200000 0x55555555>, /* UHD/4096x2160@30 SVSL1 */
+ < 489600 269330000 0x55555555>, /* 1080p@60, 720p@120 SVS */
+ < 345600 200000000 0x55555555>, /* 2560x1440@24, 1080p@30 */
+ /* SVS2 */
+
+ /* Decoders */
+ <2211840 533000000 0xffffffff>, /* 4kx2304@60, 1080p@240 */
+ /* TURBO */
+ <1728000 444000000 0xffffffff>, /* 2560x1440@120 */
+ /* NOMINAL */
+ <1675472 355200000 0xffffffff>, /* 4kx2304@44 */ /*SVSL1*/
+ <1105920 269330000 0xffffffff>, /* UHD/4k2304@30, 1080p@120 */
+ /* SVS */
+ < 829440 200000000 0xffffffff>; /* 720p@120, 1080p@60 */
+ /* SVS2 */
+
+ qcom,imem-ab-tbl =
+ <200000000 1560000>,/* imem @ svs2 freq 75 Mhz */
+ <269330000 3570000>,/* imem @ svs freq 171 Mhz */
+ <355200000 3570000>,/* imem @ svs freq 171 Mhz */
+ <444000000 6750000>,/* imem @ nom freq 323 Mhz */
+ <533000000 8490000>;/* imem @ turbo freq 406 Mhz */
+
+ qcom,dcvs-tbl = /* minLoad LoadLow LoadHigh CodecCheck */
+ /* Decode */
+ /* Load > Nominal, Nominal <-> Turbo Eg.3840x2160@60 */
+ <1728000 1728000 2211840 0x3f00000c>,
+ /* Encoder */
+ /* Load > Nominal, Nominal <-> Turbo Eg. 4kx2304@30 */
+ <1036800 1036800 1105920 0x04000004>,
+ /* Load > SVSL1, SVSL1<-> Nominal Eg. 3840x2160@30 */
+ < 829440 829440 1036800 0x04000004>,
+ /* Load > SVS , SVS <-> SVSL1 Eg. 4kx2304@24 */
+ < 489600 489600 829440 0x04000004>;
+
+ qcom,dcvs-limit = /* Min Frame size, Min MBs/sec */
+ <32400 30>, /* Encoder 3840x2160@30 */
+ <32400 60>; /* Decoder 3840x2160@60 */
+
+};
+
+&soc {
+ /* Gold L2 SAW */
+ qcom,spm@178120000 {
+ qcom,saw2-avs-limit = <0x4200420>;
+ };
+
+ /* Silver L2 SAW */
+ qcom,spm@179120000 {
+ qcom,saw2-avs-limit = <0x4200420>;
+ };
+};
+
+/* GPU overrides */
+&msm_gpu {
+ /* Updated chip ID */
+ qcom,chipid = <0x05040001>;
+ qcom,initial-pwrlevel = <5>;
+
+ qcom,gpu-pwrlevels {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "qcom,gpu-pwrlevels";
+
+ qcom,gpu-pwrlevel@0 {
+ reg = <0>;
+ qcom,gpu-freq = <670000000>;
+ qcom,bus-freq = <12>;
+ qcom,bus-min = <11>;
+ qcom,bus-max = <12>;
+ };
+
+ qcom,gpu-pwrlevel@1 {
+ reg = <1>;
+ qcom,gpu-freq = <596000000>;
+ qcom,bus-freq = <11>;
+ qcom,bus-min = <9>;
+ qcom,bus-max = <12>;
+ };
+
+ qcom,gpu-pwrlevel@2 {
+ reg = <2>;
+ qcom,gpu-freq = <515000000>;
+ qcom,bus-freq = <11>;
+ qcom,bus-min = <9>;
+ qcom,bus-max = <12>;
+ };
+
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <414000000>;
+ qcom,bus-freq = <9>;
+ qcom,bus-min = <8>;
+ qcom,bus-max = <11>;
+ };
+
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
+ qcom,gpu-freq = <342000000>;
+ qcom,bus-freq = <8>;
+ qcom,bus-min = <5>;
+ qcom,bus-max = <9>;
+ };
+
+ qcom,gpu-pwrlevel@5 {
+ reg = <5>;
+ qcom,gpu-freq = <257000000>;
+ qcom,bus-freq = <5>;
+ qcom,bus-min = <3>;
+ qcom,bus-max = <8>;
+ };
+
+ qcom,gpu-pwrlevel@6 {
+ reg = <6>;
+ qcom,gpu-freq = <180000000>;
+ qcom,bus-freq = <3>;
+ qcom,bus-min = <1>;
+ qcom,bus-max = <5>;
+ };
+ qcom,gpu-pwrlevel@7 {
+ reg = <7>;
+ qcom,gpu-freq = <27000000>;
+ qcom,bus-freq = <0>;
+ qcom,bus-min = <0>;
+ qcom,bus-max = <0>;
+ };
+ };
+};
+
+&spss_utils {
+ qcom,spss-test-firmware-name = "spss2t"; /* 8 chars max */
+ qcom,spss-prod-firmware-name = "spss2p"; /* 8 chars max */
+};
+
+&ufs1 {
+ clock-names =
+ "core_clk",
+ "bus_aggr_clk",
+ "iface_clk",
+ "core_clk_unipro",
+ "core_clk_ice",
+ "ref_clk",
+ "tx_lane0_sync_clk",
+ "rx_lane0_sync_clk",
+ "rx_lane1_sync_clk";
+ clocks =
+ <&clock_gcc clk_gcc_ufs_axi_hw_ctl_clk>,
+ <&clock_gcc clk_gcc_aggre1_ufs_axi_clk>,
+ <&clock_gcc clk_gcc_ufs_ahb_clk>,
+ <&clock_gcc clk_gcc_ufs_unipro_core_hw_ctl_clk>,
+ <&clock_gcc clk_gcc_ufs_ice_core_hw_ctl_clk>,
+ <&clock_gcc clk_ln_bb_clk1>,
+ <&clock_gcc clk_gcc_ufs_tx_symbol_0_clk>,
+ <&clock_gcc clk_gcc_ufs_rx_symbol_0_clk>,
+ <&clock_gcc clk_gcc_ufs_rx_symbol_1_clk>;
+ freq-table-hz =
+ <50000000 200000000>,
+ <0 0>,
+ <0 0>,
+ <37500000 150000000>,
+ <75000000 300000000>,
+ <0 0>,
+ <0 0>,
+ <0 0>,
+ <0 0>;
+
+ lanes-per-direction = <2>;
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-cdp.dts b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-cdp.dts
new file mode 100644
index 000000000000..ac564d700cd8
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-cdp.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 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.
+ */
+
+
+/dts-v1/;
+
+#include "msmcobalt-v2.1-interposer-msmfalcon.dtsi"
+#include "msmcobalt-interposer-msmfalcon-cdp.dtsi"
+#include "msmcobalt-interposer-pmfalcon.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM COBALT v2.1 MSM FALCON Interposer CDP";
+ compatible = "qcom,msmcobalt-cdp", "qcom,msmcobalt", "qcom,cdp";
+ qcom,board-id = <1 1>;
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-mtp.dts b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-mtp.dts
new file mode 100644
index 000000000000..aaa56ea2f492
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-mtp.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 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.
+ */
+
+
+/dts-v1/;
+
+#include "msmcobalt-v2.1-interposer-msmfalcon.dtsi"
+#include "msmcobalt-interposer-msmfalcon-mtp.dtsi"
+#include "msmcobalt-interposer-pmfalcon.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM COBALT v2.1 MSM FALCON Interposer MTP";
+ compatible = "qcom,msmcobalt-mtp", "qcom,msmcobalt", "qcom,mtp";
+ qcom,board-id = <8 2>;
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dts b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dts
new file mode 100644
index 000000000000..69a5419503ac
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dts
@@ -0,0 +1,23 @@
+/* Copyright (c) 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.
+ */
+
+
+/dts-v1/;
+
+#include "msmcobalt-v2.1-interposer-msmfalcon-qrd.dtsi"
+
+/ {
+ model =
+ "Qualcomm Technologies, Inc. MSM COBALT v2.1 MSM FALCON Interposer QRD";
+ compatible = "qcom,msmcobalt-qrd", "qcom,msmcobalt", "qcom,qrd";
+ qcom,board-id = <0x03000b 0x80>;
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dtsi
new file mode 100644
index 000000000000..fbb1e56b7090
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon-qrd.dtsi
@@ -0,0 +1,105 @@
+/* Copyright (c) 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.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include "msmcobalt-v2.1-interposer-msmfalcon.dtsi"
+
+&uartblsp2dm1 {
+ status = "ok";
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart_console_active>;
+};
+
+&ufsphy1 {
+ vdda-phy-supply = <&pmcobalt_l1>;
+ vdda-pll-supply = <&pmcobalt_l2>;
+ vddp-ref-clk-supply = <&pmcobalt_l26>;
+ vdda-phy-max-microamp = <51400>;
+ vdda-pll-max-microamp = <14600>;
+ vddp-ref-clk-max-microamp = <100>;
+ vddp-ref-clk-always-on;
+ status = "ok";
+};
+
+&ufs1 {
+ vdd-hba-supply = <&gdsc_ufs>;
+ vdd-hba-fixed-regulator;
+ vcc-supply = <&pmcobalt_l20>;
+ vccq-supply = <&pmcobalt_l26>;
+ vccq2-supply = <&pmcobalt_s4>;
+ vcc-max-microamp = <750000>;
+ vccq-max-microamp = <560000>;
+ vccq2-max-microamp = <750000>;
+ status = "ok";
+};
+
+&ufs_ice {
+ status = "ok";
+};
+
+&sdc2_cd_on {
+ mux {
+ pins = "gpio54";
+ };
+
+ config {
+ pins = "gpio54";
+ /delete-property/ bias-pull-up;
+ bias-disable;
+ };
+};
+
+&sdc2_cd_off {
+ mux {
+ pins = "gpio54";
+ };
+
+ config {
+ pins = "gpio54";
+ /delete-property/ bias-pull-up;
+ bias-disable;
+ };
+};
+
+&sdhc_2 {
+ vdd-supply = <&pmcobalt_l21>;
+ qcom,vdd-voltage-level = <2950000 2960000>;
+ qcom,vdd-current-level = <200 800000>;
+
+ vdd-io-supply = <&pmcobalt_l13>;
+ qcom,vdd-io-voltage-level = <1808000 2960000>;
+ qcom,vdd-io-current-level = <200 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ qcom,clk-rates = <400000 20000000 25000000
+ 50000000 100000000 200000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+ cd-gpios = <&tlmm 54 0x0>;
+
+ status = "ok";
+};
+
+/{
+ qrd_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+
+ #include "batterydata-qrd-skuk-4v4-3000mah.dtsi"
+ };
+};
+
+&pmicobalt_fg {
+ qcom,battery-data = <&qrd_batterydata>;
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon.dtsi
new file mode 100644
index 000000000000..96ff7f70788f
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.1-interposer-msmfalcon.dtsi
@@ -0,0 +1,18 @@
+/* Copyright (c) 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.
+ */
+
+#include "msmcobalt-v2-interposer-msmfalcon.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSMCOBALT v2.1";
+ qcom,msm-id = <292 0x20001>;
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
index beecee843778..f09f4d8b3adb 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
@@ -26,6 +26,25 @@
&clock_cpu {
compatible = "qcom,cpu-clock-osm-msmcobalt-v2";
+ reg = <0x179c0000 0x4000>,
+ <0x17916000 0x1000>,
+ <0x17816000 0x1000>,
+ <0x179d1000 0x1000>,
+ <0x17914800 0x800>,
+ <0x17814800 0x800>,
+ <0x00784130 0x8>,
+ <0x1791101c 0x8>;
+ reg-names = "osm", "pwrcl_pll", "perfcl_pll",
+ "apcs_common", "pwrcl_acd", "perfcl_acd",
+ "perfcl_efuse", "debug";
+
+ qcom,acdtd-val = <0x00009611 0x00009611>;
+ qcom,acdcr-val = <0x002b5ffd 0x002b5ffd>;
+ qcom,acdsscr-val = <0x00000501 0x00000501>;
+ qcom,acdextint0-val = <0x2cf9ae8 0x2cf9ae8>;
+ qcom,acdextint1-val = <0x2cf9afc 0x2cf9afc>;
+ qcom,acdautoxfer-val = <0x00000015 0x00000015>;
+
/delete-property/ qcom,llm-sw-overr;
qcom,pwrcl-speedbin0-v0 =
< 300000000 0x0004000f 0x01200020 0x1 1 >,
@@ -422,48 +441,50 @@
<40000 24000 0 30000>,
<40000 24000 0 30000>,
<40000 24000 0 30000>,
- <40000 24000 0 30000>,
- <40000 24000 0 30000>,
- <40000 24000 0 30000>,
- <40000 24000 0 30000>,
- <40000 24000 0 30000>,
+ <25000 9000 (-15000) 15000>,
+ <25000 9000 (-15000) 15000>,
+ <25000 9000 (-15000) 15000>,
+ <25000 9000 (-15000) 15000>,
+ <25000 9000 (-15000) 15000>,
/* Speed bin 1 */
<40000 24000 0 30000>,
<40000 24000 0 30000>,
<40000 24000 0 30000>,
- <40000 24000 0 30000>,
- <40000 24000 0 30000>,
- <40000 24000 0 30000>,
- <40000 24000 0 30000>,
- <40000 24000 0 30000>;
+ <25000 9000 (-15000) 15000>,
+ <25000 9000 (-15000) 15000>,
+ <25000 9000 (-15000) 15000>,
+ <25000 9000 (-15000) 15000>,
+ <25000 9000 (-15000) 15000>;
qcom,cpr-closed-loop-voltage-fuse-adjustment =
/* Speed bin 0 */
<20000 26000 0 30000>,
<20000 26000 0 30000>,
<20000 26000 0 30000>,
- <20000 26000 0 30000>,
- <20000 26000 0 30000>,
- <20000 26000 0 30000>,
- <20000 26000 0 30000>,
- <20000 26000 0 30000>,
+ <5000 11000 (-15000) 15000>,
+ <5000 11000 (-15000) 15000>,
+ <5000 11000 (-15000) 15000>,
+ <5000 11000 (-15000) 15000>,
+ <5000 11000 (-15000) 15000>,
/* Speed bin 1 */
<20000 26000 0 30000>,
<20000 26000 0 30000>,
<20000 26000 0 30000>,
- <20000 26000 0 30000>,
- <20000 26000 0 30000>,
- <20000 26000 0 30000>,
- <20000 26000 0 30000>,
- <20000 26000 0 30000>;
+ <5000 11000 (-15000) 15000>,
+ <5000 11000 (-15000) 15000>,
+ <5000 11000 (-15000) 15000>,
+ <5000 11000 (-15000) 15000>,
+ <5000 11000 (-15000) 15000>;
qcom,allow-voltage-interpolation;
qcom,allow-quotient-interpolation;
qcom,cpr-scaled-open-loop-voltage-as-ceiling;
qcom,cpr-aging-ref-corner = <22 22>;
- qcom,cpr-aging-ro-scaling-factor = <2950>;
- qcom,allow-aging-voltage-adjustment = <0>;
+ qcom,cpr-aging-ro-scaling-factor = <1620>;
+ qcom,allow-aging-voltage-adjustment =
+ <0 0 0 1 1 1 1 1>,
+ <0 0 0 1 1 1 1 1>;
};
&apc1_cpr {
@@ -583,48 +604,50 @@
<8000 0 0 52000>,
<8000 0 0 52000>,
<8000 0 0 52000>,
- <8000 0 0 52000>,
- <8000 0 0 52000>,
- <8000 0 0 52000>,
- <8000 0 0 52000>,
- <8000 0 0 52000>,
+ <(-7000) (-15000) (-15000) 37000>,
+ <(-7000) (-15000) (-15000) 37000>,
+ <(-7000) (-15000) (-15000) 37000>,
+ <(-7000) (-15000) (-15000) 37000>,
+ <(-7000) (-15000) (-15000) 37000>,
/* Speed bin 1 */
<8000 0 0 52000>,
<8000 0 0 52000>,
<8000 0 0 52000>,
- <8000 0 0 52000>,
- <8000 0 0 52000>,
- <8000 0 0 52000>,
- <8000 0 0 52000>,
- <8000 0 0 52000>;
+ <(-7000) (-15000) (-15000) 37000>,
+ <(-7000) (-15000) (-15000) 37000>,
+ <(-7000) (-15000) (-15000) 37000>,
+ <(-7000) (-15000) (-15000) 37000>,
+ <(-7000) (-15000) (-15000) 37000>;
qcom,cpr-closed-loop-voltage-fuse-adjustment =
/* Speed bin 0 */
<0 0 0 50000>,
<0 0 0 50000>,
<0 0 0 50000>,
- <0 0 0 50000>,
- <0 0 0 50000>,
- <0 0 0 50000>,
- <0 0 0 50000>,
- <0 0 0 50000>,
+ <(-15000) (-15000) (-15000) 35000>,
+ <(-15000) (-15000) (-15000) 35000>,
+ <(-15000) (-15000) (-15000) 35000>,
+ <(-15000) (-15000) (-15000) 35000>,
+ <(-15000) (-15000) (-15000) 35000>,
/* Speed bin 1 */
<0 0 0 50000>,
<0 0 0 50000>,
<0 0 0 50000>,
- <0 0 0 50000>,
- <0 0 0 50000>,
- <0 0 0 50000>,
- <0 0 0 50000>,
- <0 0 0 50000>;
+ <(-15000) (-15000) (-15000) 35000>,
+ <(-15000) (-15000) (-15000) 35000>,
+ <(-15000) (-15000) (-15000) 35000>,
+ <(-15000) (-15000) (-15000) 35000>,
+ <(-15000) (-15000) (-15000) 35000>;
qcom,allow-voltage-interpolation;
qcom,allow-quotient-interpolation;
qcom,cpr-scaled-open-loop-voltage-as-ceiling;
qcom,cpr-aging-ref-corner = <30 26>;
- qcom,cpr-aging-ro-scaling-factor = <2950>;
- qcom,allow-aging-voltage-adjustment = <0>;
+ qcom,cpr-aging-ro-scaling-factor = <1700>;
+ qcom,allow-aging-voltage-adjustment =
+ <0 0 0 1 1 1 1 1>,
+ <0 0 0 1 1 1 1 1>;
};
&pm8005_s1 {
@@ -648,14 +671,14 @@
qcom,cpr-corner-fmax-map = <1 3 5 8>;
qcom,cpr-voltage-ceiling =
- <656000 716000 772000 880000 908000 948000 1016000 1088000>,
- <660000 724000 772000 832000 916000 968000 1024000 1024000>,
- <660000 724000 772000 832000 916000 968000 1024000 1024000>,
- <660000 724000 772000 832000 916000 968000 1024000 1024000>,
- <660000 724000 772000 832000 916000 968000 1024000 1024000>,
- <660000 724000 772000 832000 916000 968000 1024000 1024000>,
- <660000 724000 772000 832000 916000 968000 1024000 1024000>,
- <660000 724000 772000 832000 916000 968000 1024000 1024000>;
+ <716000 716000 772000 880000 908000 948000 1016000 1088000>,
+ <724000 724000 772000 832000 916000 968000 1024000 1024000>,
+ <724000 724000 772000 832000 916000 968000 1024000 1024000>,
+ <724000 724000 772000 832000 916000 968000 1024000 1024000>,
+ <724000 724000 772000 832000 916000 968000 1024000 1024000>,
+ <724000 724000 772000 832000 916000 968000 1024000 1024000>,
+ <724000 724000 772000 832000 916000 968000 1024000 1024000>,
+ <724000 724000 772000 832000 916000 968000 1024000 1024000>;
qcom,cpr-voltage-floor =
<516000 516000 532000 584000 632000 672000 712000 756000>;
@@ -703,45 +726,45 @@
0 0 2168 0 2209 1849 1997 0>;
qcom,cpr-open-loop-voltage-fuse-adjustment =
- < 100000 0 0 0>,
- < 100000 0 0 0>,
- < 85000 (-15000) (-15000) (-15000)>,
- < 85000 (-15000) (-15000) (-15000)>,
- < 85000 (-15000) (-15000) (-15000)>,
- < 85000 (-15000) (-15000) (-15000)>,
- < 85000 (-15000) (-15000) (-15000)>,
- < 85000 (-15000) (-15000) (-15000)>;
+ < 60000 0 0 0>,
+ < 60000 0 0 0>,
+ < 45000 (-15000) (-15000) (-15000)>,
+ < 45000 (-15000) (-15000) (-15000)>,
+ < 45000 (-15000) (-15000) (-15000)>,
+ < 45000 (-15000) (-15000) (-15000)>,
+ < 45000 (-15000) (-15000) (-15000)>,
+ < 45000 (-15000) (-15000) (-15000)>;
qcom,cpr-closed-loop-voltage-adjustment =
- < 96000 18000 4000 0
- 0 13000 9000 0>,
- < 96000 18000 4000 0
- 0 13000 9000 0>,
- < 81000 3000 (-11000) (-15000)
- (-15000) (-2000) (-6000) (-15000)>,
- < 81000 3000 (-11000) (-15000)
- (-15000) (-2000) (-6000) (-15000)>,
- < 81000 3000 (-11000) (-15000)
- (-15000) (-2000) (-6000) (-15000)>,
- < 81000 3000 (-11000) (-15000)
- (-15000) (-2000) (-6000) (-15000)>,
- < 81000 3000 (-11000) (-15000)
- (-15000) (-2000) (-6000) (-15000)>,
- < 81000 3000 (-11000) (-15000)
- (-15000) (-2000) (-6000) (-15000)>;
+ < 90000 38000 28000 8000
+ 0 29000 11000 0>,
+ < 90000 38000 28000 8000
+ 0 29000 11000 0>,
+ < 75000 23000 13000 (-7000)
+ (-15000) 14000 (-4000) (-15000)>,
+ < 75000 23000 13000 (-7000)
+ (-15000) 14000 (-4000) (-15000)>,
+ < 75000 23000 13000 (-7000)
+ (-15000) 14000 (-4000) (-15000)>,
+ < 75000 23000 13000 (-7000)
+ (-15000) 14000 (-4000) (-15000)>,
+ < 75000 23000 13000 (-7000)
+ (-15000) 14000 (-4000) (-15000)>,
+ < 75000 23000 13000 (-7000)
+ (-15000) 14000 (-4000) (-15000)>;
qcom,cpr-floor-to-ceiling-max-range =
<50000 50000 50000 50000 50000 50000 70000 70000>;
qcom,cpr-fused-closed-loop-voltage-adjustment-map =
- <0 0 1 2 3 0 0 4>;
+ <0 0 0 0 1 2 3 4>;
qcom,allow-voltage-interpolation;
qcom,cpr-scaled-open-loop-voltage-as-ceiling;
qcom,cpr-aging-max-voltage-adjustment = <15000>;
qcom,cpr-aging-ref-corner = <8>;
- qcom,cpr-aging-ro-scaling-factor = <2950>;
+ qcom,cpr-aging-ro-scaling-factor = <1620>;
qcom,allow-aging-voltage-adjustment = <0 0 1 1 1 1 1 1>;
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
index b58e2d2c7cc6..328ae458eb06 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
@@ -1788,6 +1788,16 @@
qcom,msm-bus,num-cases = <22>;
qcom,msm-bus,num-paths = <2>;
qcom,msm-bus,vectors-KBps =
+ /*
+ * During HS G3 UFS runs at nominal voltage corner, vote
+ * higher bandwidth to push other buses in the data path
+ * to run at nominal to achieve max throughput.
+ * 4GBps pushes BIMC to run at nominal.
+ * 200MBps pushes CNOC to run at nominal.
+ * Vote for half of this bandwidth for HS G3 1-lane.
+ * For max bandwidth, vote high enough to push the buses
+ * to run in turbo voltage corner.
+ */
<95 512 0 0>, <1 650 0 0>, /* No vote */
<95 512 922 0>, <1 650 1000 0>, /* PWM G1 */
<95 512 1844 0>, <1 650 1000 0>, /* PWM G2 */
@@ -1799,17 +1809,17 @@
<95 512 14752 0>, <1 650 1000 0>, /* PWM G4 L2 */
<95 512 127796 0>, <1 650 1000 0>, /* HS G1 RA */
<95 512 255591 0>, <1 650 1000 0>, /* HS G2 RA */
- <95 512 511181 0>, <1 650 1000 0>, /* HS G3 RA */
+ <95 512 2097152 0>, <1 650 102400 0>, /* HS G3 RA */
<95 512 255591 0>, <1 650 1000 0>, /* HS G1 RA L2 */
<95 512 511181 0>, <1 650 1000 0>, /* HS G2 RA L2 */
- <95 512 1022362 0>, <1 650 1000 0>, /* HS G3 RA L2 */
+ <95 512 4194304 0>, <1 650 204800 0>, /* HS G3 RA L2 */
<95 512 149422 0>, <1 650 1000 0>, /* HS G1 RB */
<95 512 298189 0>, <1 650 1000 0>, /* HS G2 RB */
- <95 512 596378 0>, <1 650 1000 0>, /* HS G3 RB */
+ <95 512 2097152 0>, <1 650 102400 0>, /* HS G3 RB */
<95 512 298189 0>, <1 650 1000 0>, /* HS G1 RB L2 */
<95 512 596378 0>, <1 650 1000 0>, /* HS G2 RB L2 */
- <95 512 1192756 0>, <1 650 1000 0>, /* HS G3 RB L2 */
- <95 512 4096000 0>, <1 650 1000 0>; /* Max. bandwidth */
+ <95 512 4194304 0>, <1 650 204800 0>, /* HS G3 RB L2 */
+ <95 512 7643136 0>, <1 650 307200 0>; /* Max. bandwidth */
qcom,bus-vector-names = "MIN",
"PWM_G1_L1", "PWM_G2_L1", "PWM_G3_L1", "PWM_G4_L1",
"PWM_G1_L2", "PWM_G2_L2", "PWM_G3_L2", "PWM_G4_L2",
@@ -1877,6 +1887,7 @@
usb-phy = <&qusb_phy0>, <&ssphy>;
tx-fifo-resize;
snps,nominal-elastic-buffer;
+ snps,disable-clk-gating;
snps,hird_thresh = <0x10>;
snps,num-gsi-evt-buffs = <0x3>;
};
@@ -2147,6 +2158,32 @@
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>;
};
+ qcom,memshare {
+ compatible = "qcom,memshare";
+
+ qcom,client_1 {
+ compatible = "qcom,memshare-peripheral";
+ qcom,peripheral-size = <0x200000>;
+ qcom,client-id = <0>;
+ qcom,allocate-boot-time;
+ label = "modem";
+ };
+
+ qcom,client_2 {
+ compatible = "qcom,memshare-peripheral";
+ qcom,peripheral-size = <0x300000>;
+ qcom,client-id = <2>;
+ label = "modem";
+ };
+
+ mem_client_3_size: qcom,client_3 {
+ compatible = "qcom,memshare-peripheral";
+ qcom,peripheral-size = <0x0>;
+ qcom,client-id = <1>;
+ label = "modem";
+ };
+ };
+
pil_modem: qcom,mss@4080000 {
compatible = "qcom,pil-q6v55-mss";
reg = <0x4080000 0x100>,
@@ -3107,5 +3144,6 @@
#include "msm-audio-lpass.dtsi"
#include "msmcobalt-mdss.dtsi"
#include "msmcobalt-mdss-pll.dtsi"
+#include "msm-rdbg.dtsi"
#include "msmcobalt-blsp.dtsi"
#include "msmcobalt-audio.dtsi"
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-regulator.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-regulator.dtsi
index 124ab341ba6b..75cf4de97672 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon-regulator.dtsi
@@ -10,351 +10,415 @@
* GNU General Public License for more details.
*/
-/* Stub regulators */
-
-/ {
- /* PMFALCON S1 - VDD_APC0 supply */
- pmfalcon_s1a: regulator-pmfalcon-s1a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_s1a";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <565000>;
- regulator-max-microvolt = <1170000>;
- };
-
- /* PMFALCON S2 + S3 = VDD_APC1 supply */
- pmfalcon_s2a: regulator-pmfalcon-s2a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_s2a";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <565000>;
- regulator-max-microvolt = <1170000>;
- };
-
- pmfalcon_s4a: regulator-pmfalcon-s4a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_s4a";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <1805000>;
- regulator-max-microvolt = <2040000>;
- };
-
- pmfalcon_s5a: regulator-pmfalcon-s5a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_s5a";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <1350000>;
- regulator-max-microvolt = <1350000>;
- };
-
- pmfalcon_s6a: regulator-pmfalcon-s6a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_s6a";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <504000>;
- regulator-max-microvolt = <992000>;
- };
-
- pmfalcon_s1b: regulator-pmfalcon-s1b {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_s1b";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <1125000>;
- regulator-max-microvolt = <1125000>;
- };
-
- pmfalcon_s2b: regulator-pmfalcon-s2b {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_s2b";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <1050000>;
- regulator-max-microvolt = <1050000>;
- };
-
- /* PMFALCON S3 + S4 - VDD_CX supply */
- pmfalcon_s3b_level: regulator-pmfalcon-s3b-level {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_s3b_level";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
- regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
- };
-
- pmfalcon_s3b_floor_level: regulator-pmfalcon-s3b-floor-level {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_s3b_floor_level";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
- regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
- };
-
- pmfalcon_s3b_level_ao: regulator-pmfalcon-s3b-level-ao {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_s3b_level_ao";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
- regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
- };
-
- /* PMFALCON S5 - VDD_MX supply */
- pmfalcon_s5b_level: regulator-pmfalcon-s5b-level {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_s5b_level";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
- regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
- };
-
- pmfalcon_s5b_floor_level: regulator-pmfalcon-s5b-floor-level {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_s5b_floor_level";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
- regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
- };
-
- pmfalcon_s5b_level_ao: regulator-pmfalcon-s5b-level-ao {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_s5b_level_ao";
- qcom,hpm-min-load = <100000>;
- regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
- regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
- };
-
- pmfalcon_l1a: regulator-pmfalcon-l1a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l1a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1150000>;
- regulator-max-microvolt = <1250000>;
- };
-
- pmfalcon_l2a: regulator-pmfalcon-l2a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l2a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <950000>;
- regulator-max-microvolt = <1010000>;
- };
-
- pmfalcon_l3a: regulator-pmfalcon-l3a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l3a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <950000>;
- regulator-max-microvolt = <1010000>;
+&rpm_bus {
+ rpm-regulator-smpa4 {
+ status = "okay";
+ pmfalcon_s4: regulator-s4 {
+ regulator-min-microvolt = <1805000>;
+ regulator-max-microvolt = <2040000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpa5 {
+ status = "okay";
+ pmfalcon_s5: regulator-s5 {
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpa6 {
+ status = "okay";
+ pmfalcon_s6: regulator-s6 {
+ regulator-min-microvolt = <504000>;
+ regulator-max-microvolt = <992000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpb1 {
+ status = "okay";
+ pm2falcon_s1: regulator-s1 {
+ regulator-min-microvolt = <1125000>;
+ regulator-max-microvolt = <1125000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpb2 {
+ status = "okay";
+ pm2falcon_s2: regulator-s2 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ status = "okay";
+ };
+ };
+
+ /* PM2FALCON S3 + S4 - VDD_CX supply */
+ rpm-regulator-smpb3 {
+ status = "okay";
+ pm2falcon_s3_level: regulator-s3-level {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_s3_level";
+ qcom,set = <3>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,use-voltage-level;
+ };
+
+ pm2falcon_s3_floor_level: regulator-s3-floor-level {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_s3_floor_level";
+ qcom,set = <3>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,use-voltage-floor-level;
+ qcom,always-send-voltage;
+ };
+
+ pm2falcon_s3_level_ao: regulator-s3-level-ao {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_s3_level_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,use-voltage-level;
+ };
+ };
+
+ /* PM2FALCON S5 - VDD_MX supply */
+ rpm-regulator-smpb5 {
+ status = "okay";
+ pm2falcon_s5_level: regulator-s5-level {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_s5_level";
+ qcom,set = <3>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,use-voltage-level;
+ };
+
+ pm2falcon_s5_floor_level: regulator-s5-floor-level {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_s5_floor_level";
+ qcom,set = <3>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,use-voltage-floor-level;
+ qcom,always-send-voltage;
+ };
+
+ pm2falcon_s5_level_ao: regulator-s5-level-ao {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_s5_level_ao";
+ qcom,set = <1>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,use-voltage-level;
+ };
+ };
+
+ rpm-regulator-ldoa1 {
+ status = "okay";
+ pmfalcon_l1: regulator-l1 {
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1250000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa2 {
+ pmfalcon_l2: regulator-l2 {
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1010000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa3 {
+ pmfalcon_l3: regulator-l3 {
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1010000>;
+ status = "okay";
+ };
};
/* TODO: remove if ADRASTEA CX/MX not voted from APPS */
- pmfalcon_l5a: regulator-pmfalcon-l5a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l5a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <525000>;
- regulator-max-microvolt = <950000>;
+ rpm-regulator-ldoa5 {
+ pmfalcon_l5: regulator-l5 {
+ regulator-min-microvolt = <525000>;
+ regulator-max-microvolt = <950000>;
+ status = "okay";
+ };
};
-
- pmfalcon_l6a: regulator-pmfalcon-l6a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l6a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1370000>;
+
+ rpm-regulator-ldoa6 {
+ pmfalcon_l6: regulator-l6 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1370000>;
+ status = "okay";
+ };
};
-
- pmfalcon_l7a: regulator-pmfalcon-l7a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l7a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
+
+ rpm-regulator-ldoa7 {
+ pmfalcon_l7: regulator-l7 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ status = "okay";
+ };
};
-
- pmfalcon_l8a: regulator-pmfalcon-l8a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l8a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1750000>;
- regulator-max-microvolt = <1900000>;
+
+ rpm-regulator-ldoa8 {
+ pmfalcon_l8: regulator-l8 {
+ regulator-min-microvolt = <1750000>;
+ regulator-max-microvolt = <1900000>;
+ status = "okay";
+ };
};
-
- pmfalcon_l9a: regulator-pmfalcon-l9a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l9a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1750000>;
- regulator-max-microvolt = <1900000>;
+
+ rpm-regulator-ldoa9 {
+ pmfalcon_l9: regulator-l9 {
+ regulator-min-microvolt = <1750000>;
+ regulator-max-microvolt = <1900000>;
+ status = "okay";
+ };
};
-
- pmfalcon_l10a: regulator-pmfalcon-l10a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l10a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1780000>;
- regulator-max-microvolt = <1950000>;
+
+ rpm-regulator-ldoa10 {
+ pmfalcon_l10: regulator-l10 {
+ regulator-min-microvolt = <1780000>;
+ regulator-max-microvolt = <1950000>;
+ status = "okay";
+ };
};
-
- pmfalcon_l11a: regulator-pmfalcon-l11a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l11a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1780000>;
- regulator-max-microvolt = <1950000>;
- };
-
- pmfalcon_l12a: regulator-pmfalcon-l12a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l12a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1780000>;
- regulator-max-microvolt = <1950000>;
- };
-
- pmfalcon_l13a: regulator-pmfalcon-l13a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l13a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1750000>;
- regulator-max-microvolt = <1950000>;
- };
-
- pmfalcon_l14a: regulator-pmfalcon-l14a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l14a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1710000>;
- regulator-max-microvolt = <1900000>;
- };
-
- pmfalcon_l15a: regulator-pmfalcon-l15a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l15a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1650000>;
- regulator-max-microvolt = <2950000>;
- };
-
- pmfalcon_l17a: regulator-pmfalcon-l17a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l17a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1650000>;
- regulator-max-microvolt = <2950000>;
+
+ rpm-regulator-ldoa11 {
+ pmfalcon_l11: regulator-l11 {
+ regulator-min-microvolt = <1780000>;
+ regulator-max-microvolt = <1950000>;
+ status = "okay";
+ };
};
-
- pmfalcon_l19a: regulator-pmfalcon-l19a {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l19a";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <3200000>;
- regulator-max-microvolt = <3400000>;
+
+ rpm-regulator-ldoa12 {
+ pmfalcon_l12: regulator-l12 {
+ regulator-min-microvolt = <1780000>;
+ regulator-max-microvolt = <1950000>;
+ status = "okay";
+ };
};
-
- pmfalcon_l1b: regulator-pmfalcon-l1b {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l1b";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <800000>;
- regulator-max-microvolt = <925000>;
+
+ rpm-regulator-ldoa13 {
+ pmfalcon_l13: regulator-l13 {
+ regulator-min-microvolt = <1780000>;
+ regulator-max-microvolt = <1950000>;
+ status = "okay";
+ };
};
-
- pmfalcon_l2b: regulator-pmfalcon-l2b {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l2b";
- qcom,hpm-min-load = <5000>;
- regulator-min-microvolt = <350000>;
- regulator-max-microvolt = <3100000>;
- };
-
- pmfalcon_l3b: regulator-pmfalcon-l3b {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l3b";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1710000>;
- regulator-max-microvolt = <3600000>;
- };
-
- pmfalcon_l4b: regulator-pmfalcon-l4b {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l4b";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1700000>;
- regulator-max-microvolt = <2950000>;
- };
-
- pmfalcon_l5b: regulator-pmfalcon-l5b {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l5b";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <1721000>;
- regulator-max-microvolt = <3600000>;
- };
-
- pmfalcon_l6b: regulator-pmfalcon-l6b {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l6b";
- qcom,hpm-min-load = <5000>;
- regulator-min-microvolt = <1700000>;
- regulator-max-microvolt = <3300000>;
- };
-
- pmfalcon_l7b: regulator-pmfalcon-l7b {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l7b";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <2700000>;
- regulator-max-microvolt = <3125000>;
- };
-
- pmfalcon_l8b: regulator-pmfalcon-l8b {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l8b";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <3200000>;
- regulator-max-microvolt = <3400000>;
- };
-
- /* PMFALCON L9 = VDD_SSC_CX supply */
- pmfalcon_l9b_level: regulator-pmfalcon-l9b-level {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l9b_level";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
- regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
- };
-
- pmfalcon_l9b_floor_level: regulator-pmfalcon-l9b-floor-level {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l9b_floor_level";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
- regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
- };
-
- /* PMFALCON L10 = VDD_SSC_MX supply */
- pmfalcon_l10b_level: regulator-pmfalcon-l10b-level {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l10b_level";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
- regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
- };
-
- pmfalcon_l10b_floor_level: regulator-pmfalcon-l10b-floor-level {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_l10b_floor_level";
- qcom,hpm-min-load = <10000>;
- regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
- regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
- };
-
- pmfalcon_bob: regulator-pmfalcon-bob {
- compatible = "qcom,stub-regulator";
- regulator-name = "pmfalcon_bob";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
+
+ rpm-regulator-ldoa14 {
+ pmfalcon_l14: regulator-l14 {
+ regulator-min-microvolt = <1710000>;
+ regulator-max-microvolt = <1900000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa15 {
+ pmfalcon_l15: regulator-l15 {
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa17 {
+ pmfalcon_l17: regulator-l17 {
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa19 {
+ pmfalcon_l19: regulator-l19 {
+ regulator-min-microvolt = <3200000>;
+ regulator-max-microvolt = <3400000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldob1 {
+ pm2falcon_l1: regulator-l1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <925000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldob2 {
+ pm2falcon_l2: regulator-l2 {
+ regulator-min-microvolt = <350000>;
+ regulator-max-microvolt = <3100000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldob3 {
+ pm2falcon_l3: regulator-l3 {
+ regulator-min-microvolt = <1710000>;
+ regulator-max-microvolt = <3600000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldob4 {
+ pm2falcon_l4: regulator-l4 {
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldob5 {
+ pm2falcon_l5: regulator-l5 {
+ regulator-min-microvolt = <1721000>;
+ regulator-max-microvolt = <3600000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldob6 {
+ pm2falcon_l6: regulator-l6 {
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <3300000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldob7 {
+ pm2falcon_l7: regulator-l7 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3125000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldob8 {
+ pm2falcon_l8: regulator-l8 {
+ regulator-min-microvolt = <3200000>;
+ regulator-max-microvolt = <3400000>;
+ status = "okay";
+ };
+ };
+
+ /* PM2FALCON L9 = VDD_SSC_CX supply */
+ rpm-regulator-ldob9 {
+ status = "okay";
+ pm2falcon_l9_level: regulator-l9-level {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l9_level";
+ qcom,set = <3>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,use-voltage-level;
+ };
+
+ pm2falcon_l9_floor_level: regulator-l9-floor-level {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l9_floor_level";
+ qcom,set = <3>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,use-voltage-floor-level;
+ qcom,always-send-voltage;
+ };
+ };
+
+ /* PM2FALCON L10 = VDD_SSC_MX supply */
+ rpm-regulator-ldob10 {
+ status = "okay";
+ pm2falcon_l10_level: regulator-l10-level {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l10_level";
+ qcom,set = <3>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,use-voltage-level;
+ };
+
+ pm2falcon_l10_floor_level: regulator-l10-floor-level {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_l10_floor_level";
+ qcom,set = <3>;
+ regulator-min-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt =
+ <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ qcom,use-voltage-floor-level;
+ qcom,always-send-voltage;
+ };
+ };
+
+ rpm-regulator-bobb {
+ status = "okay";
+ pm2falcon_bob: regulator-bob {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3600000>;
+ status = "okay";
+ };
+
+ pm2falcon_bob_pin1: regulator-bob-pin1 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_bob_pin1";
+ qcom,set = <3>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3600000>;
+ qcom,use-pin-ctrl-voltage1;
+ };
+
+ pm2falcon_bob_pin2: regulator-bob-pin2 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_bob_pin2";
+ qcom,set = <3>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3600000>;
+ qcom,use-pin-ctrl-voltage2;
+ };
+
+ pm2falcon_bob_pin3: regulator-bob-pin3 {
+ compatible = "qcom,rpm-smd-regulator";
+ regulator-name = "pm2falcon_bob_pin3";
+ qcom,set = <3>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3600000>;
+ qcom,use-pin-ctrl-voltage3;
+ };
};
+};
+/* Stub regulators */
+/ {
/* GFX Supply */
gfx_vreg_corner: regulator-gfx-corner {
compatible = "qcom,stub-regulator";
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts
index f0ba8b115120..9d76681bab2d 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts
+++ b/arch/arm/boot/dts/qcom/msmfalcon-rumi.dts
@@ -20,6 +20,10 @@
model = "Qualcomm Technologies, Inc. MSM FALCON RUMI";
compatible = "qcom,msmfalcon-rumi", "qcom,msmfalcon", "qcom,rumi";
qcom,board-id = <15 0>;
+
+ chosen {
+ bootargs = "lpm_levels.sleep_disabled=1";
+ };
};
&uartblsp1dm1 {
@@ -30,12 +34,12 @@
&sdhc_1 {
/* device core power supply */
- vdd-supply = <&pmfalcon_l4b>;
+ vdd-supply = <&pm2falcon_l4>;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <200 570000>;
/* device communication power supply */
- vdd-io-supply = <&pmfalcon_l8a>;
+ vdd-io-supply = <&pmfalcon_l8>;
qcom,vdd-io-always-on;
qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 1800000>;
diff --git a/arch/arm/boot/dts/qcom/msmfalcon-sim.dts b/arch/arm/boot/dts/qcom/msmfalcon-sim.dts
index 085419b7e108..00d97c8fdd32 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon-sim.dts
+++ b/arch/arm/boot/dts/qcom/msmfalcon-sim.dts
@@ -20,6 +20,10 @@
model = "Qualcomm Technologies, Inc. MSM FALCON SIM";
compatible = "qcom,msmfalcon-sim", "qcom,msmfalcon", "qcom,sim";
qcom,board-id = <16 0>;
+
+ chosen {
+ bootargs = "lpm_levels.sleep_disabled=1";
+ };
};
&uartblsp1dm1 {
@@ -30,12 +34,12 @@
&sdhc_1 {
/* device core power supply */
- vdd-supply = <&pmfalcon_l4b>;
+ vdd-supply = <&pm2falcon_l4>;
qcom,vdd-voltage-level = <2950000 2950000>;
qcom,vdd-current-level = <200 570000>;
/* device communication power supply */
- vdd-io-supply = <&pmfalcon_l8a>;
+ vdd-io-supply = <&pmfalcon_l8>;
qcom,vdd-io-always-on;
qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 1800000>;
diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
index f2adc32fb732..b035bc3c0f14 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
@@ -287,6 +287,32 @@
qcom,pipe-attr-ee;
};
+ qcom,memshare {
+ compatible = "qcom,memshare";
+
+ qcom,client_1 {
+ compatible = "qcom,memshare-peripheral";
+ qcom,peripheral-size = <0x200000>;
+ qcom,client-id = <0>;
+ qcom,allocate-boot-time;
+ label = "modem";
+ };
+
+ qcom,client_2 {
+ compatible = "qcom,memshare-peripheral";
+ qcom,peripheral-size = <0x300000>;
+ qcom,client-id = <2>;
+ label = "modem";
+ };
+
+ mem_client_3_size: qcom,client_3 {
+ compatible = "qcom,memshare-peripheral";
+ qcom,peripheral-size = <0x0>;
+ qcom,client-id = <1>;
+ label = "modem";
+ };
+ };
+
tsens: tsens@10ad000 {
compatible = "qcom,msmfalcon-tsens";
reg = <0x10ad000 0x2000>,
@@ -384,8 +410,10 @@
};
clock_gcc: clock-controller@100000 {
- compatible = "qcom,dummycc";
- clock-output-names = "gcc_clocks";
+ compatible = "qcom,gcc-msmfalcon";
+ reg = <0x100000 0x94000>;
+ vdd_dig-supply = <&pm2falcon_s3_level>;
+ vdd_dig_ao-supply = <&pm2falcon_s3_level_ao>;
#clock-cells = <1>;
#reset-cells = <1>;
};
@@ -696,7 +724,7 @@
reg = <0x15700000 0x00100>;
interrupts = <0 162 1>;
- vdd_cx-supply = <&pmfalcon_s3b_level>;
+ vdd_cx-supply = <&pm2falcon_s3_level>;
qcom,proxy-reg-names = "vdd_cx";
qcom,vdd_cx-uV-uA = <RPM_SMD_REGULATOR_LEVEL_TURBO 100000>;
@@ -728,7 +756,7 @@
reg = <0x1a300000 0x00100>;
interrupts = <0 518 1>;
- vdd_cx-supply = <&pmfalcon_s3b_level>;
+ vdd_cx-supply = <&pm2falcon_s3_level>;
qcom,proxy-reg-names = "vdd_cx";
qcom,vdd_cx-uV-uA = <RPM_SMD_REGULATOR_LEVEL_TURBO 100000>;
@@ -783,9 +811,9 @@
"mnoc_axi_clk";
interrupts = <0 448 1>;
- vdd_cx-supply = <&pmfalcon_s3b_level>;
+ vdd_cx-supply = <&pm2falcon_s3_level>;
vdd_cx-voltage = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
- vdd_mx-supply = <&pmfalcon_s5b_level>;
+ vdd_mx-supply = <&pm2falcon_s5_level>;
vdd_mx-uV = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
qcom,firmware-name = "modem";
qcom,pil-self-auth;
@@ -807,10 +835,25 @@
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
status = "ok";
};
+
+ qcom,msm-imem@146bf000 {
+ compatible = "qcom,msm-imem";
+ reg = <0x146bf000 0x1000>;
+ ranges = <0x0 0x146bf000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pil@94c {
+ compatible = "qcom,msm-imem-pil";
+ reg = <0x94c 200>;
+ };
+ };
};
#include "msmfalcon-ion.dtsi"
#include "msmfalcon-bus.dtsi"
+#include "msm-pmfalcon-rpm-regulator.dtsi"
+#include "msm-pm2falcon-rpm-regulator.dtsi"
#include "msmfalcon-regulator.dtsi"
#include "msm-gdsc-falcon.dtsi"
diff --git a/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi b/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi
new file mode 100644
index 000000000000..323024278406
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msmtriton-regulator.dtsi
@@ -0,0 +1,365 @@
+/* Copyright (c) 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.
+ */
+
+/* Stub regulators */
+
+/ {
+ /* PMFALCON S1 - VDD_APC0 supply */
+ pmfalcon_s1: regulator-pmfalcon-s1 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_s1";
+ qcom,hpm-min-load = <100000>;
+ regulator-min-microvolt = <565000>;
+ regulator-max-microvolt = <1170000>;
+ };
+
+ /* PMFALCON S2 + S3 = VDD_APC1 supply */
+ pmfalcon_s2: regulator-pmfalcon-s2 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_s2";
+ qcom,hpm-min-load = <100000>;
+ regulator-min-microvolt = <565000>;
+ regulator-max-microvolt = <1170000>;
+ };
+
+ pmfalcon_s4: regulator-pmfalcon-s4 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_s4";
+ qcom,hpm-min-load = <100000>;
+ regulator-min-microvolt = <1805000>;
+ regulator-max-microvolt = <2040000>;
+ };
+
+ pmfalcon_s5: regulator-pmfalcon-s5 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_s5";
+ qcom,hpm-min-load = <100000>;
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ };
+
+ pmfalcon_s6: regulator-pmfalcon-s6 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_s6";
+ qcom,hpm-min-load = <100000>;
+ regulator-min-microvolt = <504000>;
+ regulator-max-microvolt = <992000>;
+ };
+
+ pm2falcon_s1: regulator-pm2falcon-s1 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_s1";
+ qcom,hpm-min-load = <100000>;
+ regulator-min-microvolt = <1125000>;
+ regulator-max-microvolt = <1125000>;
+ };
+
+ pm2falcon_s2: regulator-pm2falcon-s2 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_s2";
+ qcom,hpm-min-load = <100000>;
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ /* PMFALCON S3 + S4 - VDD_CX supply */
+ pm2falcon_s3_level: regulator-pm2falcon-s3-level {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_s3_level";
+ qcom,hpm-min-load = <100000>;
+ regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ };
+
+ pm2falcon_s3_floor_level: regulator-pm2falcon-s3-floor-level {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_s3_floor_level";
+ qcom,hpm-min-load = <100000>;
+ regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ };
+
+ pm2falcon_s3_level_ao: regulator-pm2falcon-s3-level-ao {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_s3_level_ao";
+ qcom,hpm-min-load = <100000>;
+ regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ };
+
+ /* PMFALCON S5 - VDD_MX supply */
+ pm2falcon_s5_level: regulator-pm2falcon-s5-level {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_s5_level";
+ qcom,hpm-min-load = <100000>;
+ regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ };
+
+ pm2falcon_s5_floor_level: regulator-pm2falcon-s5-floor-level {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_s5_floor_level";
+ qcom,hpm-min-load = <100000>;
+ regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ };
+
+ pm2falcon_s5_level_ao: regulator-pm2falcon-s5-level-ao {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_s5_level_ao";
+ qcom,hpm-min-load = <100000>;
+ regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ };
+
+ pmfalcon_l1: regulator-pmfalcon-l1 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l1";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1250000>;
+ };
+
+ pmfalcon_l2: regulator-pmfalcon-l2 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l2";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1010000>;
+ };
+
+ pmfalcon_l3: regulator-pmfalcon-l3 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l3";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1010000>;
+ };
+
+ /* TODO: remove if ADRASTEA CX/MX not voted from APPS */
+ pmfalcon_l5: regulator-pmfalcon-l5 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l5";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <525000>;
+ regulator-max-microvolt = <950000>;
+ };
+
+ pmfalcon_l6: regulator-pmfalcon-l6 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l6";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1370000>;
+ };
+
+ pmfalcon_l7: regulator-pmfalcon-l7 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l7";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pmfalcon_l8: regulator-pmfalcon-l8 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l8";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1750000>;
+ regulator-max-microvolt = <1900000>;
+ };
+
+ pmfalcon_l9: regulator-pmfalcon-l9 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l9";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1750000>;
+ regulator-max-microvolt = <1900000>;
+ };
+
+ pmfalcon_l10: regulator-pmfalcon-l10 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l10";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1780000>;
+ regulator-max-microvolt = <1950000>;
+ };
+
+ pmfalcon_l11: regulator-pmfalcon-l11 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l11";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1780000>;
+ regulator-max-microvolt = <1950000>;
+ };
+
+ pmfalcon_l12: regulator-pmfalcon-l12 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l12";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1780000>;
+ regulator-max-microvolt = <1950000>;
+ };
+
+ pmfalcon_l13: regulator-pmfalcon-l13 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l13";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1750000>;
+ regulator-max-microvolt = <1950000>;
+ };
+
+ pmfalcon_l14: regulator-pmfalcon-l14 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l14";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1710000>;
+ regulator-max-microvolt = <1900000>;
+ };
+
+ pmfalcon_l15: regulator-pmfalcon-l15 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l15";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pmfalcon_l17: regulator-pmfalcon-l17 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l17";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pmfalcon_l19: regulator-pmfalcon-l19 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pmfalcon_l19";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <3200000>;
+ regulator-max-microvolt = <3400000>;
+ };
+
+ pm2falcon_l1: regulator-pm2falcon-l1 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_l1";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <925000>;
+ };
+
+ pm2falcon_l2: regulator-pm2falcon-l2 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_l2";
+ qcom,hpm-min-load = <5000>;
+ regulator-min-microvolt = <350000>;
+ regulator-max-microvolt = <3100000>;
+ };
+
+ pm2falcon_l3: regulator-pm2falcon-l3 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_l3";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1710000>;
+ regulator-max-microvolt = <3600000>;
+ };
+
+ pm2falcon_l4: regulator-pm2falcon-l4 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_l4";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm2falcon_l5: regulator-pm2falcon-l5 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_l5";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <1721000>;
+ regulator-max-microvolt = <3600000>;
+ };
+
+ pm2falcon_l6: regulator-pm2falcon-l6 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_l6";
+ qcom,hpm-min-load = <5000>;
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm2falcon_l7: regulator-pm2falcon-l7 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_l7";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3125000>;
+ };
+
+ pm2falcon_l8: regulator-pm2falcon-l8 {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_l8";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <3200000>;
+ regulator-max-microvolt = <3400000>;
+ };
+
+ /* PMFALCON L9 = VDD_SSC_CX supply */
+ pm2falcon_l9_level: regulator-pm2falcon-l9-level {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_l9_level";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ };
+
+ pm2falcon_l9_floor_level: regulator-pm2falcon-l9-floor-level {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_l9_floor_level";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ };
+
+ /* PMFALCON L10 = VDD_SSC_MX supply */
+ pm2falcon_l10_level: regulator-pm2falcon-l10-level {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_l10_level";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ };
+
+ pm2falcon_l10_floor_level: regulator-pm2falcon-l10-floor-level {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_l10_floor_level";
+ qcom,hpm-min-load = <10000>;
+ regulator-min-microvolt = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+ regulator-max-microvolt = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+ };
+
+ pm2falcon_bob: regulator-pm2falcon-bob {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "pm2falcon_bob";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ /* GFX Supply */
+ gfx_vreg_corner: regulator-gfx-corner {
+ compatible = "qcom,stub-regulator";
+ regulator-name = "gfx_corner";
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <7>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/msmtriton.dtsi b/arch/arm/boot/dts/qcom/msmtriton.dtsi
index 8374d27e5b56..49fa1ac7f192 100644
--- a/arch/arm/boot/dts/qcom/msmtriton.dtsi
+++ b/arch/arm/boot/dts/qcom/msmtriton.dtsi
@@ -340,8 +340,10 @@
};
clock_gcc: clock-controller@100000 {
- compatible = "qcom,dummycc";
- clock-output-names = "gcc_clocks";
+ compatible = "qcom,gcc-msmfalcon";
+ reg = <0x100000 0x94000>;
+ vdd_dig-supply = <&pm2falcon_s3_level>;
+ vdd_dig_ao-supply = <&pm2falcon_s3_level_ao>;
#clock-cells = <1>;
#reset-cells = <1>;
};
@@ -554,7 +556,7 @@
reg = <0x15700000 0x00100>;
interrupts = <0 162 1>;
- vdd_cx-supply = <&pmfalcon_s3b_level>;
+ vdd_cx-supply = <&pm2falcon_s3_level>;
qcom,proxy-reg-names = "vdd_cx";
qcom,vdd_cx-uV-uA = <RPM_SMD_REGULATOR_LEVEL_TURBO 100000>;
@@ -638,9 +640,9 @@
"mnoc_axi_clk";
interrupts = <0 448 1>;
- vdd_cx-supply = <&pmfalcon_s3b_level>;
+ vdd_cx-supply = <&pm2falcon_s3_level>;
vdd_cx-voltage = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
- vdd_mx-supply = <&pmfalcon_s5b_level>;
+ vdd_mx-supply = <&pm2falcon_s5_level>;
vdd_mx-uV = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
qcom,firmware-name = "modem";
qcom,pil-self-auth;
@@ -662,10 +664,23 @@
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
status = "ok";
};
+
+ qcom,msm-imem@146bf000 {
+ compatible = "qcom,msm-imem";
+ reg = <0x146bf000 0x1000>;
+ ranges = <0x0 0x146bf000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pil@94c {
+ compatible = "qcom,msm-imem-pil";
+ reg = <0x94c 200>;
+ };
+ };
};
#include "msmtriton-ion.dtsi"
-#include "msmfalcon-regulator.dtsi"
+#include "msmtriton-regulator.dtsi"
#include "msm-gdsc-falcon.dtsi"
&gdsc_usb30 {
diff --git a/arch/arm/boot/dts/sama5d2-pinfunc.h b/arch/arm/boot/dts/sama5d2-pinfunc.h
index b0c912feaa2f..8a394f336003 100644
--- a/arch/arm/boot/dts/sama5d2-pinfunc.h
+++ b/arch/arm/boot/dts/sama5d2-pinfunc.h
@@ -837,8 +837,8 @@
#define PIN_PD23__ISC_FIELD PINMUX_PIN(PIN_PD23, 6, 4)
#define PIN_PD24 120
#define PIN_PD24__GPIO PINMUX_PIN(PIN_PD24, 0, 0)
-#define PIN_PD24__UTXD2 PINMUX_PIN(PIN_PD23, 1, 2)
-#define PIN_PD24__FLEXCOM4_IO3 PINMUX_PIN(PIN_PD23, 3, 3)
+#define PIN_PD24__UTXD2 PINMUX_PIN(PIN_PD24, 1, 2)
+#define PIN_PD24__FLEXCOM4_IO3 PINMUX_PIN(PIN_PD24, 3, 3)
#define PIN_PD25 121
#define PIN_PD25__GPIO PINMUX_PIN(PIN_PD25, 0, 0)
#define PIN_PD25__SPI1_SPCK PINMUX_PIN(PIN_PD25, 1, 3)
diff --git a/arch/arm/boot/dts/sun5i-r8-chip.dts b/arch/arm/boot/dts/sun5i-r8-chip.dts
index 530ab28e9ca2..d21f50ba3172 100644
--- a/arch/arm/boot/dts/sun5i-r8-chip.dts
+++ b/arch/arm/boot/dts/sun5i-r8-chip.dts
@@ -52,7 +52,7 @@
/ {
model = "NextThing C.H.I.P.";
- compatible = "nextthing,chip", "allwinner,sun5i-r8";
+ compatible = "nextthing,chip", "allwinner,sun5i-r8", "allwinner,sun5i-a13";
aliases {
i2c0 = &i2c0;
diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig
index 8be2b187a524..f843a98ee130 100644
--- a/arch/arm/configs/msmcortex_defconfig
+++ b/arch/arm/configs/msmcortex_defconfig
@@ -440,6 +440,7 @@ CONFIG_MSM_GLINK_PKT=y
CONFIG_MSM_SPM=y
CONFIG_QCOM_SCM=y
CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_IRQ_HELPER=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_ICNSS=y
CONFIG_ICNSS_DEBUG=y
diff --git a/arch/arm/configs/msmfalcon_defconfig b/arch/arm/configs/msmfalcon_defconfig
index 0788a03ed219..511b9fe32b9b 100644
--- a/arch/arm/configs/msmfalcon_defconfig
+++ b/arch/arm/configs/msmfalcon_defconfig
@@ -38,6 +38,7 @@ CONFIG_PARTITION_ADVANCED=y
# CONFIG_IOSCHED_DEADLINE is not set
CONFIG_ARCH_QCOM=y
CONFIG_ARCH_MSMFALCON=y
+CONFIG_ARCH_MSMTRITON=y
CONFIG_SMP=y
CONFIG_SCHED_MC=y
CONFIG_NR_CPUS=8
@@ -420,6 +421,7 @@ CONFIG_RMNET_IPA3=y
CONFIG_GPIO_USB_DETECT=y
CONFIG_USB_BAM=y
CONFIG_QCOM_CLK_SMD_RPM=y
+CONFIG_MSM_GCC_FALCON=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_ARM_SMMU=y
CONFIG_IOMMU_DEBUG=y
@@ -449,6 +451,7 @@ CONFIG_MSM_GLINK_PKT=y
CONFIG_MSM_SPM=y
CONFIG_QCOM_SCM=y
CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_IRQ_HELPER=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_ICNSS=y
CONFIG_ICNSS_DEBUG=y
diff --git a/arch/arm/include/asm/mach/mmc.h b/arch/arm/include/asm/mach/mmc.h
deleted file mode 100644
index bca864ac945f..000000000000
--- a/arch/arm/include/asm/mach/mmc.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * arch/arm/include/asm/mach/mmc.h
- */
-#ifndef ASMARM_MACH_MMC_H
-#define ASMARM_MACH_MMC_H
-
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-#include <linux/mmc/sdio_func.h>
-
-struct embedded_sdio_data {
- struct sdio_cis cis;
- struct sdio_cccr cccr;
- struct sdio_embedded_func *funcs;
- int num_funcs;
-};
-
-struct mmc_platform_data {
- unsigned int ocr_mask; /* available voltages */
- int built_in; /* built-in device flag */
- int card_present; /* card detect state */
- u32 (*translate_vdd)(struct device *, unsigned int);
- unsigned int (*status)(struct device *);
- struct embedded_sdio_data *embedded_sdio;
- int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
-};
-
-#endif
diff --git a/arch/arm/include/asm/pgtable-2level.h b/arch/arm/include/asm/pgtable-2level.h
index aeddd28b3595..92fd2c8a9af0 100644
--- a/arch/arm/include/asm/pgtable-2level.h
+++ b/arch/arm/include/asm/pgtable-2level.h
@@ -193,6 +193,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
#define pmd_large(pmd) (pmd_val(pmd) & 2)
#define pmd_bad(pmd) (pmd_val(pmd) & 2)
+#define pmd_present(pmd) (pmd_val(pmd))
#define copy_pmd(pmdpd,pmdps) \
do { \
diff --git a/arch/arm/include/asm/pgtable-3level.h b/arch/arm/include/asm/pgtable-3level.h
index a745a2a53853..fd929b5ded9e 100644
--- a/arch/arm/include/asm/pgtable-3level.h
+++ b/arch/arm/include/asm/pgtable-3level.h
@@ -212,6 +212,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
: !!(pmd_val(pmd) & (val)))
#define pmd_isclear(pmd, val) (!(pmd_val(pmd) & (val)))
+#define pmd_present(pmd) (pmd_isset((pmd), L_PMD_SECT_VALID))
#define pmd_young(pmd) (pmd_isset((pmd), PMD_SECT_AF))
#define pte_special(pte) (pte_isset((pte), L_PTE_SPECIAL))
static inline pte_t pte_mkspecial(pte_t pte)
@@ -257,10 +258,10 @@ PMD_BIT_FUNC(mkyoung, |= PMD_SECT_AF);
#define pfn_pmd(pfn,prot) (__pmd(((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot)))
#define mk_pmd(page,prot) pfn_pmd(page_to_pfn(page),prot)
-/* represent a notpresent pmd by zero, this is used by pmdp_invalidate */
+/* represent a notpresent pmd by faulting entry, this is used by pmdp_invalidate */
static inline pmd_t pmd_mknotpresent(pmd_t pmd)
{
- return __pmd(0);
+ return __pmd(pmd_val(pmd) & ~L_PMD_SECT_VALID);
}
static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index 348caabb7625..d62204060cbe 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -182,7 +182,6 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
#define pgd_offset_k(addr) pgd_offset(&init_mm, addr)
#define pmd_none(pmd) (!pmd_val(pmd))
-#define pmd_present(pmd) (pmd_val(pmd))
static inline pte_t *pmd_page_vaddr(pmd_t pmd)
{
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index ef9119f7462e..4d9375814b53 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -733,8 +733,8 @@ static int vfp_set(struct task_struct *target,
if (ret)
return ret;
- vfp_flush_hwstate(thread);
thread->vfpstate.hard = new_vfp;
+ vfp_flush_hwstate(thread);
return 0;
}
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 61d96a645ff3..12d727fae0a7 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -886,11 +886,14 @@ static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache
VM_BUG_ON(pmd_present(*pmd) && pmd_pfn(*pmd) != pmd_pfn(*new_pmd));
old_pmd = *pmd;
- kvm_set_pmd(pmd, *new_pmd);
- if (pmd_present(old_pmd))
+ if (pmd_present(old_pmd)) {
+ pmd_clear(pmd);
kvm_tlb_flush_vmid_ipa(kvm, addr);
- else
+ } else {
get_page(virt_to_page(pmd));
+ }
+
+ kvm_set_pmd(pmd, *new_pmd);
return 0;
}
@@ -939,12 +942,14 @@ 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;
- kvm_set_pte(pte, *new_pte);
- if (pte_present(old_pte))
+ if (pte_present(old_pte)) {
+ kvm_set_pte(pte, __pte(0));
kvm_tlb_flush_vmid_ipa(kvm, addr);
- else
+ } else {
get_page(virt_to_page(pte));
+ }
+ kvm_set_pte(pte, *new_pte);
return 0;
}
diff --git a/arch/arm/mach-imx/mach-imx6ul.c b/arch/arm/mach-imx/mach-imx6ul.c
index acaf7056efa5..e08d02667c81 100644
--- a/arch/arm/mach-imx/mach-imx6ul.c
+++ b/arch/arm/mach-imx/mach-imx6ul.c
@@ -46,7 +46,7 @@ static int ksz8081_phy_fixup(struct phy_device *dev)
static void __init imx6ul_enet_phy_init(void)
{
if (IS_BUILTIN(CONFIG_PHYLIB))
- phy_register_fixup_for_uid(PHY_ID_KSZ8081, 0xffffffff,
+ phy_register_fixup_for_uid(PHY_ID_KSZ8081, MICREL_PHY_ID_MASK,
ksz8081_phy_fixup);
}
diff --git a/arch/arm/mach-mvebu/coherency.c b/arch/arm/mach-mvebu/coherency.c
index 55348ee5a352..feed36b32ff6 100644
--- a/arch/arm/mach-mvebu/coherency.c
+++ b/arch/arm/mach-mvebu/coherency.c
@@ -162,22 +162,16 @@ exit:
}
/*
- * This ioremap hook is used on Armada 375/38x to ensure that PCIe
- * memory areas are mapped as MT_UNCACHED instead of MT_DEVICE. This
- * is needed as a workaround for a deadlock issue between the PCIe
- * interface and the cache controller.
+ * This ioremap hook is used on Armada 375/38x to ensure that all MMIO
+ * areas are mapped as MT_UNCACHED instead of MT_DEVICE. This is
+ * needed for the HW I/O coherency mechanism to work properly without
+ * deadlock.
*/
static void __iomem *
-armada_pcie_wa_ioremap_caller(phys_addr_t phys_addr, size_t size,
- unsigned int mtype, void *caller)
+armada_wa_ioremap_caller(phys_addr_t phys_addr, size_t size,
+ unsigned int mtype, void *caller)
{
- struct resource pcie_mem;
-
- mvebu_mbus_get_pcie_mem_aperture(&pcie_mem);
-
- if (pcie_mem.start <= phys_addr && (phys_addr + size) <= pcie_mem.end)
- mtype = MT_UNCACHED;
-
+ mtype = MT_UNCACHED;
return __arm_ioremap_caller(phys_addr, size, mtype, caller);
}
@@ -186,7 +180,7 @@ static void __init armada_375_380_coherency_init(struct device_node *np)
struct device_node *cache_dn;
coherency_cpu_base = of_iomap(np, 0);
- arch_ioremap_caller = armada_pcie_wa_ioremap_caller;
+ arch_ioremap_caller = armada_wa_ioremap_caller;
/*
* We should switch the PL310 to I/O coherency mode only if
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index d4d355531169..cbccbeb483c9 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -39,6 +39,38 @@ config ARCH_MSMFALCON
This enables support for the MSMFALCON chipset. If you do not
wish to build a kernel that runs on this chipset, say 'N' here.
+config ARCH_MSMTRITON
+ bool "Enable Support for Qualcomm MSMTRITON"
+ select CLKDEV_LOOKUP
+ select HAVE_CLK
+ select HAVE_CLK_PREPARE
+ select PM_OPP
+ select SOC_BUS
+ select MSM_IRQ
+ select THERMAL_WRITABLE_TRIPS
+ select ARM_GIC_V3
+ select ARM_AMBA
+ select SPARSE_IRQ
+ select MULTI_IRQ_HANDLER
+ select HAVE_ARM_ARCH_TIMER
+ select MAY_HAVE_SPARSE_IRQ
+ select MSM_PM if PM
+ select QMI_ENCDEC
+ select CPU_FREQ
+ select CPU_FREQ_MSM
+ select PM_DEVFREQ
+ select MSM_DEVFREQ_DEVBW
+ select DEVFREQ_SIMPLE_DEV
+ select DEVFREQ_GOV_MSM_BW_HWMON
+ select MSM_BIMC_BWMON
+ select MSM_QDSP6V2_CODECS
+ select MSM_AUDIO_QDSP6V2 if SND_SOC
+ select MSM_RPM_SMD
+ select MSM_JTAGV8 if CORESIGHT_ETMV4
+ help
+ This enables support for the MSMTRITON chipset. If you do not
+ wish to build a kernel that runs on this chipset, say 'N' here.
+
config ARCH_MSM8X60
bool "Enable support for MSM8X60"
select ARCH_SUPPORTS_BIG_ENDIAN
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 52486c0e6598..80c4c50814d8 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -807,6 +807,7 @@ static void arm_dma_unremap(struct device *dev, void *remapped_addr,
unsigned int flags = VM_ARM_DMA_CONSISTENT | VM_USERMAP;
struct vm_struct *area;
+ size = PAGE_ALIGN(size);
remapped_addr = (void *)((unsigned long)remapped_addr & PAGE_MASK);
area = find_vm_area(remapped_addr);
@@ -1818,7 +1819,7 @@ void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
total_length = PAGE_ALIGN((iova & ~PAGE_MASK) + total_length);
iova &= PAGE_MASK;
- iommu_unmap_range(mapping->domain, iova, total_length);
+ iommu_unmap(mapping->domain, iova, total_length);
__free_iova(mapping, iova, total_length);
}
diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
index 4cdb28c92e5f..6236b3e1297c 100644
--- a/arch/arm64/Kconfig.debug
+++ b/arch/arm64/Kconfig.debug
@@ -73,7 +73,7 @@ config DEBUG_RODATA
If in doubt, say Y
config DEBUG_ALIGN_RODATA
- depends on DEBUG_RODATA && ARM64_4K_PAGES
+ depends on DEBUG_RODATA
bool "Align linker sections up to SECTION_SIZE"
help
If this option is enabled, sections that may potentially be marked as
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 14c74a66c58e..4c2298924cc3 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -116,7 +116,7 @@ dtbs: prepare scripts
dtbs_install:
$(Q)$(MAKE) $(dtbinst)=$(boot)/dts
-Image.gz-dtb: vmlinux scripts dtbs
+Image-dtb Image.gz-dtb: vmlinux scripts dtbs
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
PHONY += vdso_install
diff --git a/arch/arm64/boot/.gitignore b/arch/arm64/boot/.gitignore
index eb3551131b1e..34e35209fc2e 100644
--- a/arch/arm64/boot/.gitignore
+++ b/arch/arm64/boot/.gitignore
@@ -1,3 +1,4 @@
Image
+Image-dtb
Image.gz
Image.gz-dtb
diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile
index a0cef8edcbad..6fee388eb386 100644
--- a/arch/arm64/boot/Makefile
+++ b/arch/arm64/boot/Makefile
@@ -30,6 +30,9 @@ $(obj)/Image: vmlinux FORCE
$(obj)/Image.bz2: $(obj)/Image FORCE
$(call if_changed,bzip2)
+$(obj)/Image-dtb: $(obj)/Image $(DTB_OBJS) FORCE
+ $(call if_changed,cat)
+
$(obj)/Image.gz: $(obj)/Image FORCE
$(call if_changed,gzip)
diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts
index 53442b5ee4ff..3e1a84b01b50 100644
--- a/arch/arm64/boot/dts/arm/juno.dts
+++ b/arch/arm64/boot/dts/arm/juno.dts
@@ -143,5 +143,310 @@
<&A53_3>;
};
+ etr@20070000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0 0x20070000 0 0x1000>;
+
+ clocks = <&soc_smc50mhz>;
+ clock-names = "apb_pclk";
+ port {
+ etr_in_port: endpoint {
+ slave-mode;
+ remote-endpoint = <&replicator_out_port1>;
+ };
+ };
+ };
+
+ tpiu@20030000 {
+ compatible = "arm,coresight-tpiu", "arm,primecell";
+ reg = <0 0x20030000 0 0x1000>;
+
+ clocks = <&soc_smc50mhz>;
+ clock-names = "apb_pclk";
+ port {
+ tpiu_in_port: endpoint {
+ slave-mode;
+ remote-endpoint = <&replicator_out_port0>;
+ };
+ };
+ };
+
+ replicator@20020000 {
+ /* non-configurable replicators don't show up on the
+ * AMBA bus. As such no need to add "arm,primecell".
+ */
+ compatible = "arm,coresight-replicator";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* replicator output ports */
+ port@0 {
+ reg = <0>;
+ replicator_out_port0: endpoint {
+ remote-endpoint = <&tpiu_in_port>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ replicator_out_port1: endpoint {
+ remote-endpoint = <&etr_in_port>;
+ };
+ };
+
+ /* replicator input port */
+ port@2 {
+ reg = <0>;
+ replicator_in_port0: endpoint {
+ slave-mode;
+ remote-endpoint = <&etf_out_port>;
+ };
+ };
+ };
+ };
+
+ etf@20010000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0 0x20010000 0 0x1000>;
+
+ clocks = <&soc_smc50mhz>;
+ clock-names = "apb_pclk";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* input port */
+ port@0 {
+ reg = <0>;
+ etf_in_port: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&main_funnel_out_port>;
+ };
+ };
+
+ /* output port */
+ port@1 {
+ reg = <0>;
+ etf_out_port: endpoint {
+ remote-endpoint =
+ <&replicator_in_port0>;
+ };
+ };
+ };
+ };
+
+ main_funnel@20040000 {
+ compatible = "arm,coresight-funnel", "arm,primecell";
+ reg = <0 0x20040000 0 0x1000>;
+
+ clocks = <&soc_smc50mhz>;
+ clock-names = "apb_pclk";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ main_funnel_out_port: endpoint {
+ remote-endpoint =
+ <&etf_in_port>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ main_funnel_in_port0: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&A72_57_funnel_out_port>;
+ };
+ };
+
+ port@2 {
+ reg = <1>;
+ main_funnel_in_port1: endpoint {
+ slave-mode;
+ remote-endpoint = <&A53_funnel_out_port>;
+ };
+ };
+
+ };
+ };
+
+ A72_57_funnel@220c0000 {
+ compatible = "arm,coresight-funnel", "arm,primecell";
+ reg = <0 0x220c0000 0 0x1000>;
+
+ clocks = <&soc_smc50mhz>;
+ clock-names = "apb_pclk";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ A72_57_funnel_out_port: endpoint {
+ remote-endpoint =
+ <&main_funnel_in_port0>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ A72_57_funnel_in_port0: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&A72_57_etm0_out_port>;
+ };
+ };
+
+ port@2 {
+ reg = <1>;
+ A72_57_funnel_in_port1: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&A72_57_etm1_out_port>;
+ };
+ };
+ };
+ };
+
+ A53_funnel@220c0000 {
+ compatible = "arm,coresight-funnel", "arm,primecell";
+ reg = <0 0x230c0000 0 0x1000>;
+
+ clocks = <&soc_smc50mhz>;
+ clock-names = "apb_pclk";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ A53_funnel_out_port: endpoint {
+ remote-endpoint =
+ <&main_funnel_in_port1>;
+ };
+ };
+
+ port@1 {
+ reg = <0>;
+ A53_funnel_in_port0: endpoint {
+ slave-mode;
+ remote-endpoint = <&A53_etm0_out_port>;
+ };
+ };
+
+ port@2 {
+ reg = <1>;
+ A53_funnel_in_port1: endpoint {
+ slave-mode;
+ remote-endpoint = <&A53_etm1_out_port>;
+ };
+ };
+ port@3 {
+ reg = <2>;
+ A53_funnel_in_port2: endpoint {
+ slave-mode;
+ remote-endpoint = <&A53_etm2_out_port>;
+ };
+ };
+ port@4 {
+ reg = <3>;
+ A53_funnel_in_port3: endpoint {
+ slave-mode;
+ remote-endpoint = <&A53_etm3_out_port>;
+ };
+ };
+ };
+ };
+
+ etm@22040000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x22040000 0 0x1000>;
+
+ cpu = <&A57_0>;
+ clocks = <&soc_smc50mhz>;
+ clock-names = "apb_pclk";
+ port {
+ A72_57_etm0_out_port: endpoint {
+ remote-endpoint = <&A72_57_funnel_in_port0>;
+ };
+ };
+ };
+
+ etm@22140000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x22140000 0 0x1000>;
+
+ cpu = <&A57_1>;
+ clocks = <&soc_smc50mhz>;
+ clock-names = "apb_pclk";
+ port {
+ A72_57_etm1_out_port: endpoint {
+ remote-endpoint = <&A72_57_funnel_in_port1>;
+ };
+ };
+ };
+
+ etm@23040000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x23040000 0 0x1000>;
+
+ cpu = <&A53_0>;
+ clocks = <&soc_smc50mhz>;
+ clock-names = "apb_pclk";
+ port {
+ A53_etm0_out_port: endpoint {
+ remote-endpoint = <&A53_funnel_in_port0>;
+ };
+ };
+ };
+
+ etm@23140000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x23140000 0 0x1000>;
+
+ cpu = <&A53_1>;
+ clocks = <&soc_smc50mhz>;
+ clock-names = "apb_pclk";
+ port {
+ A53_etm1_out_port: endpoint {
+ remote-endpoint = <&A53_funnel_in_port1>;
+ };
+ };
+ };
+
+ etm@23240000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x23240000 0 0x1000>;
+
+ cpu = <&A53_2>;
+ clocks = <&soc_smc50mhz>;
+ clock-names = "apb_pclk";
+ port {
+ A53_etm2_out_port: endpoint {
+ remote-endpoint = <&A53_funnel_in_port2>;
+ };
+ };
+ };
+
+ etm@23340000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x23340000 0 0x1000>;
+
+ cpu = <&A53_3>;
+ clocks = <&soc_smc50mhz>;
+ clock-names = "apb_pclk";
+ port {
+ A53_etm3_out_port: endpoint {
+ remote-endpoint = <&A53_funnel_in_port3>;
+ };
+ };
+ };
+
#include "juno-base.dtsi"
};
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 0bda100dfb5a..df65a3db12f5 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -249,6 +249,8 @@ CONFIG_DM_CRYPT=y
CONFIG_DM_REQ_CRYPT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_ANDROID_VERITY=y
CONFIG_NETDEVICES=y
CONFIG_BONDING=y
CONFIG_DUMMY=y
@@ -380,9 +382,9 @@ CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
CONFIG_MSMB_JPEG=y
CONFIG_MSM_FD=y
CONFIG_MSM_JPEGDMA=y
-CONFIG_MSM_VIDC_V4L2=m
-CONFIG_MSM_VIDC_VMEM=m
-CONFIG_MSM_VIDC_GOVERNORS=m
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_VMEM=y
+CONFIG_MSM_VIDC_GOVERNORS=y
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
CONFIG_QCOM_KGSL=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index 3568fe4ed29f..2f7dfa9216b1 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -251,6 +251,8 @@ CONFIG_DM_CRYPT=y
CONFIG_DM_REQ_CRYPT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_ANDROID_VERITY=y
CONFIG_NETDEVICES=y
CONFIG_BONDING=y
CONFIG_DUMMY=y
@@ -383,9 +385,9 @@ CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
CONFIG_MSMB_JPEG=y
CONFIG_MSM_FD=y
CONFIG_MSM_JPEGDMA=y
-CONFIG_MSM_VIDC_V4L2=m
-CONFIG_MSM_VIDC_VMEM=m
-CONFIG_MSM_VIDC_GOVERNORS=m
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_VMEM=y
+CONFIG_MSM_VIDC_GOVERNORS=y
CONFIG_MSM_SDE_ROTATOR=y
CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
CONFIG_QCOM_KGSL=y
diff --git a/arch/arm64/configs/msmfalcon-perf_defconfig b/arch/arm64/configs/msmfalcon-perf_defconfig
index 5d271cad0aad..df695f993ed9 100644
--- a/arch/arm64/configs/msmfalcon-perf_defconfig
+++ b/arch/arm64/configs/msmfalcon-perf_defconfig
@@ -13,13 +13,16 @@ CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
CONFIG_CGROUP_FREEZER=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHEDTUNE=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_SCHED_HMP=y
CONFIG_SCHED_HMP_CSTATE_AWARE=y
+CONFIG_SCHED_CORE_CTL=y
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
# CONFIG_PID_NS is not set
CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SCHED_TUNE=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
@@ -90,6 +93,7 @@ CONFIG_IP_PNP_DHCP=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
+CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
@@ -255,9 +259,15 @@ CONFIG_SMSC911X=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
CONFIG_USB_USBNET=y
CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_ATH_CARDS=y
@@ -271,6 +281,7 @@ CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
+CONFIG_SECURE_TOUCH=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_UINPUT=y
@@ -314,7 +325,9 @@ CONFIG_MSM_BCL_PERIPHERAL_CTL=y
CONFIG_BATTERY_BCL=y
CONFIG_QPNP_SMB2=y
CONFIG_SMB138X_CHARGER=y
+CONFIG_QPNP_QNOVO=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_CPU_THERMAL=y
CONFIG_LIMITS_MONITOR=y
CONFIG_LIMITS_LITE_HW=y
CONFIG_THERMAL_MONITOR=y
@@ -373,10 +386,11 @@ CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
CONFIG_MSMB_JPEG=y
CONFIG_MSM_FD=y
CONFIG_MSM_JPEGDMA=y
-CONFIG_MSM_VIDC_V4L2=y
-CONFIG_MSM_VIDC_VMEM=y
-CONFIG_MSM_VIDC_GOVERNORS=y
+CONFIG_MSM_VIDC_V4L2=m
+CONFIG_MSM_VIDC_VMEM=m
+CONFIG_MSM_VIDC_GOVERNORS=m
CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
CONFIG_QCOM_KGSL=y
CONFIG_FB=y
CONFIG_FB_ARMCLCD=y
@@ -430,6 +444,7 @@ CONFIG_USB_CONFIGFS_F_MTP=y
CONFIG_USB_CONFIGFS_F_PTP=y
CONFIG_USB_CONFIGFS_F_ACC=y
CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_DIAG=y
CONFIG_USB_CONFIGFS_F_GSI=y
@@ -474,6 +489,7 @@ CONFIG_GPIO_USB_DETECT=y
CONFIG_SEEMP_CORE=y
CONFIG_USB_BAM=y
CONFIG_QCOM_CLK_SMD_RPM=y
+CONFIG_MSM_GCC_FALCON=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_IOMMU_IO_PGTABLE_FAST=y
CONFIG_ARM_SMMU=y
@@ -489,6 +505,7 @@ CONFIG_MSM_GLINK_SMD_XPRT=y
CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
CONFIG_MSM_GLINK_SPI_XPRT=y
CONFIG_MSM_SPCOM=y
+CONFIG_MSM_SPSS_UTILS=y
CONFIG_MSM_SMEM_LOGGING=y
CONFIG_MSM_SMP2P=y
CONFIG_MSM_SMP2P_TEST=y
@@ -525,6 +542,8 @@ CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_RPM_STATS_LOG=y
CONFIG_QSEE_IPC_IRQ_BRIDGE=y
+CONFIG_QCOM_SMCINVOKE=y
+CONFIG_QCOM_EARLY_RANDOM=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_ARM_MEMLAT_MON=y
@@ -536,16 +555,21 @@ CONFIG_DEVFREQ_SPDM=y
CONFIG_EXTCON=y
CONFIG_IIO=y
CONFIG_QCOM_RRADC=y
+CONFIG_QCOM_TADC=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_ARM_GIC_V3_ACL=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_MSM_TZ_LOG=y
CONFIG_SENSORS_SSC=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
CONFIG_FUSE_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
@@ -568,6 +592,7 @@ CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_DEBUG_RODATA=y
CONFIG_DEBUG_ALIGN_RODATA=y
CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_LINKS_AND_SINKS=y
CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
CONFIG_CORESIGHT_QCOM_REPLICATOR=y
diff --git a/arch/arm64/configs/msmfalcon_defconfig b/arch/arm64/configs/msmfalcon_defconfig
index 707bc68c825f..8719eb7cb92e 100644
--- a/arch/arm64/configs/msmfalcon_defconfig
+++ b/arch/arm64/configs/msmfalcon_defconfig
@@ -13,13 +13,16 @@ CONFIG_CGROUP_DEBUG=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CPUSETS=y
CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHEDTUNE=y
CONFIG_CGROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_SCHED_HMP=y
CONFIG_SCHED_HMP_CSTATE_AWARE=y
+CONFIG_SCHED_CORE_CTL=y
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
# CONFIG_PID_NS is not set
+CONFIG_SCHED_TUNE=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
@@ -89,6 +92,7 @@ CONFIG_IP_PNP_DHCP=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
+CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
CONFIG_IPV6_OPTIMISTIC_DAD=y
@@ -256,9 +260,15 @@ CONFIG_PHYLIB=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_ATH_CARDS=y
CONFIG_WIL6210=m
@@ -272,6 +282,7 @@ CONFIG_INPUT_JOYSTICK=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
+CONFIG_SECURE_TOUCH=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_KEYCHORD=y
@@ -317,7 +328,9 @@ CONFIG_MSM_BCL_PERIPHERAL_CTL=y
CONFIG_BATTERY_BCL=y
CONFIG_QPNP_SMB2=y
CONFIG_SMB138X_CHARGER=y
+CONFIG_QPNP_QNOVO=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_CPU_THERMAL=y
CONFIG_LIMITS_MONITOR=y
CONFIG_LIMITS_LITE_HW=y
CONFIG_THERMAL_MONITOR=y
@@ -376,10 +389,11 @@ CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
CONFIG_MSMB_JPEG=y
CONFIG_MSM_FD=y
CONFIG_MSM_JPEGDMA=y
-CONFIG_MSM_VIDC_V4L2=y
-CONFIG_MSM_VIDC_VMEM=y
-CONFIG_MSM_VIDC_GOVERNORS=y
+CONFIG_MSM_VIDC_V4L2=m
+CONFIG_MSM_VIDC_VMEM=m
+CONFIG_MSM_VIDC_GOVERNORS=m
CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
CONFIG_QCOM_KGSL=y
CONFIG_FB=y
CONFIG_FB_VIRTUAL=y
@@ -432,6 +446,7 @@ CONFIG_USB_CONFIGFS_F_MTP=y
CONFIG_USB_CONFIGFS_F_PTP=y
CONFIG_USB_CONFIGFS_F_ACC=y
CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
CONFIG_USB_CONFIGFS_F_HID=y
CONFIG_USB_CONFIGFS_F_DIAG=y
CONFIG_USB_CONFIGFS_F_GSI=y
@@ -484,6 +499,7 @@ CONFIG_GPIO_USB_DETECT=y
CONFIG_SEEMP_CORE=y
CONFIG_USB_BAM=y
CONFIG_QCOM_CLK_SMD_RPM=y
+CONFIG_MSM_GCC_FALCON=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_IOMMU_IO_PGTABLE_FAST=y
CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST=y
@@ -502,6 +518,7 @@ CONFIG_MSM_GLINK_SMD_XPRT=y
CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
CONFIG_MSM_GLINK_SPI_XPRT=y
CONFIG_MSM_SPCOM=y
+CONFIG_MSM_SPSS_UTILS=y
CONFIG_MSM_SMEM_LOGGING=y
CONFIG_MSM_SMP2P=y
CONFIG_MSM_SMP2P_TEST=y
@@ -545,6 +562,8 @@ CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_RPM_STATS_LOG=y
CONFIG_QSEE_IPC_IRQ_BRIDGE=y
+CONFIG_QCOM_SMCINVOKE=y
+CONFIG_QCOM_EARLY_RANDOM=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_ARM_MEMLAT_MON=y
@@ -556,6 +575,7 @@ CONFIG_DEVFREQ_SPDM=y
CONFIG_EXTCON=y
CONFIG_IIO=y
CONFIG_QCOM_RRADC=y
+CONFIG_QCOM_TADC=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_ARM_GIC_V3_ACL=y
@@ -568,6 +588,9 @@ CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
CONFIG_FUSE_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
@@ -633,6 +656,7 @@ CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_DEBUG_RODATA=y
CONFIG_FREE_PAGES_RDONLY=y
CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
CONFIG_CORESIGHT_SOURCE_ETM4X=y
CONFIG_CORESIGHT_REMOTE_ETM=y
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index fcaf3cce639a..f8856a450852 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -245,4 +245,24 @@ lr .req x30 // link register
.long \sym\()_hi32
.endm
+ /*
+ * mov_q - move an immediate constant into a 64-bit register using
+ * between 2 and 4 movz/movk instructions (depending on the
+ * magnitude and sign of the operand)
+ */
+ .macro mov_q, reg, val
+ .if (((\val) >> 31) == 0 || ((\val) >> 31) == 0x1ffffffff)
+ movz \reg, :abs_g1_s:\val
+ .else
+ .if (((\val) >> 47) == 0 || ((\val) >> 47) == 0x1ffff)
+ movz \reg, :abs_g2_s:\val
+ .else
+ movz \reg, :abs_g3:\val
+ movk \reg, :abs_g2_nc:\val
+ .endif
+ movk \reg, :abs_g1_nc:\val
+ .endif
+ movk \reg, :abs_g0_nc:\val
+ .endm
+
#endif /* __ASM_ASSEMBLER_H */
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 24ed037f09fd..83d48a599f69 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -160,14 +160,14 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
#define STACK_RND_MASK (0x3ffff >> (PAGE_SHIFT - 12))
#endif
-#ifdef CONFIG_COMPAT
-
#ifdef __AARCH64EB__
#define COMPAT_ELF_PLATFORM ("v8b")
#else
#define COMPAT_ELF_PLATFORM ("v8l")
#endif
+#ifdef CONFIG_COMPAT
+
#define COMPAT_ELF_ET_DYN_BASE (2 * TASK_SIZE_32 / 3)
/* AArch32 registers. */
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index 5c25b831273d..9786f770088d 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -133,7 +133,6 @@
* Section
*/
#define PMD_SECT_VALID (_AT(pmdval_t, 1) << 0)
-#define PMD_SECT_PROT_NONE (_AT(pmdval_t, 1) << 58)
#define PMD_SECT_USER (_AT(pmdval_t, 1) << 6) /* AP[1] */
#define PMD_SECT_RDONLY (_AT(pmdval_t, 1) << 7) /* AP[2] */
#define PMD_SECT_S (_AT(pmdval_t, 3) << 8)
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index c3c2518eecfe..9a09ccf7122d 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -348,6 +348,7 @@ void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address,
#endif /* CONFIG_HAVE_RCU_TABLE_FREE */
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+#define pmd_present(pmd) pte_present(pmd_pte(pmd))
#define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd))
#define pmd_young(pmd) pte_young(pmd_pte(pmd))
#define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd)))
@@ -357,7 +358,7 @@ void pmdp_splitting_flush(struct vm_area_struct *vma, unsigned long address,
#define pmd_mkclean(pmd) pte_pmd(pte_mkclean(pmd_pte(pmd)))
#define pmd_mkdirty(pmd) pte_pmd(pte_mkdirty(pmd_pte(pmd)))
#define pmd_mkyoung(pmd) pte_pmd(pte_mkyoung(pmd_pte(pmd)))
-#define pmd_mknotpresent(pmd) (__pmd(pmd_val(pmd) & ~PMD_TYPE_MASK))
+#define pmd_mknotpresent(pmd) (__pmd(pmd_val(pmd) & ~PMD_SECT_VALID))
#define __HAVE_ARCH_PMD_WRITE
#define pmd_write(pmd) pte_write(pmd_pte(pmd))
@@ -396,7 +397,6 @@ extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
unsigned long size, pgprot_t vma_prot);
#define pmd_none(pmd) (!pmd_val(pmd))
-#define pmd_present(pmd) (pmd_val(pmd))
#define pmd_bad(pmd) (!(pmd_val(pmd) & 2))
@@ -595,6 +595,21 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
}
#ifdef CONFIG_ARM64_HW_AFDBM
+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+extern int ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep,
+ pte_t entry, int dirty);
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+#define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS
+static inline int pmdp_set_access_flags(struct vm_area_struct *vma,
+ unsigned long address, pmd_t *pmdp,
+ pmd_t entry, int dirty)
+{
+ return ptep_set_access_flags(vma, address, (pte_t *)pmdp, pmd_pte(entry), dirty);
+}
+#endif
+
/*
* Atomic pte/pmd modifications.
*/
@@ -647,9 +662,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-#define __HAVE_ARCH_PMDP_GET_AND_CLEAR
-static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
- unsigned long address, pmd_t *pmdp)
+#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
+static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
+ unsigned long address, pmd_t *pmdp)
{
return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp));
}
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index e9e5467e0bf4..a307eb6e7fa8 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -58,6 +58,7 @@
#define COMPAT_PSR_Z_BIT 0x40000000
#define COMPAT_PSR_N_BIT 0x80000000
#define COMPAT_PSR_IT_MASK 0x0600fc00 /* If-Then execution state mask */
+#define COMPAT_PSR_GE_MASK 0x000f0000
#ifdef CONFIG_CPU_BIG_ENDIAN
#define COMPAT_PSR_ENDSTATE COMPAT_PSR_E_BIT
@@ -151,35 +152,9 @@ static inline unsigned long regs_return_value(struct pt_regs *regs)
return regs->regs[0];
}
-/*
- * Are the current registers suitable for user mode? (used to maintain
- * security in signal handlers)
- */
-static inline int valid_user_regs(struct user_pt_regs *regs)
-{
- if (user_mode(regs) && (regs->pstate & PSR_I_BIT) == 0) {
- regs->pstate &= ~(PSR_F_BIT | PSR_A_BIT);
-
- /* The T bit is reserved for AArch64 */
- if (!(regs->pstate & PSR_MODE32_BIT))
- regs->pstate &= ~COMPAT_PSR_T_BIT;
-
- return 1;
- }
-
- /*
- * Force PSR to something logical...
- */
- regs->pstate &= PSR_f | PSR_s | (PSR_x & ~PSR_A_BIT) | \
- COMPAT_PSR_T_BIT | PSR_MODE32_BIT;
-
- if (!(regs->pstate & PSR_MODE32_BIT)) {
- regs->pstate &= ~COMPAT_PSR_T_BIT;
- regs->pstate |= PSR_MODE_EL0t;
- }
-
- return 0;
-}
+/* We must avoid circular header include via sched.h */
+struct task_struct;
+int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task);
#define instruction_pointer(regs) ((unsigned long)(regs)->pc)
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 17cf73e70752..4b2caefd3a8f 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -23,6 +23,8 @@
#include <linux/bitops.h>
#include <linux/bug.h>
+#include <linux/compat.h>
+#include <linux/elf.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/personality.h>
@@ -107,6 +109,7 @@ static const char *const compat_hwcap2_str[] = {
static int c_show(struct seq_file *m, void *v)
{
int i, j;
+ bool compat = personality(current->personality) == PER_LINUX32;
seq_printf(m, "Processor\t: AArch64 Processor rev %d (%s)\n",
read_cpuid_id() & 15, ELF_PLATFORM);
@@ -120,6 +123,9 @@ static int c_show(struct seq_file *m, void *v)
* "processor". Give glibc what it expects.
*/
seq_printf(m, "processor\t: %d\n", i);
+ if (compat)
+ seq_printf(m, "model name\t: ARMv8 Processor rev %d (%s)\n",
+ MIDR_REVISION(midr), COMPAT_ELF_PLATFORM);
seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
loops_per_jiffy / (500000UL/HZ),
@@ -132,7 +138,7 @@ static int c_show(struct seq_file *m, void *v)
* software which does already (at least for 32-bit).
*/
seq_puts(m, "Features\t:");
- if (personality(current->personality) == PER_LINUX32) {
+ if (compat) {
#ifdef CONFIG_COMPAT
for (j = 0; compat_hwcap_str[j]; j++)
if (compat_elf_hwcap & (1 << j))
diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
index f82036e02485..936022f0655e 100644
--- a/arch/arm64/kernel/efi-entry.S
+++ b/arch/arm64/kernel/efi-entry.S
@@ -61,7 +61,7 @@ ENTRY(entry)
*/
mov x20, x0 // DTB address
ldr x0, [sp, #16] // relocated _text address
- movz x21, #:abs_g0:stext_offset
+ ldr w21, =stext_offset
add x21, x0, x21
/*
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index a88a15447c3b..491ad4124615 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -25,6 +25,7 @@
#include <linux/irqchip/arm-gic-v3.h>
#include <asm/assembler.h>
+#include <asm/boot.h>
#include <asm/ptrace.h>
#include <asm/asm-offsets.h>
#include <asm/cache.h>
@@ -100,8 +101,6 @@ _head:
#endif
#ifdef CONFIG_EFI
- .globl __efistub_stext_offset
- .set __efistub_stext_offset, stext - _head
.align 3
pe_header:
.ascii "PE"
@@ -121,11 +120,11 @@ optional_header:
.short 0x20b // PE32+ format
.byte 0x02 // MajorLinkerVersion
.byte 0x14 // MinorLinkerVersion
- .long _end - stext // SizeOfCode
+ .long _end - efi_header_end // SizeOfCode
.long 0 // SizeOfInitializedData
.long 0 // SizeOfUninitializedData
.long __efistub_entry - _head // AddressOfEntryPoint
- .long __efistub_stext_offset // BaseOfCode
+ .long efi_header_end - _head // BaseOfCode
extra_header_fields:
.quad 0 // ImageBase
@@ -142,7 +141,7 @@ extra_header_fields:
.long _end - _head // SizeOfImage
// Everything before the kernel image is considered part of the header
- .long __efistub_stext_offset // SizeOfHeaders
+ .long efi_header_end - _head // SizeOfHeaders
.long 0 // CheckSum
.short 0xa // Subsystem (EFI application)
.short 0 // DllCharacteristics
@@ -186,10 +185,10 @@ section_table:
.byte 0
.byte 0
.byte 0 // end of 0 padding of section name
- .long _end - stext // VirtualSize
- .long __efistub_stext_offset // VirtualAddress
- .long _edata - stext // SizeOfRawData
- .long __efistub_stext_offset // PointerToRawData
+ .long _end - efi_header_end // VirtualSize
+ .long efi_header_end - _head // VirtualAddress
+ .long _edata - efi_header_end // SizeOfRawData
+ .long efi_header_end - _head // PointerToRawData
.long 0 // PointerToRelocations (0 for executables)
.long 0 // PointerToLineNumbers (0 for executables)
@@ -198,20 +197,23 @@ section_table:
.long 0xe0500020 // Characteristics (section flags)
/*
- * EFI will load stext onwards at the 4k section alignment
+ * EFI will load .text onwards at the 4k section alignment
* described in the PE/COFF header. To ensure that instruction
* sequences using an adrp and a :lo12: immediate will function
- * correctly at this alignment, we must ensure that stext is
+ * correctly at this alignment, we must ensure that .text is
* placed at a 4k boundary in the Image to begin with.
*/
.align 12
+efi_header_end:
#endif
+ __INIT
+
ENTRY(stext)
bl preserve_boot_args
bl el2_setup // Drop to EL1, w20=cpu_boot_mode
- mov x23, xzr // KASLR offset, defaults to 0
adrp x24, __PHYS_OFFSET
+ and x23, x24, MIN_KIMG_ALIGN - 1 // KASLR offset, defaults to 0
bl set_cpu_boot_mode_flag
bl __create_page_tables // x25=TTBR0, x26=TTBR1
/*
@@ -220,13 +222,11 @@ ENTRY(stext)
* On return, the CPU will be ready for the MMU to be turned on and
* the TCR will have been set.
*/
- ldr x27, 0f // address to jump to after
+ bl __cpu_setup // initialise processor
+ adr_l x27, __primary_switch // address to jump to after
// MMU has been enabled
- adr_l lr, __enable_mmu // return (PIC) address
- b __cpu_setup // initialise processor
+ b __enable_mmu
ENDPROC(stext)
- .align 3
-0: .quad __mmap_switched - (_head - TEXT_OFFSET) + KIMAGE_VADDR
/*
* Preserve the arguments passed by the bootloader in x0 .. x3
@@ -336,7 +336,7 @@ __create_page_tables:
cmp x0, x6
b.lo 1b
- ldr x7, =SWAPPER_MM_MMUFLAGS
+ mov x7, SWAPPER_MM_MMUFLAGS
/*
* Create the identity mapping.
@@ -392,12 +392,13 @@ __create_page_tables:
* Map the kernel image (starting with PHYS_OFFSET).
*/
mov x0, x26 // swapper_pg_dir
- ldr x5, =KIMAGE_VADDR
+ mov_q x5, KIMAGE_VADDR + TEXT_OFFSET // compile time __va(_text)
add x5, x5, x23 // add KASLR displacement
create_pgd_entry x0, x5, x3, x6
- ldr w6, kernel_img_size
- add x6, x6, x5
- mov x3, x24 // phys offset
+ adrp x6, _end // runtime __pa(_end)
+ adrp x3, _text // runtime __pa(_text)
+ sub x6, x6, x3 // _end - _text
+ add x6, x6, x5 // runtime __va(_end)
create_block_map x0, x7, x3, x5, x6
/*
@@ -412,16 +413,13 @@ __create_page_tables:
ret x28
ENDPROC(__create_page_tables)
-
-kernel_img_size:
- .long _end - (_head - TEXT_OFFSET)
.ltorg
/*
* The following fragment of code is executed with the MMU enabled.
*/
.set initial_sp, init_thread_union + THREAD_START_SP
-__mmap_switched:
+__primary_switched:
mov x28, lr // preserve LR
adr_l x8, vectors // load VBAR_EL1 with virtual
msr vbar_el1, x8 // vector table address
@@ -435,44 +433,6 @@ __mmap_switched:
bl __pi_memset
dsb ishst // Make zero page visible to PTW
-#ifdef CONFIG_RELOCATABLE
-
- /*
- * Iterate over each entry in the relocation table, and apply the
- * relocations in place.
- */
- adr_l x8, __dynsym_start // start of symbol table
- adr_l x9, __reloc_start // start of reloc table
- adr_l x10, __reloc_end // end of reloc table
-
-0: cmp x9, x10
- b.hs 2f
- ldp x11, x12, [x9], #24
- ldr x13, [x9, #-8]
- cmp w12, #R_AARCH64_RELATIVE
- b.ne 1f
- add x13, x13, x23 // relocate
- str x13, [x11, x23]
- b 0b
-
-1: cmp w12, #R_AARCH64_ABS64
- b.ne 0b
- add x12, x12, x12, lsl #1 // symtab offset: 24x top word
- add x12, x8, x12, lsr #(32 - 3) // ... shifted into bottom word
- ldrsh w14, [x12, #6] // Elf64_Sym::st_shndx
- ldr x15, [x12, #8] // Elf64_Sym::st_value
- cmp w14, #-0xf // SHN_ABS (0xfff1) ?
- add x14, x15, x23 // relocate
- csel x15, x14, x15, ne
- add x15, x13, x15
- str x15, [x11, x23]
- b 0b
-
-2: adr_l x8, kimage_vaddr // make relocated kimage_vaddr
- dc cvac, x8 // value visible to secondaries
- dsb sy // with MMU off
-#endif
-
adr_l sp, initial_sp, x4
mov x4, sp
and x4, x4, #~(THREAD_SIZE - 1)
@@ -488,17 +448,19 @@ __mmap_switched:
bl kasan_early_init
#endif
#ifdef CONFIG_RANDOMIZE_BASE
- cbnz x23, 0f // already running randomized?
+ tst x23, ~(MIN_KIMG_ALIGN - 1) // already running randomized?
+ b.ne 0f
mov x0, x21 // pass FDT address in x0
+ mov x1, x23 // pass modulo offset in x1
bl kaslr_early_init // parse FDT for KASLR options
cbz x0, 0f // KASLR disabled? just proceed
- mov x23, x0 // record KASLR offset
+ orr x23, x23, x0 // record KASLR offset
ret x28 // we must enable KASLR, return
// to __enable_mmu()
0:
#endif
b start_kernel
-ENDPROC(__mmap_switched)
+ENDPROC(__primary_switched)
/*
* end early head section, begin head code that is also used for
@@ -613,7 +575,7 @@ ENDPROC(el2_setup)
* Sets the __boot_cpu_mode flag depending on the CPU boot mode passed
* in x20. See arch/arm64/include/asm/virt.h for more info.
*/
-ENTRY(set_cpu_boot_mode_flag)
+set_cpu_boot_mode_flag:
adr_l x1, __boot_cpu_mode
cmp w20, #BOOT_CPU_MODE_EL2
b.ne 1f
@@ -646,7 +608,7 @@ ENTRY(secondary_holding_pen)
bl el2_setup // Drop to EL1, w20=cpu_boot_mode
bl set_cpu_boot_mode_flag
mrs x0, mpidr_el1
- ldr x1, =MPIDR_HWID_BITMASK
+ mov_q x1, MPIDR_HWID_BITMASK
and x0, x0, x1
adr_l x3, secondary_holding_pen_release
pen: ldr x4, [x3]
@@ -666,7 +628,7 @@ ENTRY(secondary_entry)
b secondary_startup
ENDPROC(secondary_entry)
-ENTRY(secondary_startup)
+secondary_startup:
/*
* Common entry point for secondary CPUs.
*/
@@ -674,14 +636,11 @@ ENTRY(secondary_startup)
adrp x26, swapper_pg_dir
bl __cpu_setup // initialise processor
- ldr x8, kimage_vaddr
- ldr w9, 0f
- sub x27, x8, w9, sxtw // address to jump to after enabling the MMU
+ adr_l x27, __secondary_switch // address to jump to after enabling the MMU
b __enable_mmu
ENDPROC(secondary_startup)
-0: .long (_text - TEXT_OFFSET) - __secondary_switched
-ENTRY(__secondary_switched)
+__secondary_switched:
adr_l x5, vectors
msr vbar_el1, x5
isb
@@ -743,7 +702,6 @@ __enable_mmu:
ic iallu // flush instructions fetched
dsb nsh // via old mapping
isb
- add x27, x27, x23 // relocated __mmap_switched
#endif
br x27
ENDPROC(__enable_mmu)
@@ -752,3 +710,53 @@ __no_granule_support:
wfe
b __no_granule_support
ENDPROC(__no_granule_support)
+
+__primary_switch:
+#ifdef CONFIG_RELOCATABLE
+ /*
+ * Iterate over each entry in the relocation table, and apply the
+ * relocations in place.
+ */
+ ldr w8, =__dynsym_offset // offset to symbol table
+ ldr w9, =__rela_offset // offset to reloc table
+ ldr w10, =__rela_size // size of reloc table
+
+ mov_q x11, KIMAGE_VADDR // default virtual offset
+ add x11, x11, x23 // actual virtual offset
+ add x8, x8, x11 // __va(.dynsym)
+ add x9, x9, x11 // __va(.rela)
+ add x10, x9, x10 // __va(.rela) + sizeof(.rela)
+
+0: cmp x9, x10
+ b.hs 2f
+ ldp x11, x12, [x9], #24
+ ldr x13, [x9, #-8]
+ cmp w12, #R_AARCH64_RELATIVE
+ b.ne 1f
+ add x13, x13, x23 // relocate
+ str x13, [x11, x23]
+ b 0b
+
+1: cmp w12, #R_AARCH64_ABS64
+ b.ne 0b
+ add x12, x12, x12, lsl #1 // symtab offset: 24x top word
+ add x12, x8, x12, lsr #(32 - 3) // ... shifted into bottom word
+ ldrsh w14, [x12, #6] // Elf64_Sym::st_shndx
+ ldr x15, [x12, #8] // Elf64_Sym::st_value
+ cmp w14, #-0xf // SHN_ABS (0xfff1) ?
+ add x14, x15, x23 // relocate
+ csel x15, x14, x15, ne
+ add x15, x13, x15
+ str x15, [x11, x23]
+ b 0b
+
+2:
+#endif
+ ldr x8, =__primary_switched
+ br x8
+ENDPROC(__primary_switch)
+
+__secondary_switch:
+ ldr x8, =__secondary_switched
+ br x8
+ENDPROC(__secondary_switch)
diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h
index db1bf57948f1..f0be31f1dd45 100644
--- a/arch/arm64/kernel/image.h
+++ b/arch/arm64/kernel/image.h
@@ -73,6 +73,8 @@
#ifdef CONFIG_EFI
+__efistub_stext_offset = stext - _text;
+
/*
* Prevent the symbol aliases below from being emitted into the kallsyms
* table, by forcing them to be absolute symbols (which are conveniently
diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c
index 582983920054..b05469173ba5 100644
--- a/arch/arm64/kernel/kaslr.c
+++ b/arch/arm64/kernel/kaslr.c
@@ -74,7 +74,7 @@ extern void *__init __fixmap_remap_fdt(phys_addr_t dt_phys, int *size,
* containing function pointers) to be reinitialized, and zero-initialized
* .bss variables will be reset to 0.
*/
-u64 __init kaslr_early_init(u64 dt_phys)
+u64 __init kaslr_early_init(u64 dt_phys, u64 modulo_offset)
{
void *fdt;
u64 seed, offset, mask, module_range;
@@ -132,8 +132,8 @@ u64 __init kaslr_early_init(u64 dt_phys)
* boundary (for 4KB/16KB/64KB granule kernels, respectively). If this
* happens, increase the KASLR offset by the size of the kernel image.
*/
- if ((((u64)_text + offset) >> SWAPPER_TABLE_SHIFT) !=
- (((u64)_end + offset) >> SWAPPER_TABLE_SHIFT))
+ if ((((u64)_text + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT) !=
+ (((u64)_end + offset + modulo_offset) >> SWAPPER_TABLE_SHIFT))
offset = (offset + (u64)(_end - _text)) & mask;
if (IS_ENABLED(CONFIG_KASAN))
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index ff7f13239515..fc779ec6f051 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -39,6 +39,7 @@
#include <linux/elf.h>
#include <asm/compat.h>
+#include <asm/cpufeature.h>
#include <asm/debug-monitors.h>
#include <asm/pgtable.h>
#include <asm/syscall.h>
@@ -500,7 +501,7 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
if (ret)
return ret;
- if (!valid_user_regs(&newregs))
+ if (!valid_user_regs(&newregs, target))
return -EINVAL;
task_pt_regs(target)->user_regs = newregs;
@@ -770,7 +771,7 @@ static int compat_gpr_set(struct task_struct *target,
}
- if (valid_user_regs(&newregs.user_regs))
+ if (valid_user_regs(&newregs.user_regs, target))
*task_pt_regs(target) = newregs;
else
ret = -EINVAL;
@@ -1272,3 +1273,79 @@ asmlinkage void syscall_trace_exit(struct pt_regs *regs)
if (test_thread_flag(TIF_SYSCALL_TRACE))
tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
}
+
+/*
+ * Bits which are always architecturally RES0 per ARM DDI 0487A.h
+ * Userspace cannot use these until they have an architectural meaning.
+ * We also reserve IL for the kernel; SS is handled dynamically.
+ */
+#define SPSR_EL1_AARCH64_RES0_BITS \
+ (GENMASK_ULL(63,32) | GENMASK_ULL(27, 22) | GENMASK_ULL(20, 10) | \
+ GENMASK_ULL(5, 5))
+#define SPSR_EL1_AARCH32_RES0_BITS \
+ (GENMASK_ULL(63,32) | GENMASK_ULL(24, 22) | GENMASK_ULL(20,20))
+
+static int valid_compat_regs(struct user_pt_regs *regs)
+{
+ regs->pstate &= ~SPSR_EL1_AARCH32_RES0_BITS;
+
+ if (!system_supports_mixed_endian_el0()) {
+ if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
+ regs->pstate |= COMPAT_PSR_E_BIT;
+ else
+ regs->pstate &= ~COMPAT_PSR_E_BIT;
+ }
+
+ if (user_mode(regs) && (regs->pstate & PSR_MODE32_BIT) &&
+ (regs->pstate & COMPAT_PSR_A_BIT) == 0 &&
+ (regs->pstate & COMPAT_PSR_I_BIT) == 0 &&
+ (regs->pstate & COMPAT_PSR_F_BIT) == 0) {
+ return 1;
+ }
+
+ /*
+ * Force PSR to a valid 32-bit EL0t, preserving the same bits as
+ * arch/arm.
+ */
+ regs->pstate &= COMPAT_PSR_N_BIT | COMPAT_PSR_Z_BIT |
+ COMPAT_PSR_C_BIT | COMPAT_PSR_V_BIT |
+ COMPAT_PSR_Q_BIT | COMPAT_PSR_IT_MASK |
+ COMPAT_PSR_GE_MASK | COMPAT_PSR_E_BIT |
+ COMPAT_PSR_T_BIT;
+ regs->pstate |= PSR_MODE32_BIT;
+
+ return 0;
+}
+
+static int valid_native_regs(struct user_pt_regs *regs)
+{
+ regs->pstate &= ~SPSR_EL1_AARCH64_RES0_BITS;
+
+ if (user_mode(regs) && !(regs->pstate & PSR_MODE32_BIT) &&
+ (regs->pstate & PSR_D_BIT) == 0 &&
+ (regs->pstate & PSR_A_BIT) == 0 &&
+ (regs->pstate & PSR_I_BIT) == 0 &&
+ (regs->pstate & PSR_F_BIT) == 0) {
+ return 1;
+ }
+
+ /* Force PSR to a valid 64-bit EL0t */
+ regs->pstate &= PSR_N_BIT | PSR_Z_BIT | PSR_C_BIT | PSR_V_BIT;
+
+ return 0;
+}
+
+/*
+ * Are the current registers suitable for user mode? (used to maintain
+ * security in signal handlers)
+ */
+int valid_user_regs(struct user_pt_regs *regs, struct task_struct *task)
+{
+ if (!test_tsk_thread_flag(task, TIF_SINGLESTEP))
+ regs->pstate &= ~DBG_SPSR_SS;
+
+ if (is_compat_thread(task_thread_info(task)))
+ return valid_compat_regs(regs);
+ else
+ return valid_native_regs(regs);
+}
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index e18c48cb6db1..a8eafdbc7cb8 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -115,7 +115,7 @@ static int restore_sigframe(struct pt_regs *regs,
*/
regs->syscallno = ~0UL;
- err |= !valid_user_regs(&regs->user_regs);
+ err |= !valid_user_regs(&regs->user_regs, current);
if (err == 0) {
struct fpsimd_context *fpsimd_ctx =
@@ -307,7 +307,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
/*
* Check that the resulting registers are actually sane.
*/
- ret |= !valid_user_regs(&regs->user_regs);
+ ret |= !valid_user_regs(&regs->user_regs, current);
/*
* Fast forward the stepping logic so we step into the signal
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 71ef6dc89ae5..107335637390 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -356,7 +356,7 @@ static int compat_restore_sigframe(struct pt_regs *regs,
*/
regs->syscallno = ~0UL;
- err |= !valid_user_regs(&regs->user_regs);
+ err |= !valid_user_regs(&regs->user_regs, current);
aux = (struct compat_aux_sigframe __user *) sf->uc.uc_regspace;
if (err == 0)
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 6b562a318f84..8b4623eeb62d 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -64,14 +64,19 @@ PECOFF_FILE_ALIGNMENT = 0x200;
#endif
#if defined(CONFIG_DEBUG_ALIGN_RODATA)
-#define ALIGN_DEBUG_RO . = ALIGN(1<<SECTION_SHIFT);
-#define ALIGN_DEBUG_RO_MIN(min) ALIGN_DEBUG_RO
-#elif defined(CONFIG_DEBUG_RODATA)
-#define ALIGN_DEBUG_RO . = ALIGN(1<<PAGE_SHIFT);
-#define ALIGN_DEBUG_RO_MIN(min) ALIGN_DEBUG_RO
+/*
+ * 4 KB granule: 1 level 2 entry
+ * 16 KB granule: 128 level 3 entries, with contiguous bit
+ * 64 KB granule: 32 level 3 entries, with contiguous bit
+ */
+#define SEGMENT_ALIGN SZ_2M
#else
-#define ALIGN_DEBUG_RO
-#define ALIGN_DEBUG_RO_MIN(min) . = ALIGN(min);
+/*
+ * 4 KB granule: 16 level 3 entries, with contiguous bit
+ * 16 KB granule: 4 level 3 entries, without contiguous bit
+ * 64 KB granule: 1 level 3 entry
+ */
+#define SEGMENT_ALIGN SZ_64K
#endif
SECTIONS
@@ -97,7 +102,6 @@ SECTIONS
_text = .;
HEAD_TEXT
}
- ALIGN_DEBUG_RO_MIN(PAGE_SIZE)
.text : { /* Real text segment */
_stext = .; /* Text and read-only data */
__exception_text_start = .;
@@ -115,11 +119,12 @@ SECTIONS
*(.got) /* Global offset table */
}
- RO_DATA(PAGE_SIZE)
- EXCEPTION_TABLE(8)
+ . = ALIGN(SEGMENT_ALIGN);
+ RO_DATA(PAGE_SIZE) /* everything from this point to */
+ EXCEPTION_TABLE(8) /* _etext will be marked RO NX */
NOTES
- ALIGN_DEBUG_RO_MIN(PAGE_SIZE)
+ . = ALIGN(SEGMENT_ALIGN);
_etext = .; /* End of text and rodata section */
__init_begin = .;
@@ -152,12 +157,9 @@ SECTIONS
*(.altinstr_replacement)
}
.rela : ALIGN(8) {
- __reloc_start = .;
*(.rela .rela*)
- __reloc_end = .;
}
.dynsym : ALIGN(8) {
- __dynsym_start = .;
*(.dynsym)
}
.dynstr : {
@@ -167,7 +169,11 @@ SECTIONS
*(.hash)
}
- . = ALIGN(PAGE_SIZE);
+ __rela_offset = ADDR(.rela) - KIMAGE_VADDR;
+ __rela_size = SIZEOF(.rela);
+ __dynsym_offset = ADDR(.dynsym) - KIMAGE_VADDR;
+
+ . = ALIGN(SEGMENT_ALIGN);
__init_end = .;
_data = .;
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index 648112e90ed5..3972e65fbd5a 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -130,7 +130,7 @@ static void inject_abt64(struct kvm_vcpu *vcpu, bool is_iabt, unsigned long addr
esr |= (ESR_ELx_EC_IABT_CUR << ESR_ELx_EC_SHIFT);
if (!is_iabt)
- esr |= ESR_ELx_EC_DABT_LOW;
+ esr |= ESR_ELx_EC_DABT_LOW << ESR_ELx_EC_SHIFT;
vcpu_sys_reg(vcpu, ESR_EL1) = esr | ESR_ELx_FSC_EXTABT;
}
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 07c67348b815..df083e9350c4 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -455,6 +455,7 @@ static void arm64_dma_unremap(struct device *dev, void *remapped_addr,
{
struct vm_struct *area;
+ size = PAGE_ALIGN(size);
remapped_addr = (void *)((unsigned long)remapped_addr & PAGE_MASK);
area = find_vm_area(remapped_addr);
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 69079e5bfc84..55b944a913cb 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -84,6 +84,56 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
printk("\n");
}
+#ifdef CONFIG_ARM64_HW_AFDBM
+/*
+ * This function sets the access flags (dirty, accessed), as well as write
+ * permission, and only to a more permissive setting.
+ *
+ * It needs to cope with hardware update of the accessed/dirty state by other
+ * agents in the system and can safely skip the __sync_icache_dcache() call as,
+ * like set_pte_at(), the PTE is never changed from no-exec to exec here.
+ *
+ * Returns whether or not the PTE actually changed.
+ */
+int ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long address, pte_t *ptep,
+ pte_t entry, int dirty)
+{
+ pteval_t old_pteval;
+ unsigned int tmp;
+
+ if (pte_same(*ptep, entry))
+ return 0;
+
+ /* only preserve the access flags and write permission */
+ pte_val(entry) &= PTE_AF | PTE_WRITE | PTE_DIRTY;
+
+ /*
+ * PTE_RDONLY is cleared by default in the asm below, so set it in
+ * back if necessary (read-only or clean PTE).
+ */
+ if (!pte_write(entry) || !pte_sw_dirty(entry))
+ pte_val(entry) |= PTE_RDONLY;
+
+ /*
+ * Setting the flags must be done atomically to avoid racing with the
+ * hardware update of the access/dirty state.
+ */
+ asm volatile("// ptep_set_access_flags\n"
+ " prfm pstl1strm, %2\n"
+ "1: ldxr %0, %2\n"
+ " and %0, %0, %3 // clear PTE_RDONLY\n"
+ " orr %0, %0, %4 // set flags\n"
+ " stxr %w1, %0, %2\n"
+ " cbnz %w1, 1b\n"
+ : "=&r" (old_pteval), "=&r" (tmp), "+Q" (pte_val(*ptep))
+ : "L" (~PTE_RDONLY), "r" (pte_val(entry)));
+
+ flush_tlb_fix_spurious_fault(vma, address);
+ return 1;
+}
+#endif
+
/*
* The kernel tried to access some page that wasn't present.
*/
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 0d5b0d0578b3..4a49093dddd7 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -372,6 +372,7 @@ void __init mem_init(void)
" vmalloc : 0x%16lx - 0x%16lx (%6ld GB)\n"
" .init : 0x%p" " - 0x%p" " (%6ld KB)\n"
" .text : 0x%p" " - 0x%p" " (%6ld KB)\n"
+ " .rodata : 0x%p" " - 0x%p" " (%6ld KB)\n"
" .data : 0x%p" " - 0x%p" " (%6ld KB)\n"
#ifdef CONFIG_SPARSEMEM_VMEMMAP
" vmemmap : 0x%16lx - 0x%16lx (%6ld GB maximum)\n"
@@ -386,7 +387,8 @@ void __init mem_init(void)
MLM(MODULES_VADDR, MODULES_END),
MLG(VMALLOC_START, VMALLOC_END),
MLK_ROUNDUP(__init_begin, __init_end),
- MLK_ROUNDUP(_text, _etext),
+ MLK_ROUNDUP(_text, __start_rodata),
+ MLK_ROUNDUP(__start_rodata, _etext),
MLK_ROUNDUP(_sdata, _edata),
#ifdef CONFIG_SPARSEMEM_VMEMMAP
MLG(VMEMMAP_START,
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 62096a7e047a..a8a6f91343cc 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -391,7 +391,7 @@ static void create_mapping_late(phys_addr_t phys, unsigned long virt,
static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end)
{
- unsigned long kernel_start = __pa(_stext);
+ unsigned long kernel_start = __pa(_text);
unsigned long kernel_end = __pa(_etext);
/*
@@ -423,7 +423,7 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end
early_pgtable_alloc);
/*
- * Map the linear alias of the [_stext, _etext) interval as
+ * Map the linear alias of the [_text, _etext) interval as
* read-only/non-executable. This makes the contents of the
* region accessible to subsystems such as hibernate, but
* protects it from inadvertent modification or execution.
@@ -451,12 +451,18 @@ static void __init map_mem(pgd_t *pgd)
void mark_rodata_ro(void)
{
- if (!IS_ENABLED(CONFIG_DEBUG_RODATA))
- return;
+ unsigned long section_size;
- create_mapping_late(__pa(_stext), (unsigned long)_stext,
- (unsigned long)_etext - (unsigned long)_stext,
- PAGE_KERNEL_ROX);
+ section_size = (unsigned long)__start_rodata - (unsigned long)_text;
+ create_mapping_late(__pa(_text), (unsigned long)_text,
+ section_size, PAGE_KERNEL_ROX);
+ /*
+ * mark .rodata as read only. Use _etext rather than __end_rodata to
+ * cover NOTES and EXCEPTION_TABLE.
+ */
+ section_size = (unsigned long)_etext - (unsigned long)__start_rodata;
+ create_mapping_late(__pa(__start_rodata), (unsigned long)__start_rodata,
+ section_size, PAGE_KERNEL_RO);
}
void fixup_init(void)
@@ -469,8 +475,8 @@ void fixup_init(void)
unmap_kernel_range((u64)__init_begin, (u64)(__init_end - __init_begin));
}
-static void __init map_kernel_chunk(pgd_t *pgd, void *va_start, void *va_end,
- pgprot_t prot, struct vm_struct *vma)
+static void __init map_kernel_segment(pgd_t *pgd, void *va_start, void *va_end,
+ pgprot_t prot, struct vm_struct *vma)
{
phys_addr_t pa_start = __pa(va_start);
unsigned long size = va_end - va_start;
@@ -495,12 +501,13 @@ static void __init map_kernel_chunk(pgd_t *pgd, void *va_start, void *va_end,
*/
static void __init map_kernel(pgd_t *pgd)
{
- static struct vm_struct vmlinux_text, vmlinux_init, vmlinux_data;
+ static struct vm_struct vmlinux_text, vmlinux_rodata, vmlinux_init, vmlinux_data;
- map_kernel_chunk(pgd, _stext, _etext, PAGE_KERNEL_EXEC, &vmlinux_text);
- map_kernel_chunk(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC,
- &vmlinux_init);
- map_kernel_chunk(pgd, _data, _end, PAGE_KERNEL, &vmlinux_data);
+ map_kernel_segment(pgd, _text, __start_rodata, PAGE_KERNEL_EXEC, &vmlinux_text);
+ map_kernel_segment(pgd, __start_rodata, _etext, PAGE_KERNEL, &vmlinux_rodata);
+ map_kernel_segment(pgd, __init_begin, __init_end, PAGE_KERNEL_EXEC,
+ &vmlinux_init);
+ map_kernel_segment(pgd, _data, _end, PAGE_KERNEL, &vmlinux_data);
if (!pgd_val(*pgd_offset_raw(pgd, FIXADDR_START))) {
/*
diff --git a/arch/mips/ath79/early_printk.c b/arch/mips/ath79/early_printk.c
index b955fafc58ba..d1adc59af5bf 100644
--- a/arch/mips/ath79/early_printk.c
+++ b/arch/mips/ath79/early_printk.c
@@ -31,13 +31,15 @@ static inline void prom_putchar_wait(void __iomem *reg, u32 mask, u32 val)
} while (1);
}
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
static void prom_putchar_ar71xx(unsigned char ch)
{
void __iomem *base = (void __iomem *)(KSEG1ADDR(AR71XX_UART_BASE));
- prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE);
+ prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY);
__raw_writel(ch, base + UART_TX * 4);
- prom_putchar_wait(base + UART_LSR * 4, UART_LSR_THRE, UART_LSR_THRE);
+ prom_putchar_wait(base + UART_LSR * 4, BOTH_EMPTY, BOTH_EMPTY);
}
static void prom_putchar_ar933x(unsigned char ch)
diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h
index 867f924b05c7..e689b894353c 100644
--- a/arch/mips/include/asm/asmmacro.h
+++ b/arch/mips/include/asm/asmmacro.h
@@ -298,21 +298,21 @@
.set pop
.endm
- .macro copy_u_w ws, n
+ .macro copy_s_w ws, n
.set push
.set mips32r2
.set fp=64
.set msa
- copy_u.w $1, $w\ws[\n]
+ copy_s.w $1, $w\ws[\n]
.set pop
.endm
- .macro copy_u_d ws, n
+ .macro copy_s_d ws, n
.set push
.set mips64r2
.set fp=64
.set msa
- copy_u.d $1, $w\ws[\n]
+ copy_s.d $1, $w\ws[\n]
.set pop
.endm
@@ -346,8 +346,8 @@
#define STH_MSA_INSN 0x5800081f
#define STW_MSA_INSN 0x5800082f
#define STD_MSA_INSN 0x5800083f
-#define COPY_UW_MSA_INSN 0x58f00056
-#define COPY_UD_MSA_INSN 0x58f80056
+#define COPY_SW_MSA_INSN 0x58b00056
+#define COPY_SD_MSA_INSN 0x58b80056
#define INSERT_W_MSA_INSN 0x59300816
#define INSERT_D_MSA_INSN 0x59380816
#else
@@ -361,8 +361,8 @@
#define STH_MSA_INSN 0x78000825
#define STW_MSA_INSN 0x78000826
#define STD_MSA_INSN 0x78000827
-#define COPY_UW_MSA_INSN 0x78f00059
-#define COPY_UD_MSA_INSN 0x78f80059
+#define COPY_SW_MSA_INSN 0x78b00059
+#define COPY_SD_MSA_INSN 0x78b80059
#define INSERT_W_MSA_INSN 0x79300819
#define INSERT_D_MSA_INSN 0x79380819
#endif
@@ -393,7 +393,7 @@
.set push
.set noat
SET_HARDFLOAT
- addu $1, \base, \off
+ PTR_ADDU $1, \base, \off
.word LDB_MSA_INSN | (\wd << 6)
.set pop
.endm
@@ -402,7 +402,7 @@
.set push
.set noat
SET_HARDFLOAT
- addu $1, \base, \off
+ PTR_ADDU $1, \base, \off
.word LDH_MSA_INSN | (\wd << 6)
.set pop
.endm
@@ -411,7 +411,7 @@
.set push
.set noat
SET_HARDFLOAT
- addu $1, \base, \off
+ PTR_ADDU $1, \base, \off
.word LDW_MSA_INSN | (\wd << 6)
.set pop
.endm
@@ -420,7 +420,7 @@
.set push
.set noat
SET_HARDFLOAT
- addu $1, \base, \off
+ PTR_ADDU $1, \base, \off
.word LDD_MSA_INSN | (\wd << 6)
.set pop
.endm
@@ -429,7 +429,7 @@
.set push
.set noat
SET_HARDFLOAT
- addu $1, \base, \off
+ PTR_ADDU $1, \base, \off
.word STB_MSA_INSN | (\wd << 6)
.set pop
.endm
@@ -438,7 +438,7 @@
.set push
.set noat
SET_HARDFLOAT
- addu $1, \base, \off
+ PTR_ADDU $1, \base, \off
.word STH_MSA_INSN | (\wd << 6)
.set pop
.endm
@@ -447,7 +447,7 @@
.set push
.set noat
SET_HARDFLOAT
- addu $1, \base, \off
+ PTR_ADDU $1, \base, \off
.word STW_MSA_INSN | (\wd << 6)
.set pop
.endm
@@ -456,26 +456,26 @@
.set push
.set noat
SET_HARDFLOAT
- addu $1, \base, \off
+ PTR_ADDU $1, \base, \off
.word STD_MSA_INSN | (\wd << 6)
.set pop
.endm
- .macro copy_u_w ws, n
+ .macro copy_s_w ws, n
.set push
.set noat
SET_HARDFLOAT
.insn
- .word COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11)
+ .word COPY_SW_MSA_INSN | (\n << 16) | (\ws << 11)
.set pop
.endm
- .macro copy_u_d ws, n
+ .macro copy_s_d ws, n
.set push
.set noat
SET_HARDFLOAT
.insn
- .word COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11)
+ .word COPY_SD_MSA_INSN | (\n << 16) | (\ws << 11)
.set pop
.endm
diff --git a/arch/mips/include/asm/cacheflush.h b/arch/mips/include/asm/cacheflush.h
index 723229f4cf27..176de586a71a 100644
--- a/arch/mips/include/asm/cacheflush.h
+++ b/arch/mips/include/asm/cacheflush.h
@@ -51,7 +51,6 @@ extern void (*flush_cache_range)(struct vm_area_struct *vma,
unsigned long start, unsigned long end);
extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
extern void __flush_dcache_page(struct page *page);
-extern void __flush_icache_page(struct vm_area_struct *vma, struct page *page);
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
static inline void flush_dcache_page(struct page *page)
@@ -77,11 +76,6 @@ static inline void flush_anon_page(struct vm_area_struct *vma,
static inline void flush_icache_page(struct vm_area_struct *vma,
struct page *page)
{
- if (!cpu_has_ic_fills_f_dc && (vma->vm_flags & VM_EXEC) &&
- Page_dcache_dirty(page)) {
- __flush_icache_page(vma, page);
- ClearPageDcacheDirty(page);
- }
}
extern void (*flush_icache_range)(unsigned long start, unsigned long end);
diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h
index 6ded8d347af9..dd7cee795709 100644
--- a/arch/mips/include/asm/kvm_host.h
+++ b/arch/mips/include/asm/kvm_host.h
@@ -372,6 +372,7 @@ struct kvm_mips_tlb {
#define KVM_MIPS_GUEST_TLB_SIZE 64
struct kvm_vcpu_arch {
void *host_ebase, *guest_ebase;
+ int (*vcpu_run)(struct kvm_run *run, struct kvm_vcpu *vcpu);
unsigned long host_stack;
unsigned long host_gp;
@@ -784,7 +785,7 @@ extern enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,
uint32_t kvm_mips_read_count(struct kvm_vcpu *vcpu);
void kvm_mips_write_count(struct kvm_vcpu *vcpu, uint32_t count);
-void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare);
+void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare, bool ack);
void kvm_mips_init_count(struct kvm_vcpu *vcpu);
int kvm_mips_set_count_ctl(struct kvm_vcpu *vcpu, s64 count_ctl);
int kvm_mips_set_count_resume(struct kvm_vcpu *vcpu, s64 count_resume);
diff --git a/arch/mips/include/asm/msa.h b/arch/mips/include/asm/msa.h
index bbb85fe21642..6e4effa6f626 100644
--- a/arch/mips/include/asm/msa.h
+++ b/arch/mips/include/asm/msa.h
@@ -147,6 +147,19 @@ static inline void restore_msa(struct task_struct *t)
_restore_msa(t);
}
+static inline void init_msa_upper(void)
+{
+ /*
+ * Check cpu_has_msa only if it's a constant. This will allow the
+ * compiler to optimise out code for CPUs without MSA without adding
+ * an extra redundant check for CPUs with MSA.
+ */
+ if (__builtin_constant_p(cpu_has_msa) && !cpu_has_msa)
+ return;
+
+ _init_msa_upper();
+}
+
#ifdef TOOLCHAIN_SUPPORTS_MSA
#define __BUILD_MSA_CTL_REG(name, cs) \
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index 18826aa15a7c..4e68c644acc5 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -127,10 +127,14 @@ do { \
} \
} while(0)
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pteval);
+
#if defined(CONFIG_PHYS_ADDR_T_64BIT) && defined(CONFIG_CPU_MIPS32)
#define pte_none(pte) (!(((pte).pte_high) & ~_PAGE_GLOBAL))
#define pte_present(pte) ((pte).pte_low & _PAGE_PRESENT)
+#define pte_no_exec(pte) ((pte).pte_low & _PAGE_NO_EXEC)
static inline void set_pte(pte_t *ptep, pte_t pte)
{
@@ -148,7 +152,6 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
buddy->pte_high |= _PAGE_GLOBAL;
}
}
-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
@@ -166,6 +169,7 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
#define pte_none(pte) (!(pte_val(pte) & ~_PAGE_GLOBAL))
#define pte_present(pte) (pte_val(pte) & _PAGE_PRESENT)
+#define pte_no_exec(pte) (pte_val(pte) & _PAGE_NO_EXEC)
/*
* Certain architectures need to do special things when pte's
@@ -218,7 +222,6 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
}
#endif
}
-#define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
@@ -234,6 +237,22 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *pt
}
#endif
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t pteval)
+{
+ extern void __update_cache(unsigned long address, pte_t pte);
+
+ if (!pte_present(pteval))
+ goto cache_sync_done;
+
+ if (pte_present(*ptep) && (pte_pfn(*ptep) == pte_pfn(pteval)))
+ goto cache_sync_done;
+
+ __update_cache(addr, pteval);
+cache_sync_done:
+ set_pte(ptep, pteval);
+}
+
/*
* (pmds are folded into puds so this doesn't get actually called,
* but the define is needed for a generic inline function.)
@@ -430,15 +449,12 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
extern void __update_tlb(struct vm_area_struct *vma, unsigned long address,
pte_t pte);
-extern void __update_cache(struct vm_area_struct *vma, unsigned long address,
- pte_t pte);
static inline void update_mmu_cache(struct vm_area_struct *vma,
unsigned long address, pte_t *ptep)
{
pte_t pte = *ptep;
__update_tlb(vma, address, pte);
- __update_cache(vma, address, pte);
}
static inline void update_mmu_cache_pmd(struct vm_area_struct *vma,
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 3f832c3dd8f5..041153f5cf93 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -45,7 +45,7 @@ extern unsigned int vced_count, vcei_count;
* User space process size: 2GB. This is hardcoded into a few places,
* so don't change it unless you know what you are doing.
*/
-#define TASK_SIZE 0x7fff8000UL
+#define TASK_SIZE 0x80000000UL
#endif
#define STACK_TOP_MAX TASK_SIZE
diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h
index 28b5d84a5022..ebb5c0f2f90d 100644
--- a/arch/mips/include/asm/switch_to.h
+++ b/arch/mips/include/asm/switch_to.h
@@ -105,7 +105,7 @@ do { \
__clear_software_ll_bit(); \
if (cpu_has_userlocal) \
write_c0_userlocal(task_thread_info(next)->tp_value); \
- __restore_watch(); \
+ __restore_watch(next); \
(last) = resume(prev, next, task_thread_info(next)); \
} while (0)
diff --git a/arch/mips/include/asm/watch.h b/arch/mips/include/asm/watch.h
index 20126ec79359..6ffe3eadf105 100644
--- a/arch/mips/include/asm/watch.h
+++ b/arch/mips/include/asm/watch.h
@@ -12,21 +12,21 @@
#include <asm/mipsregs.h>
-void mips_install_watch_registers(void);
+void mips_install_watch_registers(struct task_struct *t);
void mips_read_watch_registers(void);
void mips_clear_watch_registers(void);
void mips_probe_watch_registers(struct cpuinfo_mips *c);
#ifdef CONFIG_HARDWARE_WATCHPOINTS
-#define __restore_watch() do { \
+#define __restore_watch(task) do { \
if (unlikely(test_bit(TIF_LOAD_WATCH, \
- &current_thread_info()->flags))) { \
- mips_install_watch_registers(); \
+ &task_thread_info(task)->flags))) { \
+ mips_install_watch_registers(task); \
} \
} while (0)
#else
-#define __restore_watch() do {} while (0)
+#define __restore_watch(task) do {} while (0)
#endif
#endif /* _ASM_WATCH_H */
diff --git a/arch/mips/include/uapi/asm/siginfo.h b/arch/mips/include/uapi/asm/siginfo.h
index 2cb7fdead570..e2b5337e840f 100644
--- a/arch/mips/include/uapi/asm/siginfo.h
+++ b/arch/mips/include/uapi/asm/siginfo.h
@@ -28,7 +28,7 @@
#define __ARCH_SIGSYS
-#include <uapi/asm-generic/siginfo.h>
+#include <asm-generic/siginfo.h>
/* We can't use generic siginfo_t, because our si_code and si_errno are swapped */
typedef struct siginfo {
@@ -42,13 +42,13 @@ typedef struct siginfo {
/* kill() */
struct {
- pid_t _pid; /* sender's pid */
+ __kernel_pid_t _pid; /* sender's pid */
__ARCH_SI_UID_T _uid; /* sender's uid */
} _kill;
/* POSIX.1b timers */
struct {
- timer_t _tid; /* timer id */
+ __kernel_timer_t _tid; /* timer id */
int _overrun; /* overrun count */
char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)];
sigval_t _sigval; /* same as below */
@@ -57,26 +57,26 @@ typedef struct siginfo {
/* POSIX.1b signals */
struct {
- pid_t _pid; /* sender's pid */
+ __kernel_pid_t _pid; /* sender's pid */
__ARCH_SI_UID_T _uid; /* sender's uid */
sigval_t _sigval;
} _rt;
/* SIGCHLD */
struct {
- pid_t _pid; /* which child */
+ __kernel_pid_t _pid; /* which child */
__ARCH_SI_UID_T _uid; /* sender's uid */
int _status; /* exit code */
- clock_t _utime;
- clock_t _stime;
+ __kernel_clock_t _utime;
+ __kernel_clock_t _stime;
} _sigchld;
/* IRIX SIGCHLD */
struct {
- pid_t _pid; /* which child */
- clock_t _utime;
+ __kernel_pid_t _pid; /* which child */
+ __kernel_clock_t _utime;
int _status; /* exit code */
- clock_t _stime;
+ __kernel_clock_t _stime;
} _irix_sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
@@ -118,6 +118,4 @@ typedef struct siginfo {
#define SI_TIMER __SI_CODE(__SI_TIMER, -3) /* sent by timer expiration */
#define SI_MESGQ __SI_CODE(__SI_MESGQ, -4) /* sent by real time mesq state change */
-#include <asm-generic/siginfo.h>
-
#endif /* _UAPI_ASM_SIGINFO_H */
diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c
index 1f5aac7f9ec3..4674a74a08b5 100644
--- a/arch/mips/kernel/mips-r2-to-r6-emul.c
+++ b/arch/mips/kernel/mips-r2-to-r6-emul.c
@@ -28,6 +28,7 @@
#include <asm/inst.h>
#include <asm/mips-r2-to-r6-emul.h>
#include <asm/local.h>
+#include <asm/mipsregs.h>
#include <asm/ptrace.h>
#include <asm/uaccess.h>
@@ -1251,10 +1252,10 @@ fpu_emul:
" j 10b\n"
" .previous\n"
" .section __ex_table,\"a\"\n"
- " .word 1b,8b\n"
- " .word 2b,8b\n"
- " .word 3b,8b\n"
- " .word 4b,8b\n"
+ STR(PTR) " 1b,8b\n"
+ STR(PTR) " 2b,8b\n"
+ STR(PTR) " 3b,8b\n"
+ STR(PTR) " 4b,8b\n"
" .previous\n"
" .set pop\n"
: "+&r"(rt), "=&r"(rs),
@@ -1326,10 +1327,10 @@ fpu_emul:
" j 10b\n"
" .previous\n"
" .section __ex_table,\"a\"\n"
- " .word 1b,8b\n"
- " .word 2b,8b\n"
- " .word 3b,8b\n"
- " .word 4b,8b\n"
+ STR(PTR) " 1b,8b\n"
+ STR(PTR) " 2b,8b\n"
+ STR(PTR) " 3b,8b\n"
+ STR(PTR) " 4b,8b\n"
" .previous\n"
" .set pop\n"
: "+&r"(rt), "=&r"(rs),
@@ -1397,10 +1398,10 @@ fpu_emul:
" j 9b\n"
" .previous\n"
" .section __ex_table,\"a\"\n"
- " .word 1b,8b\n"
- " .word 2b,8b\n"
- " .word 3b,8b\n"
- " .word 4b,8b\n"
+ STR(PTR) " 1b,8b\n"
+ STR(PTR) " 2b,8b\n"
+ STR(PTR) " 3b,8b\n"
+ STR(PTR) " 4b,8b\n"
" .previous\n"
" .set pop\n"
: "+&r"(rt), "=&r"(rs),
@@ -1467,10 +1468,10 @@ fpu_emul:
" j 9b\n"
" .previous\n"
" .section __ex_table,\"a\"\n"
- " .word 1b,8b\n"
- " .word 2b,8b\n"
- " .word 3b,8b\n"
- " .word 4b,8b\n"
+ STR(PTR) " 1b,8b\n"
+ STR(PTR) " 2b,8b\n"
+ STR(PTR) " 3b,8b\n"
+ STR(PTR) " 4b,8b\n"
" .previous\n"
" .set pop\n"
: "+&r"(rt), "=&r"(rs),
@@ -1582,14 +1583,14 @@ fpu_emul:
" j 9b\n"
" .previous\n"
" .section __ex_table,\"a\"\n"
- " .word 1b,8b\n"
- " .word 2b,8b\n"
- " .word 3b,8b\n"
- " .word 4b,8b\n"
- " .word 5b,8b\n"
- " .word 6b,8b\n"
- " .word 7b,8b\n"
- " .word 0b,8b\n"
+ STR(PTR) " 1b,8b\n"
+ STR(PTR) " 2b,8b\n"
+ STR(PTR) " 3b,8b\n"
+ STR(PTR) " 4b,8b\n"
+ STR(PTR) " 5b,8b\n"
+ STR(PTR) " 6b,8b\n"
+ STR(PTR) " 7b,8b\n"
+ STR(PTR) " 0b,8b\n"
" .previous\n"
" .set pop\n"
: "+&r"(rt), "=&r"(rs),
@@ -1701,14 +1702,14 @@ fpu_emul:
" j 9b\n"
" .previous\n"
" .section __ex_table,\"a\"\n"
- " .word 1b,8b\n"
- " .word 2b,8b\n"
- " .word 3b,8b\n"
- " .word 4b,8b\n"
- " .word 5b,8b\n"
- " .word 6b,8b\n"
- " .word 7b,8b\n"
- " .word 0b,8b\n"
+ STR(PTR) " 1b,8b\n"
+ STR(PTR) " 2b,8b\n"
+ STR(PTR) " 3b,8b\n"
+ STR(PTR) " 4b,8b\n"
+ STR(PTR) " 5b,8b\n"
+ STR(PTR) " 6b,8b\n"
+ STR(PTR) " 7b,8b\n"
+ STR(PTR) " 0b,8b\n"
" .previous\n"
" .set pop\n"
: "+&r"(rt), "=&r"(rs),
@@ -1820,14 +1821,14 @@ fpu_emul:
" j 9b\n"
" .previous\n"
" .section __ex_table,\"a\"\n"
- " .word 1b,8b\n"
- " .word 2b,8b\n"
- " .word 3b,8b\n"
- " .word 4b,8b\n"
- " .word 5b,8b\n"
- " .word 6b,8b\n"
- " .word 7b,8b\n"
- " .word 0b,8b\n"
+ STR(PTR) " 1b,8b\n"
+ STR(PTR) " 2b,8b\n"
+ STR(PTR) " 3b,8b\n"
+ STR(PTR) " 4b,8b\n"
+ STR(PTR) " 5b,8b\n"
+ STR(PTR) " 6b,8b\n"
+ STR(PTR) " 7b,8b\n"
+ STR(PTR) " 0b,8b\n"
" .previous\n"
" .set pop\n"
: "+&r"(rt), "=&r"(rs),
@@ -1938,14 +1939,14 @@ fpu_emul:
" j 9b\n"
" .previous\n"
" .section __ex_table,\"a\"\n"
- " .word 1b,8b\n"
- " .word 2b,8b\n"
- " .word 3b,8b\n"
- " .word 4b,8b\n"
- " .word 5b,8b\n"
- " .word 6b,8b\n"
- " .word 7b,8b\n"
- " .word 0b,8b\n"
+ STR(PTR) " 1b,8b\n"
+ STR(PTR) " 2b,8b\n"
+ STR(PTR) " 3b,8b\n"
+ STR(PTR) " 4b,8b\n"
+ STR(PTR) " 5b,8b\n"
+ STR(PTR) " 6b,8b\n"
+ STR(PTR) " 7b,8b\n"
+ STR(PTR) " 0b,8b\n"
" .previous\n"
" .set pop\n"
: "+&r"(rt), "=&r"(rs),
@@ -2000,7 +2001,7 @@ fpu_emul:
"j 2b\n"
".previous\n"
".section __ex_table,\"a\"\n"
- ".word 1b, 3b\n"
+ STR(PTR) " 1b,3b\n"
".previous\n"
: "=&r"(res), "+&r"(err)
: "r"(vaddr), "i"(SIGSEGV)
@@ -2058,7 +2059,7 @@ fpu_emul:
"j 2b\n"
".previous\n"
".section __ex_table,\"a\"\n"
- ".word 1b, 3b\n"
+ STR(PTR) " 1b,3b\n"
".previous\n"
: "+&r"(res), "+&r"(err)
: "r"(vaddr), "i"(SIGSEGV));
@@ -2119,7 +2120,7 @@ fpu_emul:
"j 2b\n"
".previous\n"
".section __ex_table,\"a\"\n"
- ".word 1b, 3b\n"
+ STR(PTR) " 1b,3b\n"
".previous\n"
: "=&r"(res), "+&r"(err)
: "r"(vaddr), "i"(SIGSEGV)
@@ -2182,7 +2183,7 @@ fpu_emul:
"j 2b\n"
".previous\n"
".section __ex_table,\"a\"\n"
- ".word 1b, 3b\n"
+ STR(PTR) " 1b,3b\n"
".previous\n"
: "+&r"(res), "+&r"(err)
: "r"(vaddr), "i"(SIGSEGV));
diff --git a/arch/mips/kernel/pm.c b/arch/mips/kernel/pm.c
index fefdf39d3df3..dc814892133c 100644
--- a/arch/mips/kernel/pm.c
+++ b/arch/mips/kernel/pm.c
@@ -56,7 +56,7 @@ static void mips_cpu_restore(void)
write_c0_userlocal(current_thread_info()->tp_value);
/* Restore watch registers */
- __restore_watch();
+ __restore_watch(current);
}
/**
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index f2975d4d1e44..89847bee2b53 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -457,7 +457,7 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page,
*sp + sizeof(*regs) <= stack_page + THREAD_SIZE - 32) {
regs = (struct pt_regs *)*sp;
pc = regs->cp0_epc;
- if (__kernel_text_address(pc)) {
+ if (!user_mode(regs) && __kernel_text_address(pc)) {
*sp = regs->regs[29];
*ra = regs->regs[31];
return pc;
@@ -603,6 +603,9 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
if (!(value & PR_FP_MODE_FR) && cpu_has_fpu && cpu_has_mips_r6)
return -EOPNOTSUPP;
+ /* Proceed with the mode switch */
+ preempt_disable();
+
/* Save FP & vector context, then disable FPU & MSA */
if (task->signal == current->signal)
lose_fpu(1);
@@ -661,6 +664,7 @@ int mips_set_process_fp_mode(struct task_struct *task, unsigned int value)
/* Allow threads to use FP again */
atomic_set(&task->mm->context.fp_mode_switching, 0);
+ preempt_enable();
return 0;
}
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 4f0ac78d17f1..74d581569778 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -57,8 +57,7 @@ static void init_fp_ctx(struct task_struct *target)
/* Begin with data registers set to all 1s... */
memset(&target->thread.fpu.fpr, ~0, sizeof(target->thread.fpu.fpr));
- /* ...and FCSR zeroed */
- target->thread.fpu.fcr31 = 0;
+ /* FCSR has been preset by `mips_set_personality_nan'. */
/*
* Record that the target has "used" math, such that the context
@@ -80,6 +79,22 @@ void ptrace_disable(struct task_struct *child)
}
/*
+ * Poke at FCSR according to its mask. Don't set the cause bits as
+ * this is currently not handled correctly in FP context restoration
+ * and will cause an oops if a corresponding enable bit is set.
+ */
+static void ptrace_setfcr31(struct task_struct *child, u32 value)
+{
+ u32 fcr31;
+ u32 mask;
+
+ value &= ~FPU_CSR_ALL_X;
+ fcr31 = child->thread.fpu.fcr31;
+ mask = boot_cpu_data.fpu_msk31;
+ child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
+}
+
+/*
* Read a general register set. We always use the 64-bit format, even
* for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
* Registers are sign extended to fill the available space.
@@ -159,9 +174,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
{
union fpureg *fregs;
u64 fpr_val;
- u32 fcr31;
u32 value;
- u32 mask;
int i;
if (!access_ok(VERIFY_READ, data, 33 * 8))
@@ -176,9 +189,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
}
__get_user(value, data + 64);
- fcr31 = child->thread.fpu.fcr31;
- mask = boot_cpu_data.fpu_msk31;
- child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
+ ptrace_setfcr31(child, value);
/* FIR may not be written. */
@@ -808,7 +819,7 @@ long arch_ptrace(struct task_struct *child, long request,
break;
#endif
case FPC_CSR:
- child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X;
+ ptrace_setfcr31(child, data);
break;
case DSP_BASE ... DSP_BASE + 5: {
dspreg_t *dregs;
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index f09546ee2cdc..bc74485ec805 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -244,17 +244,17 @@ LEAF(\name)
.set push
.set noat
#ifdef CONFIG_64BIT
- copy_u_d \wr, 1
+ copy_s_d \wr, 1
EX sd $1, \off(\base)
#elif defined(CONFIG_CPU_LITTLE_ENDIAN)
- copy_u_w \wr, 2
+ copy_s_w \wr, 2
EX sw $1, \off(\base)
- copy_u_w \wr, 3
+ copy_s_w \wr, 3
EX sw $1, (\off+4)(\base)
#else /* CONFIG_CPU_BIG_ENDIAN */
- copy_u_w \wr, 2
+ copy_s_w \wr, 2
EX sw $1, (\off+4)(\base)
- copy_u_w \wr, 3
+ copy_s_w \wr, 3
EX sw $1, \off(\base)
#endif
.set pop
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 66aac55df349..8acae316f26b 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -706,6 +706,9 @@ static void __init arch_mem_init(char **cmdline_p)
for_each_memblock(reserved, reg)
if (reg->size != 0)
reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
+
+ reserve_bootmem_region(__pa_symbol(&__nosave_begin),
+ __pa_symbol(&__nosave_end)); /* Reserve for hibernation */
}
static void __init resource_init(void)
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index bf792e2839a6..9e35b6b26aa8 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -195,6 +195,9 @@ static int restore_msa_extcontext(void __user *buf, unsigned int size)
unsigned int csr;
int i, err;
+ if (!config_enabled(CONFIG_CPU_HAS_MSA))
+ return SIGSYS;
+
if (size != sizeof(*msa))
return -EINVAL;
@@ -398,8 +401,8 @@ int protected_restore_fp_context(void __user *sc)
}
fp_done:
- if (used & USED_EXTCONTEXT)
- err |= restore_extcontext(sc_to_extcontext(sc));
+ if (!err && (used & USED_EXTCONTEXT))
+ err = restore_extcontext(sc_to_extcontext(sc));
return err ?: sig;
}
@@ -767,15 +770,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
sigset_t *oldset = sigmask_to_save();
int ret;
struct mips_abi *abi = current->thread.abi;
-#ifdef CONFIG_CPU_MICROMIPS
- void *vdso;
- unsigned long tmp = (unsigned long)current->mm->context.vdso;
-
- set_isa16_mode(tmp);
- vdso = (void *)tmp;
-#else
void *vdso = current->mm->context.vdso;
-#endif
if (regs->regs[0]) {
switch(regs->regs[2]) {
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index ca9a81007489..99a402231f4d 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -144,7 +144,7 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs)
if (!task)
task = current;
- if (raw_show_trace || !__kernel_text_address(pc)) {
+ if (raw_show_trace || user_mode(regs) || !__kernel_text_address(pc)) {
show_raw_backtrace(sp);
return;
}
@@ -1241,7 +1241,7 @@ static int enable_restore_fp_context(int msa)
err = init_fpu();
if (msa && !err) {
enable_msa();
- _init_msa_upper();
+ init_msa_upper();
set_thread_flag(TIF_USEDMSA);
set_thread_flag(TIF_MSA_CTX_LIVE);
}
@@ -1304,7 +1304,7 @@ static int enable_restore_fp_context(int msa)
*/
prior_msa = test_and_set_thread_flag(TIF_MSA_CTX_LIVE);
if (!prior_msa && was_fpu_owner) {
- _init_msa_upper();
+ init_msa_upper();
goto out;
}
@@ -1321,7 +1321,7 @@ static int enable_restore_fp_context(int msa)
* of each vector register such that it cannot see data left
* behind by another task.
*/
- _init_msa_upper();
+ init_msa_upper();
} else {
/* We need to restore the vector context. */
restore_msa(current);
diff --git a/arch/mips/kernel/watch.c b/arch/mips/kernel/watch.c
index 2a03abb5bd2c..9b78e375118e 100644
--- a/arch/mips/kernel/watch.c
+++ b/arch/mips/kernel/watch.c
@@ -15,10 +15,9 @@
* Install the watch registers for the current thread. A maximum of
* four registers are installed although the machine may have more.
*/
-void mips_install_watch_registers(void)
+void mips_install_watch_registers(struct task_struct *t)
{
- struct mips3264_watch_reg_state *watches =
- &current->thread.watch.mips3264;
+ struct mips3264_watch_reg_state *watches = &t->thread.watch.mips3264;
switch (current_cpu_data.watch_reg_use_cnt) {
default:
BUG();
diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c
index 41b1b090f56f..dc10c77b7500 100644
--- a/arch/mips/kvm/emulate.c
+++ b/arch/mips/kvm/emulate.c
@@ -302,12 +302,31 @@ static inline ktime_t kvm_mips_count_time(struct kvm_vcpu *vcpu)
*/
static uint32_t kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now)
{
- ktime_t expires;
+ struct mips_coproc *cop0 = vcpu->arch.cop0;
+ ktime_t expires, threshold;
+ uint32_t count, compare;
int running;
- /* Is the hrtimer pending? */
+ /* Calculate the biased and scaled guest CP0_Count */
+ count = vcpu->arch.count_bias + kvm_mips_ktime_to_count(vcpu, now);
+ compare = kvm_read_c0_guest_compare(cop0);
+
+ /*
+ * Find whether CP0_Count has reached the closest timer interrupt. If
+ * not, we shouldn't inject it.
+ */
+ if ((int32_t)(count - compare) < 0)
+ return count;
+
+ /*
+ * The CP0_Count we're going to return has already reached the closest
+ * timer interrupt. Quickly check if it really is a new interrupt by
+ * looking at whether the interval until the hrtimer expiry time is
+ * less than 1/4 of the timer period.
+ */
expires = hrtimer_get_expires(&vcpu->arch.comparecount_timer);
- if (ktime_compare(now, expires) >= 0) {
+ threshold = ktime_add_ns(now, vcpu->arch.count_period / 4);
+ if (ktime_before(expires, threshold)) {
/*
* Cancel it while we handle it so there's no chance of
* interference with the timeout handler.
@@ -329,8 +348,7 @@ static uint32_t kvm_mips_read_count_running(struct kvm_vcpu *vcpu, ktime_t now)
}
}
- /* Return the biased and scaled guest CP0_Count */
- return vcpu->arch.count_bias + kvm_mips_ktime_to_count(vcpu, now);
+ return count;
}
/**
@@ -420,32 +438,6 @@ static void kvm_mips_resume_hrtimer(struct kvm_vcpu *vcpu,
}
/**
- * kvm_mips_update_hrtimer() - Update next expiry time of hrtimer.
- * @vcpu: Virtual CPU.
- *
- * Recalculates and updates the expiry time of the hrtimer. This can be used
- * after timer parameters have been altered which do not depend on the time that
- * the change occurs (in those cases kvm_mips_freeze_hrtimer() and
- * kvm_mips_resume_hrtimer() are used directly).
- *
- * It is guaranteed that no timer interrupts will be lost in the process.
- *
- * Assumes !kvm_mips_count_disabled(@vcpu) (guest CP0_Count timer is running).
- */
-static void kvm_mips_update_hrtimer(struct kvm_vcpu *vcpu)
-{
- ktime_t now;
- uint32_t count;
-
- /*
- * freeze_hrtimer takes care of a timer interrupts <= count, and
- * resume_hrtimer the hrtimer takes care of a timer interrupts > count.
- */
- now = kvm_mips_freeze_hrtimer(vcpu, &count);
- kvm_mips_resume_hrtimer(vcpu, now, count);
-}
-
-/**
* kvm_mips_write_count() - Modify the count and update timer.
* @vcpu: Virtual CPU.
* @count: Guest CP0_Count value to set.
@@ -540,23 +532,42 @@ int kvm_mips_set_count_hz(struct kvm_vcpu *vcpu, s64 count_hz)
* kvm_mips_write_compare() - Modify compare and update timer.
* @vcpu: Virtual CPU.
* @compare: New CP0_Compare value.
+ * @ack: Whether to acknowledge timer interrupt.
*
* Update CP0_Compare to a new value and update the timeout.
+ * If @ack, atomically acknowledge any pending timer interrupt, otherwise ensure
+ * any pending timer interrupt is preserved.
*/
-void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare)
+void kvm_mips_write_compare(struct kvm_vcpu *vcpu, uint32_t compare, bool ack)
{
struct mips_coproc *cop0 = vcpu->arch.cop0;
+ int dc;
+ u32 old_compare = kvm_read_c0_guest_compare(cop0);
+ ktime_t now;
+ uint32_t count;
/* if unchanged, must just be an ack */
- if (kvm_read_c0_guest_compare(cop0) == compare)
+ if (old_compare == compare) {
+ if (!ack)
+ return;
+ kvm_mips_callbacks->dequeue_timer_int(vcpu);
+ kvm_write_c0_guest_compare(cop0, compare);
return;
+ }
+
+ /* freeze_hrtimer() takes care of timer interrupts <= count */
+ dc = kvm_mips_count_disabled(vcpu);
+ if (!dc)
+ now = kvm_mips_freeze_hrtimer(vcpu, &count);
+
+ if (ack)
+ kvm_mips_callbacks->dequeue_timer_int(vcpu);
- /* Update compare */
kvm_write_c0_guest_compare(cop0, compare);
- /* Update timeout if count enabled */
- if (!kvm_mips_count_disabled(vcpu))
- kvm_mips_update_hrtimer(vcpu);
+ /* resume_hrtimer() takes care of timer interrupts > count */
+ if (!dc)
+ kvm_mips_resume_hrtimer(vcpu, now, count);
}
/**
@@ -1095,9 +1106,9 @@ enum emulation_result kvm_mips_emulate_CP0(uint32_t inst, uint32_t *opc,
/* If we are writing to COMPARE */
/* Clear pending timer interrupt, if any */
- kvm_mips_callbacks->dequeue_timer_int(vcpu);
kvm_mips_write_compare(vcpu,
- vcpu->arch.gprs[rt]);
+ vcpu->arch.gprs[rt],
+ true);
} else if ((rd == MIPS_CP0_STATUS) && (sel == 0)) {
unsigned int old_val, val, change;
diff --git a/arch/mips/kvm/interrupt.h b/arch/mips/kvm/interrupt.h
index 4ab4bdfad703..2143884709e4 100644
--- a/arch/mips/kvm/interrupt.h
+++ b/arch/mips/kvm/interrupt.h
@@ -28,6 +28,7 @@
#define MIPS_EXC_MAX 12
/* XXXSL More to follow */
+extern char __kvm_mips_vcpu_run_end[];
extern char mips32_exception[], mips32_exceptionEnd[];
extern char mips32_GuestException[], mips32_GuestExceptionEnd[];
diff --git a/arch/mips/kvm/locore.S b/arch/mips/kvm/locore.S
index 7e2210846b8b..77706433651b 100644
--- a/arch/mips/kvm/locore.S
+++ b/arch/mips/kvm/locore.S
@@ -227,6 +227,7 @@ FEXPORT(__kvm_mips_load_k0k1)
/* Jump to guest */
eret
+EXPORT(__kvm_mips_vcpu_run_end)
VECTOR(MIPSX(exception), unknown)
/* Find out what mode we came from and jump to the proper handler. */
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index 2683d04fdda5..e86b7499921a 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -314,6 +314,15 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
memcpy(gebase + offset, mips32_GuestException,
mips32_GuestExceptionEnd - mips32_GuestException);
+#ifdef MODULE
+ offset += mips32_GuestExceptionEnd - mips32_GuestException;
+ memcpy(gebase + offset, (char *)__kvm_mips_vcpu_run,
+ __kvm_mips_vcpu_run_end - (char *)__kvm_mips_vcpu_run);
+ vcpu->arch.vcpu_run = gebase + offset;
+#else
+ vcpu->arch.vcpu_run = __kvm_mips_vcpu_run;
+#endif
+
/* Invalidate the icache for these ranges */
local_flush_icache_range((unsigned long)gebase,
(unsigned long)gebase + ALIGN(size, PAGE_SIZE));
@@ -403,7 +412,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
/* Disable hardware page table walking while in guest */
htw_stop();
- r = __kvm_mips_vcpu_run(run, vcpu);
+ r = vcpu->arch.vcpu_run(run, vcpu);
/* Re-enable HTW before enabling interrupts */
htw_start();
diff --git a/arch/mips/kvm/trap_emul.c b/arch/mips/kvm/trap_emul.c
index d836ed5b0bc7..307cc4c98bdd 100644
--- a/arch/mips/kvm/trap_emul.c
+++ b/arch/mips/kvm/trap_emul.c
@@ -547,7 +547,7 @@ static int kvm_trap_emul_set_one_reg(struct kvm_vcpu *vcpu,
kvm_mips_write_count(vcpu, v);
break;
case KVM_REG_MIPS_CP0_COMPARE:
- kvm_mips_write_compare(vcpu, v);
+ kvm_mips_write_compare(vcpu, v, false);
break;
case KVM_REG_MIPS_CP0_CAUSE:
/*
diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c
index beb80f316095..927dc94a030f 100644
--- a/arch/mips/lib/ashldi3.c
+++ b/arch/mips/lib/ashldi3.c
@@ -2,7 +2,7 @@
#include "libgcc.h"
-long long __ashldi3(long long u, word_type b)
+long long notrace __ashldi3(long long u, word_type b)
{
DWunion uu, w;
word_type bm;
diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c
index c884a912b660..9fdf1a598428 100644
--- a/arch/mips/lib/ashrdi3.c
+++ b/arch/mips/lib/ashrdi3.c
@@ -2,7 +2,7 @@
#include "libgcc.h"
-long long __ashrdi3(long long u, word_type b)
+long long notrace __ashrdi3(long long u, word_type b)
{
DWunion uu, w;
word_type bm;
diff --git a/arch/mips/lib/bswapdi.c b/arch/mips/lib/bswapdi.c
index 77e5f9c1f005..e3e77aa52c95 100644
--- a/arch/mips/lib/bswapdi.c
+++ b/arch/mips/lib/bswapdi.c
@@ -1,6 +1,6 @@
#include <linux/module.h>
-unsigned long long __bswapdi2(unsigned long long u)
+unsigned long long notrace __bswapdi2(unsigned long long u)
{
return (((u) & 0xff00000000000000ull) >> 56) |
(((u) & 0x00ff000000000000ull) >> 40) |
diff --git a/arch/mips/lib/bswapsi.c b/arch/mips/lib/bswapsi.c
index 2b302ff121d2..530a8afe6fda 100644
--- a/arch/mips/lib/bswapsi.c
+++ b/arch/mips/lib/bswapsi.c
@@ -1,6 +1,6 @@
#include <linux/module.h>
-unsigned int __bswapsi2(unsigned int u)
+unsigned int notrace __bswapsi2(unsigned int u)
{
return (((u) & 0xff000000) >> 24) |
(((u) & 0x00ff0000) >> 8) |
diff --git a/arch/mips/lib/cmpdi2.c b/arch/mips/lib/cmpdi2.c
index 8c1306437ed1..06857da96993 100644
--- a/arch/mips/lib/cmpdi2.c
+++ b/arch/mips/lib/cmpdi2.c
@@ -2,7 +2,7 @@
#include "libgcc.h"
-word_type __cmpdi2(long long a, long long b)
+word_type notrace __cmpdi2(long long a, long long b)
{
const DWunion au = {
.ll = a
diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c
index dcf8d6810b7c..364547449c65 100644
--- a/arch/mips/lib/lshrdi3.c
+++ b/arch/mips/lib/lshrdi3.c
@@ -2,7 +2,7 @@
#include "libgcc.h"
-long long __lshrdi3(long long u, word_type b)
+long long notrace __lshrdi3(long long u, word_type b)
{
DWunion uu, w;
word_type bm;
diff --git a/arch/mips/lib/ucmpdi2.c b/arch/mips/lib/ucmpdi2.c
index bb4cb2f828ea..bd599f58234c 100644
--- a/arch/mips/lib/ucmpdi2.c
+++ b/arch/mips/lib/ucmpdi2.c
@@ -2,7 +2,7 @@
#include "libgcc.h"
-word_type __ucmpdi2(unsigned long long a, unsigned long long b)
+word_type notrace __ucmpdi2(unsigned long long a, unsigned long long b)
{
const DWunion au = {.ll = a};
const DWunion bu = {.ll = b};
diff --git a/arch/mips/loongson64/loongson-3/numa.c b/arch/mips/loongson64/loongson-3/numa.c
index 6f9e010cec4d..282c5a8c2fcd 100644
--- a/arch/mips/loongson64/loongson-3/numa.c
+++ b/arch/mips/loongson64/loongson-3/numa.c
@@ -213,10 +213,10 @@ static void __init node_mem_init(unsigned int node)
BOOTMEM_DEFAULT);
if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) {
- /* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */
+ /* Reserve 0xfe000000~0xffffffff for RS780E integrated GPU */
reserve_bootmem_node(NODE_DATA(node),
- (node_addrspace_offset | 0xff800000),
- 8 << 20, BOOTMEM_DEFAULT);
+ (node_addrspace_offset | 0xfe000000),
+ 32 << 20, BOOTMEM_DEFAULT);
}
sparse_memory_present_with_active_regions(node);
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 32f0e19a0d7f..734a2c7665ec 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -445,9 +445,11 @@ static int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
case spec_op:
switch (insn.r_format.func) {
case jalr_op:
- regs->regs[insn.r_format.rd] =
- regs->cp0_epc + dec_insn.pc_inc +
- dec_insn.next_pc_inc;
+ if (insn.r_format.rd != 0) {
+ regs->regs[insn.r_format.rd] =
+ regs->cp0_epc + dec_insn.pc_inc +
+ dec_insn.next_pc_inc;
+ }
/* Fall through */
case jr_op:
/* For R6, JR already emulated in jalr_op */
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index aab218c36e0d..e87bccd6e0aa 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -16,6 +16,7 @@
#include <linux/mm.h>
#include <asm/cacheflush.h>
+#include <asm/highmem.h>
#include <asm/processor.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
@@ -83,8 +84,6 @@ void __flush_dcache_page(struct page *page)
struct address_space *mapping = page_mapping(page);
unsigned long addr;
- if (PageHighMem(page))
- return;
if (mapping && !mapping_mapped(mapping)) {
SetPageDcacheDirty(page);
return;
@@ -95,8 +94,15 @@ void __flush_dcache_page(struct page *page)
* case is for exec env/arg pages and those are %99 certainly going to
* get faulted into the tlb (and thus flushed) anyways.
*/
- addr = (unsigned long) page_address(page);
+ if (PageHighMem(page))
+ addr = (unsigned long)kmap_atomic(page);
+ else
+ addr = (unsigned long)page_address(page);
+
flush_data_cache_page(addr);
+
+ if (PageHighMem(page))
+ __kunmap_atomic((void *)addr);
}
EXPORT_SYMBOL(__flush_dcache_page);
@@ -119,33 +125,28 @@ void __flush_anon_page(struct page *page, unsigned long vmaddr)
EXPORT_SYMBOL(__flush_anon_page);
-void __flush_icache_page(struct vm_area_struct *vma, struct page *page)
-{
- unsigned long addr;
-
- if (PageHighMem(page))
- return;
-
- addr = (unsigned long) page_address(page);
- flush_data_cache_page(addr);
-}
-EXPORT_SYMBOL_GPL(__flush_icache_page);
-
-void __update_cache(struct vm_area_struct *vma, unsigned long address,
- pte_t pte)
+void __update_cache(unsigned long address, pte_t pte)
{
struct page *page;
unsigned long pfn, addr;
- int exec = (vma->vm_flags & VM_EXEC) && !cpu_has_ic_fills_f_dc;
+ int exec = !pte_no_exec(pte) && !cpu_has_ic_fills_f_dc;
pfn = pte_pfn(pte);
if (unlikely(!pfn_valid(pfn)))
return;
page = pfn_to_page(pfn);
- if (page_mapping(page) && Page_dcache_dirty(page)) {
- addr = (unsigned long) page_address(page);
+ if (Page_dcache_dirty(page)) {
+ if (PageHighMem(page))
+ addr = (unsigned long)kmap_atomic(page);
+ else
+ addr = (unsigned long)page_address(page);
+
if (exec || pages_do_alias(addr, address & PAGE_MASK))
flush_data_cache_page(addr);
+
+ if (PageHighMem(page))
+ __kunmap_atomic((void *)addr);
+
ClearPageDcacheDirty(page);
}
}
diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile
index 14568900fc1d..090393aa0f20 100644
--- a/arch/mips/vdso/Makefile
+++ b/arch/mips/vdso/Makefile
@@ -5,10 +5,12 @@ obj-vdso-y := elf.o gettimeofday.o sigreturn.o
ccflags-vdso := \
$(filter -I%,$(KBUILD_CFLAGS)) \
$(filter -E%,$(KBUILD_CFLAGS)) \
+ $(filter -mmicromips,$(KBUILD_CFLAGS)) \
$(filter -march=%,$(KBUILD_CFLAGS))
cflags-vdso := $(ccflags-vdso) \
$(filter -W%,$(filter-out -Wa$(comma)%,$(KBUILD_CFLAGS))) \
- -O2 -g -fPIC -fno-common -fno-builtin -G 0 -DDISABLE_BRANCH_PROFILING \
+ -O2 -g -fPIC -fno-strict-aliasing -fno-common -fno-builtin -G 0 \
+ -DDISABLE_BRANCH_PROFILING \
$(call cc-option, -fno-stack-protector)
aflags-vdso := $(ccflags-vdso) \
$(filter -I%,$(KBUILD_CFLAGS)) \
diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
index d7c0acb35ec2..8d49614d600d 100644
--- a/arch/parisc/kernel/unaligned.c
+++ b/arch/parisc/kernel/unaligned.c
@@ -666,7 +666,7 @@ void handle_unaligned(struct pt_regs *regs)
break;
}
- if (modify && R1(regs->iir))
+ if (ret == 0 && modify && R1(regs->iir))
regs->gr[R1(regs->iir)] = newbase;
@@ -677,6 +677,14 @@ void handle_unaligned(struct pt_regs *regs)
if (ret)
{
+ /*
+ * The unaligned handler failed.
+ * If we were called by __get_user() or __put_user() jump
+ * to it's exception fixup handler instead of crashing.
+ */
+ if (!user_mode(regs) && fixup_exception(regs))
+ return;
+
printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
die_if_kernel("Unaligned data reference", regs, 28);
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 2220f7a60def..070fa8552051 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -707,7 +707,7 @@
#define MMCR0_FCWAIT 0x00000002UL /* freeze counter in WAIT state */
#define MMCR0_FCHV 0x00000001UL /* freeze conditions in hypervisor mode */
#define SPRN_MMCR1 798
-#define SPRN_MMCR2 769
+#define SPRN_MMCR2 785
#define SPRN_MMCRA 0x312
#define MMCRA_SDSYNC 0x80000000UL /* SDAR synced with SIAR */
#define MMCRA_SDAR_DCACHE_MISS 0x40000000UL
@@ -744,13 +744,13 @@
#define SPRN_PMC6 792
#define SPRN_PMC7 793
#define SPRN_PMC8 794
-#define SPRN_SIAR 780
-#define SPRN_SDAR 781
#define SPRN_SIER 784
#define SIER_SIPR 0x2000000 /* Sampled MSR_PR */
#define SIER_SIHV 0x1000000 /* Sampled MSR_HV */
#define SIER_SIAR_VALID 0x0400000 /* SIAR contents valid */
#define SIER_SDAR_VALID 0x0200000 /* SDAR contents valid */
+#define SPRN_SIAR 796
+#define SPRN_SDAR 797
#define SPRN_TACR 888
#define SPRN_TCSCR 889
#define SPRN_CSIGR 890
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 40e4d4a27663..b34e8a54f7db 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -1072,7 +1072,7 @@ void eeh_add_device_early(struct pci_dn *pdn)
struct pci_controller *phb;
struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
- if (!edev || !eeh_enabled())
+ if (!edev)
return;
if (!eeh_has_flag(EEH_PROBE_MODE_DEVTREE))
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 52c1e273f8cd..247a0dc012f1 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -166,6 +166,16 @@ static void *eeh_dev_save_state(void *data, void *userdata)
if (!edev)
return NULL;
+ /*
+ * We cannot access the config space on some adapters.
+ * Otherwise, it will cause fenced PHB. We don't save
+ * the content in their config space and will restore
+ * from the initial config space saved when the EEH
+ * device is created.
+ */
+ if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED))
+ return NULL;
+
pdev = eeh_dev_to_pci_dev(edev);
if (!pdev)
return NULL;
@@ -305,6 +315,19 @@ static void *eeh_dev_restore_state(void *data, void *userdata)
if (!edev)
return NULL;
+ /*
+ * The content in the config space isn't saved because
+ * the blocked config space on some adapters. We have
+ * to restore the initial saved config space when the
+ * EEH device is created.
+ */
+ if (edev->pe && (edev->pe->state & EEH_PE_CFG_RESTRICTED)) {
+ if (list_is_last(&edev->list, &edev->pe->edevs))
+ eeh_pe_restore_bars(edev->pe);
+
+ return NULL;
+ }
+
pdev = eeh_dev_to_pci_dev(edev);
if (!pdev)
return NULL;
@@ -504,9 +527,6 @@ int eeh_pe_reset_and_recover(struct eeh_pe *pe)
/* Save states */
eeh_pe_dev_traverse(pe, eeh_dev_save_state, NULL);
- /* Report error */
- eeh_pe_dev_traverse(pe, eeh_report_error, &result);
-
/* Issue reset */
ret = eeh_reset_pe(pe);
if (ret) {
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 0a0399c2af11..b81ccc5fb32d 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -962,11 +962,6 @@ hv_facility_unavailable_relon_trampoline:
#endif
STD_RELON_EXCEPTION_PSERIES(0x5700, 0x1700, altivec_assist)
- /* Other future vectors */
- .align 7
- .globl __end_interrupts
-__end_interrupts:
-
.align 7
system_call_entry:
b system_call_common
@@ -1253,6 +1248,17 @@ __end_handlers:
STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable)
STD_RELON_EXCEPTION_HV_OOL(0xf80, hv_facility_unavailable)
+ /*
+ * The __end_interrupts marker must be past the out-of-line (OOL)
+ * handlers, so that they are copied to real address 0x100 when running
+ * a relocatable kernel. This ensures they can be reached from the short
+ * trampoline handlers (like 0x4f00, 0x4f20, etc.) which branch
+ * directly, without using LOAD_HANDLER().
+ */
+ .align 7
+ .globl __end_interrupts
+__end_interrupts:
+
#if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
/*
* Data area reserved for FWNMI option.
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index a7b91b54c813..b7abf3cd2a67 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1239,6 +1239,16 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
current->thread.regs = regs - 1;
}
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ /*
+ * Clear any transactional state, we're exec()ing. The cause is
+ * not important as there will never be a recheckpoint so it's not
+ * user visible.
+ */
+ if (MSR_TM_SUSPENDED(mfmsr()))
+ tm_reclaim_current(0);
+#endif
+
memset(regs->gpr, 0, sizeof(regs->gpr));
regs->ctr = 0;
regs->link = 0;
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 92dea8df6b26..b7e86e00048f 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -655,6 +655,7 @@ unsigned char ibm_architecture_vec[] = {
W(0xffff0000), W(0x003e0000), /* POWER6 */
W(0xffff0000), W(0x003f0000), /* POWER7 */
W(0xffff0000), W(0x004b0000), /* POWER8E */
+ W(0xffff0000), W(0x004c0000), /* POWER8NVL */
W(0xffff0000), W(0x004d0000), /* POWER8 */
W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */
W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */
@@ -717,7 +718,7 @@ unsigned char ibm_architecture_vec[] = {
* must match by the macro below. Update the definition if
* the structure layout changes.
*/
-#define IBM_ARCH_VEC_NRCORES_OFFSET 125
+#define IBM_ARCH_VEC_NRCORES_OFFSET 133
W(NR_CPUS), /* number of cores supported */
0,
0,
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
index ac3ffd97e059..405baaf96864 100644
--- a/arch/powerpc/platforms/pseries/eeh_pseries.c
+++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
@@ -615,29 +615,50 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe)
{
int config_addr;
int ret;
+ /* Waiting 0.2s maximum before skipping configuration */
+ int max_wait = 200;
/* Figure out the PE address */
config_addr = pe->config_addr;
if (pe->addr)
config_addr = pe->addr;
- /* Use new configure-pe function, if supported */
- if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
- ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
- config_addr, BUID_HI(pe->phb->buid),
- BUID_LO(pe->phb->buid));
- } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
- ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
- config_addr, BUID_HI(pe->phb->buid),
- BUID_LO(pe->phb->buid));
- } else {
- return -EFAULT;
- }
+ while (max_wait > 0) {
+ /* Use new configure-pe function, if supported */
+ if (ibm_configure_pe != RTAS_UNKNOWN_SERVICE) {
+ ret = rtas_call(ibm_configure_pe, 3, 1, NULL,
+ config_addr, BUID_HI(pe->phb->buid),
+ BUID_LO(pe->phb->buid));
+ } else if (ibm_configure_bridge != RTAS_UNKNOWN_SERVICE) {
+ ret = rtas_call(ibm_configure_bridge, 3, 1, NULL,
+ config_addr, BUID_HI(pe->phb->buid),
+ BUID_LO(pe->phb->buid));
+ } else {
+ return -EFAULT;
+ }
- if (ret)
- pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
- __func__, pe->phb->global_number, pe->addr, ret);
+ if (!ret)
+ return ret;
+
+ /*
+ * If RTAS returns a delay value that's above 100ms, cut it
+ * down to 100ms in case firmware made a mistake. For more
+ * on how these delay values work see rtas_busy_delay_time
+ */
+ if (ret > RTAS_EXTENDED_DELAY_MIN+2 &&
+ ret <= RTAS_EXTENDED_DELAY_MAX)
+ ret = RTAS_EXTENDED_DELAY_MIN+2;
+
+ max_wait -= rtas_busy_delay_time(ret);
+
+ if (max_wait < 0)
+ break;
+
+ rtas_busy_delay(ret);
+ }
+ pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n",
+ __func__, pe->phb->global_number, pe->addr, ret);
return ret;
}
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c
index bd98ce2be17b..3e8865b187de 100644
--- a/arch/powerpc/platforms/pseries/iommu.c
+++ b/arch/powerpc/platforms/pseries/iommu.c
@@ -912,7 +912,8 @@ machine_arch_initcall(pseries, find_existing_ddw_windows);
static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
struct ddw_query_response *query)
{
- struct eeh_dev *edev;
+ struct device_node *dn;
+ struct pci_dn *pdn;
u32 cfg_addr;
u64 buid;
int ret;
@@ -923,11 +924,10 @@ static int query_ddw(struct pci_dev *dev, const u32 *ddw_avail,
* Retrieve them from the pci device, not the node with the
* dma-window property
*/
- edev = pci_dev_to_eeh_dev(dev);
- cfg_addr = edev->config_addr;
- if (edev->pe_config_addr)
- cfg_addr = edev->pe_config_addr;
- buid = edev->phb->buid;
+ dn = pci_device_to_OF_node(dev);
+ pdn = PCI_DN(dn);
+ buid = pdn->phb->buid;
+ cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8));
ret = rtas_call(ddw_avail[0], 3, 5, (u32 *)query,
cfg_addr, BUID_HI(buid), BUID_LO(buid));
@@ -941,7 +941,8 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
struct ddw_create_response *create, int page_shift,
int window_shift)
{
- struct eeh_dev *edev;
+ struct device_node *dn;
+ struct pci_dn *pdn;
u32 cfg_addr;
u64 buid;
int ret;
@@ -952,11 +953,10 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
* Retrieve them from the pci device, not the node with the
* dma-window property
*/
- edev = pci_dev_to_eeh_dev(dev);
- cfg_addr = edev->config_addr;
- if (edev->pe_config_addr)
- cfg_addr = edev->pe_config_addr;
- buid = edev->phb->buid;
+ dn = pci_device_to_OF_node(dev);
+ pdn = PCI_DN(dn);
+ buid = pdn->phb->buid;
+ cfg_addr = ((pdn->busno << 16) | (pdn->devfn << 8));
do {
/* extra outputs are LIOBN and dma-addr (hi, lo) */
diff --git a/arch/s390/include/asm/fpu/api.h b/arch/s390/include/asm/fpu/api.h
index 5e04f3cbd320..8ae236b0f80b 100644
--- a/arch/s390/include/asm/fpu/api.h
+++ b/arch/s390/include/asm/fpu/api.h
@@ -22,7 +22,7 @@ static inline int test_fp_ctl(u32 fpc)
" la %0,0\n"
"1:\n"
EX_TABLE(0b,1b)
- : "=d" (rc), "=d" (orig_fpc)
+ : "=d" (rc), "=&d" (orig_fpc)
: "d" (fpc), "0" (-EINVAL));
return rc;
}
diff --git a/arch/s390/net/bpf_jit.h b/arch/s390/net/bpf_jit.h
index f010c93a88b1..fda605dbc1b4 100644
--- a/arch/s390/net/bpf_jit.h
+++ b/arch/s390/net/bpf_jit.h
@@ -37,7 +37,7 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
* | | |
* +---------------+ |
* | 8 byte skbp | |
- * R15+170 -> +---------------+ |
+ * R15+176 -> +---------------+ |
* | 8 byte hlen | |
* R15+168 -> +---------------+ |
* | 4 byte align | |
@@ -58,7 +58,7 @@ extern u8 sk_load_word[], sk_load_half[], sk_load_byte[];
#define STK_OFF (STK_SPACE - STK_160_UNUSED)
#define STK_OFF_TMP 160 /* Offset of tmp buffer on stack */
#define STK_OFF_HLEN 168 /* Offset of SKB header length on stack */
-#define STK_OFF_SKBP 170 /* Offset of SKB pointer on stack */
+#define STK_OFF_SKBP 176 /* Offset of SKB pointer on stack */
#define STK_OFF_R6 (160 - 11 * 8) /* Offset of r6 on stack */
#define STK_OFF_TCCNT (160 - 12 * 8) /* Offset of tail_call_cnt on stack */
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index 9a0c4c22e536..0e2919dd8df3 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -45,7 +45,7 @@ struct bpf_jit {
int labels[1]; /* Labels for local jumps */
};
-#define BPF_SIZE_MAX 0x7ffff /* Max size for program (20 bit signed displ) */
+#define BPF_SIZE_MAX 0xffff /* Max size for program (16 bit branches) */
#define SEEN_SKB 1 /* skb access */
#define SEEN_MEM 2 /* use mem[] for temporary storage */
@@ -446,7 +446,7 @@ static void bpf_jit_prologue(struct bpf_jit *jit, bool is_classic)
emit_load_skb_data_hlen(jit);
if (jit->seen & SEEN_SKB_CHANGE)
/* stg %b1,ST_OFF_SKBP(%r0,%r15) */
- EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15,
+ EMIT6_DISP_LH(0xe3000000, 0x0024, BPF_REG_1, REG_0, REG_15,
STK_OFF_SKBP);
/* Clear A (%b0) and X (%b7) registers for converted BPF programs */
if (is_classic) {
diff --git a/arch/sparc/include/asm/head_64.h b/arch/sparc/include/asm/head_64.h
index 10e9dabc4c41..f0700cfeedd7 100644
--- a/arch/sparc/include/asm/head_64.h
+++ b/arch/sparc/include/asm/head_64.h
@@ -15,6 +15,10 @@
#define PTREGS_OFF (STACK_BIAS + STACKFRAME_SZ)
+#define RTRAP_PSTATE (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
+#define RTRAP_PSTATE_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV)
+#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
+
#define __CHEETAH_ID 0x003e0014
#define __JALAPENO_ID 0x003e0016
#define __SERRANO_ID 0x003e0022
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 131d36fcd07a..408b715c95a5 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -375,7 +375,7 @@ static inline pgprot_t pgprot_noncached(pgprot_t prot)
#define pgprot_noncached pgprot_noncached
#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-static inline pte_t pte_mkhuge(pte_t pte)
+static inline unsigned long __pte_huge_mask(void)
{
unsigned long mask;
@@ -390,8 +390,19 @@ static inline pte_t pte_mkhuge(pte_t pte)
: "=r" (mask)
: "i" (_PAGE_SZHUGE_4U), "i" (_PAGE_SZHUGE_4V));
- return __pte(pte_val(pte) | mask);
+ return mask;
+}
+
+static inline pte_t pte_mkhuge(pte_t pte)
+{
+ return __pte(pte_val(pte) | __pte_huge_mask());
+}
+
+static inline bool is_hugetlb_pte(pte_t pte)
+{
+ return !!(pte_val(pte) & __pte_huge_mask());
}
+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static inline pmd_t pmd_mkhuge(pmd_t pmd)
{
@@ -403,6 +414,11 @@ static inline pmd_t pmd_mkhuge(pmd_t pmd)
return __pmd(pte_val(pte));
}
#endif
+#else
+static inline bool is_hugetlb_pte(pte_t pte)
+{
+ return false;
+}
#endif
static inline pte_t pte_mkdirty(pte_t pte)
@@ -865,6 +881,19 @@ static inline unsigned long pud_pfn(pud_t pud)
void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
pte_t *ptep, pte_t orig, int fullmm);
+static void maybe_tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
+ pte_t *ptep, pte_t orig, int fullmm)
+{
+ /* It is more efficient to let flush_tlb_kernel_range()
+ * handle init_mm tlb flushes.
+ *
+ * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
+ * and SUN4V pte layout, so this inline test is fine.
+ */
+ if (likely(mm != &init_mm) && pte_accessible(mm, orig))
+ tlb_batch_add(mm, vaddr, ptep, orig, fullmm);
+}
+
#define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
unsigned long addr,
@@ -881,15 +910,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t orig = *ptep;
*ptep = pte;
-
- /* It is more efficient to let flush_tlb_kernel_range()
- * handle init_mm tlb flushes.
- *
- * SUN4V NOTE: _PAGE_VALID is the same value in both the SUN4U
- * and SUN4V pte layout, so this inline test is fine.
- */
- if (likely(mm != &init_mm) && pte_accessible(mm, orig))
- tlb_batch_add(mm, addr, ptep, orig, fullmm);
+ maybe_tlb_batch_add(mm, addr, ptep, orig, fullmm);
}
#define set_pte_at(mm,addr,ptep,pte) \
diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h
index dea1cfa2122b..a8e192e90700 100644
--- a/arch/sparc/include/asm/tlbflush_64.h
+++ b/arch/sparc/include/asm/tlbflush_64.h
@@ -8,6 +8,7 @@
#define TLB_BATCH_NR 192
struct tlb_batch {
+ bool huge;
struct mm_struct *mm;
unsigned long tlb_nr;
unsigned long active;
@@ -16,7 +17,7 @@ struct tlb_batch {
void flush_tsb_kernel_range(unsigned long start, unsigned long end);
void flush_tsb_user(struct tlb_batch *tb);
-void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr);
+void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr, bool huge);
/* TLB flush operations. */
diff --git a/arch/sparc/include/asm/ttable.h b/arch/sparc/include/asm/ttable.h
index 71b5a67522ab..781b9f1dbdc2 100644
--- a/arch/sparc/include/asm/ttable.h
+++ b/arch/sparc/include/asm/ttable.h
@@ -589,8 +589,8 @@ user_rtt_fill_64bit: \
restored; \
nop; nop; nop; nop; nop; nop; \
nop; nop; nop; nop; nop; \
- ba,a,pt %xcc, user_rtt_fill_fixup; \
- ba,a,pt %xcc, user_rtt_fill_fixup; \
+ ba,a,pt %xcc, user_rtt_fill_fixup_dax; \
+ ba,a,pt %xcc, user_rtt_fill_fixup_mna; \
ba,a,pt %xcc, user_rtt_fill_fixup;
@@ -652,8 +652,8 @@ user_rtt_fill_32bit: \
restored; \
nop; nop; nop; nop; nop; \
nop; nop; nop; \
- ba,a,pt %xcc, user_rtt_fill_fixup; \
- ba,a,pt %xcc, user_rtt_fill_fixup; \
+ ba,a,pt %xcc, user_rtt_fill_fixup_dax; \
+ ba,a,pt %xcc, user_rtt_fill_fixup_mna; \
ba,a,pt %xcc, user_rtt_fill_fixup;
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 7cf9c6ea3f1f..fdb13327fded 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -21,6 +21,7 @@ CFLAGS_REMOVE_perf_event.o := -pg
CFLAGS_REMOVE_pcr.o := -pg
endif
+obj-$(CONFIG_SPARC64) += urtt_fill.o
obj-$(CONFIG_SPARC32) += entry.o wof.o wuf.o
obj-$(CONFIG_SPARC32) += etrap_32.o
obj-$(CONFIG_SPARC32) += rtrap_32.o
diff --git a/arch/sparc/kernel/cherrs.S b/arch/sparc/kernel/cherrs.S
index 4ee1ad420862..655628def68e 100644
--- a/arch/sparc/kernel/cherrs.S
+++ b/arch/sparc/kernel/cherrs.S
@@ -214,8 +214,7 @@ do_dcpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */
subcc %g1, %g2, %g1 ! Next cacheline
bge,pt %icc, 1b
nop
- ba,pt %xcc, dcpe_icpe_tl1_common
- nop
+ ba,a,pt %xcc, dcpe_icpe_tl1_common
do_dcpe_tl1_fatal:
sethi %hi(1f), %g7
@@ -224,8 +223,7 @@ do_dcpe_tl1_fatal:
mov 0x2, %o0
call cheetah_plus_parity_error
add %sp, PTREGS_OFF, %o1
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
.size do_dcpe_tl1,.-do_dcpe_tl1
.globl do_icpe_tl1
@@ -259,8 +257,7 @@ do_icpe_tl1_nonfatal: /* Ok we may use interrupt globals safely. */
subcc %g1, %g2, %g1
bge,pt %icc, 1b
nop
- ba,pt %xcc, dcpe_icpe_tl1_common
- nop
+ ba,a,pt %xcc, dcpe_icpe_tl1_common
do_icpe_tl1_fatal:
sethi %hi(1f), %g7
@@ -269,8 +266,7 @@ do_icpe_tl1_fatal:
mov 0x3, %o0
call cheetah_plus_parity_error
add %sp, PTREGS_OFF, %o1
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
.size do_icpe_tl1,.-do_icpe_tl1
.type dcpe_icpe_tl1_common,#function
@@ -456,7 +452,7 @@ __cheetah_log_error:
cmp %g2, 0x63
be c_cee
nop
- ba,pt %xcc, c_deferred
+ ba,a,pt %xcc, c_deferred
.size __cheetah_log_error,.-__cheetah_log_error
/* Cheetah FECC trap handling, we get here from tl{0,1}_fecc
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S
index 33c02b15f478..a83707c83be8 100644
--- a/arch/sparc/kernel/entry.S
+++ b/arch/sparc/kernel/entry.S
@@ -948,7 +948,24 @@ linux_syscall_trace:
cmp %o0, 0
bne 3f
mov -ENOSYS, %o0
+
+ /* Syscall tracing can modify the registers. */
+ ld [%sp + STACKFRAME_SZ + PT_G1], %g1
+ sethi %hi(sys_call_table), %l7
+ ld [%sp + STACKFRAME_SZ + PT_I0], %i0
+ or %l7, %lo(sys_call_table), %l7
+ ld [%sp + STACKFRAME_SZ + PT_I1], %i1
+ ld [%sp + STACKFRAME_SZ + PT_I2], %i2
+ ld [%sp + STACKFRAME_SZ + PT_I3], %i3
+ ld [%sp + STACKFRAME_SZ + PT_I4], %i4
+ ld [%sp + STACKFRAME_SZ + PT_I5], %i5
+ cmp %g1, NR_syscalls
+ bgeu 3f
+ mov -ENOSYS, %o0
+
+ sll %g1, 2, %l4
mov %i0, %o0
+ ld [%l7 + %l4], %l7
mov %i1, %o1
mov %i2, %o2
mov %i3, %o3
diff --git a/arch/sparc/kernel/fpu_traps.S b/arch/sparc/kernel/fpu_traps.S
index a6864826a4bd..336d2750fe78 100644
--- a/arch/sparc/kernel/fpu_traps.S
+++ b/arch/sparc/kernel/fpu_traps.S
@@ -100,8 +100,8 @@ do_fpdis:
fmuld %f0, %f2, %f26
faddd %f0, %f2, %f28
fmuld %f0, %f2, %f30
- b,pt %xcc, fpdis_exit
- nop
+ ba,a,pt %xcc, fpdis_exit
+
2: andcc %g5, FPRS_DU, %g0
bne,pt %icc, 3f
fzero %f32
@@ -144,8 +144,8 @@ do_fpdis:
fmuld %f32, %f34, %f58
faddd %f32, %f34, %f60
fmuld %f32, %f34, %f62
- ba,pt %xcc, fpdis_exit
- nop
+ ba,a,pt %xcc, fpdis_exit
+
3: mov SECONDARY_CONTEXT, %g3
add %g6, TI_FPREGS, %g1
@@ -197,8 +197,7 @@ fpdis_exit2:
fp_other_bounce:
call do_fpother
add %sp, PTREGS_OFF, %o0
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
.size fp_other_bounce,.-fp_other_bounce
.align 32
diff --git a/arch/sparc/kernel/head_64.S b/arch/sparc/kernel/head_64.S
index f2d30cab5b3f..51faf92ace00 100644
--- a/arch/sparc/kernel/head_64.S
+++ b/arch/sparc/kernel/head_64.S
@@ -461,9 +461,8 @@ sun4v_chip_type:
subcc %g3, 1, %g3
bne,pt %xcc, 41b
add %g1, 1, %g1
- mov SUN4V_CHIP_SPARC64X, %g4
ba,pt %xcc, 5f
- nop
+ mov SUN4V_CHIP_SPARC64X, %g4
49:
mov SUN4V_CHIP_UNKNOWN, %g4
@@ -548,8 +547,7 @@ sun4u_init:
stxa %g0, [%g7] ASI_DMMU
membar #Sync
- ba,pt %xcc, sun4u_continue
- nop
+ ba,a,pt %xcc, sun4u_continue
sun4v_init:
/* Set ctx 0 */
@@ -560,14 +558,12 @@ sun4v_init:
mov SECONDARY_CONTEXT, %g7
stxa %g0, [%g7] ASI_MMU
membar #Sync
- ba,pt %xcc, niagara_tlb_fixup
- nop
+ ba,a,pt %xcc, niagara_tlb_fixup
sun4u_continue:
BRANCH_IF_ANY_CHEETAH(g1, g7, cheetah_tlb_fixup)
- ba,pt %xcc, spitfire_tlb_fixup
- nop
+ ba,a,pt %xcc, spitfire_tlb_fixup
niagara_tlb_fixup:
mov 3, %g2 /* Set TLB type to hypervisor. */
@@ -639,8 +635,7 @@ niagara_patch:
call hypervisor_patch_cachetlbops
nop
- ba,pt %xcc, tlb_fixup_done
- nop
+ ba,a,pt %xcc, tlb_fixup_done
cheetah_tlb_fixup:
mov 2, %g2 /* Set TLB type to cheetah+. */
@@ -659,8 +654,7 @@ cheetah_tlb_fixup:
call cheetah_patch_cachetlbops
nop
- ba,pt %xcc, tlb_fixup_done
- nop
+ ba,a,pt %xcc, tlb_fixup_done
spitfire_tlb_fixup:
/* Set TLB type to spitfire. */
@@ -782,8 +776,7 @@ setup_trap_table:
call %o1
add %sp, (2047 + 128), %o0
- ba,pt %xcc, 2f
- nop
+ ba,a,pt %xcc, 2f
1: sethi %hi(sparc64_ttable_tl0), %o0
set prom_set_trap_table_name, %g2
@@ -822,8 +815,7 @@ setup_trap_table:
BRANCH_IF_ANY_CHEETAH(o2, o3, 1f)
- ba,pt %xcc, 2f
- nop
+ ba,a,pt %xcc, 2f
/* Disable STICK_INT interrupts. */
1:
diff --git a/arch/sparc/kernel/misctrap.S b/arch/sparc/kernel/misctrap.S
index 753b4f031bfb..34b4933900bf 100644
--- a/arch/sparc/kernel/misctrap.S
+++ b/arch/sparc/kernel/misctrap.S
@@ -18,8 +18,7 @@ __do_privact:
109: or %g7, %lo(109b), %g7
call do_privact
add %sp, PTREGS_OFF, %o0
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
.size __do_privact,.-__do_privact
.type do_mna,#function
@@ -46,8 +45,7 @@ do_mna:
mov %l5, %o2
call mem_address_unaligned
add %sp, PTREGS_OFF, %o0
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
.size do_mna,.-do_mna
.type do_lddfmna,#function
@@ -65,8 +63,7 @@ do_lddfmna:
mov %l5, %o2
call handle_lddfmna
add %sp, PTREGS_OFF, %o0
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
.size do_lddfmna,.-do_lddfmna
.type do_stdfmna,#function
@@ -84,8 +81,7 @@ do_stdfmna:
mov %l5, %o2
call handle_stdfmna
add %sp, PTREGS_OFF, %o0
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
.size do_stdfmna,.-do_stdfmna
.type breakpoint_trap,#function
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index badf0951d73c..9f9614df9e1e 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -994,6 +994,23 @@ void pcibios_set_master(struct pci_dev *dev)
/* No special bus mastering setup handling */
}
+#ifdef CONFIG_PCI_IOV
+int pcibios_add_device(struct pci_dev *dev)
+{
+ struct pci_dev *pdev;
+
+ /* Add sriov arch specific initialization here.
+ * Copy dev_archdata from PF to VF
+ */
+ if (dev->is_virtfn) {
+ pdev = dev->physfn;
+ memcpy(&dev->dev.archdata, &pdev->dev.archdata,
+ sizeof(struct dev_archdata));
+ }
+ return 0;
+}
+#endif /* CONFIG_PCI_IOV */
+
static int __init pcibios_init(void)
{
pci_dfl_cache_line_size = 64 >> 2;
diff --git a/arch/sparc/kernel/rtrap_64.S b/arch/sparc/kernel/rtrap_64.S
index d08bdaffdbfc..216948ca4382 100644
--- a/arch/sparc/kernel/rtrap_64.S
+++ b/arch/sparc/kernel/rtrap_64.S
@@ -14,10 +14,6 @@
#include <asm/visasm.h>
#include <asm/processor.h>
-#define RTRAP_PSTATE (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_IE)
-#define RTRAP_PSTATE_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV)
-#define RTRAP_PSTATE_AG_IRQOFF (PSTATE_TSO|PSTATE_PEF|PSTATE_PRIV|PSTATE_AG)
-
#ifdef CONFIG_CONTEXT_TRACKING
# define SCHEDULE_USER schedule_user
#else
@@ -242,52 +238,17 @@ rt_continue: ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
wrpr %g1, %cwp
ba,a,pt %xcc, user_rtt_fill_64bit
-user_rtt_fill_fixup:
- rdpr %cwp, %g1
- add %g1, 1, %g1
- wrpr %g1, 0x0, %cwp
-
- rdpr %wstate, %g2
- sll %g2, 3, %g2
- wrpr %g2, 0x0, %wstate
-
- /* We know %canrestore and %otherwin are both zero. */
-
- sethi %hi(sparc64_kern_pri_context), %g2
- ldx [%g2 + %lo(sparc64_kern_pri_context)], %g2
- mov PRIMARY_CONTEXT, %g1
-
-661: stxa %g2, [%g1] ASI_DMMU
- .section .sun4v_1insn_patch, "ax"
- .word 661b
- stxa %g2, [%g1] ASI_MMU
- .previous
-
- sethi %hi(KERNBASE), %g1
- flush %g1
+user_rtt_fill_fixup_dax:
+ ba,pt %xcc, user_rtt_fill_fixup_common
+ mov 1, %g3
- or %g4, FAULT_CODE_WINFIXUP, %g4
- stb %g4, [%g6 + TI_FAULT_CODE]
- stx %g5, [%g6 + TI_FAULT_ADDR]
+user_rtt_fill_fixup_mna:
+ ba,pt %xcc, user_rtt_fill_fixup_common
+ mov 2, %g3
- mov %g6, %l1
- wrpr %g0, 0x0, %tl
-
-661: nop
- .section .sun4v_1insn_patch, "ax"
- .word 661b
- SET_GL(0)
- .previous
-
- wrpr %g0, RTRAP_PSTATE, %pstate
-
- mov %l1, %g6
- ldx [%g6 + TI_TASK], %g4
- LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3)
- call do_sparc64_fault
- add %sp, PTREGS_OFF, %o0
- ba,pt %xcc, rtrap
- nop
+user_rtt_fill_fixup:
+ ba,pt %xcc, user_rtt_fill_fixup_common
+ clr %g3
user_rtt_pre_restore:
add %g1, 1, %g1
diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c
index 4eed773a7735..77655f0f0fc7 100644
--- a/arch/sparc/kernel/signal32.c
+++ b/arch/sparc/kernel/signal32.c
@@ -138,12 +138,24 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
return 0;
}
+/* Checks if the fp is valid. We always build signal frames which are
+ * 16-byte aligned, therefore we can always enforce that the restore
+ * frame has that property as well.
+ */
+static bool invalid_frame_pointer(void __user *fp, int fplen)
+{
+ if ((((unsigned long) fp) & 15) ||
+ ((unsigned long)fp) > 0x100000000ULL - fplen)
+ return true;
+ return false;
+}
+
void do_sigreturn32(struct pt_regs *regs)
{
struct signal_frame32 __user *sf;
compat_uptr_t fpu_save;
compat_uptr_t rwin_save;
- unsigned int psr;
+ unsigned int psr, ufp;
unsigned pc, npc;
sigset_t set;
compat_sigset_t seta;
@@ -158,11 +170,16 @@ void do_sigreturn32(struct pt_regs *regs)
sf = (struct signal_frame32 __user *) regs->u_regs[UREG_FP];
/* 1. Make sure we are not getting garbage from the user */
- if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
- (((unsigned long) sf) & 3))
+ if (invalid_frame_pointer(sf, sizeof(*sf)))
+ goto segv;
+
+ if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
+ goto segv;
+
+ if (ufp & 0x7)
goto segv;
- if (get_user(pc, &sf->info.si_regs.pc) ||
+ if (__get_user(pc, &sf->info.si_regs.pc) ||
__get_user(npc, &sf->info.si_regs.npc))
goto segv;
@@ -227,7 +244,7 @@ segv:
asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
{
struct rt_signal_frame32 __user *sf;
- unsigned int psr, pc, npc;
+ unsigned int psr, pc, npc, ufp;
compat_uptr_t fpu_save;
compat_uptr_t rwin_save;
sigset_t set;
@@ -242,11 +259,16 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
sf = (struct rt_signal_frame32 __user *) regs->u_regs[UREG_FP];
/* 1. Make sure we are not getting garbage from the user */
- if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
- (((unsigned long) sf) & 3))
+ if (invalid_frame_pointer(sf, sizeof(*sf)))
goto segv;
- if (get_user(pc, &sf->regs.pc) ||
+ if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
+ goto segv;
+
+ if (ufp & 0x7)
+ goto segv;
+
+ if (__get_user(pc, &sf->regs.pc) ||
__get_user(npc, &sf->regs.npc))
goto segv;
@@ -307,14 +329,6 @@ segv:
force_sig(SIGSEGV, current);
}
-/* Checks if the fp is valid */
-static int invalid_frame_pointer(void __user *fp, int fplen)
-{
- if ((((unsigned long) fp) & 7) || ((unsigned long)fp) > 0x100000000ULL - fplen)
- return 1;
- return 0;
-}
-
static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
{
unsigned long sp;
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index 52aa5e4ce5e7..c3c12efe0bc0 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -60,10 +60,22 @@ struct rt_signal_frame {
#define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7)))
#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7)))
+/* Checks if the fp is valid. We always build signal frames which are
+ * 16-byte aligned, therefore we can always enforce that the restore
+ * frame has that property as well.
+ */
+static inline bool invalid_frame_pointer(void __user *fp, int fplen)
+{
+ if ((((unsigned long) fp) & 15) || !__access_ok((unsigned long)fp, fplen))
+ return true;
+
+ return false;
+}
+
asmlinkage void do_sigreturn(struct pt_regs *regs)
{
+ unsigned long up_psr, pc, npc, ufp;
struct signal_frame __user *sf;
- unsigned long up_psr, pc, npc;
sigset_t set;
__siginfo_fpu_t __user *fpu_save;
__siginfo_rwin_t __user *rwin_save;
@@ -77,10 +89,13 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
sf = (struct signal_frame __user *) regs->u_regs[UREG_FP];
/* 1. Make sure we are not getting garbage from the user */
- if (!access_ok(VERIFY_READ, sf, sizeof(*sf)))
+ if (!invalid_frame_pointer(sf, sizeof(*sf)))
+ goto segv_and_exit;
+
+ if (get_user(ufp, &sf->info.si_regs.u_regs[UREG_FP]))
goto segv_and_exit;
- if (((unsigned long) sf) & 3)
+ if (ufp & 0x7)
goto segv_and_exit;
err = __get_user(pc, &sf->info.si_regs.pc);
@@ -127,7 +142,7 @@ segv_and_exit:
asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
{
struct rt_signal_frame __user *sf;
- unsigned int psr, pc, npc;
+ unsigned int psr, pc, npc, ufp;
__siginfo_fpu_t __user *fpu_save;
__siginfo_rwin_t __user *rwin_save;
sigset_t set;
@@ -135,8 +150,13 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
synchronize_user_stack();
sf = (struct rt_signal_frame __user *) regs->u_regs[UREG_FP];
- if (!access_ok(VERIFY_READ, sf, sizeof(*sf)) ||
- (((unsigned long) sf) & 0x03))
+ if (!invalid_frame_pointer(sf, sizeof(*sf)))
+ goto segv;
+
+ if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
+ goto segv;
+
+ if (ufp & 0x7)
goto segv;
err = __get_user(pc, &sf->regs.pc);
@@ -178,15 +198,6 @@ segv:
force_sig(SIGSEGV, current);
}
-/* Checks if the fp is valid */
-static inline int invalid_frame_pointer(void __user *fp, int fplen)
-{
- if ((((unsigned long) fp) & 7) || !__access_ok((unsigned long)fp, fplen))
- return 1;
-
- return 0;
-}
-
static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
{
unsigned long sp = regs->u_regs[UREG_FP];
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index d88beff47bab..5ee930c48f4c 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -52,7 +52,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
unsigned char fenab;
int err;
- flush_user_windows();
+ synchronize_user_stack();
if (get_thread_wsaved() ||
(((unsigned long)ucp) & (sizeof(unsigned long)-1)) ||
(!__access_ok(ucp, sizeof(*ucp))))
@@ -234,6 +234,17 @@ do_sigsegv:
goto out;
}
+/* Checks if the fp is valid. We always build rt signal frames which
+ * are 16-byte aligned, therefore we can always enforce that the
+ * restore frame has that property as well.
+ */
+static bool invalid_frame_pointer(void __user *fp)
+{
+ if (((unsigned long) fp) & 15)
+ return true;
+ return false;
+}
+
struct rt_signal_frame {
struct sparc_stackf ss;
siginfo_t info;
@@ -246,8 +257,8 @@ struct rt_signal_frame {
void do_rt_sigreturn(struct pt_regs *regs)
{
+ unsigned long tpc, tnpc, tstate, ufp;
struct rt_signal_frame __user *sf;
- unsigned long tpc, tnpc, tstate;
__siginfo_fpu_t __user *fpu_save;
__siginfo_rwin_t __user *rwin_save;
sigset_t set;
@@ -261,10 +272,16 @@ void do_rt_sigreturn(struct pt_regs *regs)
(regs->u_regs [UREG_FP] + STACK_BIAS);
/* 1. Make sure we are not getting garbage from the user */
- if (((unsigned long) sf) & 3)
+ if (invalid_frame_pointer(sf))
+ goto segv;
+
+ if (get_user(ufp, &sf->regs.u_regs[UREG_FP]))
goto segv;
- err = get_user(tpc, &sf->regs.tpc);
+ if ((ufp + STACK_BIAS) & 0x7)
+ goto segv;
+
+ err = __get_user(tpc, &sf->regs.tpc);
err |= __get_user(tnpc, &sf->regs.tnpc);
if (test_thread_flag(TIF_32BIT)) {
tpc &= 0xffffffff;
@@ -308,14 +325,6 @@ segv:
force_sig(SIGSEGV, current);
}
-/* Checks if the fp is valid */
-static int invalid_frame_pointer(void __user *fp)
-{
- if (((unsigned long) fp) & 15)
- return 1;
- return 0;
-}
-
static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
{
unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS;
diff --git a/arch/sparc/kernel/sigutil_32.c b/arch/sparc/kernel/sigutil_32.c
index 0f6eebe71e6c..e5fe8cef9a69 100644
--- a/arch/sparc/kernel/sigutil_32.c
+++ b/arch/sparc/kernel/sigutil_32.c
@@ -48,6 +48,10 @@ int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
{
int err;
+
+ if (((unsigned long) fpu) & 3)
+ return -EFAULT;
+
#ifdef CONFIG_SMP
if (test_tsk_thread_flag(current, TIF_USEDFPU))
regs->psr &= ~PSR_EF;
@@ -97,7 +101,10 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp)
struct thread_info *t = current_thread_info();
int i, wsaved, err;
- __get_user(wsaved, &rp->wsaved);
+ if (((unsigned long) rp) & 3)
+ return -EFAULT;
+
+ get_user(wsaved, &rp->wsaved);
if (wsaved > NSWINS)
return -EFAULT;
diff --git a/arch/sparc/kernel/sigutil_64.c b/arch/sparc/kernel/sigutil_64.c
index 387834a9c56a..36aadcbeac69 100644
--- a/arch/sparc/kernel/sigutil_64.c
+++ b/arch/sparc/kernel/sigutil_64.c
@@ -37,7 +37,10 @@ int restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
unsigned long fprs;
int err;
- err = __get_user(fprs, &fpu->si_fprs);
+ if (((unsigned long) fpu) & 7)
+ return -EFAULT;
+
+ err = get_user(fprs, &fpu->si_fprs);
fprs_write(0);
regs->tstate &= ~TSTATE_PEF;
if (fprs & FPRS_DL)
@@ -72,7 +75,10 @@ int restore_rwin_state(__siginfo_rwin_t __user *rp)
struct thread_info *t = current_thread_info();
int i, wsaved, err;
- __get_user(wsaved, &rp->wsaved);
+ if (((unsigned long) rp) & 7)
+ return -EFAULT;
+
+ get_user(wsaved, &rp->wsaved);
if (wsaved > NSWINS)
return -EFAULT;
diff --git a/arch/sparc/kernel/spiterrs.S b/arch/sparc/kernel/spiterrs.S
index c357e40ffd01..4a73009f66a5 100644
--- a/arch/sparc/kernel/spiterrs.S
+++ b/arch/sparc/kernel/spiterrs.S
@@ -85,8 +85,7 @@ __spitfire_cee_trap_continue:
ba,pt %xcc, etraptl1
rd %pc, %g7
- ba,pt %xcc, 2f
- nop
+ ba,a,pt %xcc, 2f
1: ba,pt %xcc, etrap_irq
rd %pc, %g7
@@ -100,8 +99,7 @@ __spitfire_cee_trap_continue:
mov %l5, %o2
call spitfire_access_error
add %sp, PTREGS_OFF, %o0
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
.size __spitfire_access_error,.-__spitfire_access_error
/* This is the trap handler entry point for ECC correctable
@@ -179,8 +177,7 @@ __spitfire_data_access_exception_tl1:
mov %l5, %o2
call spitfire_data_access_exception_tl1
add %sp, PTREGS_OFF, %o0
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
.size __spitfire_data_access_exception_tl1,.-__spitfire_data_access_exception_tl1
.type __spitfire_data_access_exception,#function
@@ -200,8 +197,7 @@ __spitfire_data_access_exception:
mov %l5, %o2
call spitfire_data_access_exception
add %sp, PTREGS_OFF, %o0
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
.size __spitfire_data_access_exception,.-__spitfire_data_access_exception
.type __spitfire_insn_access_exception_tl1,#function
@@ -220,8 +216,7 @@ __spitfire_insn_access_exception_tl1:
mov %l5, %o2
call spitfire_insn_access_exception_tl1
add %sp, PTREGS_OFF, %o0
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
.size __spitfire_insn_access_exception_tl1,.-__spitfire_insn_access_exception_tl1
.type __spitfire_insn_access_exception,#function
@@ -240,6 +235,5 @@ __spitfire_insn_access_exception:
mov %l5, %o2
call spitfire_insn_access_exception
add %sp, PTREGS_OFF, %o0
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
.size __spitfire_insn_access_exception,.-__spitfire_insn_access_exception
diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S
index bb0008927598..c4a1b5c40e4e 100644
--- a/arch/sparc/kernel/syscalls.S
+++ b/arch/sparc/kernel/syscalls.S
@@ -158,7 +158,25 @@ linux_syscall_trace32:
add %sp, PTREGS_OFF, %o0
brnz,pn %o0, 3f
mov -ENOSYS, %o0
+
+ /* Syscall tracing can modify the registers. */
+ ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
+ sethi %hi(sys_call_table32), %l7
+ ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0
+ or %l7, %lo(sys_call_table32), %l7
+ ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1
+ ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2
+ ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3
+ ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4
+ ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5
+
+ cmp %g1, NR_syscalls
+ bgeu,pn %xcc, 3f
+ mov -ENOSYS, %o0
+
+ sll %g1, 2, %l4
srl %i0, 0, %o0
+ lduw [%l7 + %l4], %l7
srl %i4, 0, %o4
srl %i1, 0, %o1
srl %i2, 0, %o2
@@ -170,7 +188,25 @@ linux_syscall_trace:
add %sp, PTREGS_OFF, %o0
brnz,pn %o0, 3f
mov -ENOSYS, %o0
+
+ /* Syscall tracing can modify the registers. */
+ ldx [%sp + PTREGS_OFF + PT_V9_G1], %g1
+ sethi %hi(sys_call_table64), %l7
+ ldx [%sp + PTREGS_OFF + PT_V9_I0], %i0
+ or %l7, %lo(sys_call_table64), %l7
+ ldx [%sp + PTREGS_OFF + PT_V9_I1], %i1
+ ldx [%sp + PTREGS_OFF + PT_V9_I2], %i2
+ ldx [%sp + PTREGS_OFF + PT_V9_I3], %i3
+ ldx [%sp + PTREGS_OFF + PT_V9_I4], %i4
+ ldx [%sp + PTREGS_OFF + PT_V9_I5], %i5
+
+ cmp %g1, NR_syscalls
+ bgeu,pn %xcc, 3f
+ mov -ENOSYS, %o0
+
+ sll %g1, 2, %l4
mov %i0, %o0
+ lduw [%l7 + %l4], %l7
mov %i1, %o1
mov %i2, %o2
mov %i3, %o3
diff --git a/arch/sparc/kernel/urtt_fill.S b/arch/sparc/kernel/urtt_fill.S
new file mode 100644
index 000000000000..5604a2b051d4
--- /dev/null
+++ b/arch/sparc/kernel/urtt_fill.S
@@ -0,0 +1,98 @@
+#include <asm/thread_info.h>
+#include <asm/trap_block.h>
+#include <asm/spitfire.h>
+#include <asm/ptrace.h>
+#include <asm/head.h>
+
+ .text
+ .align 8
+ .globl user_rtt_fill_fixup_common
+user_rtt_fill_fixup_common:
+ rdpr %cwp, %g1
+ add %g1, 1, %g1
+ wrpr %g1, 0x0, %cwp
+
+ rdpr %wstate, %g2
+ sll %g2, 3, %g2
+ wrpr %g2, 0x0, %wstate
+
+ /* We know %canrestore and %otherwin are both zero. */
+
+ sethi %hi(sparc64_kern_pri_context), %g2
+ ldx [%g2 + %lo(sparc64_kern_pri_context)], %g2
+ mov PRIMARY_CONTEXT, %g1
+
+661: stxa %g2, [%g1] ASI_DMMU
+ .section .sun4v_1insn_patch, "ax"
+ .word 661b
+ stxa %g2, [%g1] ASI_MMU
+ .previous
+
+ sethi %hi(KERNBASE), %g1
+ flush %g1
+
+ mov %g4, %l4
+ mov %g5, %l5
+ brnz,pn %g3, 1f
+ mov %g3, %l3
+
+ or %g4, FAULT_CODE_WINFIXUP, %g4
+ stb %g4, [%g6 + TI_FAULT_CODE]
+ stx %g5, [%g6 + TI_FAULT_ADDR]
+1:
+ mov %g6, %l1
+ wrpr %g0, 0x0, %tl
+
+661: nop
+ .section .sun4v_1insn_patch, "ax"
+ .word 661b
+ SET_GL(0)
+ .previous
+
+ wrpr %g0, RTRAP_PSTATE, %pstate
+
+ mov %l1, %g6
+ ldx [%g6 + TI_TASK], %g4
+ LOAD_PER_CPU_BASE(%g5, %g6, %g1, %g2, %g3)
+
+ brnz,pn %l3, 1f
+ nop
+
+ call do_sparc64_fault
+ add %sp, PTREGS_OFF, %o0
+ ba,pt %xcc, rtrap
+ nop
+
+1: cmp %g3, 2
+ bne,pn %xcc, 2f
+ nop
+
+ sethi %hi(tlb_type), %g1
+ lduw [%g1 + %lo(tlb_type)], %g1
+ cmp %g1, 3
+ bne,pt %icc, 1f
+ add %sp, PTREGS_OFF, %o0
+ mov %l4, %o2
+ call sun4v_do_mna
+ mov %l5, %o1
+ ba,a,pt %xcc, rtrap
+1: mov %l4, %o1
+ mov %l5, %o2
+ call mem_address_unaligned
+ nop
+ ba,a,pt %xcc, rtrap
+
+2: sethi %hi(tlb_type), %g1
+ mov %l4, %o1
+ lduw [%g1 + %lo(tlb_type)], %g1
+ mov %l5, %o2
+ cmp %g1, 3
+ bne,pt %icc, 1f
+ add %sp, PTREGS_OFF, %o0
+ call sun4v_data_access_exception
+ nop
+ ba,a,pt %xcc, rtrap
+
+1: call spitfire_data_access_exception
+ nop
+ ba,a,pt %xcc, rtrap
diff --git a/arch/sparc/kernel/utrap.S b/arch/sparc/kernel/utrap.S
index b7f0f3f3a909..c731e8023d3e 100644
--- a/arch/sparc/kernel/utrap.S
+++ b/arch/sparc/kernel/utrap.S
@@ -11,8 +11,7 @@ utrap_trap: /* %g3=handler,%g4=level */
mov %l4, %o1
call bad_trap
add %sp, PTREGS_OFF, %o0
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
invoke_utrap:
sllx %g3, 3, %g3
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index f1a2f688b28a..4a41d412dd3d 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -33,6 +33,10 @@ ENTRY(_start)
jiffies = jiffies_64;
#endif
+#ifdef CONFIG_SPARC64
+ASSERT((swapper_tsb == 0x0000000000408000), "Error: sparc64 early assembler too large")
+#endif
+
SECTIONS
{
#ifdef CONFIG_SPARC64
diff --git a/arch/sparc/kernel/winfixup.S b/arch/sparc/kernel/winfixup.S
index 1e67ce958369..855019a8590e 100644
--- a/arch/sparc/kernel/winfixup.S
+++ b/arch/sparc/kernel/winfixup.S
@@ -32,8 +32,7 @@ fill_fixup:
rd %pc, %g7
call do_sparc64_fault
add %sp, PTREGS_OFF, %o0
- ba,pt %xcc, rtrap
- nop
+ ba,a,pt %xcc, rtrap
/* Be very careful about usage of the trap globals here.
* You cannot touch %g5 as that has the fault information.
diff --git a/arch/sparc/mm/hugetlbpage.c b/arch/sparc/mm/hugetlbpage.c
index 131eaf4ad7f5..364d093f46c6 100644
--- a/arch/sparc/mm/hugetlbpage.c
+++ b/arch/sparc/mm/hugetlbpage.c
@@ -176,17 +176,31 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t entry)
{
int i;
+ pte_t orig[2];
+ unsigned long nptes;
if (!pte_present(*ptep) && pte_present(entry))
mm->context.huge_pte_count++;
addr &= HPAGE_MASK;
- for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- set_pte_at(mm, addr, ptep, entry);
+
+ nptes = 1 << HUGETLB_PAGE_ORDER;
+ orig[0] = *ptep;
+ orig[1] = *(ptep + nptes / 2);
+ for (i = 0; i < nptes; i++) {
+ *ptep = entry;
ptep++;
addr += PAGE_SIZE;
pte_val(entry) += PAGE_SIZE;
}
+
+ /* Issue TLB flush at REAL_HPAGE_SIZE boundaries */
+ addr -= REAL_HPAGE_SIZE;
+ ptep -= nptes / 2;
+ maybe_tlb_batch_add(mm, addr, ptep, orig[1], 0);
+ addr -= REAL_HPAGE_SIZE;
+ ptep -= nptes / 2;
+ maybe_tlb_batch_add(mm, addr, ptep, orig[0], 0);
}
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
@@ -194,19 +208,28 @@ pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
{
pte_t entry;
int i;
+ unsigned long nptes;
entry = *ptep;
if (pte_present(entry))
mm->context.huge_pte_count--;
addr &= HPAGE_MASK;
-
- for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- pte_clear(mm, addr, ptep);
+ nptes = 1 << HUGETLB_PAGE_ORDER;
+ for (i = 0; i < nptes; i++) {
+ *ptep = __pte(0UL);
addr += PAGE_SIZE;
ptep++;
}
+ /* Issue TLB flush at REAL_HPAGE_SIZE boundaries */
+ addr -= REAL_HPAGE_SIZE;
+ ptep -= nptes / 2;
+ maybe_tlb_batch_add(mm, addr, ptep, entry, 0);
+ addr -= REAL_HPAGE_SIZE;
+ ptep -= nptes / 2;
+ maybe_tlb_batch_add(mm, addr, ptep, entry, 0);
+
return entry;
}
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 3025bd57f7ab..3c4b8975fa76 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -324,18 +324,6 @@ static void __update_mmu_tsb_insert(struct mm_struct *mm, unsigned long tsb_inde
tsb_insert(tsb, tag, tte);
}
-#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
-static inline bool is_hugetlb_pte(pte_t pte)
-{
- if ((tlb_type == hypervisor &&
- (pte_val(pte) & _PAGE_SZALL_4V) == _PAGE_SZHUGE_4V) ||
- (tlb_type != hypervisor &&
- (pte_val(pte) & _PAGE_SZALL_4U) == _PAGE_SZHUGE_4U))
- return true;
- return false;
-}
-#endif
-
void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
{
struct mm_struct *mm;
@@ -1267,13 +1255,6 @@ static int __init numa_parse_mdesc(void)
int i, j, err, count;
u64 node;
- /* Some sane defaults for numa latency values */
- for (i = 0; i < MAX_NUMNODES; i++) {
- for (j = 0; j < MAX_NUMNODES; j++)
- numa_latency[i][j] = (i == j) ?
- LOCAL_DISTANCE : REMOTE_DISTANCE;
- }
-
node = mdesc_node_by_name(md, MDESC_NODE_NULL, "latency-groups");
if (node == MDESC_NODE_NULL) {
mdesc_release(md);
@@ -1369,10 +1350,18 @@ static int __init numa_parse_sun4u(void)
static int __init bootmem_init_numa(void)
{
+ int i, j;
int err = -1;
numadbg("bootmem_init_numa()\n");
+ /* Some sane defaults for numa latency values */
+ for (i = 0; i < MAX_NUMNODES; i++) {
+ for (j = 0; j < MAX_NUMNODES; j++)
+ numa_latency[i][j] = (i == j) ?
+ LOCAL_DISTANCE : REMOTE_DISTANCE;
+ }
+
if (numa_enabled) {
if (tlb_type == hypervisor)
err = numa_parse_mdesc();
@@ -2832,9 +2821,10 @@ void hugetlb_setup(struct pt_regs *regs)
* the Data-TLB for huge pages.
*/
if (tlb_type == cheetah_plus) {
+ bool need_context_reload = false;
unsigned long ctx;
- spin_lock(&ctx_alloc_lock);
+ spin_lock_irq(&ctx_alloc_lock);
ctx = mm->context.sparc64_ctx_val;
ctx &= ~CTX_PGSZ_MASK;
ctx |= CTX_PGSZ_BASE << CTX_PGSZ0_SHIFT;
@@ -2853,9 +2843,12 @@ void hugetlb_setup(struct pt_regs *regs)
* also executing in this address space.
*/
mm->context.sparc64_ctx_val = ctx;
- on_each_cpu(context_reload, mm, 0);
+ need_context_reload = true;
}
- spin_unlock(&ctx_alloc_lock);
+ spin_unlock_irq(&ctx_alloc_lock);
+
+ if (need_context_reload)
+ on_each_cpu(context_reload, mm, 0);
}
}
#endif
diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c
index 9df2190c097e..f81cd9736700 100644
--- a/arch/sparc/mm/tlb.c
+++ b/arch/sparc/mm/tlb.c
@@ -67,7 +67,7 @@ void arch_leave_lazy_mmu_mode(void)
}
static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,
- bool exec)
+ bool exec, bool huge)
{
struct tlb_batch *tb = &get_cpu_var(tlb_batch);
unsigned long nr;
@@ -84,13 +84,21 @@ static void tlb_batch_add_one(struct mm_struct *mm, unsigned long vaddr,
}
if (!tb->active) {
- flush_tsb_user_page(mm, vaddr);
+ flush_tsb_user_page(mm, vaddr, huge);
global_flush_tlb_page(mm, vaddr);
goto out;
}
- if (nr == 0)
+ if (nr == 0) {
tb->mm = mm;
+ tb->huge = huge;
+ }
+
+ if (tb->huge != huge) {
+ flush_tlb_pending();
+ tb->huge = huge;
+ nr = 0;
+ }
tb->vaddrs[nr] = vaddr;
tb->tlb_nr = ++nr;
@@ -104,6 +112,8 @@ out:
void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
pte_t *ptep, pte_t orig, int fullmm)
{
+ bool huge = is_hugetlb_pte(orig);
+
if (tlb_type != hypervisor &&
pte_dirty(orig)) {
unsigned long paddr, pfn = pte_pfn(orig);
@@ -129,7 +139,7 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr,
no_cache_flush:
if (!fullmm)
- tlb_batch_add_one(mm, vaddr, pte_exec(orig));
+ tlb_batch_add_one(mm, vaddr, pte_exec(orig), huge);
}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -145,7 +155,7 @@ static void tlb_batch_pmd_scan(struct mm_struct *mm, unsigned long vaddr,
if (pte_val(*pte) & _PAGE_VALID) {
bool exec = pte_exec(*pte);
- tlb_batch_add_one(mm, vaddr, exec);
+ tlb_batch_add_one(mm, vaddr, exec, false);
}
pte++;
vaddr += PAGE_SIZE;
@@ -185,8 +195,9 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr,
pte_t orig_pte = __pte(pmd_val(orig));
bool exec = pte_exec(orig_pte);
- tlb_batch_add_one(mm, addr, exec);
- tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec);
+ tlb_batch_add_one(mm, addr, exec, true);
+ tlb_batch_add_one(mm, addr + REAL_HPAGE_SIZE, exec,
+ true);
} else {
tlb_batch_pmd_scan(mm, addr, orig);
}
diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c
index a06576683c38..a0604a493a36 100644
--- a/arch/sparc/mm/tsb.c
+++ b/arch/sparc/mm/tsb.c
@@ -76,14 +76,15 @@ void flush_tsb_user(struct tlb_batch *tb)
spin_lock_irqsave(&mm->context.lock, flags);
- base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
- nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
- if (tlb_type == cheetah_plus || tlb_type == hypervisor)
- base = __pa(base);
- __flush_tsb_one(tb, PAGE_SHIFT, base, nentries);
-
+ if (!tb->huge) {
+ base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
+ nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
+ if (tlb_type == cheetah_plus || tlb_type == hypervisor)
+ base = __pa(base);
+ __flush_tsb_one(tb, PAGE_SHIFT, base, nentries);
+ }
#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
- if (mm->context.tsb_block[MM_TSB_HUGE].tsb) {
+ if (tb->huge && mm->context.tsb_block[MM_TSB_HUGE].tsb) {
base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb;
nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries;
if (tlb_type == cheetah_plus || tlb_type == hypervisor)
@@ -94,20 +95,21 @@ void flush_tsb_user(struct tlb_batch *tb)
spin_unlock_irqrestore(&mm->context.lock, flags);
}
-void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr)
+void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr, bool huge)
{
unsigned long nentries, base, flags;
spin_lock_irqsave(&mm->context.lock, flags);
- base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
- nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
- if (tlb_type == cheetah_plus || tlb_type == hypervisor)
- base = __pa(base);
- __flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries);
-
+ if (!huge) {
+ base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb;
+ nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries;
+ if (tlb_type == cheetah_plus || tlb_type == hypervisor)
+ base = __pa(base);
+ __flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries);
+ }
#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE)
- if (mm->context.tsb_block[MM_TSB_HUGE].tsb) {
+ if (huge && mm->context.tsb_block[MM_TSB_HUGE].tsb) {
base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb;
nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries;
if (tlb_type == cheetah_plus || tlb_type == hypervisor)
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index bbe1a62efc02..4a3a140f26bf 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -163,6 +163,9 @@ isoimage: $(obj)/bzImage
for i in lib lib64 share end ; do \
if [ -f /usr/$$i/syslinux/isolinux.bin ] ; then \
cp /usr/$$i/syslinux/isolinux.bin $(obj)/isoimage ; \
+ if [ -f /usr/$$i/syslinux/ldlinux.c32 ]; then \
+ cp /usr/$$i/syslinux/ldlinux.c32 $(obj)/isoimage ; \
+ fi ; \
break ; \
fi ; \
if [ $$i = end ] ; then exit 1 ; fi ; \
diff --git a/arch/x86/kernel/amd_nb.c b/arch/x86/kernel/amd_nb.c
index 29fa475ec518..c986d0b3bc35 100644
--- a/arch/x86/kernel/amd_nb.c
+++ b/arch/x86/kernel/amd_nb.c
@@ -71,8 +71,8 @@ int amd_cache_northbridges(void)
while ((misc = next_northbridge(misc, amd_nb_misc_ids)) != NULL)
i++;
- if (i == 0)
- return 0;
+ if (!i)
+ return -ENODEV;
nb = kzalloc(i * sizeof(struct amd_northbridge), GFP_KERNEL);
if (!nb)
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 078de2e86b7a..5f82cd59f0e5 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -3601,7 +3601,7 @@ __init int intel_pmu_init(void)
c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1;
}
c->idxmsk64 &=
- ~(~0UL << (INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed));
+ ~(~0ULL << (INTEL_PMC_IDX_FIXED + x86_pmu.num_counters_fixed));
c->weight = hweight64(c->idxmsk64);
}
}
diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c b/arch/x86/kernel/cpu/perf_event_intel_pt.c
index 868e1194337f..49e35d003b74 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_pt.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_pt.c
@@ -694,6 +694,7 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
/* clear STOP and INT from current entry */
buf->topa_index[buf->stop_pos]->stop = 0;
+ buf->topa_index[buf->stop_pos]->intr = 0;
buf->topa_index[buf->intr_pos]->intr = 0;
/* how many pages till the STOP marker */
@@ -718,6 +719,7 @@ static int pt_buffer_reset_markers(struct pt_buffer *buf,
buf->intr_pos = idx;
buf->topa_index[buf->stop_pos]->stop = 1;
+ buf->topa_index[buf->stop_pos]->intr = 1;
buf->topa_index[buf->intr_pos]->intr = 1;
return 0;
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 1deffe6cc873..023c442c33bb 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -959,7 +959,19 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
* normal page fault.
*/
regs->ip = (unsigned long)cur->addr;
+ /*
+ * Trap flag (TF) has been set here because this fault
+ * happened where the single stepping will be done.
+ * So clear it by resetting the current kprobe:
+ */
+ regs->flags &= ~X86_EFLAGS_TF;
+
+ /*
+ * If the TF flag was set before the kprobe hit,
+ * don't touch it:
+ */
regs->flags |= kcb->kprobe_old_flags;
+
if (kcb->kprobe_status == KPROBE_REENTER)
restore_previous_kprobe(kcb);
else
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index ade185a46b1d..679302c312f8 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -109,6 +109,12 @@ static inline void preempt_conditional_cli(struct pt_regs *regs)
preempt_count_dec();
}
+/*
+ * In IST context, we explicitly disable preemption. This serves two
+ * purposes: it makes it much less likely that we would accidentally
+ * schedule in IST context and it will force a warning if we somehow
+ * manage to schedule by accident.
+ */
void ist_enter(struct pt_regs *regs)
{
if (user_mode(regs)) {
@@ -123,13 +129,7 @@ void ist_enter(struct pt_regs *regs)
rcu_nmi_enter();
}
- /*
- * We are atomic because we're on the IST stack; or we're on
- * x86_32, in which case we still shouldn't schedule; or we're
- * on x86_64 and entered from user mode, in which case we're
- * still atomic unless ist_begin_non_atomic is called.
- */
- preempt_count_add(HARDIRQ_OFFSET);
+ preempt_disable();
/* This code is a bit fragile. Test it. */
RCU_LOCKDEP_WARN(!rcu_is_watching(), "ist_enter didn't work");
@@ -137,7 +137,7 @@ void ist_enter(struct pt_regs *regs)
void ist_exit(struct pt_regs *regs)
{
- preempt_count_sub(HARDIRQ_OFFSET);
+ preempt_enable_no_resched();
if (!user_mode(regs))
rcu_nmi_exit();
@@ -168,7 +168,7 @@ void ist_begin_non_atomic(struct pt_regs *regs)
BUG_ON((unsigned long)(current_top_of_stack() -
current_stack_pointer()) >= THREAD_SIZE);
- preempt_count_sub(HARDIRQ_OFFSET);
+ preempt_enable_no_resched();
}
/**
@@ -178,7 +178,7 @@ void ist_begin_non_atomic(struct pt_regs *regs)
*/
void ist_end_non_atomic(void)
{
- preempt_count_add(HARDIRQ_OFFSET);
+ preempt_disable();
}
static nokprobe_inline int
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 6525e926f566..2e1fd586b895 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -509,6 +509,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
do_cpuid_1_ent(&entry[i], function, idx);
if (idx == 1) {
entry[i].eax &= kvm_supported_word10_x86_features;
+ cpuid_mask(&entry[i].eax, 10);
entry[i].ebx = 0;
if (entry[i].eax & (F(XSAVES)|F(XSAVEC)))
entry[i].ebx =
diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c
index 3f8c732117ec..c146f3c262c3 100644
--- a/arch/x86/kvm/mtrr.c
+++ b/arch/x86/kvm/mtrr.c
@@ -44,8 +44,6 @@ static bool msr_mtrr_valid(unsigned msr)
case MSR_MTRRdefType:
case MSR_IA32_CR_PAT:
return true;
- case 0x2f8:
- return true;
}
return false;
}
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index f34ab71dfd57..41e7943004fe 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4954,8 +4954,8 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
vmcs_write16(VIRTUAL_PROCESSOR_ID, vmx->vpid);
cr0 = X86_CR0_NW | X86_CR0_CD | X86_CR0_ET;
- vmx_set_cr0(vcpu, cr0); /* enter rmode */
vmx->vcpu.arch.cr0 = cr0;
+ vmx_set_cr0(vcpu, cr0); /* enter rmode */
vmx_set_cr4(vcpu, 0);
vmx_set_efer(vcpu, 0);
vmx_fpu_activate(vcpu);
@@ -6579,7 +6579,13 @@ static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
/* Checks for #GP/#SS exceptions. */
exn = false;
- if (is_protmode(vcpu)) {
+ if (is_long_mode(vcpu)) {
+ /* Long mode: #GP(0)/#SS(0) if the memory address is in a
+ * non-canonical form. This is the only check on the memory
+ * destination for long mode!
+ */
+ exn = is_noncanonical_address(*ret);
+ } else if (is_protmode(vcpu)) {
/* Protected mode: apply checks for segment validity in the
* following order:
* - segment type check (#GP(0) may be thrown)
@@ -6596,17 +6602,10 @@ static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
* execute-only code segment
*/
exn = ((s.type & 0xa) == 8);
- }
- if (exn) {
- kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
- return 1;
- }
- if (is_long_mode(vcpu)) {
- /* Long mode: #GP(0)/#SS(0) if the memory address is in a
- * non-canonical form. This is an only check for long mode.
- */
- exn = is_noncanonical_address(*ret);
- } else if (is_protmode(vcpu)) {
+ if (exn) {
+ kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
+ return 1;
+ }
/* Protected mode: #GP(0)/#SS(0) if the segment is unusable.
*/
exn = (s.unusable != 0);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 605cea75eb0d..be222666b1c2 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3014,6 +3014,11 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
if (dbgregs->flags)
return -EINVAL;
+ if (dbgregs->dr6 & ~0xffffffffull)
+ return -EINVAL;
+ if (dbgregs->dr7 & ~0xffffffffull)
+ return -EINVAL;
+
memcpy(vcpu->arch.db, dbgregs->db, sizeof(vcpu->arch.db));
kvm_update_dr0123(vcpu);
vcpu->arch.dr6 = dbgregs->dr6;
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index ff31ab464213..c6d6efed392a 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -488,8 +488,11 @@ int __init pci_xen_initial_domain(void)
#endif
__acpi_register_gsi = acpi_register_gsi_xen;
__acpi_unregister_gsi = NULL;
- /* Pre-allocate legacy irqs */
- for (irq = 0; irq < nr_legacy_irqs(); irq++) {
+ /*
+ * Pre-allocate the legacy IRQs. Use NR_LEGACY_IRQS here
+ * because we don't have a PIC and thus nr_legacy_irqs() is zero.
+ */
+ for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
int trigger, polarity;
if (acpi_get_override_irq(irq, &trigger, &polarity) == -1)
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 7ab29518a3b9..e345891450c3 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -393,6 +393,9 @@ static unsigned long __init xen_set_identity_and_remap_chunk(
unsigned long i = 0;
unsigned long n = end_pfn - start_pfn;
+ if (remap_pfn == 0)
+ remap_pfn = nr_pages;
+
while (i < n) {
unsigned long cur_pfn = start_pfn + i;
unsigned long left = n - i;
@@ -438,17 +441,29 @@ static unsigned long __init xen_set_identity_and_remap_chunk(
return remap_pfn;
}
-static void __init xen_set_identity_and_remap(unsigned long nr_pages)
+static unsigned long __init xen_count_remap_pages(
+ unsigned long start_pfn, unsigned long end_pfn, unsigned long nr_pages,
+ unsigned long remap_pages)
+{
+ if (start_pfn >= nr_pages)
+ return remap_pages;
+
+ return remap_pages + min(end_pfn, nr_pages) - start_pfn;
+}
+
+static unsigned long __init xen_foreach_remap_area(unsigned long nr_pages,
+ unsigned long (*func)(unsigned long start_pfn, unsigned long end_pfn,
+ unsigned long nr_pages, unsigned long last_val))
{
phys_addr_t start = 0;
- unsigned long last_pfn = nr_pages;
+ unsigned long ret_val = 0;
const struct e820entry *entry = xen_e820_map;
int i;
/*
* Combine non-RAM regions and gaps until a RAM region (or the
- * end of the map) is reached, then set the 1:1 map and
- * remap the memory in those non-RAM regions.
+ * end of the map) is reached, then call the provided function
+ * to perform its duty on the non-RAM region.
*
* The combined non-RAM regions are rounded to a whole number
* of pages so any partial pages are accessible via the 1:1
@@ -466,14 +481,13 @@ static void __init xen_set_identity_and_remap(unsigned long nr_pages)
end_pfn = PFN_UP(entry->addr);
if (start_pfn < end_pfn)
- last_pfn = xen_set_identity_and_remap_chunk(
- start_pfn, end_pfn, nr_pages,
- last_pfn);
+ ret_val = func(start_pfn, end_pfn, nr_pages,
+ ret_val);
start = end;
}
}
- pr_info("Released %ld page(s)\n", xen_released_pages);
+ return ret_val;
}
/*
@@ -596,35 +610,6 @@ static void __init xen_ignore_unusable(void)
}
}
-static unsigned long __init xen_count_remap_pages(unsigned long max_pfn)
-{
- unsigned long extra = 0;
- unsigned long start_pfn, end_pfn;
- const struct e820entry *entry = xen_e820_map;
- int i;
-
- end_pfn = 0;
- for (i = 0; i < xen_e820_map_entries; i++, entry++) {
- start_pfn = PFN_DOWN(entry->addr);
- /* Adjacent regions on non-page boundaries handling! */
- end_pfn = min(end_pfn, start_pfn);
-
- if (start_pfn >= max_pfn)
- return extra + max_pfn - end_pfn;
-
- /* Add any holes in map to result. */
- extra += start_pfn - end_pfn;
-
- end_pfn = PFN_UP(entry->addr + entry->size);
- end_pfn = min(end_pfn, max_pfn);
-
- if (entry->type != E820_RAM)
- extra += end_pfn - start_pfn;
- }
-
- return extra;
-}
-
bool __init xen_is_e820_reserved(phys_addr_t start, phys_addr_t size)
{
struct e820entry *entry;
@@ -804,7 +789,7 @@ char * __init xen_memory_setup(void)
max_pages = xen_get_max_pages();
/* How many extra pages do we need due to remapping? */
- max_pages += xen_count_remap_pages(max_pfn);
+ max_pages += xen_foreach_remap_area(max_pfn, xen_count_remap_pages);
if (max_pages > max_pfn)
extra_pages += max_pages - max_pfn;
@@ -922,7 +907,9 @@ char * __init xen_memory_setup(void)
* Set identity map on non-RAM pages and prepare remapping the
* underlying RAM.
*/
- xen_set_identity_and_remap(max_pfn);
+ xen_foreach_remap_area(max_pfn, xen_set_identity_and_remap_chunk);
+
+ pr_info("Released %ld page(s)\n", xen_released_pages);
return "Xen";
}
diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 4870f28403f5..05bfe568cd30 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -14,6 +14,7 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
select MPILIB
select PUBLIC_KEY_ALGO_RSA
select CRYPTO_HASH_INFO
+ select CRYPTO_AKCIPHER
help
This option provides support for asymmetric public key type handling.
If signature generation and/or verification are to be used,
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index 43fe85f20d57..7097a3395b25 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -455,6 +455,7 @@ static const int crypto_msg_min[CRYPTO_NR_MSGTYPES] = {
[CRYPTO_MSG_NEWALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
[CRYPTO_MSG_DELALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
[CRYPTO_MSG_UPDATEALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+ [CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
[CRYPTO_MSG_DELRNG - CRYPTO_MSG_BASE] = 0,
};
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 32d684af0ec7..a000ecb995e6 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -135,7 +135,7 @@ static struct osi_linux {
unsigned int enable:1;
unsigned int dmi:1;
unsigned int cmdline:1;
- unsigned int default_disabling:1;
+ u8 default_disabling;
} osi_linux = {0, 0, 0, 0};
static u32 acpi_osi_handler(acpi_string interface, u32 supported)
@@ -1444,10 +1444,13 @@ void __init acpi_osi_setup(char *str)
if (*str == '!') {
str++;
if (*str == '\0') {
- osi_linux.default_disabling = 1;
+ /* Do not override acpi_osi=!* */
+ if (!osi_linux.default_disabling)
+ osi_linux.default_disabling =
+ ACPI_DISABLE_ALL_VENDOR_STRINGS;
return;
} else if (*str == '*') {
- acpi_update_interfaces(ACPI_DISABLE_ALL_STRINGS);
+ osi_linux.default_disabling = ACPI_DISABLE_ALL_STRINGS;
for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
osi = &osi_setup_entries[i];
osi->enable = false;
@@ -1520,10 +1523,13 @@ static void __init acpi_osi_setup_late(void)
acpi_status status;
if (osi_linux.default_disabling) {
- status = acpi_update_interfaces(ACPI_DISABLE_ALL_VENDOR_STRINGS);
+ status = acpi_update_interfaces(osi_linux.default_disabling);
if (ACPI_SUCCESS(status))
- printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors\n");
+ printk(KERN_INFO PREFIX "Disabled all _OSI OS vendors%s\n",
+ osi_linux.default_disabling ==
+ ACPI_DISABLE_ALL_STRINGS ?
+ " and feature groups" : "");
}
for (i = 0; i < OSI_STRING_ENTRIES_MAX; i++) {
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index f80cfc36a354..a3f458fd2238 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1074,7 +1074,7 @@ static int binder_dec_node(struct binder_node *node, int strong, int internal)
static struct binder_ref *binder_get_ref(struct binder_proc *proc,
- uint32_t desc)
+ uint32_t desc, bool need_strong_ref)
{
struct rb_node *n = proc->refs_by_desc.rb_node;
struct binder_ref *ref;
@@ -1082,12 +1082,16 @@ static struct binder_ref *binder_get_ref(struct binder_proc *proc,
while (n) {
ref = rb_entry(n, struct binder_ref, rb_node_desc);
- if (desc < ref->desc)
+ if (desc < ref->desc) {
n = n->rb_left;
- else if (desc > ref->desc)
+ } else if (desc > ref->desc) {
n = n->rb_right;
- else
+ } else if (need_strong_ref && !ref->strong) {
+ binder_user_error("tried to use weak ref as strong ref\n");
+ return NULL;
+ } else {
return ref;
+ }
}
return NULL;
}
@@ -1357,7 +1361,8 @@ static void binder_transaction_buffer_release(struct binder_proc *proc,
} break;
case BINDER_TYPE_HANDLE:
case BINDER_TYPE_WEAK_HANDLE: {
- struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+ struct binder_ref *ref = binder_get_ref(proc, fp->handle,
+ fp->type == BINDER_TYPE_HANDLE);
if (ref == NULL) {
pr_err("transaction release %d bad handle %d\n",
@@ -1452,7 +1457,7 @@ static void binder_transaction(struct binder_proc *proc,
if (tr->target.handle) {
struct binder_ref *ref;
- ref = binder_get_ref(proc, tr->target.handle);
+ ref = binder_get_ref(proc, tr->target.handle, true);
if (ref == NULL) {
binder_user_error("%d:%d got transaction to invalid handle\n",
proc->pid, thread->pid);
@@ -1649,7 +1654,9 @@ static void binder_transaction(struct binder_proc *proc,
fp->type = BINDER_TYPE_HANDLE;
else
fp->type = BINDER_TYPE_WEAK_HANDLE;
+ fp->binder = 0;
fp->handle = ref->desc;
+ fp->cookie = 0;
binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
&thread->todo);
@@ -1661,7 +1668,8 @@ static void binder_transaction(struct binder_proc *proc,
} break;
case BINDER_TYPE_HANDLE:
case BINDER_TYPE_WEAK_HANDLE: {
- struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+ struct binder_ref *ref = binder_get_ref(proc, fp->handle,
+ fp->type == BINDER_TYPE_HANDLE);
if (ref == NULL) {
binder_user_error("%d:%d got transaction with invalid handle, %d\n",
@@ -1696,7 +1704,9 @@ static void binder_transaction(struct binder_proc *proc,
return_error = BR_FAILED_REPLY;
goto err_binder_get_ref_for_node_failed;
}
+ fp->binder = 0;
fp->handle = new_ref->desc;
+ fp->cookie = 0;
binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
trace_binder_transaction_ref_to_ref(t, ref,
new_ref);
@@ -1750,6 +1760,7 @@ static void binder_transaction(struct binder_proc *proc,
binder_debug(BINDER_DEBUG_TRANSACTION,
" fd %d -> %d\n", fp->handle, target_fd);
/* TODO: fput? */
+ fp->binder = 0;
fp->handle = target_fd;
} break;
@@ -1880,7 +1891,9 @@ static int binder_thread_write(struct binder_proc *proc,
ref->desc);
}
} else
- ref = binder_get_ref(proc, target);
+ ref = binder_get_ref(proc, target,
+ cmd == BC_ACQUIRE ||
+ cmd == BC_RELEASE);
if (ref == NULL) {
binder_user_error("%d:%d refcount change on invalid ref %d\n",
proc->pid, thread->pid, target);
@@ -2076,7 +2089,7 @@ static int binder_thread_write(struct binder_proc *proc,
if (get_user_preempt_disabled(cookie, (binder_uintptr_t __user *)ptr))
return -EFAULT;
ptr += sizeof(binder_uintptr_t);
- ref = binder_get_ref(proc, target);
+ ref = binder_get_ref(proc, target, false);
if (ref == NULL) {
binder_user_error("%d:%d %s invalid ref %d\n",
proc->pid, thread->pid,
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 961acc788f44..91a9e6af2ec4 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -606,7 +606,7 @@ void ata_scsi_error(struct Scsi_Host *host)
ata_scsi_port_error_handler(host, ap);
/* finish or retry handled scmd's and clean up */
- WARN_ON(host->host_failed || !list_empty(&eh_work_q));
+ WARN_ON(!list_empty(&eh_work_q));
DPRINTK("EXIT\n");
}
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 918ce439534b..0dd6379ac215 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -228,6 +228,8 @@ static void driver_bound(struct device *dev)
klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
+ device_pm_check_callbacks(dev);
+
/*
* Make sure the device is no longer in one of the deferred lists and
* kick off retrying all pending devices
@@ -720,6 +722,7 @@ static void __device_release_driver(struct device *dev)
dev->pm_domain->dismiss(dev);
klist_remove(&dev->p->knode_driver);
+ device_pm_check_callbacks(dev);
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_UNBOUND_DRIVER,
diff --git a/drivers/base/module.c b/drivers/base/module.c
index db930d3ee312..2a215780eda2 100644
--- a/drivers/base/module.c
+++ b/drivers/base/module.c
@@ -24,10 +24,12 @@ static char *make_driver_name(struct device_driver *drv)
static void module_create_drivers_dir(struct module_kobject *mk)
{
- if (!mk || mk->drivers_dir)
- return;
+ static DEFINE_MUTEX(drivers_dir_mutex);
- mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj);
+ mutex_lock(&drivers_dir_mutex);
+ if (mk && !mk->drivers_dir)
+ mk->drivers_dir = kobject_create_and_add("drivers", &mk->kobj);
+ mutex_unlock(&drivers_dir_mutex);
}
void module_add_driver(struct module *mod, struct device_driver *drv)
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 6ed8b9326629..7eea95d490e6 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -35,8 +35,6 @@
#include <linux/timer.h>
#include <linux/wakeup_reason.h>
-#include <asm/current.h>
-
#include "../base.h"
#include "power.h"
@@ -62,12 +60,6 @@ struct suspend_stats suspend_stats;
static DEFINE_MUTEX(dpm_list_mtx);
static pm_message_t pm_transition;
-static void dpm_drv_timeout(unsigned long data);
-struct dpm_drv_wd_data {
- struct device *dev;
- struct task_struct *tsk;
-};
-
static int async_error;
static char *pm_verb(int event)
@@ -134,6 +126,7 @@ void device_pm_add(struct device *dev)
{
pr_debug("PM: Adding info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
+ device_pm_check_callbacks(dev);
mutex_lock(&dpm_list_mtx);
if (dev->parent && dev->parent->power.is_prepared)
dev_warn(dev, "parent %s should not be sleeping\n",
@@ -156,6 +149,7 @@ void device_pm_remove(struct device *dev)
mutex_unlock(&dpm_list_mtx);
device_wakeup_disable(dev);
pm_runtime_remove(dev);
+ device_pm_check_callbacks(dev);
}
/**
@@ -839,30 +833,6 @@ static void async_resume(void *data, async_cookie_t cookie)
}
/**
- * dpm_drv_timeout - Driver suspend / resume watchdog handler
- * @data: struct device which timed out
- *
- * Called when a driver has timed out suspending or resuming.
- * There's not much we can do here to recover so
- * BUG() out for a crash-dump
- *
- */
-static void dpm_drv_timeout(unsigned long data)
-{
- struct dpm_drv_wd_data *wd_data = (void *)data;
- struct device *dev = wd_data->dev;
- struct task_struct *tsk = wd_data->tsk;
-
- printk(KERN_EMERG "**** DPM device timeout: %s (%s)\n", dev_name(dev),
- (dev->driver ? dev->driver->name : "no driver"));
-
- printk(KERN_EMERG "dpm suspend stack:\n");
- show_stack(tsk, NULL);
-
- BUG();
-}
-
-/**
* dpm_resume - Execute "resume" callbacks for non-sysdev devices.
* @state: PM transition of the system being carried out.
*
@@ -1295,14 +1265,15 @@ int dpm_suspend_late(pm_message_t state)
error = device_suspend_late(dev);
mutex_lock(&dpm_list_mtx);
+ if (!list_empty(&dev->power.entry))
+ list_move(&dev->power.entry, &dpm_late_early_list);
+
if (error) {
pm_dev_err(dev, state, " late", error);
dpm_save_failed_dev(dev_name(dev));
put_device(dev);
break;
}
- if (!list_empty(&dev->power.entry))
- list_move(&dev->power.entry, &dpm_late_early_list);
put_device(dev);
if (async_error)
@@ -1380,8 +1351,6 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
pm_callback_t callback = NULL;
char *info = NULL;
int error = 0;
- struct timer_list timer;
- struct dpm_drv_wd_data data;
char suspend_abort[MAX_SUSPEND_ABORT_LEN];
DECLARE_DPM_WATCHDOG_ON_STACK(wd);
@@ -1412,14 +1381,6 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
if (dev->power.syscore)
goto Complete;
-
- data.dev = dev;
- data.tsk = current;
- init_timer_on_stack(&timer);
- timer.expires = jiffies + HZ * 12;
- timer.function = dpm_drv_timeout;
- timer.data = (unsigned long)&data;
- add_timer(&timer);
if (dev->power.direct_complete) {
if (pm_runtime_status_suspended(dev)) {
@@ -1500,9 +1461,6 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
device_unlock(dev);
dpm_watchdog_clear(&wd);
- del_timer_sync(&timer);
- destroy_timer_on_stack(&timer);
-
Complete:
complete_all(&dev->power.completion);
if (error)
@@ -1619,6 +1577,11 @@ static int device_prepare(struct device *dev, pm_message_t state)
dev->power.wakeup_path = device_may_wakeup(dev);
+ if (dev->power.no_pm_callbacks) {
+ ret = 1; /* Let device go direct_complete */
+ goto unlock;
+ }
+
if (dev->pm_domain) {
info = "preparing power domain ";
callback = dev->pm_domain->ops.prepare;
@@ -1641,6 +1604,7 @@ static int device_prepare(struct device *dev, pm_message_t state)
if (callback)
ret = callback(dev);
+unlock:
device_unlock(dev);
if (ret < 0) {
@@ -1769,3 +1733,30 @@ void dpm_for_each_dev(void *data, void (*fn)(struct device *, void *))
device_pm_unlock();
}
EXPORT_SYMBOL_GPL(dpm_for_each_dev);
+
+static bool pm_ops_is_empty(const struct dev_pm_ops *ops)
+{
+ if (!ops)
+ return true;
+
+ return !ops->prepare &&
+ !ops->suspend &&
+ !ops->suspend_late &&
+ !ops->suspend_noirq &&
+ !ops->resume_noirq &&
+ !ops->resume_early &&
+ !ops->resume &&
+ !ops->complete;
+}
+
+void device_pm_check_callbacks(struct device *dev)
+{
+ spin_lock_irq(&dev->power.lock);
+ dev->power.no_pm_callbacks =
+ (!dev->bus || pm_ops_is_empty(dev->bus->pm)) &&
+ (!dev->class || pm_ops_is_empty(dev->class->pm)) &&
+ (!dev->type || pm_ops_is_empty(dev->type->pm)) &&
+ (!dev->pm_domain || pm_ops_is_empty(&dev->pm_domain->ops)) &&
+ (!dev->driver || pm_ops_is_empty(dev->driver->pm));
+ spin_unlock_irq(&dev->power.lock);
+}
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index 998fa6b23084..297beae64314 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -123,6 +123,7 @@ extern void device_pm_remove(struct device *);
extern void device_pm_move_before(struct device *, struct device *);
extern void device_pm_move_after(struct device *, struct device *);
extern void device_pm_move_last(struct device *);
+extern void device_pm_check_callbacks(struct device *dev);
#else /* !CONFIG_PM_SLEEP */
@@ -141,6 +142,8 @@ static inline void device_pm_move_after(struct device *deva,
struct device *devb) {}
static inline void device_pm_move_last(struct device *dev) {}
+static inline void device_pm_check_callbacks(struct device *dev) {}
+
#endif /* !CONFIG_PM_SLEEP */
static inline void device_pm_init(struct device *dev)
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index e1a10a03df8e..9796a1a15ef6 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1468,11 +1468,16 @@ int pm_runtime_force_resume(struct device *dev)
goto out;
}
- ret = callback(dev);
+ ret = pm_runtime_set_active(dev);
if (ret)
goto out;
- pm_runtime_set_active(dev);
+ ret = callback(dev);
+ if (ret) {
+ pm_runtime_set_suspended(dev);
+ goto out;
+ }
+
pm_runtime_mark_last_busy(dev);
out:
pm_runtime_enable(dev);
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c
index ed888e302bc3..597b2d16b775 100644
--- a/drivers/bluetooth/hci_vhci.c
+++ b/drivers/bluetooth/hci_vhci.c
@@ -50,6 +50,7 @@ struct vhci_data {
wait_queue_head_t read_wait;
struct sk_buff_head readq;
+ struct mutex open_mutex;
struct delayed_work open_timeout;
};
@@ -87,12 +88,15 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return 0;
}
-static int vhci_create_device(struct vhci_data *data, __u8 opcode)
+static int __vhci_create_device(struct vhci_data *data, __u8 opcode)
{
struct hci_dev *hdev;
struct sk_buff *skb;
__u8 dev_type;
+ if (data->hdev)
+ return -EBADFD;
+
/* bits 0-1 are dev_type (BR/EDR or AMP) */
dev_type = opcode & 0x03;
@@ -151,6 +155,17 @@ static int vhci_create_device(struct vhci_data *data, __u8 opcode)
return 0;
}
+static int vhci_create_device(struct vhci_data *data, __u8 opcode)
+{
+ int err;
+
+ mutex_lock(&data->open_mutex);
+ err = __vhci_create_device(data, opcode);
+ mutex_unlock(&data->open_mutex);
+
+ return err;
+}
+
static inline ssize_t vhci_get_user(struct vhci_data *data,
struct iov_iter *from)
{
@@ -189,11 +204,6 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
break;
case HCI_VENDOR_PKT:
- if (data->hdev) {
- kfree_skb(skb);
- return -EBADFD;
- }
-
cancel_delayed_work_sync(&data->open_timeout);
opcode = *((__u8 *) skb->data);
@@ -320,6 +330,7 @@ static int vhci_open(struct inode *inode, struct file *file)
skb_queue_head_init(&data->readq);
init_waitqueue_head(&data->read_wait);
+ mutex_init(&data->open_mutex);
INIT_DELAYED_WORK(&data->open_timeout, vhci_open_timeout);
file->private_data = data;
@@ -333,15 +344,18 @@ static int vhci_open(struct inode *inode, struct file *file)
static int vhci_release(struct inode *inode, struct file *file)
{
struct vhci_data *data = file->private_data;
- struct hci_dev *hdev = data->hdev;
+ struct hci_dev *hdev;
cancel_delayed_work_sync(&data->open_timeout);
+ hdev = data->hdev;
+
if (hdev) {
hci_unregister_dev(hdev);
hci_free_dev(hdev);
}
+ skb_queue_purge(&data->readq);
file->private_data = NULL;
kfree(data);
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index ca9a8684de94..1046c262b46b 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -590,10 +590,6 @@ config DEVPORT
depends on ISA || PCI
default y
-config DCC_TTY
- tristate "DCC tty driver"
- depends on ARM
-
source "drivers/s390/char/Kconfig"
config TILE_SROM
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index fe696f180841..e180562c725e 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -53,7 +53,6 @@ obj-$(CONFIG_PCMCIA) += pcmcia/
obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
obj-$(CONFIG_TCG_TPM) += tpm/
-obj-$(CONFIG_DCC_TTY) += dcc_tty.o
obj-$(CONFIG_PS3_FLASH) += ps3flash.o
obj-$(CONFIG_JS_RTC) += js-rtc.o
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index ef8aaac6e0a2..7767086df849 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -490,7 +490,7 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map)
ion_free(fl->apps->client, map->handle);
if (sess->smmu.enabled) {
if (map->size || map->phys)
- msm_dma_unmap_sg(fl->sctx->dev,
+ msm_dma_unmap_sg(sess->dev,
map->table->sgl,
map->table->nents, DMA_BIDIRECTIONAL,
map->buf);
diff --git a/drivers/char/dcc_tty.c b/drivers/char/dcc_tty.c
deleted file mode 100644
index 0a62d410286f..000000000000
--- a/drivers/char/dcc_tty.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/* drivers/char/dcc_tty.c
- *
- * Copyright (C) 2007 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/console.h>
-#include <linux/hrtimer.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-
-MODULE_DESCRIPTION("DCC TTY Driver");
-MODULE_LICENSE("GPL");
-MODULE_VERSION("1.0");
-
-DEFINE_SPINLOCK(g_dcc_tty_lock);
-static struct hrtimer g_dcc_timer;
-static char g_dcc_buffer[16];
-static int g_dcc_buffer_head;
-static int g_dcc_buffer_count;
-static unsigned g_dcc_write_delay_usecs = 1;
-static struct tty_driver *g_dcc_tty_driver;
-static struct tty_struct *g_dcc_tty;
-static int g_dcc_tty_open_count;
-
-static void dcc_poll_locked(void)
-{
- char ch;
- int rch;
- int written;
-
- while (g_dcc_buffer_count) {
- ch = g_dcc_buffer[g_dcc_buffer_head];
- asm(
- "mrc 14, 0, r15, c0, c1, 0\n"
- "mcrcc 14, 0, %1, c0, c5, 0\n"
- "movcc %0, #1\n"
- "movcs %0, #0\n"
- : "=r" (written)
- : "r" (ch)
- );
- if (written) {
- if (ch == '\n')
- g_dcc_buffer[g_dcc_buffer_head] = '\r';
- else {
- g_dcc_buffer_head = (g_dcc_buffer_head + 1) % ARRAY_SIZE(g_dcc_buffer);
- g_dcc_buffer_count--;
- if (g_dcc_tty)
- tty_wakeup(g_dcc_tty);
- }
- g_dcc_write_delay_usecs = 1;
- } else {
- if (g_dcc_write_delay_usecs > 0x100)
- break;
- g_dcc_write_delay_usecs <<= 1;
- udelay(g_dcc_write_delay_usecs);
- }
- }
-
- if (g_dcc_tty && !test_bit(TTY_THROTTLED, &g_dcc_tty->flags)) {
- asm(
- "mrc 14, 0, %0, c0, c1, 0\n"
- "tst %0, #(1 << 30)\n"
- "moveq %0, #-1\n"
- "mrcne 14, 0, %0, c0, c5, 0\n"
- : "=r" (rch)
- );
- if (rch >= 0) {
- ch = rch;
- tty_insert_flip_string(g_dcc_tty->port, &ch, 1);
- tty_flip_buffer_push(g_dcc_tty->port);
- }
- }
-
-
- if (g_dcc_buffer_count)
- hrtimer_start(&g_dcc_timer, ktime_set(0, g_dcc_write_delay_usecs * NSEC_PER_USEC), HRTIMER_MODE_REL);
- else
- hrtimer_start(&g_dcc_timer, ktime_set(0, 20 * NSEC_PER_MSEC), HRTIMER_MODE_REL);
-}
-
-static int dcc_tty_open(struct tty_struct * tty, struct file * filp)
-{
- int ret;
- unsigned long irq_flags;
-
- spin_lock_irqsave(&g_dcc_tty_lock, irq_flags);
- if (g_dcc_tty == NULL || g_dcc_tty == tty) {
- g_dcc_tty = tty;
- g_dcc_tty_open_count++;
- ret = 0;
- } else
- ret = -EBUSY;
- spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags);
-
- printk("dcc_tty_open, tty %p, f_flags %x, returned %d\n", tty, filp->f_flags, ret);
-
- return ret;
-}
-
-static void dcc_tty_close(struct tty_struct * tty, struct file * filp)
-{
- printk("dcc_tty_close, tty %p, f_flags %x\n", tty, filp->f_flags);
- if (g_dcc_tty == tty) {
- if (--g_dcc_tty_open_count == 0)
- g_dcc_tty = NULL;
- }
-}
-
-static int dcc_write(const unsigned char *buf_start, int count)
-{
- const unsigned char *buf = buf_start;
- unsigned long irq_flags;
- int copy_len;
- int space_left;
- int tail;
-
- if (count < 1)
- return 0;
-
- spin_lock_irqsave(&g_dcc_tty_lock, irq_flags);
- do {
- tail = (g_dcc_buffer_head + g_dcc_buffer_count) % ARRAY_SIZE(g_dcc_buffer);
- copy_len = ARRAY_SIZE(g_dcc_buffer) - tail;
- space_left = ARRAY_SIZE(g_dcc_buffer) - g_dcc_buffer_count;
- if (copy_len > space_left)
- copy_len = space_left;
- if (copy_len > count)
- copy_len = count;
- memcpy(&g_dcc_buffer[tail], buf, copy_len);
- g_dcc_buffer_count += copy_len;
- buf += copy_len;
- count -= copy_len;
- if (copy_len < count && copy_len < space_left) {
- space_left -= copy_len;
- copy_len = count;
- if (copy_len > space_left) {
- copy_len = space_left;
- }
- memcpy(g_dcc_buffer, buf, copy_len);
- buf += copy_len;
- count -= copy_len;
- g_dcc_buffer_count += copy_len;
- }
- dcc_poll_locked();
- space_left = ARRAY_SIZE(g_dcc_buffer) - g_dcc_buffer_count;
- } while(count && space_left);
- spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags);
- return buf - buf_start;
-}
-
-static int dcc_tty_write(struct tty_struct * tty, const unsigned char *buf, int count)
-{
- int ret;
- /* printk("dcc_tty_write %p, %d\n", buf, count); */
- ret = dcc_write(buf, count);
- if (ret != count)
- printk("dcc_tty_write %p, %d, returned %d\n", buf, count, ret);
- return ret;
-}
-
-static int dcc_tty_write_room(struct tty_struct *tty)
-{
- int space_left;
- unsigned long irq_flags;
-
- spin_lock_irqsave(&g_dcc_tty_lock, irq_flags);
- space_left = ARRAY_SIZE(g_dcc_buffer) - g_dcc_buffer_count;
- spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags);
- return space_left;
-}
-
-static int dcc_tty_chars_in_buffer(struct tty_struct *tty)
-{
- int ret;
- asm(
- "mrc 14, 0, %0, c0, c1, 0\n"
- "mov %0, %0, LSR #30\n"
- "and %0, %0, #1\n"
- : "=r" (ret)
- );
- return ret;
-}
-
-static void dcc_tty_unthrottle(struct tty_struct * tty)
-{
- unsigned long irq_flags;
-
- spin_lock_irqsave(&g_dcc_tty_lock, irq_flags);
- dcc_poll_locked();
- spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags);
-}
-
-static enum hrtimer_restart dcc_tty_timer_func(struct hrtimer *timer)
-{
- unsigned long irq_flags;
-
- spin_lock_irqsave(&g_dcc_tty_lock, irq_flags);
- dcc_poll_locked();
- spin_unlock_irqrestore(&g_dcc_tty_lock, irq_flags);
- return HRTIMER_NORESTART;
-}
-
-void dcc_console_write(struct console *co, const char *b, unsigned count)
-{
-#if 1
- dcc_write(b, count);
-#else
- /* blocking printk */
- while (count > 0) {
- int written;
- written = dcc_write(b, count);
- if (written) {
- b += written;
- count -= written;
- }
- }
-#endif
-}
-
-static struct tty_driver *dcc_console_device(struct console *c, int *index)
-{
- *index = 0;
- return g_dcc_tty_driver;
-}
-
-static int __init dcc_console_setup(struct console *co, char *options)
-{
- if (co->index != 0)
- return -ENODEV;
- return 0;
-}
-
-
-static struct console dcc_console =
-{
- .name = "ttyDCC",
- .write = dcc_console_write,
- .device = dcc_console_device,
- .setup = dcc_console_setup,
- .flags = CON_PRINTBUFFER,
- .index = -1,
-};
-
-static struct tty_operations dcc_tty_ops = {
- .open = dcc_tty_open,
- .close = dcc_tty_close,
- .write = dcc_tty_write,
- .write_room = dcc_tty_write_room,
- .chars_in_buffer = dcc_tty_chars_in_buffer,
- .unthrottle = dcc_tty_unthrottle,
-};
-
-static int __init dcc_tty_init(void)
-{
- int ret;
-
- hrtimer_init(&g_dcc_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- g_dcc_timer.function = dcc_tty_timer_func;
-
- g_dcc_tty_driver = alloc_tty_driver(1);
- if (!g_dcc_tty_driver) {
- printk(KERN_ERR "dcc_tty_probe: alloc_tty_driver failed\n");
- ret = -ENOMEM;
- goto err_alloc_tty_driver_failed;
- }
- g_dcc_tty_driver->owner = THIS_MODULE;
- g_dcc_tty_driver->driver_name = "dcc";
- g_dcc_tty_driver->name = "ttyDCC";
- g_dcc_tty_driver->major = 0; // auto assign
- g_dcc_tty_driver->minor_start = 0;
- g_dcc_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
- g_dcc_tty_driver->subtype = SERIAL_TYPE_NORMAL;
- g_dcc_tty_driver->init_termios = tty_std_termios;
- g_dcc_tty_driver->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
- tty_set_operations(g_dcc_tty_driver, &dcc_tty_ops);
- ret = tty_register_driver(g_dcc_tty_driver);
- if (ret) {
- printk(KERN_ERR "dcc_tty_probe: tty_register_driver failed, %d\n", ret);
- goto err_tty_register_driver_failed;
- }
- tty_register_device(g_dcc_tty_driver, 0, NULL);
-
- register_console(&dcc_console);
- hrtimer_start(&g_dcc_timer, ktime_set(0, 0), HRTIMER_MODE_REL);
-
- return 0;
-
-err_tty_register_driver_failed:
- put_tty_driver(g_dcc_tty_driver);
- g_dcc_tty_driver = NULL;
-err_alloc_tty_driver_failed:
- return ret;
-}
-
-static void __exit dcc_tty_exit(void)
-{
- int ret;
-
- tty_unregister_device(g_dcc_tty_driver, 0);
- ret = tty_unregister_driver(g_dcc_tty_driver);
- if (ret < 0) {
- printk(KERN_ERR "dcc_tty_remove: tty_unregister_driver failed, %d\n", ret);
- } else {
- put_tty_driver(g_dcc_tty_driver);
- }
- g_dcc_tty_driver = NULL;
-}
-
-module_init(dcc_tty_init);
-module_exit(dcc_tty_exit);
-
-
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 2aef98f4fe04..35cbe3b6b596 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -509,6 +509,7 @@ struct diagchar_dev {
struct list_head cmd_reg_list;
struct mutex cmd_reg_mutex;
uint32_t cmd_reg_count;
+ struct mutex diagfwd_channel_mutex;
/* Sizes that reflect memory pool sizes */
unsigned int poolsize;
unsigned int poolsize_hdlc;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 39be6ef3735e..a5781f6db269 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -3394,6 +3394,7 @@ static int __init diagchar_init(void)
mutex_init(&driver->diag_file_mutex);
mutex_init(&driver->delayed_rsp_mutex);
mutex_init(&apps_data_mutex);
+ mutex_init(&driver->diagfwd_channel_mutex);
init_waitqueue_head(&driver->wait_q);
INIT_WORK(&(driver->diag_drain_work), diag_drain_work_fn);
INIT_WORK(&(driver->update_user_clients),
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index 22b9e05086bd..40fdcbaaf31a 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -651,9 +651,9 @@ void diagfwd_close_transport(uint8_t transport, uint8_t peripheral)
break;
default:
return;
-
}
+ mutex_lock(&driver->diagfwd_channel_mutex);
fwd_info = &early_init_info[transport][peripheral];
if (fwd_info->p_ops && fwd_info->p_ops->close)
fwd_info->p_ops->close(fwd_info->ctxt);
@@ -677,6 +677,7 @@ void diagfwd_close_transport(uint8_t transport, uint8_t peripheral)
diagfwd_late_open(dest_info);
diagfwd_cntl_open(dest_info);
init_fn(peripheral);
+ mutex_unlock(&driver->diagfwd_channel_mutex);
diagfwd_queue_read(&peripheral_info[TYPE_DATA][peripheral]);
diagfwd_queue_read(&peripheral_info[TYPE_CMD][peripheral]);
}
diff --git a/drivers/char/diag/diagfwd_socket.c b/drivers/char/diag/diagfwd_socket.c
index fd927e931414..2f9ec51a17ba 100644
--- a/drivers/char/diag/diagfwd_socket.c
+++ b/drivers/char/diag/diagfwd_socket.c
@@ -959,7 +959,9 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
(info->data_ready > 0) || (!info->hdl) ||
(atomic_read(&info->diag_state) == 0));
if (err) {
+ mutex_lock(&driver->diagfwd_channel_mutex);
diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
+ mutex_unlock(&driver->diagfwd_channel_mutex);
return -ERESTARTSYS;
}
@@ -971,7 +973,9 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"%s closing read thread. diag state is closed\n",
info->name);
+ mutex_lock(&driver->diagfwd_channel_mutex);
diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
+ mutex_unlock(&driver->diagfwd_channel_mutex);
return 0;
}
@@ -1038,8 +1042,10 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
if (total_recd > 0) {
DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s read total bytes: %d\n",
info->name, total_recd);
+ mutex_lock(&driver->diagfwd_channel_mutex);
err = diagfwd_channel_read_done(info->fwd_ctxt,
buf, total_recd);
+ mutex_unlock(&driver->diagfwd_channel_mutex);
if (err)
goto fail;
} else {
@@ -1052,7 +1058,9 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
return 0;
fail:
+ mutex_lock(&driver->diagfwd_channel_mutex);
diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
+ mutex_unlock(&driver->diagfwd_channel_mutex);
return -EIO;
}
diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c
index 30cf4623184f..aa30af5f0f2b 100644
--- a/drivers/char/hw_random/exynos-rng.c
+++ b/drivers/char/hw_random/exynos-rng.c
@@ -89,6 +89,7 @@ static int exynos_read(struct hwrng *rng, void *buf,
struct exynos_rng, rng);
u32 *data = buf;
int retry = 100;
+ int ret = 4;
pm_runtime_get_sync(exynos_rng->dev);
@@ -97,17 +98,20 @@ static int exynos_read(struct hwrng *rng, void *buf,
while (!(exynos_rng_readl(exynos_rng,
EXYNOS_PRNG_STATUS_OFFSET) & PRNG_DONE) && --retry)
cpu_relax();
- if (!retry)
- return -ETIMEDOUT;
+ if (!retry) {
+ ret = -ETIMEDOUT;
+ goto out;
+ }
exynos_rng_writel(exynos_rng, PRNG_DONE, EXYNOS_PRNG_STATUS_OFFSET);
*data = exynos_rng_readl(exynos_rng, EXYNOS_PRNG_OUT1_OFFSET);
+out:
pm_runtime_mark_last_busy(exynos_rng->dev);
pm_runtime_put_sync_autosuspend(exynos_rng->dev);
- return 4;
+ return ret;
}
static int exynos_rng_probe(struct platform_device *pdev)
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index e3536da05c88..a084a4751fa9 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -3819,6 +3819,7 @@ static void handle_new_recv_msgs(ipmi_smi_t intf)
while (!list_empty(&intf->waiting_rcv_msgs)) {
smi_msg = list_entry(intf->waiting_rcv_msgs.next,
struct ipmi_smi_msg, link);
+ list_del(&smi_msg->link);
if (!run_to_completion)
spin_unlock_irqrestore(&intf->waiting_rcv_msgs_lock,
flags);
@@ -3828,11 +3829,14 @@ static void handle_new_recv_msgs(ipmi_smi_t intf)
if (rv > 0) {
/*
* To preserve message order, quit if we
- * can't handle a message.
+ * can't handle a message. Add the message
+ * back at the head, this is safe because this
+ * tasklet is the only thing that pulls the
+ * messages.
*/
+ list_add(&smi_msg->link, &intf->waiting_rcv_msgs);
break;
} else {
- list_del(&smi_msg->link);
if (rv == 0)
/* Message handled */
ipmi_free_smi_msg(smi_msg);
diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c
index 61566bcefa53..a165230e7eda 100644
--- a/drivers/clk/at91/clk-h32mx.c
+++ b/drivers/clk/at91/clk-h32mx.c
@@ -116,7 +116,7 @@ void __init of_sama5d4_clk_h32mx_setup(struct device_node *np,
h32mxclk->pmc = pmc;
clk = clk_register(NULL, &h32mxclk->hw);
- if (!clk) {
+ if (IS_ERR(clk)) {
kfree(h32mxclk);
return;
}
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 4f9830c1b121..6029313aa995 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -890,8 +890,14 @@ static void bcm2835_pll_off(struct clk_hw *hw)
struct bcm2835_cprman *cprman = pll->cprman;
const struct bcm2835_pll_data *data = pll->data;
- cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST);
- cprman_write(cprman, data->a2w_ctrl_reg, A2W_PLL_CTRL_PWRDN);
+ spin_lock(&cprman->regs_lock);
+ cprman_write(cprman, data->cm_ctrl_reg,
+ cprman_read(cprman, data->cm_ctrl_reg) |
+ CM_PLL_ANARST);
+ cprman_write(cprman, data->a2w_ctrl_reg,
+ cprman_read(cprman, data->a2w_ctrl_reg) |
+ A2W_PLL_CTRL_PWRDN);
+ spin_unlock(&cprman->regs_lock);
}
static int bcm2835_pll_on(struct clk_hw *hw)
@@ -901,6 +907,10 @@ static int bcm2835_pll_on(struct clk_hw *hw)
const struct bcm2835_pll_data *data = pll->data;
ktime_t timeout;
+ cprman_write(cprman, data->a2w_ctrl_reg,
+ cprman_read(cprman, data->a2w_ctrl_reg) &
+ ~A2W_PLL_CTRL_PWRDN);
+
/* Take the PLL out of reset. */
cprman_write(cprman, data->cm_ctrl_reg,
cprman_read(cprman, data->cm_ctrl_reg) & ~CM_PLL_ANARST);
@@ -1068,10 +1078,12 @@ static void bcm2835_pll_divider_off(struct clk_hw *hw)
struct bcm2835_cprman *cprman = divider->cprman;
const struct bcm2835_pll_divider_data *data = divider->data;
+ spin_lock(&cprman->regs_lock);
cprman_write(cprman, data->cm_reg,
(cprman_read(cprman, data->cm_reg) &
~data->load_mask) | data->hold_mask);
cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE);
+ spin_unlock(&cprman->regs_lock);
}
static int bcm2835_pll_divider_on(struct clk_hw *hw)
@@ -1080,12 +1092,14 @@ static int bcm2835_pll_divider_on(struct clk_hw *hw)
struct bcm2835_cprman *cprman = divider->cprman;
const struct bcm2835_pll_divider_data *data = divider->data;
+ spin_lock(&cprman->regs_lock);
cprman_write(cprman, data->a2w_reg,
cprman_read(cprman, data->a2w_reg) &
~A2W_PLL_CHANNEL_DISABLE);
cprman_write(cprman, data->cm_reg,
cprman_read(cprman, data->cm_reg) & ~data->hold_mask);
+ spin_unlock(&cprman->regs_lock);
return 0;
}
@@ -1167,8 +1181,9 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
div &= ~unused_frac_mask;
}
- /* Clamp to the limits. */
- div = max(div, unused_frac_mask + 1);
+ /* clamp to min divider of 1 */
+ div = max_t(u32, div, 1 << CM_DIV_FRAC_BITS);
+ /* clamp to the highest possible fractional divider */
div = min_t(u32, div, GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1,
CM_DIV_FRAC_BITS - data->frac_bits));
diff --git a/drivers/clk/imx/clk-imx35.c b/drivers/clk/imx/clk-imx35.c
index a71d24cb4c06..b0978d3b83e2 100644
--- a/drivers/clk/imx/clk-imx35.c
+++ b/drivers/clk/imx/clk-imx35.c
@@ -66,7 +66,7 @@ static const char *std_sel[] = {"ppll", "arm"};
static const char *ipg_per_sel[] = {"ahb_per_div", "arm_per_div"};
enum mx35_clks {
- ckih, ckil, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg,
+ ckih, mpll, ppll, mpll_075, arm, hsp, hsp_div, hsp_sel, ahb, ipg,
arm_per_div, ahb_per_div, ipg_per, uart_sel, uart_div, esdhc_sel,
esdhc1_div, esdhc2_div, esdhc3_div, spdif_sel, spdif_div_pre,
spdif_div_post, ssi_sel, ssi1_div_pre, ssi1_div_post, ssi2_div_pre,
@@ -79,7 +79,7 @@ enum mx35_clks {
rtc_gate, rtic_gate, scc_gate, sdma_gate, spba_gate, spdif_gate,
ssi1_gate, ssi2_gate, uart1_gate, uart2_gate, uart3_gate, usbotg_gate,
wdog_gate, max_gate, admux_gate, csi_gate, csi_div, csi_sel, iim_gate,
- gpu2d_gate, clk_max
+ gpu2d_gate, ckil, clk_max
};
static struct clk *clk[clk_max];
diff --git a/drivers/clk/msm/clock-osm.c b/drivers/clk/msm/clock-osm.c
index 5391ef456aae..3e45aee1c0f7 100644
--- a/drivers/clk/msm/clock-osm.c
+++ b/drivers/clk/msm/clock-osm.c
@@ -49,6 +49,7 @@ enum clk_osm_bases {
OSM_BASE,
PLL_BASE,
EFUSE_BASE,
+ ACD_BASE,
NUM_BASES,
};
@@ -228,11 +229,43 @@ enum clk_osm_trace_packet_id {
#define MSMCOBALTV2_PWRCL_BOOT_RATE 1555200000
#define MSMCOBALTV2_PERFCL_BOOT_RATE 1728000000
+/* ACD registers */
+#define ACD_HW_VERSION 0x0
+#define ACDCR 0x4
+#define ACDTD 0x8
+#define ACDSSCR 0x28
+#define ACD_EXTINT_CFG 0x30
+#define ACD_DCVS_SW 0x34
+#define ACD_GFMUX_CFG 0x3c
+#define ACD_READOUT_CFG 0x48
+#define ACD_AUTOXFER_CFG 0x80
+#define ACD_AUTOXFER 0x84
+#define ACD_AUTOXFER_CTL 0x88
+#define ACD_AUTOXFER_STATUS 0x8c
+#define ACD_WRITE_CTL 0x90
+#define ACD_WRITE_STATUS 0x94
+#define ACD_READOUT 0x98
+
+#define ACD_MASTER_ONLY_REG_ADDR 0x80
+#define ACD_WRITE_CTL_UPDATE_EN BIT(0)
+#define ACD_WRITE_CTL_SELECT_SHIFT 1
+#define ACD_GFMUX_CFG_SELECT BIT(0)
+#define ACD_AUTOXFER_START_CLEAR 0
+#define ACD_AUTOXFER_START_SET BIT(0)
+#define AUTO_XFER_DONE_MASK BIT(0)
+#define ACD_DCVS_SW_DCVS_IN_PRGR_SET BIT(0)
+#define ACD_DCVS_SW_DCVS_IN_PRGR_CLEAR 0
+#define ACD_LOCAL_TRANSFER_TIMEOUT_NS 500
+
static void __iomem *virt_base;
static void __iomem *debug_base;
#define lmh_lite_clk_src_source_val 1
+#define ACD_REG_RELATIVE_ADDR(addr) (addr / 4)
+#define ACD_REG_RELATIVE_ADDR_BITMASK(addr) \
+ (1 << (ACD_REG_RELATIVE_ADDR(addr)))
+
#define FIXDIV(div) (div ? (2 * (div) - 1) : (0))
#define F(f, s, div, m, n) \
@@ -341,6 +374,14 @@ struct clk_osm {
u32 apm_ctrl_status;
u32 osm_clk_rate;
u32 xo_clk_rate;
+ u32 acd_td;
+ u32 acd_cr;
+ u32 acd_sscr;
+ u32 acd_extint0_cfg;
+ u32 acd_extint1_cfg;
+ u32 acd_autoxfer_ctl;
+ u32 acd_debugfs_addr;
+ bool acd_init;
bool secure_init;
bool red_fsm_en;
bool boost_fsm_en;
@@ -394,6 +435,161 @@ static inline int clk_osm_mb(struct clk_osm *c, int base)
return readl_relaxed_no_log((char *)c->vbases[base] + VERSION_REG);
}
+static inline int clk_osm_acd_mb(struct clk_osm *c)
+{
+ return readl_relaxed_no_log((char *)c->vbases[ACD_BASE] +
+ ACD_HW_VERSION);
+}
+
+static inline void clk_osm_acd_master_write_reg(struct clk_osm *c,
+ u32 val, u32 offset)
+{
+ writel_relaxed(val, (char *)c->vbases[ACD_BASE] + offset);
+}
+
+static int clk_osm_acd_local_read_reg(struct clk_osm *c, u32 offset)
+{
+ u32 reg = 0;
+ int timeout;
+
+ if (offset >= ACD_MASTER_ONLY_REG_ADDR) {
+ pr_err("ACD register at offset=0x%x not locally readable\n",
+ offset);
+ return -EINVAL;
+ }
+
+ /* Set select field in read control register */
+ writel_relaxed(ACD_REG_RELATIVE_ADDR(offset),
+ (char *)c->vbases[ACD_BASE] + ACD_READOUT_CFG);
+
+ /* Clear write control register */
+ writel_relaxed(reg, (char *)c->vbases[ACD_BASE] + ACD_WRITE_CTL);
+
+ /* Set select and update_en fields in write control register */
+ reg = (ACD_REG_RELATIVE_ADDR(ACD_READOUT_CFG)
+ << ACD_WRITE_CTL_SELECT_SHIFT)
+ | ACD_WRITE_CTL_UPDATE_EN;
+ writel_relaxed(reg, (char *)c->vbases[ACD_BASE] + ACD_WRITE_CTL);
+
+ /* Ensure writes complete before polling */
+ clk_osm_acd_mb(c);
+
+ /* Poll write status register */
+ for (timeout = ACD_LOCAL_TRANSFER_TIMEOUT_NS; timeout > 0;
+ timeout -= 100) {
+ reg = readl_relaxed((char *)c->vbases[ACD_BASE]
+ + ACD_WRITE_STATUS);
+ if ((reg & (ACD_REG_RELATIVE_ADDR_BITMASK(ACD_READOUT_CFG))))
+ break;
+ ndelay(100);
+ }
+
+ if (!timeout) {
+ pr_err("local read timed out, offset=0x%x status=0x%x\n",
+ offset, reg);
+ return -ETIMEDOUT;
+ }
+
+ reg = readl_relaxed((char *)c->vbases[ACD_BASE]
+ + ACD_READOUT);
+ return reg;
+}
+
+static int clk_osm_acd_local_write_reg(struct clk_osm *c, u32 val, u32 offset)
+{
+ u32 reg = 0;
+ int timeout;
+
+ if (offset >= ACD_MASTER_ONLY_REG_ADDR) {
+ pr_err("ACD register at offset=0x%x not transferrable\n",
+ offset);
+ return -EINVAL;
+ }
+
+ /* Clear write control register */
+ writel_relaxed(reg, (char *)c->vbases[ACD_BASE] + ACD_WRITE_CTL);
+
+ /* Set select and update_en fields in write control register */
+ reg = (ACD_REG_RELATIVE_ADDR(offset) << ACD_WRITE_CTL_SELECT_SHIFT)
+ | ACD_WRITE_CTL_UPDATE_EN;
+ writel_relaxed(reg, (char *)c->vbases[ACD_BASE] + ACD_WRITE_CTL);
+
+ /* Ensure writes complete before polling */
+ clk_osm_acd_mb(c);
+
+ /* Poll write status register */
+ for (timeout = ACD_LOCAL_TRANSFER_TIMEOUT_NS; timeout > 0;
+ timeout -= 100) {
+ reg = readl_relaxed((char *)c->vbases[ACD_BASE]
+ + ACD_WRITE_STATUS);
+ if ((reg & (ACD_REG_RELATIVE_ADDR_BITMASK(offset))))
+ break;
+ ndelay(100);
+ }
+
+ if (!timeout) {
+ pr_err("local write timed out, offset=0x%x val=0x%x status=0x%x\n",
+ offset, val, reg);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int clk_osm_acd_master_write_through_reg(struct clk_osm *c,
+ u32 val, u32 offset)
+{
+ writel_relaxed(val, (char *)c->vbases[ACD_BASE] + offset);
+
+ /* Ensure writes complete before transfer to local copy */
+ clk_osm_acd_mb(c);
+
+ return clk_osm_acd_local_write_reg(c, val, offset);
+}
+
+static int clk_osm_acd_auto_local_write_reg(struct clk_osm *c, u32 mask)
+{
+ u32 numregs, bitmask = mask;
+ u32 reg = 0;
+ int timeout;
+
+ /* count number of bits set in register mask */
+ for (numregs = 0; bitmask; numregs++)
+ bitmask &= bitmask - 1;
+
+ /* Program auto-transfter mask */
+ writel_relaxed(mask, (char *)c->vbases[ACD_BASE] + ACD_AUTOXFER_CFG);
+
+ /* Clear start field in auto-transfer register */
+ writel_relaxed(ACD_AUTOXFER_START_CLEAR,
+ (char *)c->vbases[ACD_BASE] + ACD_AUTOXFER);
+
+ /* Set start field in auto-transfer register */
+ writel_relaxed(ACD_AUTOXFER_START_SET,
+ (char *)c->vbases[ACD_BASE] + ACD_AUTOXFER);
+
+ /* Ensure writes complete before polling */
+ clk_osm_acd_mb(c);
+
+ /* Poll auto-transfer status register */
+ for (timeout = ACD_LOCAL_TRANSFER_TIMEOUT_NS * numregs;
+ timeout > 0; timeout -= 100) {
+ reg = readl_relaxed((char *)c->vbases[ACD_BASE]
+ + ACD_AUTOXFER_STATUS);
+ if (reg & AUTO_XFER_DONE_MASK)
+ break;
+ ndelay(100);
+ }
+
+ if (!timeout) {
+ pr_err("local register auto-transfer timed out, mask=0x%x registers=%d status=0x%x\n",
+ mask, numregs, reg);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
static inline int clk_osm_count_ns(struct clk_osm *c, u64 nsec)
{
u64 temp;
@@ -813,6 +1009,74 @@ static int clk_osm_parse_dt_configs(struct platform_device *pdev)
LLM_SW_OVERRIDE_CNT + i,
&perfcl_clk.llm_sw_overr[i]);
+ if (pwrcl_clk.acd_init || perfcl_clk.acd_init) {
+ rc = of_property_read_u32_array(of, "qcom,acdtd-val",
+ array, MAX_CLUSTER_CNT);
+ if (rc) {
+ dev_err(&pdev->dev, "unable to find qcom,acdtd-val property, rc=%d\n",
+ rc);
+ return -EINVAL;
+ }
+
+ pwrcl_clk.acd_td = array[pwrcl_clk.cluster_num];
+ perfcl_clk.acd_td = array[perfcl_clk.cluster_num];
+
+ rc = of_property_read_u32_array(of, "qcom,acdcr-val",
+ array, MAX_CLUSTER_CNT);
+ if (rc) {
+ dev_err(&pdev->dev, "unable to find qcom,acdcr-val property, rc=%d\n",
+ rc);
+ return -EINVAL;
+ }
+
+ pwrcl_clk.acd_cr = array[pwrcl_clk.cluster_num];
+ perfcl_clk.acd_cr = array[perfcl_clk.cluster_num];
+
+ rc = of_property_read_u32_array(of, "qcom,acdsscr-val",
+ array, MAX_CLUSTER_CNT);
+ if (rc) {
+ dev_err(&pdev->dev, "unable to find qcom,acdsscr-val property, rc=%d\n",
+ rc);
+ return -EINVAL;
+ }
+
+ pwrcl_clk.acd_sscr = array[pwrcl_clk.cluster_num];
+ perfcl_clk.acd_sscr = array[perfcl_clk.cluster_num];
+
+ rc = of_property_read_u32_array(of, "qcom,acdextint0-val",
+ array, MAX_CLUSTER_CNT);
+ if (rc) {
+ dev_err(&pdev->dev, "unable to find qcom,acdextint0-val property, rc=%d\n",
+ rc);
+ return -EINVAL;
+ }
+
+ pwrcl_clk.acd_extint0_cfg = array[pwrcl_clk.cluster_num];
+ perfcl_clk.acd_extint0_cfg = array[perfcl_clk.cluster_num];
+
+ rc = of_property_read_u32_array(of, "qcom,acdextint1-val",
+ array, MAX_CLUSTER_CNT);
+ if (rc) {
+ dev_err(&pdev->dev, "unable to find qcom,acdextint1-val property, rc=%d\n",
+ rc);
+ return -EINVAL;
+ }
+
+ pwrcl_clk.acd_extint1_cfg = array[pwrcl_clk.cluster_num];
+ perfcl_clk.acd_extint1_cfg = array[perfcl_clk.cluster_num];
+
+ rc = of_property_read_u32_array(of, "qcom,acdautoxfer-val",
+ array, MAX_CLUSTER_CNT);
+ if (rc) {
+ dev_err(&pdev->dev, "unable to find qcom,acdautoxfer-val property, rc=%d\n",
+ rc);
+ return -EINVAL;
+ }
+
+ pwrcl_clk.acd_autoxfer_ctl = array[pwrcl_clk.cluster_num];
+ perfcl_clk.acd_autoxfer_ctl = array[perfcl_clk.cluster_num];
+ }
+
rc = of_property_read_u32(of, "qcom,xo-clk-rate",
&pwrcl_clk.xo_clk_rate);
if (rc) {
@@ -1037,6 +1301,40 @@ static int clk_osm_resources_init(struct platform_device *pdev)
perfcl_clk.vbases[EFUSE_BASE] = vbase;
}
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "pwrcl_acd");
+ if (res) {
+ pbase = (unsigned long)res->start;
+ vbase = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!vbase) {
+ dev_err(&pdev->dev, "Unable to map in pwrcl_acd base\n");
+ return -ENOMEM;
+ }
+ pwrcl_clk.pbases[ACD_BASE] = pbase;
+ pwrcl_clk.vbases[ACD_BASE] = vbase;
+ pwrcl_clk.acd_init = true;
+ } else {
+ pwrcl_clk.acd_init = false;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "perfcl_acd");
+ if (res) {
+ pbase = (unsigned long)res->start;
+ vbase = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!vbase) {
+ dev_err(&pdev->dev, "Unable to map in perfcl_acd base\n");
+ return -ENOMEM;
+ }
+ perfcl_clk.pbases[ACD_BASE] = pbase;
+ perfcl_clk.vbases[ACD_BASE] = vbase;
+ perfcl_clk.acd_init = true;
+ } else {
+ perfcl_clk.acd_init = false;
+ }
+
vdd_pwrcl = devm_regulator_get(&pdev->dev, "vdd-pwrcl");
if (IS_ERR(vdd_pwrcl)) {
rc = PTR_ERR(vdd_pwrcl);
@@ -2402,6 +2700,55 @@ DEFINE_SIMPLE_ATTRIBUTE(debugfs_perf_state_deviation_corrected_irq_fops,
debugfs_set_perf_state_deviation_corrected_irq,
"%llu\n");
+static int debugfs_get_debug_reg(void *data, u64 *val)
+{
+ struct clk_osm *c = data;
+
+ if (c->acd_debugfs_addr >= ACD_MASTER_ONLY_REG_ADDR)
+ *val = readl_relaxed((char *)c->vbases[ACD_BASE] +
+ c->acd_debugfs_addr);
+ else
+ *val = clk_osm_acd_local_read_reg(c, c->acd_debugfs_addr);
+ return 0;
+}
+
+static int debugfs_set_debug_reg(void *data, u64 val)
+{
+ struct clk_osm *c = data;
+
+ if (c->acd_debugfs_addr >= ACD_MASTER_ONLY_REG_ADDR)
+ clk_osm_acd_master_write_reg(c, val, c->acd_debugfs_addr);
+ else
+ clk_osm_acd_master_write_through_reg(c, val,
+ c->acd_debugfs_addr);
+
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(debugfs_acd_debug_reg_fops,
+ debugfs_get_debug_reg,
+ debugfs_set_debug_reg,
+ "0x%llx\n");
+
+static int debugfs_get_debug_reg_addr(void *data, u64 *val)
+{
+ struct clk_osm *c = data;
+
+ *val = c->acd_debugfs_addr;
+ return 0;
+}
+
+static int debugfs_set_debug_reg_addr(void *data, u64 val)
+{
+ struct clk_osm *c = data;
+
+ c->acd_debugfs_addr = val;
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(debugfs_acd_debug_reg_addr_fops,
+ debugfs_get_debug_reg_addr,
+ debugfs_set_debug_reg_addr,
+ "%llu\n");
+
static void populate_debugfs_dir(struct clk_osm *c)
{
struct dentry *temp;
@@ -2493,6 +2840,24 @@ static void populate_debugfs_dir(struct clk_osm *c)
goto exit;
}
+ temp = debugfs_create_file("acd_debug_reg",
+ S_IRUGO | S_IWUSR,
+ c->debugfs, c,
+ &debugfs_acd_debug_reg_fops);
+ if (IS_ERR_OR_NULL(temp)) {
+ pr_err("debugfs_acd_debug_reg_fops debugfs file creation failed\n");
+ goto exit;
+ }
+
+ temp = debugfs_create_file("acd_debug_reg_addr",
+ S_IRUGO | S_IWUSR,
+ c->debugfs, c,
+ &debugfs_acd_debug_reg_addr_fops);
+ if (IS_ERR_OR_NULL(temp)) {
+ pr_err("debugfs_acd_debug_reg_addr_fops debugfs file creation failed\n");
+ goto exit;
+ }
+
exit:
if (IS_ERR_OR_NULL(temp))
debugfs_remove_recursive(c->debugfs);
@@ -2537,6 +2902,81 @@ static int clk_osm_panic_callback(struct notifier_block *nfb,
return NOTIFY_OK;
}
+static int clk_osm_acd_init(struct clk_osm *c)
+{
+
+ int rc = 0;
+ u32 auto_xfer_mask = 0;
+
+ if (!c->acd_init)
+ return 0;
+
+ c->acd_debugfs_addr = ACD_HW_VERSION;
+
+ /* Program ACD tunable-length delay register */
+ clk_osm_acd_master_write_reg(c, c->acd_td, ACDTD);
+ auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACDTD);
+
+ /* Program ACD control register */
+ clk_osm_acd_master_write_reg(c, c->acd_cr, ACDCR);
+ auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACDCR);
+
+ /* Program ACD soft start control register */
+ clk_osm_acd_master_write_reg(c, c->acd_sscr, ACDSSCR);
+ auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACDSSCR);
+
+ /* Program initial ACD external interface configuration register */
+ clk_osm_acd_master_write_reg(c, c->acd_extint0_cfg, ACD_EXTINT_CFG);
+ auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACD_EXTINT_CFG);
+
+ /* Program ACD auto-register transfer control register */
+ clk_osm_acd_master_write_reg(c, c->acd_autoxfer_ctl, ACD_AUTOXFER_CTL);
+
+ /* Ensure writes complete before transfers to local copy */
+ clk_osm_acd_mb(c);
+
+ /* Transfer master copies */
+ rc = clk_osm_acd_auto_local_write_reg(c, auto_xfer_mask);
+ if (rc)
+ return rc;
+
+ /* Switch CPUSS clock source to ACD clock */
+ rc = clk_osm_acd_master_write_through_reg(c, ACD_GFMUX_CFG_SELECT,
+ ACD_GFMUX_CFG);
+ if (rc)
+ return rc;
+
+ /* Program ACD_DCVS_SW */
+ rc = clk_osm_acd_master_write_through_reg(c,
+ ACD_DCVS_SW_DCVS_IN_PRGR_SET,
+ ACD_DCVS_SW);
+ if (rc)
+ return rc;
+
+ rc = clk_osm_acd_master_write_through_reg(c,
+ ACD_DCVS_SW_DCVS_IN_PRGR_CLEAR,
+ ACD_DCVS_SW);
+ if (rc)
+ return rc;
+
+ udelay(1);
+
+ /* Program final ACD external interface configuration register */
+ rc = clk_osm_acd_master_write_through_reg(c, c->acd_extint1_cfg,
+ ACD_EXTINT_CFG);
+ if (rc)
+ return rc;
+
+ /*
+ * ACDCR, ACDTD, ACDSSCR, ACD_EXTINT_CFG, ACD_GFMUX_CFG
+ * must be copied from master to local copy on PC exit.
+ */
+ auto_xfer_mask |= ACD_REG_RELATIVE_ADDR_BITMASK(ACD_GFMUX_CFG);
+ clk_osm_acd_master_write_reg(c, auto_xfer_mask, ACD_AUTOXFER_CFG);
+
+ return 0;
+}
+
static unsigned long init_rate = 300000000;
static unsigned long osm_clk_init_rate = 200000000;
@@ -2717,6 +3157,17 @@ static int cpu_clock_osm_driver_probe(struct platform_device *pdev)
clk_osm_setup_cluster_pll(&perfcl_clk);
}
+ rc = clk_osm_acd_init(&pwrcl_clk);
+ if (rc) {
+ pr_err("failed to initialize ACD for pwrcl, rc=%d\n", rc);
+ return rc;
+ }
+ rc = clk_osm_acd_init(&perfcl_clk);
+ if (rc) {
+ pr_err("failed to initialize ACD for perfcl, rc=%d\n", rc);
+ return rc;
+ }
+
spin_lock_init(&pwrcl_clk.lock);
spin_lock_init(&perfcl_clk.lock);
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 4d46d65898d1..1501c5da4a6c 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -20,28 +20,34 @@
#include "clk-alpha-pll.h"
#define PLL_MODE 0x00
-# define PLL_OUTCTRL BIT(0)
-# define PLL_BYPASSNL BIT(1)
-# define PLL_RESET_N BIT(2)
-# define PLL_LOCK_COUNT_SHIFT 8
-# define PLL_LOCK_COUNT_MASK 0x3f
-# define PLL_BIAS_COUNT_SHIFT 14
-# define PLL_BIAS_COUNT_MASK 0x3f
-# define PLL_VOTE_FSM_ENA BIT(20)
-# define PLL_VOTE_FSM_RESET BIT(21)
-# define PLL_ACTIVE_FLAG BIT(30)
-# define PLL_LOCK_DET BIT(31)
+#define PLL_OUTCTRL BIT(0)
+#define PLL_BYPASSNL BIT(1)
+#define PLL_RESET_N BIT(2)
+#define PLL_LOCK_COUNT_SHIFT 8
+#define PLL_LOCK_COUNT_MASK 0x3f
+#define PLL_LOCK_COUNT_VAL 0x0
+#define PLL_BIAS_COUNT_SHIFT 14
+#define PLL_BIAS_COUNT_MASK 0x3f
+#define PLL_BIAS_COUNT_VAL 0x6
+#define PLL_LATCH_INTERFACE BIT(11)
+#define PLL_VOTE_FSM_ENA BIT(20)
+#define PLL_VOTE_FSM_RESET BIT(21)
+#define PLL_UPDATE BIT(22)
+#define PLL_HW_UPDATE_LOGIC_BYPASS BIT(23)
+#define PLL_ALPHA_EN BIT(24)
+#define PLL_ACTIVE_FLAG BIT(30)
+#define PLL_LOCK_DET BIT(31)
+#define PLL_ACK_LATCH BIT(29)
#define PLL_L_VAL 0x04
#define PLL_ALPHA_VAL 0x08
#define PLL_ALPHA_VAL_U 0x0c
#define PLL_USER_CTL 0x10
-# define PLL_POST_DIV_SHIFT 8
-# define PLL_POST_DIV_MASK 0xf
-# define PLL_ALPHA_EN BIT(24)
-# define PLL_VCO_SHIFT 20
-# define PLL_VCO_MASK 0x3
+#define PLL_POST_DIV_SHIFT 8
+#define PLL_POST_DIV_MASK 0xf
+#define PLL_VCO_SHIFT 20
+#define PLL_VCO_MASK 0x3
#define PLL_USER_CTL_U 0x14
@@ -79,7 +85,7 @@ static int wait_for_pll(struct clk_alpha_pll *pll, u32 mask, bool inverse,
ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
if (ret)
return ret;
- if (inverse && (val & mask))
+ if (inverse && !(val & mask))
return 0;
else if ((val & mask) == mask)
return 0;
@@ -106,6 +112,10 @@ static int wait_for_pll_offline(struct clk_alpha_pll *pll, u32 mask)
return wait_for_pll(pll, mask, 0, "offline");
}
+static int wait_for_pll_latch_ack(struct clk_alpha_pll *pll, u32 mask)
+{
+ return wait_for_pll(pll, mask, 0, "latch_ack");
+}
/* alpha pll with hwfsm support */
@@ -114,29 +124,105 @@ static int wait_for_pll_offline(struct clk_alpha_pll *pll, u32 mask)
#define PLL_OFFLINE_ACK BIT(28)
#define PLL_ACTIVE_FLAG BIT(30)
+static void clk_alpha_set_fsm_mode(struct clk_alpha_pll *pll)
+{
+ u32 val;
+
+ regmap_read(pll->clkr.regmap, pll->offset + PLL_MODE, &val);
+
+ /* De-assert reset to FSM */
+ val &= ~PLL_VOTE_FSM_RESET;
+
+ /* Program bias count */
+ val &= ~(PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT);
+ val |= PLL_BIAS_COUNT_VAL << PLL_BIAS_COUNT_SHIFT;
+
+ /* Program lock count */
+ val &= ~(PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT);
+ val |= PLL_LOCK_COUNT_VAL << PLL_LOCK_COUNT_SHIFT;
+
+ /* Enable PLL FSM voting */
+ val |= PLL_VOTE_FSM_ENA;
+
+ regmap_write(pll->clkr.regmap, pll->offset + PLL_MODE, val);
+}
+
void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
- const struct pll_config *config)
+ const struct pll_config *config)
{
u32 val, mask;
- regmap_write(regmap, pll->offset + PLL_CONFIG_CTL,
- config->config_ctl_val);
+ if (config->l)
+ regmap_write(regmap, pll->offset + PLL_L_VAL,
+ config->l);
+ if (config->alpha)
+ regmap_write(regmap, pll->offset + PLL_ALPHA_VAL,
+ config->alpha);
+ if (config->alpha_u)
+ regmap_write(regmap, pll->offset + PLL_ALPHA_VAL_U,
+ config->alpha_u);
+ if (config->config_ctl_val)
+ regmap_write(regmap, pll->offset + PLL_CONFIG_CTL,
+ config->config_ctl_val);
+
+ if (config->main_output_mask || config->aux_output_mask ||
+ config->aux2_output_mask || config->early_output_mask ||
+ config->vco_val || config->alpha_en_mask) {
+
+ val = config->main_output_mask;
+ val |= config->aux_output_mask;
+ val |= config->aux2_output_mask;
+ val |= config->early_output_mask;
+ val |= config->vco_val;
+ val |= config->alpha_en_mask;
+
+ mask = config->main_output_mask;
+ mask |= config->aux_output_mask;
+ mask |= config->aux2_output_mask;
+ mask |= config->early_output_mask;
+ mask |= config->vco_mask;
+ mask |= config->alpha_en_mask;
+
+ regmap_update_bits(regmap, pll->offset + PLL_USER_CTL,
+ mask, val);
+ }
+
+ if (config->post_div_mask) {
+ mask = config->post_div_mask;
+ val = config->post_div_val;
+ regmap_update_bits(regmap, pll->offset + PLL_USER_CTL,
+ mask, val);
+ }
+
+ /* Do not bypass the latch interface */
+ if (pll->flags & SUPPORTS_SLEW)
+ regmap_update_bits(regmap, pll->offset + PLL_USER_CTL_U,
+ PLL_LATCH_INTERFACE, (u32)~PLL_LATCH_INTERFACE);
- val = config->main_output_mask;
- val |= config->aux_output_mask;
- val |= config->aux2_output_mask;
- val |= config->early_output_mask;
- val |= config->post_div_val;
+ if (pll->flags & SUPPORTS_DYNAMIC_UPDATE) {
+ regmap_update_bits(regmap, pll->offset + PLL_MODE,
+ PLL_HW_UPDATE_LOGIC_BYPASS,
+ PLL_HW_UPDATE_LOGIC_BYPASS);
+ }
+
+ if (config->test_ctl_lo_mask) {
+ mask = config->test_ctl_lo_mask;
+ val = config->test_ctl_lo_val;
+ regmap_update_bits(regmap, pll->offset + PLL_TEST_CTL,
+ mask, val);
+ }
- mask = config->main_output_mask;
- mask |= config->aux_output_mask;
- mask |= config->aux2_output_mask;
- mask |= config->early_output_mask;
- mask |= config->post_div_mask;
+ if (config->test_ctl_hi_mask) {
+ mask = config->test_ctl_hi_mask;
+ val = config->test_ctl_hi_val;
+ regmap_update_bits(regmap, pll->offset + PLL_TEST_CTL_U,
+ mask, val);
+ }
- regmap_update_bits(regmap, pll->offset + PLL_USER_CTL, mask, val);
+ if (pll->flags & SUPPORTS_FSM_MODE)
+ clk_alpha_set_fsm_mode(pll);
- return;
+ pll->inited = true;
}
static int clk_alpha_pll_hwfsm_enable(struct clk_hw *hw)
@@ -190,8 +276,9 @@ static void clk_alpha_pll_hwfsm_disable(struct clk_hw *hw)
PLL_FSM_ENA, 0);
if (ret)
return;
+
wait_for_pll_disable(pll, PLL_ACTIVE_FLAG);
- return;
+
}
static int clk_alpha_pll_enable(struct clk_hw *hw)
@@ -202,6 +289,11 @@ static int clk_alpha_pll_enable(struct clk_hw *hw)
off = pll->offset;
+ if (unlikely(!pll->inited)) {
+ clk_alpha_pll_configure(pll, pll->clkr.regmap,
+ pll->config);
+ }
+
mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
if (ret)
@@ -339,7 +431,53 @@ clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
}
- return alpha_pll_calc_rate(prate, l, a);
+ ctl >>= PLL_POST_DIV_SHIFT;
+ ctl &= PLL_POST_DIV_MASK;
+
+ return alpha_pll_calc_rate(prate, l, a) >> fls(ctl);
+}
+
+static int clk_alpha_pll_dynamic_update(struct clk_alpha_pll *pll)
+{
+ int ret;
+
+ /* Latch the input to the PLL */
+ regmap_update_bits(pll->clkr.regmap, pll->offset + PLL_MODE,
+ PLL_UPDATE, PLL_UPDATE);
+
+ /* Wait for 2 reference cycle before checking ACK bit */
+ udelay(1);
+
+ ret = wait_for_pll_latch_ack(pll, PLL_ACK_LATCH);
+ if (ret)
+ return ret;
+
+ /* Return latch input to 0 */
+ regmap_update_bits(pll->clkr.regmap, pll->offset + PLL_MODE,
+ PLL_UPDATE, (u32)~PLL_UPDATE);
+
+ ret = wait_for_pll_enable(pll, PLL_LOCK_DET);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct pll_vco_data
+ *find_vco_data(const struct pll_vco_data *data,
+ unsigned long rate, size_t size)
+{
+ int i;
+
+ if (!data)
+ return NULL;
+
+ for (i = 0; i < size; i++) {
+ if (rate == data[i].freq)
+ return &data[i];
+ }
+
+ return &data[i - 1];
}
static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -347,16 +485,36 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
const struct pll_vco *vco;
+ const struct pll_vco_data *data;
+ bool is_enabled;
u32 l, off = pll->offset;
u64 a;
+ unsigned long rrate;
+
+ rrate = alpha_pll_round_rate(rate, prate, &l, &a);
- rate = alpha_pll_round_rate(rate, prate, &l, &a);
- vco = alpha_pll_find_vco(pll, rate);
+ if (rrate != rate) {
+ pr_err("alpha_pll: Call clk_set_rate with rounded rates!\n");
+ return -EINVAL;
+ }
+
+ vco = alpha_pll_find_vco(pll, rrate);
if (!vco) {
pr_err("alpha pll not in a valid vco range\n");
return -EINVAL;
}
+ is_enabled = clk_hw_is_enabled(hw);
+
+ /*
+ * For PLLs that do not support dynamic programming (dynamic_update
+ * is not set), ensure PLL is off before changing rate. For
+ * optimization reasons, assume no downstream clock is actively
+ * using it.
+ */
+ if (is_enabled && !(pll->flags & SUPPORTS_DYNAMIC_UPDATE))
+ hw->init->ops->disable(hw);
+
a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
@@ -367,9 +525,27 @@ static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
PLL_VCO_MASK << PLL_VCO_SHIFT,
vco->val << PLL_VCO_SHIFT);
+ data = find_vco_data(pll->vco_data, rate, pll->num_vco_data);
+ if (data) {
+ if (data->freq == rate)
+ regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
+ PLL_POST_DIV_MASK << PLL_POST_DIV_SHIFT,
+ data->post_div_val << PLL_POST_DIV_SHIFT);
+ else
+ regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
+ PLL_POST_DIV_MASK << PLL_POST_DIV_SHIFT,
+ 0x0 << PLL_VCO_SHIFT);
+ }
+
regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, PLL_ALPHA_EN,
PLL_ALPHA_EN);
+ if (is_enabled && (pll->flags & SUPPORTS_DYNAMIC_UPDATE))
+ clk_alpha_pll_dynamic_update(pll);
+
+ if (is_enabled && !(pll->flags & SUPPORTS_DYNAMIC_UPDATE))
+ hw->init->ops->enable(hw);
+
return 0;
}
@@ -381,6 +557,9 @@ static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
u64 a;
unsigned long min_freq, max_freq;
+ if (rate < pll->min_supported_freq)
+ return pll->min_supported_freq;
+
rate = alpha_pll_round_rate(rate, *prate, &l, &a);
if (alpha_pll_find_vco(pll, rate))
return rate;
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index 7718bd5beefc..425cf3afef9e 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-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
@@ -18,6 +18,11 @@
#include "clk-regmap.h"
#include "clk-pll.h"
+struct pll_vco_data {
+ unsigned long freq;
+ u8 post_div_val;
+};
+
struct pll_vco {
unsigned long min_freq;
unsigned long max_freq;
@@ -28,21 +33,36 @@ struct pll_vco {
* struct clk_alpha_pll - phase locked loop (PLL)
* @offset: base address of registers
* @vco_table: array of VCO settings
+ * @vco_data: array of VCO data settings like post div
* @clkr: regmap clock handle
*/
struct clk_alpha_pll {
u32 offset;
+ struct pll_config *config;
+ bool inited;
const struct pll_vco *vco_table;
size_t num_vco;
+ const struct pll_vco_data *vco_data;
+ size_t num_vco_data;
+
+ u8 flags;
+#define SUPPORTS_FSM_MODE BIT(0)
+ /* some PLLs support dynamically updating their rate
+ * without disabling the PLL first. Set this flag
+ * to enable this support.
+ */
+#define SUPPORTS_DYNAMIC_UPDATE BIT(1)
+#define SUPPORTS_SLEW BIT(2)
+
struct clk_regmap clkr;
- u32 config_ctl_val;
#define PLLOUT_MAIN BIT(0)
#define PLLOUT_AUX BIT(1)
#define PLLOUT_AUX2 BIT(2)
#define PLLOUT_EARLY BIT(3)
u32 pllout_flags;
+ unsigned long min_supported_freq;
};
/**
diff --git a/drivers/clk/qcom/clk-pll.h b/drivers/clk/qcom/clk-pll.h
index 1e64fe9326d6..4f779fda785b 100644
--- a/drivers/clk/qcom/clk-pll.h
+++ b/drivers/clk/qcom/clk-pll.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013, 2016 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
@@ -70,6 +70,8 @@ struct pll_config {
u16 l;
u32 m;
u32 n;
+ u32 alpha;
+ u32 alpha_u;
u32 vco_val;
u32 vco_mask;
u32 pre_div_val;
@@ -77,11 +79,16 @@ struct pll_config {
u32 post_div_val;
u32 post_div_mask;
u32 mn_ena_mask;
+ u32 alpha_en_mask;
u32 main_output_mask;
u32 aux_output_mask;
u32 aux2_output_mask;
u32 early_output_mask;
u32 config_ctl_val;
+ u32 test_ctl_lo_val;
+ u32 test_ctl_lo_mask;
+ u32 test_ctl_hi_val;
+ u32 test_ctl_hi_mask;
};
void clk_pll_configure_sr(struct clk_pll *pll, struct regmap *regmap,
diff --git a/drivers/clk/qcom/gcc-msm8916.c b/drivers/clk/qcom/gcc-msm8916.c
index d0a0313d6bef..2e7f03d50f4e 100644
--- a/drivers/clk/qcom/gcc-msm8916.c
+++ b/drivers/clk/qcom/gcc-msm8916.c
@@ -2346,6 +2346,7 @@ static struct clk_branch gcc_crypto_ahb_clk = {
"pcnoc_bfdcd_clk_src",
},
.num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
@@ -2381,6 +2382,7 @@ static struct clk_branch gcc_crypto_clk = {
"crypto_clk_src",
},
.num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
},
},
diff --git a/drivers/clk/qcom/gcc-msmfalcon.c b/drivers/clk/qcom/gcc-msmfalcon.c
index 42b91d70aa54..b5f7e18cf495 100644
--- a/drivers/clk/qcom/gcc-msmfalcon.c
+++ b/drivers/clk/qcom/gcc-msmfalcon.c
@@ -35,8 +35,8 @@
#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
-static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
-static DEFINE_VDD_REGULATORS(vdd_dig_ao, VDD_DIG_NUM, 1, vdd_corner, NULL);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
+static DEFINE_VDD_REGULATORS(vdd_dig_ao, VDD_DIG_NUM, 1, vdd_corner);
enum {
P_CORE_BI_PLL_TEST_SE,
@@ -2201,7 +2201,7 @@ static struct clk_branch gcc_ufs_axi_hw_ctl_clk = {
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_hw_ctl_ops,
+ .ops = &clk_branch2_ops,
},
},
};
@@ -2249,7 +2249,7 @@ static struct clk_branch gcc_ufs_ice_core_hw_ctl_clk = {
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_hw_ctl_ops,
+ .ops = &clk_branch2_ops,
},
},
};
@@ -2284,7 +2284,7 @@ static struct clk_branch gcc_ufs_phy_aux_hw_ctl_clk = {
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_hw_ctl_ops,
+ .ops = &clk_branch2_ops,
},
},
};
@@ -2355,7 +2355,7 @@ static struct clk_branch gcc_ufs_unipro_core_hw_ctl_clk = {
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
- .ops = &clk_branch2_hw_ctl_ops,
+ .ops = &clk_branch2_ops,
},
},
};
@@ -2753,9 +2753,8 @@ MODULE_DEVICE_TABLE(of, gcc_falcon_match_table);
static int gcc_falcon_probe(struct platform_device *pdev)
{
- int ret = 0, i;
+ int ret = 0;
struct regmap *regmap;
- struct clk *clk;
regmap = qcom_cc_map(pdev, &gcc_falcon_desc);
if (IS_ERR(regmap))
diff --git a/drivers/clk/qcom/gpucc-msmfalcon.c b/drivers/clk/qcom/gpucc-msmfalcon.c
index f194abb471cd..fe7cff443250 100644
--- a/drivers/clk/qcom/gpucc-msmfalcon.c
+++ b/drivers/clk/qcom/gpucc-msmfalcon.c
@@ -35,8 +35,8 @@
#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
#define F_GFX(f, s, h, m, n, sf) { (f), (s), (2 * (h) - 1), (m), (n), (sf) }
-static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
-static DEFINE_VDD_REGULATORS(vdd_mx, VDD_DIG_NUM, 1, vdd_corner, NULL);
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner);
+static DEFINE_VDD_REGULATORS(vdd_mx, VDD_DIG_NUM, 1, vdd_corner);
static DEFINE_VDD_REGS_INIT(vdd_gfx, 1);
enum {
@@ -181,6 +181,7 @@ static struct clk_init_data gpu_clks_init[] = {
* | 465000000 | 930000000 | 1 | 2 |
* | 588000000 | 1176000000 | 1 | 2 |
* | 647000000 | 1294000000 | 1 | 2 |
+ * | 700000000 | 1400000000 | 1 | 2 |
* | 750000000 | 1500000000 | 1 | 2 |
* ====================================================
*/
@@ -193,6 +194,7 @@ static const struct freq_tbl ftbl_gfx3d_clk_src[] = {
F_GFX(465000000, 0, 2, 0, 0, 930000000),
F_GFX(588000000, 0, 2, 0, 0, 1176000000),
F_GFX(647000000, 0, 2, 0, 0, 1294000000),
+ F_GFX(700000000, 0, 2, 0, 0, 1400000000),
F_GFX(750000000, 0, 2, 0, 0, 1500000000),
{ }
};
@@ -376,9 +378,9 @@ static int of_get_fmax_vdd_class(struct platform_device *pdev,
if (!vdd->vdd_uv)
return -ENOMEM;
- gpu_clks_init[index].fmax = devm_kzalloc(&pdev->dev, prop_len *
+ gpu_clks_init[index].rate_max = devm_kzalloc(&pdev->dev, prop_len *
sizeof(unsigned long), GFP_KERNEL);
- if (!gpu_clks_init[index].fmax)
+ if (!gpu_clks_init[index].rate_max)
return -ENOMEM;
array = devm_kzalloc(&pdev->dev, prop_len * sizeof(u32) * num,
@@ -388,7 +390,7 @@ static int of_get_fmax_vdd_class(struct platform_device *pdev,
of_property_read_u32_array(of, prop_name, array, prop_len * num);
for (i = 0; i < prop_len; i++) {
- gpu_clks_init[index].fmax[i] = array[num * i];
+ gpu_clks_init[index].rate_max[i] = array[num * i];
for (j = 1; j < num; j++) {
vdd->vdd_uv[(num - 1) * i + (j - 1)] =
array[num * i + j];
@@ -398,7 +400,7 @@ static int of_get_fmax_vdd_class(struct platform_device *pdev,
devm_kfree(&pdev->dev, array);
vdd->num_levels = prop_len;
vdd->cur_level = prop_len;
- gpu_clks_init[index].num_fmax = prop_len;
+ gpu_clks_init[index].num_rate_max = prop_len;
return 0;
}
diff --git a/drivers/clk/qcom/vdd-level-falcon.h b/drivers/clk/qcom/vdd-level-falcon.h
index e8699358cf91..d54e801ecc67 100644
--- a/drivers/clk/qcom/vdd-level-falcon.h
+++ b/drivers/clk/qcom/vdd-level-falcon.h
@@ -19,50 +19,52 @@
#define VDD_DIG_FMAX_MAP1(l1, f1) \
.vdd_class = &vdd_dig, \
- .fmax = (unsigned long[VDD_DIG_NUM]) { \
+ .rate_max = (unsigned long[VDD_DIG_NUM]) { \
[VDD_DIG_##l1] = (f1), \
}, \
- .num_fmax = VDD_DIG_NUM
+ .num_rate_max = VDD_DIG_NUM
+
#define VDD_DIG_FMAX_MAP2(l1, f1, l2, f2) \
.vdd_class = &vdd_dig, \
- .fmax = (unsigned long[VDD_DIG_NUM]) { \
+ .rate_max = (unsigned long[VDD_DIG_NUM]) { \
[VDD_DIG_##l1] = (f1), \
[VDD_DIG_##l2] = (f2), \
}, \
- .num_fmax = VDD_DIG_NUM
+ .num_rate_max = VDD_DIG_NUM
#define VDD_DIG_FMAX_MAP3(l1, f1, l2, f2, l3, f3) \
.vdd_class = &vdd_dig, \
- .fmax = (unsigned long[VDD_DIG_NUM]) { \
+ .rate_max = (unsigned long[VDD_DIG_NUM]) { \
[VDD_DIG_##l1] = (f1), \
[VDD_DIG_##l2] = (f2), \
[VDD_DIG_##l3] = (f3), \
}, \
- .num_fmax = VDD_DIG_NUM
+ .num_rate_max = VDD_DIG_NUM
+
#define VDD_DIG_FMAX_MAP4(l1, f1, l2, f2, l3, f3, l4, f4) \
.vdd_class = &vdd_dig, \
- .fmax = (unsigned long[VDD_DIG_NUM]) { \
+ .rate_max = (unsigned long[VDD_DIG_NUM]) { \
[VDD_DIG_##l1] = (f1), \
[VDD_DIG_##l2] = (f2), \
[VDD_DIG_##l3] = (f3), \
[VDD_DIG_##l4] = (f4), \
}, \
- .num_fmax = VDD_DIG_NUM
+ .num_rate_max = VDD_DIG_NUM
#define VDD_DIG_FMAX_MAP5(l1, f1, l2, f2, l3, f3, l4, f4, l5, f5) \
.vdd_class = &vdd_dig, \
- .fmax = (unsigned long[VDD_DIG_NUM]) { \
+ .rate_max = (unsigned long[VDD_DIG_NUM]) { \
[VDD_DIG_##l1] = (f1), \
[VDD_DIG_##l2] = (f2), \
[VDD_DIG_##l3] = (f3), \
[VDD_DIG_##l4] = (f4), \
[VDD_DIG_##l5] = (f5), \
}, \
- .num_fmax = VDD_DIG_NUM
+ .num_rate_max = VDD_DIG_NUM
#define VDD_DIG_FMAX_MAP6(l1, f1, l2, f2, l3, f3, l4, f4, l5, f5, l6, f6) \
.vdd_class = &vdd_dig, \
- .fmax = (unsigned long[VDD_DIG_NUM]) { \
+ .rate_max = (unsigned long[VDD_DIG_NUM]) { \
[VDD_DIG_##l1] = (f1), \
[VDD_DIG_##l2] = (f2), \
[VDD_DIG_##l3] = (f3), \
@@ -70,12 +72,12 @@
[VDD_DIG_##l5] = (f5), \
[VDD_DIG_##l6] = (f6), \
}, \
- .num_fmax = VDD_DIG_NUM
+ .num_rate_max = VDD_DIG_NUM
#define VDD_DIG_FMAX_MAP7(l1, f1, l2, f2, l3, f3, l4, f4, l5, f5, l6, f6, \
l7, f7) \
.vdd_class = &vdd_dig, \
- .fmax = (unsigned long[VDD_DIG_NUM]) { \
+ .rate_max = (unsigned long[VDD_DIG_NUM]) { \
[VDD_DIG_##l1] = (f1), \
[VDD_DIG_##l2] = (f2), \
[VDD_DIG_##l3] = (f3), \
@@ -84,27 +86,27 @@
[VDD_DIG_##l6] = (f6), \
[VDD_DIG_##l7] = (f7), \
}, \
- .num_fmax = VDD_DIG_NUM
+ .num_rate_max = VDD_DIG_NUM
#define VDD_DIG_FMAX_MAP1_AO(l1, f1) \
.vdd_class = &vdd_dig_ao, \
- .fmax = (unsigned long[VDD_DIG_NUM]) { \
+ .rate_max = (unsigned long[VDD_DIG_NUM]) { \
[VDD_DIG_##l1] = (f1), \
}, \
- .num_fmax = VDD_DIG_NUM
+ .num_rate_max = VDD_DIG_NUM
#define VDD_DIG_FMAX_MAP3_AO(l1, f1, l2, f2, l3, f3) \
.vdd_class = &vdd_dig_ao, \
- .fmax = (unsigned long[VDD_DIG_NUM]) { \
+ .rate_max = (unsigned long[VDD_DIG_NUM]) { \
[VDD_DIG_##l1] = (f1), \
[VDD_DIG_##l2] = (f2), \
[VDD_DIG_##l3] = (f3), \
}, \
- .num_fmax = VDD_DIG_NUM
+ .num_rate_max = VDD_DIG_NUM
#define VDD_GPU_PLL_FMAX_MAP6(l1, f1, l2, f2, l3, f3, l4, f4, l5, f5, l6, f6) \
.vdd_class = &vdd_mx, \
- .fmax = (unsigned long[VDD_DIG_NUM]) { \
+ .rate_max = (unsigned long[VDD_DIG_NUM]) { \
[VDD_DIG_##l1] = (f1), \
[VDD_DIG_##l2] = (f2), \
[VDD_DIG_##l3] = (f3), \
@@ -112,7 +114,7 @@
[VDD_DIG_##l5] = (f5), \
[VDD_DIG_##l6] = (f6), \
}, \
- .num_fmax = VDD_DIG_NUM
+ .num_rate_max = VDD_DIG_NUM
enum vdd_dig_levels {
VDD_DIG_NONE,
diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c
index 90638f325d0b..30e1a2138002 100644
--- a/drivers/cpufreq/cpufreq_interactive.c
+++ b/drivers/cpufreq/cpufreq_interactive.c
@@ -162,28 +162,6 @@ struct cpufreq_interactive_tunables {
bool enable_prediction;
};
-/*
- * HACK: FIXME: Bring back cpufreq_{get,put}_global_kobject()
- * definition removed by upstream commit 8eec1020f0c0 "cpufreq:
- * create cpu/cpufreq at boot time" to fix build failures.
- */
-static int cpufreq_global_kobject_usage;
-
-int cpufreq_get_global_kobject(void)
-{
- if (!cpufreq_global_kobject_usage++)
- return kobject_add(cpufreq_global_kobject,
- &cpu_subsys.dev_root->kobj, "%s", "cpufreq");
-
- return 0;
-}
-
-void cpufreq_put_global_kobject(void)
-{
- if (!--cpufreq_global_kobject_usage)
- kobject_del(cpufreq_global_kobject);
-}
-
/* For cases where we have single governor instance for system */
static struct cpufreq_interactive_tunables *common_tunables;
static struct cpufreq_interactive_tunables *cached_common_tunables;
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index a045b9a940e8..7f437bc4431b 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -214,7 +214,7 @@ int cpuidle_enter_state(struct cpuidle_device *dev, struct cpuidle_driver *drv,
tick_broadcast_exit();
}
- if (!cpuidle_state_is_coupled(drv, entered_state))
+ if (!cpuidle_state_is_coupled(drv, index))
local_irq_enable();
diff = ktime_to_us(ktime_sub(time_end, time_start));
@@ -433,6 +433,8 @@ static void __cpuidle_unregister_device(struct cpuidle_device *dev)
list_del(&dev->device_list);
per_cpu(cpuidle_devices, dev->cpu) = NULL;
module_put(drv->owner);
+
+ dev->registered = 0;
}
static void __cpuidle_device_init(struct cpuidle_device *dev)
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index 386c85fc714b..77aea1f41714 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -372,18 +372,18 @@ config CRYPTO_DEV_QCRYPTO
config CRYPTO_DEV_QCOM_MSM_QCE
tristate "Qualcomm Crypto Engine (QCE) module"
- select CRYPTO_DEV_QCE50 if ARCH_APQ8084 || ARCH_MSM8916 || ARCH_MSM8994 || ARCH_MSM8996 || ARCH_MSM8992 || ARCH_MSMTITANIUM || ARCH_MSM8909 || ARCH_MSMCOBALT || ARCH_MSMFALCON
+ select CRYPTO_DEV_QCE50 if ARCH_APQ8084 || ARCH_MSM8916 || ARCH_MSM8994 || ARCH_MSM8996 || ARCH_MSM8992 || ARCH_MSMTITANIUM || ARCH_MSM8909 || ARCH_MSMCOBALT || ARCH_MSMFALCON || ARCH_MSMTRITON
default n
help
This driver supports Qualcomm Crypto Engine in MSM7x30, MSM8660
MSM8x55, MSM8960, MSM9615, MSM8916, MSM8994, MSM8996, FSM9900,
- MSMTITANINUM, APQ8084, MSMCOBALT and MSMFALCON.
+ MSMTITANINUM, APQ8084, MSMCOBALT, MSMFALCON and MSMTRITON.
To compile this driver as a module, choose M here: the
For MSM7x30 MSM8660 and MSM8x55 the module is called qce
For MSM8960, APQ8064 and MSM9615 the module is called qce40
For MSM8974, MSM8916, MSM8994, MSM8996, MSM8992, MSMTITANIUM,
- APQ8084, MSMCOBALT and MSMFALCON the module is called qce50.
+ APQ8084, MSMCOBALT, MSMFALCON and MSMTRITON the module is called qce50.
config CRYPTO_DEV_QCEDEV
tristate "QCEDEV Interface to CE module"
@@ -391,8 +391,8 @@ config CRYPTO_DEV_QCEDEV
help
This driver supports Qualcomm QCEDEV Crypto in MSM7x30, MSM8660,
MSM8960, MSM9615, APQ8064, MSM8974, MSM8916, MSM8994, MSM8996,
- APQ8084, MSMCOBALT, MSMFALCON. This exposes the interface to the QCE hardware
- accelerator via IOCTLs.
+ APQ8084, MSMCOBALT, MSMFALCON, MSMTRITON. This exposes the
+ interface to the QCE hardware accelerator via IOCTLs.
To compile this driver as a module, choose M here: the
module will be called qcedev.
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index f7e0d8d4c3da..8f50a02ff68d 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -248,7 +248,7 @@ static void caam_jr_dequeue(unsigned long devarg)
struct device *caam_jr_alloc(void)
{
struct caam_drv_private_jr *jrpriv, *min_jrpriv = NULL;
- struct device *dev = NULL;
+ struct device *dev = ERR_PTR(-ENODEV);
int min_tfm_cnt = INT_MAX;
int tfm_cnt;
diff --git a/drivers/crypto/ccp/ccp-crypto-aes-xts.c b/drivers/crypto/ccp/ccp-crypto-aes-xts.c
index 52c7395cb8d8..0d0d4529ee36 100644
--- a/drivers/crypto/ccp/ccp-crypto-aes-xts.c
+++ b/drivers/crypto/ccp/ccp-crypto-aes-xts.c
@@ -122,6 +122,7 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
struct ccp_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
struct ccp_aes_req_ctx *rctx = ablkcipher_request_ctx(req);
unsigned int unit;
+ u32 unit_size;
int ret;
if (!ctx->u.aes.key_len)
@@ -133,11 +134,17 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
if (!req->info)
return -EINVAL;
- for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++)
- if (!(req->nbytes & (unit_size_map[unit].size - 1)))
- break;
+ unit_size = CCP_XTS_AES_UNIT_SIZE__LAST;
+ if (req->nbytes <= unit_size_map[0].size) {
+ for (unit = 0; unit < ARRAY_SIZE(unit_size_map); unit++) {
+ if (!(req->nbytes & (unit_size_map[unit].size - 1))) {
+ unit_size = unit_size_map[unit].value;
+ break;
+ }
+ }
+ }
- if ((unit_size_map[unit].value == CCP_XTS_AES_UNIT_SIZE__LAST) ||
+ if ((unit_size == CCP_XTS_AES_UNIT_SIZE__LAST) ||
(ctx->u.aes.key_len != AES_KEYSIZE_128)) {
/* Use the fallback to process the request for any
* unsupported unit sizes or key sizes
@@ -158,7 +165,7 @@ static int ccp_aes_xts_crypt(struct ablkcipher_request *req,
rctx->cmd.engine = CCP_ENGINE_XTS_AES_128;
rctx->cmd.u.xts.action = (encrypt) ? CCP_AES_ACTION_ENCRYPT
: CCP_AES_ACTION_DECRYPT;
- rctx->cmd.u.xts.unit_size = unit_size_map[unit].value;
+ rctx->cmd.u.xts.unit_size = unit_size;
rctx->cmd.u.xts.key = &ctx->u.aes.key_sg;
rctx->cmd.u.xts.key_len = ctx->u.aes.key_len;
rctx->cmd.u.xts.iv = &rctx->iv_sg;
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 3562de7fc967..55c043b44cea 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -3023,6 +3023,7 @@ static void qce_multireq_timeout(unsigned long data)
struct qce_device *pce_dev = (struct qce_device *)data;
int ret = 0;
int last_seq;
+ unsigned long flags;
last_seq = atomic_read(&pce_dev->bunch_cmd_seq);
if (last_seq == 0 ||
@@ -3032,21 +3033,33 @@ static void qce_multireq_timeout(unsigned long data)
return;
}
/* last bunch mode command time out */
+
+ /*
+ * From here to dummy request finish sps request and set owner back
+ * to none, we disable interrupt.
+ * So it won't get preempted or interrupted. If bam inerrupts happen
+ * between, and completion callback gets called from BAM, a new
+ * request may be issued by the client driver. Deadlock may happen.
+ */
+ local_irq_save(flags);
if (cmpxchg(&pce_dev->owner, QCE_OWNER_NONE, QCE_OWNER_TIMEOUT)
!= QCE_OWNER_NONE) {
+ local_irq_restore(flags);
mod_timer(&(pce_dev->timer), (jiffies + DELAY_IN_JIFFIES));
return;
}
- del_timer(&(pce_dev->timer));
- pce_dev->mode = IN_INTERRUPT_MODE;
- pce_dev->qce_stats.no_of_timeouts++;
- pr_debug("pcedev %d mode switch to INTR\n", pce_dev->dev_no);
ret = qce_dummy_req(pce_dev);
if (ret)
pr_warn("pcedev %d: Failed to insert dummy req\n",
pce_dev->dev_no);
cmpxchg(&pce_dev->owner, QCE_OWNER_TIMEOUT, QCE_OWNER_NONE);
+ pce_dev->mode = IN_INTERRUPT_MODE;
+ local_irq_restore(flags);
+
+ del_timer(&(pce_dev->timer));
+ pce_dev->qce_stats.no_of_timeouts++;
+ pr_debug("pcedev %d mode switch to INTR\n", pce_dev->dev_no);
}
void qce_get_driver_stats(void *handle)
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index e63f061175ad..e2099c4e7877 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1234,44 +1234,6 @@ static int qcedev_vbuf_ablk_cipher(struct qcedev_async_req *areq,
struct qcedev_cipher_op_req *saved_req;
struct qcedev_cipher_op_req *creq = &areq->cipher_op_req;
- /* Verify Source Address's */
- for (i = 0; i < areq->cipher_op_req.entries; i++)
- if (!access_ok(VERIFY_READ,
- (void __user *)areq->cipher_op_req.vbuf.src[i].vaddr,
- areq->cipher_op_req.vbuf.src[i].len))
- return -EFAULT;
-
- /* Verify Destination Address's */
- if (creq->in_place_op != 1) {
- for (i = 0, total = 0; i < QCEDEV_MAX_BUFFERS; i++) {
- if ((areq->cipher_op_req.vbuf.dst[i].vaddr != 0) &&
- (total < creq->data_len)) {
- if (!access_ok(VERIFY_WRITE,
- (void __user *)creq->vbuf.dst[i].vaddr,
- creq->vbuf.dst[i].len)) {
- pr_err("%s:DST WR_VERIFY err %d=0x%lx\n",
- __func__, i, (uintptr_t)
- creq->vbuf.dst[i].vaddr);
- return -EFAULT;
- }
- total += creq->vbuf.dst[i].len;
- }
- }
- } else {
- for (i = 0, total = 0; i < creq->entries; i++) {
- if (total < creq->data_len) {
- if (!access_ok(VERIFY_WRITE,
- (void __user *)creq->vbuf.src[i].vaddr,
- creq->vbuf.src[i].len)) {
- pr_err("%s:SRC WR_VERIFY err %d=0x%lx\n",
- __func__, i, (uintptr_t)
- creq->vbuf.src[i].vaddr);
- return -EFAULT;
- }
- total += creq->vbuf.src[i].len;
- }
- }
- }
total = 0;
if (areq->cipher_op_req.mode == QCEDEV_AES_MODE_CTR)
@@ -1569,6 +1531,36 @@ static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req,
__func__, total, req->data_len);
goto error;
}
+ /* Verify Source Address's */
+ for (i = 0, total = 0; i < req->entries; i++) {
+ if (total < req->data_len) {
+ if (!access_ok(VERIFY_READ,
+ (void __user *)req->vbuf.src[i].vaddr,
+ req->vbuf.src[i].len)) {
+ pr_err("%s:SRC RD_VERIFY err %d=0x%lx\n",
+ __func__, i, (uintptr_t)
+ req->vbuf.src[i].vaddr);
+ goto error;
+ }
+ total += req->vbuf.src[i].len;
+ }
+ }
+
+ /* Verify Destination Address's */
+ for (i = 0, total = 0; i < QCEDEV_MAX_BUFFERS; i++) {
+ if ((req->vbuf.dst[i].vaddr != 0) &&
+ (total < req->data_len)) {
+ if (!access_ok(VERIFY_WRITE,
+ (void __user *)req->vbuf.dst[i].vaddr,
+ req->vbuf.dst[i].len)) {
+ pr_err("%s:DST WR_VERIFY err %d=0x%lx\n",
+ __func__, i, (uintptr_t)
+ req->vbuf.dst[i].vaddr);
+ goto error;
+ }
+ total += req->vbuf.dst[i].len;
+ }
+ }
return 0;
error:
return -EINVAL;
diff --git a/drivers/crypto/qat/qat_common/Makefile b/drivers/crypto/qat/qat_common/Makefile
index 9e9e196c6d51..45b5adaafa6f 100644
--- a/drivers/crypto/qat/qat_common/Makefile
+++ b/drivers/crypto/qat/qat_common/Makefile
@@ -2,6 +2,7 @@ $(obj)/qat_rsapubkey-asn1.o: $(obj)/qat_rsapubkey-asn1.c \
$(obj)/qat_rsapubkey-asn1.h
$(obj)/qat_rsaprivkey-asn1.o: $(obj)/qat_rsaprivkey-asn1.c \
$(obj)/qat_rsaprivkey-asn1.h
+$(obj)/qat_asym_algs.o: $(obj)/qat_rsapubkey-asn1.h $(obj)/qat_rsaprivkey-asn1.h
clean-files += qat_rsapubkey-asn1.c qat_rsapubkey-asn1.h
clean-files += qat_rsaprivkey-asn1.c qat_rsapvivkey-asn1.h
diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h
index b9178d0a3093..aa1dbeaa9b49 100644
--- a/drivers/crypto/qat/qat_common/adf_common_drv.h
+++ b/drivers/crypto/qat/qat_common/adf_common_drv.h
@@ -145,8 +145,6 @@ int adf_enable_aer(struct adf_accel_dev *accel_dev, struct pci_driver *adf);
void adf_disable_aer(struct adf_accel_dev *accel_dev);
int adf_init_aer(void);
void adf_exit_aer(void);
-int adf_init_pf_wq(void);
-void adf_exit_pf_wq(void);
int adf_init_admin_comms(struct adf_accel_dev *accel_dev);
void adf_exit_admin_comms(struct adf_accel_dev *accel_dev);
int adf_send_admin_init(struct adf_accel_dev *accel_dev);
@@ -229,6 +227,8 @@ void adf_disable_vf2pf_interrupts(struct adf_accel_dev *accel_dev,
uint32_t vf_mask);
void adf_enable_vf2pf_interrupts(struct adf_accel_dev *accel_dev,
uint32_t vf_mask);
+int adf_init_pf_wq(void);
+void adf_exit_pf_wq(void);
#else
static inline int adf_sriov_configure(struct pci_dev *pdev, int numvfs)
{
@@ -238,5 +238,14 @@ static inline int adf_sriov_configure(struct pci_dev *pdev, int numvfs)
static inline void adf_disable_sriov(struct adf_accel_dev *accel_dev)
{
}
+
+static inline int adf_init_pf_wq(void)
+{
+ return 0;
+}
+
+static inline void adf_exit_pf_wq(void)
+{
+}
#endif
#endif
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
index a19ee127edca..e72fea737a0d 100644
--- a/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
+++ b/drivers/crypto/sunxi-ss/sun4i-ss-cipher.c
@@ -35,6 +35,7 @@ static int sun4i_ss_opti_poll(struct ablkcipher_request *areq)
unsigned int todo;
struct sg_mapping_iter mi, mo;
unsigned int oi, oo; /* offset for in and out */
+ unsigned long flags;
if (areq->nbytes == 0)
return 0;
@@ -49,7 +50,7 @@ static int sun4i_ss_opti_poll(struct ablkcipher_request *areq)
return -EINVAL;
}
- spin_lock_bh(&ss->slock);
+ spin_lock_irqsave(&ss->slock, flags);
for (i = 0; i < op->keylen; i += 4)
writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
@@ -117,7 +118,7 @@ release_ss:
sg_miter_stop(&mi);
sg_miter_stop(&mo);
writel(0, ss->base + SS_CTL);
- spin_unlock_bh(&ss->slock);
+ spin_unlock_irqrestore(&ss->slock, flags);
return err;
}
@@ -149,6 +150,7 @@ static int sun4i_ss_cipher_poll(struct ablkcipher_request *areq)
unsigned int ob = 0; /* offset in buf */
unsigned int obo = 0; /* offset in bufo*/
unsigned int obl = 0; /* length of data in bufo */
+ unsigned long flags;
if (areq->nbytes == 0)
return 0;
@@ -181,7 +183,7 @@ static int sun4i_ss_cipher_poll(struct ablkcipher_request *areq)
if (no_chunk == 1)
return sun4i_ss_opti_poll(areq);
- spin_lock_bh(&ss->slock);
+ spin_lock_irqsave(&ss->slock, flags);
for (i = 0; i < op->keylen; i += 4)
writel(*(op->key + i / 4), ss->base + SS_KEY0 + i);
@@ -308,7 +310,7 @@ release_ss:
sg_miter_stop(&mi);
sg_miter_stop(&mo);
writel(0, ss->base + SS_CTL);
- spin_unlock_bh(&ss->slock);
+ spin_unlock_irqrestore(&ss->slock, flags);
return err;
}
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index a04fea4d0063..9a8a18aafd5c 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -835,6 +835,16 @@ struct talitos_ahash_req_ctx {
struct scatterlist *psrc;
};
+struct talitos_export_state {
+ u32 hw_context[TALITOS_MDEU_MAX_CONTEXT_SIZE / sizeof(u32)];
+ u8 buf[HASH_MAX_BLOCK_SIZE];
+ unsigned int swinit;
+ unsigned int first;
+ unsigned int last;
+ unsigned int to_hash_later;
+ unsigned int nbuf;
+};
+
static int aead_setkey(struct crypto_aead *authenc,
const u8 *key, unsigned int keylen)
{
@@ -1954,6 +1964,46 @@ static int ahash_digest(struct ahash_request *areq)
return ahash_process_req(areq, areq->nbytes);
}
+static int ahash_export(struct ahash_request *areq, void *out)
+{
+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
+ struct talitos_export_state *export = out;
+
+ memcpy(export->hw_context, req_ctx->hw_context,
+ req_ctx->hw_context_size);
+ memcpy(export->buf, req_ctx->buf, req_ctx->nbuf);
+ export->swinit = req_ctx->swinit;
+ export->first = req_ctx->first;
+ export->last = req_ctx->last;
+ export->to_hash_later = req_ctx->to_hash_later;
+ export->nbuf = req_ctx->nbuf;
+
+ return 0;
+}
+
+static int ahash_import(struct ahash_request *areq, const void *in)
+{
+ struct talitos_ahash_req_ctx *req_ctx = ahash_request_ctx(areq);
+ struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
+ const struct talitos_export_state *export = in;
+
+ memset(req_ctx, 0, sizeof(*req_ctx));
+ req_ctx->hw_context_size =
+ (crypto_ahash_digestsize(tfm) <= SHA256_DIGEST_SIZE)
+ ? TALITOS_MDEU_CONTEXT_SIZE_MD5_SHA1_SHA256
+ : TALITOS_MDEU_CONTEXT_SIZE_SHA384_SHA512;
+ memcpy(req_ctx->hw_context, export->hw_context,
+ req_ctx->hw_context_size);
+ memcpy(req_ctx->buf, export->buf, export->nbuf);
+ req_ctx->swinit = export->swinit;
+ req_ctx->first = export->first;
+ req_ctx->last = export->last;
+ req_ctx->to_hash_later = export->to_hash_later;
+ req_ctx->nbuf = export->nbuf;
+
+ return 0;
+}
+
struct keyhash_result {
struct completion completion;
int err;
@@ -2348,6 +2398,7 @@ static struct talitos_alg_template driver_algs[] = {
{ .type = CRYPTO_ALG_TYPE_AHASH,
.alg.hash = {
.halg.digestsize = MD5_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct talitos_export_state),
.halg.base = {
.cra_name = "md5",
.cra_driver_name = "md5-talitos",
@@ -2363,6 +2414,7 @@ static struct talitos_alg_template driver_algs[] = {
{ .type = CRYPTO_ALG_TYPE_AHASH,
.alg.hash = {
.halg.digestsize = SHA1_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct talitos_export_state),
.halg.base = {
.cra_name = "sha1",
.cra_driver_name = "sha1-talitos",
@@ -2378,6 +2430,7 @@ static struct talitos_alg_template driver_algs[] = {
{ .type = CRYPTO_ALG_TYPE_AHASH,
.alg.hash = {
.halg.digestsize = SHA224_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct talitos_export_state),
.halg.base = {
.cra_name = "sha224",
.cra_driver_name = "sha224-talitos",
@@ -2393,6 +2446,7 @@ static struct talitos_alg_template driver_algs[] = {
{ .type = CRYPTO_ALG_TYPE_AHASH,
.alg.hash = {
.halg.digestsize = SHA256_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct talitos_export_state),
.halg.base = {
.cra_name = "sha256",
.cra_driver_name = "sha256-talitos",
@@ -2408,6 +2462,7 @@ static struct talitos_alg_template driver_algs[] = {
{ .type = CRYPTO_ALG_TYPE_AHASH,
.alg.hash = {
.halg.digestsize = SHA384_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct talitos_export_state),
.halg.base = {
.cra_name = "sha384",
.cra_driver_name = "sha384-talitos",
@@ -2423,6 +2478,7 @@ static struct talitos_alg_template driver_algs[] = {
{ .type = CRYPTO_ALG_TYPE_AHASH,
.alg.hash = {
.halg.digestsize = SHA512_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct talitos_export_state),
.halg.base = {
.cra_name = "sha512",
.cra_driver_name = "sha512-talitos",
@@ -2438,6 +2494,7 @@ static struct talitos_alg_template driver_algs[] = {
{ .type = CRYPTO_ALG_TYPE_AHASH,
.alg.hash = {
.halg.digestsize = MD5_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct talitos_export_state),
.halg.base = {
.cra_name = "hmac(md5)",
.cra_driver_name = "hmac-md5-talitos",
@@ -2453,6 +2510,7 @@ static struct talitos_alg_template driver_algs[] = {
{ .type = CRYPTO_ALG_TYPE_AHASH,
.alg.hash = {
.halg.digestsize = SHA1_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct talitos_export_state),
.halg.base = {
.cra_name = "hmac(sha1)",
.cra_driver_name = "hmac-sha1-talitos",
@@ -2468,6 +2526,7 @@ static struct talitos_alg_template driver_algs[] = {
{ .type = CRYPTO_ALG_TYPE_AHASH,
.alg.hash = {
.halg.digestsize = SHA224_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct talitos_export_state),
.halg.base = {
.cra_name = "hmac(sha224)",
.cra_driver_name = "hmac-sha224-talitos",
@@ -2483,6 +2542,7 @@ static struct talitos_alg_template driver_algs[] = {
{ .type = CRYPTO_ALG_TYPE_AHASH,
.alg.hash = {
.halg.digestsize = SHA256_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct talitos_export_state),
.halg.base = {
.cra_name = "hmac(sha256)",
.cra_driver_name = "hmac-sha256-talitos",
@@ -2498,6 +2558,7 @@ static struct talitos_alg_template driver_algs[] = {
{ .type = CRYPTO_ALG_TYPE_AHASH,
.alg.hash = {
.halg.digestsize = SHA384_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct talitos_export_state),
.halg.base = {
.cra_name = "hmac(sha384)",
.cra_driver_name = "hmac-sha384-talitos",
@@ -2513,6 +2574,7 @@ static struct talitos_alg_template driver_algs[] = {
{ .type = CRYPTO_ALG_TYPE_AHASH,
.alg.hash = {
.halg.digestsize = SHA512_DIGEST_SIZE,
+ .halg.statesize = sizeof(struct talitos_export_state),
.halg.base = {
.cra_name = "hmac(sha512)",
.cra_driver_name = "hmac-sha512-talitos",
@@ -2704,6 +2766,8 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
t_alg->algt.alg.hash.finup = ahash_finup;
t_alg->algt.alg.hash.digest = ahash_digest;
t_alg->algt.alg.hash.setkey = ahash_setkey;
+ t_alg->algt.alg.hash.import = ahash_import;
+ t_alg->algt.alg.hash.export = ahash_export;
if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
!strncmp(alg->cra_name, "hmac", 4)) {
diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c
index 66b1c3313e2e..cd4398498495 100644
--- a/drivers/crypto/ux500/hash/hash_core.c
+++ b/drivers/crypto/ux500/hash/hash_core.c
@@ -797,7 +797,7 @@ static int hash_process_data(struct hash_device_data *device_data,
&device_data->state);
memmove(req_ctx->state.buffer,
device_data->state.buffer,
- HASH_BLOCK_SIZE / sizeof(u32));
+ HASH_BLOCK_SIZE);
if (ret) {
dev_err(device_data->dev,
"%s: hash_resume_state() failed!\n",
@@ -848,7 +848,7 @@ static int hash_process_data(struct hash_device_data *device_data,
memmove(device_data->state.buffer,
req_ctx->state.buffer,
- HASH_BLOCK_SIZE / sizeof(u32));
+ HASH_BLOCK_SIZE);
if (ret) {
dev_err(device_data->dev, "%s: hash_save_state() failed!\n",
__func__);
diff --git a/drivers/crypto/vmx/aes_cbc.c b/drivers/crypto/vmx/aes_cbc.c
index 0b8fe2ec5315..f3801b983f42 100644
--- a/drivers/crypto/vmx/aes_cbc.c
+++ b/drivers/crypto/vmx/aes_cbc.c
@@ -182,7 +182,7 @@ struct crypto_alg p8_aes_cbc_alg = {
.cra_name = "cbc(aes)",
.cra_driver_name = "p8_aes_cbc",
.cra_module = THIS_MODULE,
- .cra_priority = 1000,
+ .cra_priority = 2000,
.cra_type = &crypto_blkcipher_type,
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_NEED_FALLBACK,
.cra_alignmask = 0,
diff --git a/drivers/crypto/vmx/aes_ctr.c b/drivers/crypto/vmx/aes_ctr.c
index ee1306cd8f59..404a1b69a3ab 100644
--- a/drivers/crypto/vmx/aes_ctr.c
+++ b/drivers/crypto/vmx/aes_ctr.c
@@ -166,7 +166,7 @@ struct crypto_alg p8_aes_ctr_alg = {
.cra_name = "ctr(aes)",
.cra_driver_name = "p8_aes_ctr",
.cra_module = THIS_MODULE,
- .cra_priority = 1000,
+ .cra_priority = 2000,
.cra_type = &crypto_blkcipher_type,
.cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_NEED_FALLBACK,
.cra_alignmask = 0,
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index bc1c5f6dd4bd..844a8ad666a9 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -806,7 +806,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
struct devfreq *df = to_devfreq(dev);
int ret;
char str_governor[DEVFREQ_NAME_LEN + 1];
- struct devfreq_governor *governor;
+ const struct devfreq_governor *governor, *prev_gov;
ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor);
if (ret != 1)
@@ -831,12 +831,21 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr,
goto out;
}
}
+ prev_gov = df->governor;
df->governor = governor;
strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN);
ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL);
- if (ret)
+ if (ret) {
dev_warn(dev, "%s: Governor %s not started(%d)\n",
__func__, df->governor->name, ret);
+ if (prev_gov) {
+ df->governor = prev_gov;
+ strncpy(df->governor_name, prev_gov->name,
+ DEVFREQ_NAME_LEN);
+ df->governor->event_handler(df, DEVFREQ_GOV_START,
+ NULL);
+ }
+ }
out:
mutex_unlock(&devfreq_list_lock);
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 37649221f81c..ca64b174f8a3 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -218,8 +218,11 @@ static const u32 rir_offset[MAX_RIR_RANGES][MAX_RIR_WAY] = {
{ 0x1a0, 0x1a4, 0x1a8, 0x1ac, 0x1b0, 0x1b4, 0x1b8, 0x1bc },
};
-#define RIR_RNK_TGT(reg) GET_BITFIELD(reg, 16, 19)
-#define RIR_OFFSET(reg) GET_BITFIELD(reg, 2, 14)
+#define RIR_RNK_TGT(type, reg) (((type) == BROADWELL) ? \
+ GET_BITFIELD(reg, 20, 23) : GET_BITFIELD(reg, 16, 19))
+
+#define RIR_OFFSET(type, reg) (((type) == HASWELL || (type) == BROADWELL) ? \
+ GET_BITFIELD(reg, 2, 15) : GET_BITFIELD(reg, 2, 14))
/* Device 16, functions 2-7 */
@@ -1175,14 +1178,14 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
pci_read_config_dword(pvt->pci_tad[i],
rir_offset[j][k],
&reg);
- tmp_mb = RIR_OFFSET(reg) << 6;
+ tmp_mb = RIR_OFFSET(pvt->info.type, reg) << 6;
gb = div_u64_rem(tmp_mb, 1024, &mb);
edac_dbg(0, "CH#%d RIR#%d INTL#%d, offset %u.%03u GB (0x%016Lx), tgt: %d, reg=0x%08x\n",
i, j, k,
gb, (mb*1000)/1024,
((u64)tmp_mb) << 20L,
- (u32)RIR_RNK_TGT(reg),
+ (u32)RIR_RNK_TGT(pvt->info.type, reg),
reg);
}
}
@@ -1512,7 +1515,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
pci_read_config_dword(pvt->pci_tad[ch_add + base_ch],
rir_offset[n_rir][idx],
&reg);
- *rank = RIR_RNK_TGT(reg);
+ *rank = RIR_RNK_TGT(pvt->info.type, reg);
edac_dbg(0, "RIR#%d: channel address 0x%08Lx < 0x%08Lx, RIR interleave %d, index %d\n",
n_rir,
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index e0e6b74fef8f..377d935a3380 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -61,15 +61,24 @@ efi_status_t __init handle_kernel_image(efi_system_table_t *sys_table_arg,
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) {
/*
+ * If CONFIG_DEBUG_ALIGN_RODATA is not set, produce a
+ * displacement in the interval [0, MIN_KIMG_ALIGN) that
+ * is a multiple of the minimal segment alignment (SZ_64K)
+ */
+ u32 mask = (MIN_KIMG_ALIGN - 1) & ~(SZ_64K - 1);
+ u32 offset = !IS_ENABLED(CONFIG_DEBUG_ALIGN_RODATA) ?
+ (phys_seed >> 32) & mask : TEXT_OFFSET;
+
+ /*
* If KASLR is enabled, and we have some randomness available,
* locate the kernel at a randomized offset in physical memory.
*/
- *reserve_size = kernel_memsize + TEXT_OFFSET;
+ *reserve_size = kernel_memsize + offset;
status = efi_random_alloc(sys_table_arg, *reserve_size,
MIN_KIMG_ALIGN, reserve_addr,
- phys_seed);
+ (u32)phys_seed);
- *image_addr = *reserve_addr + TEXT_OFFSET;
+ *image_addr = *reserve_addr + offset;
} else {
/*
* Else, try a straight allocation at the preferred offset.
diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c
index 33a1f9779b86..4ea71d505bce 100644
--- a/drivers/gpio/gpio-bcm-kona.c
+++ b/drivers/gpio/gpio-bcm-kona.c
@@ -551,11 +551,11 @@ static void bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio)
/* disable interrupts and clear status */
for (i = 0; i < kona_gpio->num_bank; i++) {
/* Unlock the entire bank first */
- bcm_kona_gpio_write_lock_regs(kona_gpio, i, UNLOCK_CODE);
+ bcm_kona_gpio_write_lock_regs(reg_base, i, UNLOCK_CODE);
writel(0xffffffff, reg_base + GPIO_INT_MASK(i));
writel(0xffffffff, reg_base + GPIO_INT_STATUS(i));
/* Now re-lock the bank */
- bcm_kona_gpio_write_lock_regs(kona_gpio, i, LOCK_CODE);
+ bcm_kona_gpio_write_lock_regs(reg_base, i, LOCK_CODE);
}
}
diff --git a/drivers/gpio/gpiolib-legacy.c b/drivers/gpio/gpiolib-legacy.c
index 3a5c7011ad3b..8b830996fe02 100644
--- a/drivers/gpio/gpiolib-legacy.c
+++ b/drivers/gpio/gpiolib-legacy.c
@@ -28,6 +28,10 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
if (!desc && gpio_is_valid(gpio))
return -EPROBE_DEFER;
+ err = gpiod_request(desc, label);
+ if (err)
+ return err;
+
if (flags & GPIOF_OPEN_DRAIN)
set_bit(FLAG_OPEN_DRAIN, &desc->flags);
@@ -37,10 +41,6 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
if (flags & GPIOF_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
- err = gpiod_request(desc, label);
- if (err)
- return err;
-
if (flags & GPIOF_DIR_IN)
err = gpiod_direction_input(desc);
else
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 4e4c3083ae56..06d345b087f8 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -927,14 +927,6 @@ static int __gpiod_request(struct gpio_desc *desc, const char *label)
spin_lock_irqsave(&gpio_lock, flags);
}
done:
- if (status < 0) {
- /* Clear flags that might have been set by the caller before
- * requesting the GPIO.
- */
- clear_bit(FLAG_ACTIVE_LOW, &desc->flags);
- clear_bit(FLAG_OPEN_DRAIN, &desc->flags);
- clear_bit(FLAG_OPEN_SOURCE, &desc->flags);
- }
spin_unlock_irqrestore(&gpio_lock, flags);
return status;
}
@@ -2062,28 +2054,13 @@ struct gpio_desc *__must_check gpiod_get_optional(struct device *dev,
}
EXPORT_SYMBOL_GPL(gpiod_get_optional);
-/**
- * gpiod_parse_flags - helper function to parse GPIO lookup flags
- * @desc: gpio to be setup
- * @lflags: gpio_lookup_flags - returned from of_find_gpio() or
- * of_get_gpio_hog()
- *
- * Set the GPIO descriptor flags based on the given GPIO lookup flags.
- */
-static void gpiod_parse_flags(struct gpio_desc *desc, unsigned long lflags)
-{
- if (lflags & GPIO_ACTIVE_LOW)
- set_bit(FLAG_ACTIVE_LOW, &desc->flags);
- if (lflags & GPIO_OPEN_DRAIN)
- set_bit(FLAG_OPEN_DRAIN, &desc->flags);
- if (lflags & GPIO_OPEN_SOURCE)
- set_bit(FLAG_OPEN_SOURCE, &desc->flags);
-}
/**
* gpiod_configure_flags - helper function to configure a given GPIO
* @desc: gpio whose value will be assigned
* @con_id: function within the GPIO consumer
+ * @lflags: gpio_lookup_flags - returned from of_find_gpio() or
+ * of_get_gpio_hog()
* @dflags: gpiod_flags - optional GPIO initialization flags
*
* Return 0 on success, -ENOENT if no GPIO has been assigned to the
@@ -2091,10 +2068,17 @@ static void gpiod_parse_flags(struct gpio_desc *desc, unsigned long lflags)
* occurred while trying to acquire the GPIO.
*/
static int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
- enum gpiod_flags dflags)
+ unsigned long lflags, enum gpiod_flags dflags)
{
int status;
+ if (lflags & GPIO_ACTIVE_LOW)
+ set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+ if (lflags & GPIO_OPEN_DRAIN)
+ set_bit(FLAG_OPEN_DRAIN, &desc->flags);
+ if (lflags & GPIO_OPEN_SOURCE)
+ set_bit(FLAG_OPEN_SOURCE, &desc->flags);
+
/* No particular flag request, return here... */
if (!(dflags & GPIOD_FLAGS_BIT_DIR_SET)) {
pr_debug("no flags found for %s\n", con_id);
@@ -2161,13 +2145,11 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
return desc;
}
- gpiod_parse_flags(desc, lookupflags);
-
status = gpiod_request(desc, con_id);
if (status < 0)
return ERR_PTR(status);
- status = gpiod_configure_flags(desc, con_id, flags);
+ status = gpiod_configure_flags(desc, con_id, lookupflags, flags);
if (status < 0) {
dev_dbg(dev, "setup of GPIO %s failed\n", con_id);
gpiod_put(desc);
@@ -2223,6 +2205,10 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
if (IS_ERR(desc))
return desc;
+ ret = gpiod_request(desc, NULL);
+ if (ret)
+ return ERR_PTR(ret);
+
if (active_low)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
@@ -2233,10 +2219,6 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
}
- ret = gpiod_request(desc, NULL);
- if (ret)
- return ERR_PTR(ret);
-
return desc;
}
EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
@@ -2289,8 +2271,6 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,
chip = gpiod_to_chip(desc);
hwnum = gpio_chip_hwgpio(desc);
- gpiod_parse_flags(desc, lflags);
-
local_desc = gpiochip_request_own_desc(chip, hwnum, name);
if (IS_ERR(local_desc)) {
pr_err("requesting hog GPIO %s (chip %s, offset %d) failed\n",
@@ -2298,7 +2278,7 @@ int gpiod_hog(struct gpio_desc *desc, const char *name,
return PTR_ERR(local_desc);
}
- status = gpiod_configure_flags(desc, name, dflags);
+ status = gpiod_configure_flags(desc, name, lflags, dflags);
if (status < 0) {
pr_err("setup of hog GPIO %s (chip %s, offset %d) failed\n",
name, chip->label, hwnum);
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index 182c6074985e..483bb9338ac3 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -827,9 +827,17 @@ static int qpnp_pin_get(struct gpio_chip *gpio_chip, unsigned offset)
if (WARN_ON(!q_spec))
return -ENODEV;
+ if (is_gpio_lv_mv(q_spec)) {
+ mask = Q_REG_LV_MV_MODE_SEL_MASK;
+ shift = Q_REG_LV_MV_MODE_SEL_SHIFT;
+ } else {
+ mask = Q_REG_MODE_SEL_MASK;
+ shift = Q_REG_MODE_SEL_SHIFT;
+ }
+
/* gpio val is from RT status iff input is enabled */
- if ((q_spec->regs[Q_REG_I_MODE_CTL] & Q_REG_MODE_SEL_MASK)
- == QPNP_PIN_MODE_DIG_IN) {
+ if (q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL], shift, mask)
+ == QPNP_PIN_MODE_DIG_IN) {
rc = regmap_read(q_chip->regmap,
Q_REG_ADDR(q_spec, Q_REG_STATUS1), &val);
buf[0] = (u8)val;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
index 119cdc2c43e7..7ef2c13921b4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -194,12 +194,12 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
bpc = 8;
DRM_DEBUG("%s: HDMI deep color 10 bpc exceeds max tmds clock. Using %d bpc.\n",
connector->name, bpc);
- } else if (bpc > 8) {
- /* max_tmds_clock missing, but hdmi spec mandates it for deep color. */
- DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n",
- connector->name);
- bpc = 8;
}
+ } else if (bpc > 8) {
+ /* max_tmds_clock missing, but hdmi spec mandates it for deep color. */
+ DRM_DEBUG("%s: Required max tmds clock for HDMI deep color missing. Using 8 bpc.\n",
+ connector->name);
+ bpc = 8;
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
index 7b7f4aba60c0..fe36caf1b7d7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
@@ -150,7 +150,7 @@ u32 amdgpu_dpm_get_vrefresh(struct amdgpu_device *adev)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
amdgpu_crtc = to_amdgpu_crtc(crtc);
if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) {
- vrefresh = amdgpu_crtc->hw_mode.vrefresh;
+ vrefresh = drm_mode_vrefresh(&amdgpu_crtc->hw_mode);
break;
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
index 946300764609..b57fffc2d4af 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -5463,7 +5463,7 @@ static int gfx_v7_0_eop_irq(struct amdgpu_device *adev,
case 2:
for (i = 0; i < adev->gfx.num_compute_rings; i++) {
ring = &adev->gfx.compute_ring[i];
- if ((ring->me == me_id) & (ring->pipe == pipe_id))
+ if ((ring->me == me_id) && (ring->pipe == pipe_id))
amdgpu_fence_process(ring);
}
break;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 9be007081b72..eb1da83c9902 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -242,13 +242,19 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn,
pqm_uninit(&p->pqm);
/* Iterate over all process device data structure and check
- * if we should reset all wavefronts */
- list_for_each_entry(pdd, &p->per_device_data, per_device_list)
+ * if we should delete debug managers and reset all wavefronts
+ */
+ list_for_each_entry(pdd, &p->per_device_data, per_device_list) {
+ if ((pdd->dev->dbgmgr) &&
+ (pdd->dev->dbgmgr->pasid == p->pasid))
+ kfd_dbgmgr_destroy(pdd->dev->dbgmgr);
+
if (pdd->reset_wavefronts) {
pr_warn("amdkfd: Resetting all wave fronts\n");
dbgdev_wave_reset_wavefronts(pdd->dev, p);
pdd->reset_wavefronts = false;
}
+ }
mutex_unlock(&p->mutex);
@@ -404,42 +410,52 @@ void kfd_unbind_process_from_device(struct kfd_dev *dev, unsigned int pasid)
idx = srcu_read_lock(&kfd_processes_srcu);
+ /*
+ * Look for the process that matches the pasid. If there is no such
+ * process, we either released it in amdkfd's own notifier, or there
+ * is a bug. Unfortunately, there is no way to tell...
+ */
hash_for_each_rcu(kfd_processes_table, i, p, kfd_processes)
- if (p->pasid == pasid)
- break;
+ if (p->pasid == pasid) {
- srcu_read_unlock(&kfd_processes_srcu, idx);
+ srcu_read_unlock(&kfd_processes_srcu, idx);
- BUG_ON(p->pasid != pasid);
+ pr_debug("Unbinding process %d from IOMMU\n", pasid);
- mutex_lock(&p->mutex);
+ mutex_lock(&p->mutex);
- if ((dev->dbgmgr) && (dev->dbgmgr->pasid == p->pasid))
- kfd_dbgmgr_destroy(dev->dbgmgr);
+ if ((dev->dbgmgr) && (dev->dbgmgr->pasid == p->pasid))
+ kfd_dbgmgr_destroy(dev->dbgmgr);
- pqm_uninit(&p->pqm);
+ pqm_uninit(&p->pqm);
- pdd = kfd_get_process_device_data(dev, p);
+ pdd = kfd_get_process_device_data(dev, p);
- if (!pdd) {
- mutex_unlock(&p->mutex);
- return;
- }
+ if (!pdd) {
+ mutex_unlock(&p->mutex);
+ return;
+ }
- if (pdd->reset_wavefronts) {
- dbgdev_wave_reset_wavefronts(pdd->dev, p);
- pdd->reset_wavefronts = false;
- }
+ if (pdd->reset_wavefronts) {
+ dbgdev_wave_reset_wavefronts(pdd->dev, p);
+ pdd->reset_wavefronts = false;
+ }
- /*
- * Just mark pdd as unbound, because we still need it to call
- * amd_iommu_unbind_pasid() in when the process exits.
- * We don't call amd_iommu_unbind_pasid() here
- * because the IOMMU called us.
- */
- pdd->bound = false;
+ /*
+ * Just mark pdd as unbound, because we still need it
+ * to call amd_iommu_unbind_pasid() in when the
+ * process exits.
+ * We don't call amd_iommu_unbind_pasid() here
+ * because the IOMMU called us.
+ */
+ pdd->bound = false;
- mutex_unlock(&p->mutex);
+ mutex_unlock(&p->mutex);
+
+ return;
+ }
+
+ srcu_read_unlock(&kfd_processes_srcu, idx);
}
struct kfd_process_device *kfd_get_first_process_device_data(struct kfd_process *p)
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index d0299aed517e..59d1269626b1 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -335,6 +335,8 @@ atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane,
atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff,
factor_reg);
+ } else {
+ atmel_hlcdc_layer_update_cfg(&plane->layer, 13, 0xffffffff, 0);
}
}
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index aeee083c7f95..6253775b8d9c 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -150,7 +150,7 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state)
for (i = 0; i < state->num_connector; i++) {
struct drm_connector *connector = state->connectors[i];
- if (!connector)
+ if (!connector || !connector->funcs)
continue;
/*
@@ -367,6 +367,8 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
drm_property_unreference_blob(state->mode_blob);
state->mode_blob = NULL;
+ memset(&state->mode, 0, sizeof(state->mode));
+
if (blob) {
if (blob->length != sizeof(struct drm_mode_modeinfo) ||
drm_mode_convert_umode(&state->mode,
@@ -379,7 +381,6 @@ int drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
state->mode.name, state);
} else {
- memset(&state->mode, 0, sizeof(state->mode));
state->enable = false;
DRM_DEBUG_ATOMIC("Set [NOMODE] for CRTC state %p\n",
state);
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 24c5434abd1c..dc84003f694e 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -2682,8 +2682,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
goto out;
}
- drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
-
/*
* Check whether the primary plane supports the fb pixel format.
* Drivers not implementing the universal planes API use a
@@ -3316,6 +3314,24 @@ int drm_mode_addfb2(struct drm_device *dev,
return 0;
}
+struct drm_mode_rmfb_work {
+ struct work_struct work;
+ struct list_head fbs;
+};
+
+static void drm_mode_rmfb_work_fn(struct work_struct *w)
+{
+ struct drm_mode_rmfb_work *arg = container_of(w, typeof(*arg), work);
+
+ while (!list_empty(&arg->fbs)) {
+ struct drm_framebuffer *fb =
+ list_first_entry(&arg->fbs, typeof(*fb), filp_head);
+
+ list_del_init(&fb->filp_head);
+ drm_framebuffer_remove(fb);
+ }
+}
+
/**
* drm_mode_rmfb - remove an FB from the configuration
* @dev: drm device for the ioctl
@@ -3356,7 +3372,25 @@ int drm_mode_rmfb(struct drm_device *dev,
mutex_unlock(&dev->mode_config.fb_lock);
mutex_unlock(&file_priv->fbs_lock);
- drm_framebuffer_unreference(fb);
+ /*
+ * we now own the reference that was stored in the fbs list
+ *
+ * drm_framebuffer_remove may fail with -EINTR on pending signals,
+ * so run this in a separate stack as there's no way to correctly
+ * handle this after the fb is already removed from the lookup table.
+ */
+ if (atomic_read(&fb->refcount.refcount) > 1) {
+ struct drm_mode_rmfb_work arg;
+
+ INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
+ INIT_LIST_HEAD(&arg.fbs);
+ list_add_tail(&fb->filp_head, &arg.fbs);
+
+ schedule_work(&arg.work);
+ flush_work(&arg.work);
+ destroy_work_on_stack(&arg.work);
+ } else
+ drm_framebuffer_unreference(fb);
return 0;
@@ -3509,7 +3543,6 @@ out_err1:
return ret;
}
-
/**
* drm_fb_release - remove and free the FBs on this file
* @priv: drm file for the ioctl
@@ -3524,6 +3557,9 @@ out_err1:
void drm_fb_release(struct drm_file *priv)
{
struct drm_framebuffer *fb, *tfb;
+ struct drm_mode_rmfb_work arg;
+
+ INIT_LIST_HEAD(&arg.fbs);
/*
* When the file gets released that means no one else can access the fb
@@ -3536,10 +3572,22 @@ void drm_fb_release(struct drm_file *priv)
* at it any more.
*/
list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {
- list_del_init(&fb->filp_head);
+ if (atomic_read(&fb->refcount.refcount) > 1) {
+ list_move_tail(&fb->filp_head, &arg.fbs);
+ } else {
+ list_del_init(&fb->filp_head);
- /* This drops the fpriv->fbs reference. */
- drm_framebuffer_unreference(fb);
+ /* This drops the fpriv->fbs reference. */
+ drm_framebuffer_unreference(fb);
+ }
+ }
+
+ if (!list_empty(&arg.fbs)) {
+ INIT_WORK_ONSTACK(&arg.work, drm_mode_rmfb_work_fn);
+
+ schedule_work(&arg.work);
+ flush_work(&arg.work);
+ destroy_work_on_stack(&arg.work);
}
}
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index d268bf18a662..2485fb652716 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -2874,11 +2874,9 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)
drm_dp_port_teardown_pdt(port, port->pdt);
if (!port->input && port->vcpi.vcpi > 0) {
- if (mgr->mst_state) {
- drm_dp_mst_reset_vcpi_slots(mgr, port);
- drm_dp_update_payload_part1(mgr);
- drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
- }
+ drm_dp_mst_reset_vcpi_slots(mgr, port);
+ drm_dp_update_payload_part1(mgr);
+ drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
}
kref_put(&port->kref, drm_dp_free_mst_port);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 69cbab5e5c81..5ad036741b99 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1899,7 +1899,6 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
int n, int width, int height)
{
int c, o;
- struct drm_device *dev = fb_helper->dev;
struct drm_connector *connector;
const struct drm_connector_helper_funcs *connector_funcs;
struct drm_encoder *encoder;
@@ -1918,7 +1917,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
if (modes[n] == NULL)
return best_score;
- crtcs = kzalloc(dev->mode_config.num_connector *
+ crtcs = kzalloc(fb_helper->connector_count *
sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
if (!crtcs)
return best_score;
@@ -1964,7 +1963,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
if (score > best_score) {
best_score = score;
memcpy(best_crtcs, crtcs,
- dev->mode_config.num_connector *
+ fb_helper->connector_count *
sizeof(struct drm_fb_helper_crtc *));
}
}
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index cd74a0953f42..39e30abddf08 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1487,6 +1487,8 @@ int drm_mode_convert_umode(struct drm_display_mode *out,
if (out->status != MODE_OK)
goto out;
+ drm_mode_set_crtcinfo(out, CRTC_INTERLACE_HALVE_V);
+
ret = 0;
out:
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
index 6b43ae3ffd73..1616af209bfc 100644
--- a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
@@ -72,7 +72,7 @@ static const char *const dsi_errors[] = {
"RX Prot Violation",
"HS Generic Write FIFO Full",
"LP Generic Write FIFO Full",
- "Generic Read Data Avail"
+ "Generic Read Data Avail",
"Special Packet Sent",
"Tearing Effect",
};
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c
index f7df54a8ee2b..c0a96f1ee18e 100644
--- a/drivers/gpu/drm/i915/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c
@@ -39,7 +39,7 @@ static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
if (!mutex_is_locked(mutex))
return false;
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES)
+#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_MUTEX_SPIN_ON_OWNER)
return mutex->owner == task;
#else
/* Since UP may be pre-empted, we cannot assume that we own the lock */
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 7e461dca564c..9ed9f6dde86f 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -7357,6 +7357,8 @@ enum skl_disp_power_wells {
#define TRANS_CLK_SEL_DISABLED (0x0<<29)
#define TRANS_CLK_SEL_PORT(x) (((x)+1)<<29)
+#define CDCLK_FREQ 0x46200
+
#define TRANSA_MSA_MISC 0x60410
#define TRANSB_MSA_MISC 0x61410
#define TRANSC_MSA_MISC 0x62410
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index afa81691163d..c41bc42b6fa7 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8228,12 +8228,14 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_encoder *encoder;
+ int i;
u32 val, final;
bool has_lvds = false;
bool has_cpu_edp = false;
bool has_panel = false;
bool has_ck505 = false;
bool can_ssc = false;
+ bool using_ssc_source = false;
/* We need to take the global config into account */
for_each_intel_encoder(dev, encoder) {
@@ -8260,8 +8262,22 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
can_ssc = true;
}
- DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d\n",
- has_panel, has_lvds, has_ck505);
+ /* Check if any DPLLs are using the SSC source */
+ for (i = 0; i < dev_priv->num_shared_dpll; i++) {
+ u32 temp = I915_READ(PCH_DPLL(i));
+
+ if (!(temp & DPLL_VCO_ENABLE))
+ continue;
+
+ if ((temp & PLL_REF_INPUT_MASK) ==
+ PLLB_REF_INPUT_SPREADSPECTRUMIN) {
+ using_ssc_source = true;
+ break;
+ }
+ }
+
+ DRM_DEBUG_KMS("has_panel %d has_lvds %d has_ck505 %d using_ssc_source %d\n",
+ has_panel, has_lvds, has_ck505, using_ssc_source);
/* Ironlake: try to setup display ref clock before DPLL
* enabling. This is only under driver's control after
@@ -8298,9 +8314,9 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
final |= DREF_CPU_SOURCE_OUTPUT_NONSPREAD;
} else
final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
- } else {
- final |= DREF_SSC_SOURCE_DISABLE;
- final |= DREF_CPU_SOURCE_OUTPUT_DISABLE;
+ } else if (using_ssc_source) {
+ final |= DREF_SSC_SOURCE_ENABLE;
+ final |= DREF_SSC1_ENABLE;
}
if (final == val)
@@ -8346,7 +8362,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
POSTING_READ(PCH_DREF_CONTROL);
udelay(200);
} else {
- DRM_DEBUG_KMS("Disabling SSC entirely\n");
+ DRM_DEBUG_KMS("Disabling CPU source output\n");
val &= ~DREF_CPU_SOURCE_OUTPUT_MASK;
@@ -8357,16 +8373,20 @@ static void ironlake_init_pch_refclk(struct drm_device *dev)
POSTING_READ(PCH_DREF_CONTROL);
udelay(200);
- /* Turn off the SSC source */
- val &= ~DREF_SSC_SOURCE_MASK;
- val |= DREF_SSC_SOURCE_DISABLE;
+ if (!using_ssc_source) {
+ DRM_DEBUG_KMS("Disabling SSC source\n");
- /* Turn off SSC1 */
- val &= ~DREF_SSC1_ENABLE;
+ /* Turn off the SSC source */
+ val &= ~DREF_SSC_SOURCE_MASK;
+ val |= DREF_SSC_SOURCE_DISABLE;
- I915_WRITE(PCH_DREF_CONTROL, val);
- POSTING_READ(PCH_DREF_CONTROL);
- udelay(200);
+ /* Turn off SSC1 */
+ val &= ~DREF_SSC1_ENABLE;
+
+ I915_WRITE(PCH_DREF_CONTROL, val);
+ POSTING_READ(PCH_DREF_CONTROL);
+ udelay(200);
+ }
}
BUG_ON(val != final);
@@ -9669,6 +9689,8 @@ static void broadwell_set_cdclk(struct drm_device *dev, int cdclk)
sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data);
mutex_unlock(&dev_priv->rps.hw_lock);
+ I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
+
intel_update_cdclk(dev);
WARN(cdclk != dev_priv->cdclk_freq,
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index e55a82a99e7f..8e1d6d74c203 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -3628,8 +3628,7 @@ static bool
intel_dp_reset_link_train(struct intel_dp *intel_dp, uint32_t *DP,
uint8_t dp_train_pat)
{
- if (!intel_dp->train_set_valid)
- memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
+ memset(intel_dp->train_set, 0, sizeof(intel_dp->train_set));
intel_dp_set_signal_levels(intel_dp, DP);
return intel_dp_set_link_train(intel_dp, DP, dp_train_pat);
}
@@ -3746,22 +3745,6 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
break;
}
- /*
- * if we used previously trained voltage and pre-emphasis values
- * and we don't get clock recovery, reset link training values
- */
- if (intel_dp->train_set_valid) {
- DRM_DEBUG_KMS("clock recovery not ok, reset");
- /* clear the flag as we are not reusing train set */
- intel_dp->train_set_valid = false;
- if (!intel_dp_reset_link_train(intel_dp, &DP,
- DP_TRAINING_PATTERN_1 |
- DP_LINK_SCRAMBLING_DISABLE)) {
- DRM_ERROR("failed to enable link training\n");
- return;
- }
- continue;
- }
/* Check to see if we've tried the max voltage */
for (i = 0; i < intel_dp->lane_count; i++)
@@ -3854,7 +3837,6 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
/* Make sure clock is still ok */
if (!drm_dp_clock_recovery_ok(link_status,
intel_dp->lane_count)) {
- intel_dp->train_set_valid = false;
intel_dp_link_training_clock_recovery(intel_dp);
intel_dp_set_link_train(intel_dp, &DP,
training_pattern |
@@ -3871,7 +3853,6 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
/* Try 5 times, then try clock recovery if that fails */
if (tries > 5) {
- intel_dp->train_set_valid = false;
intel_dp_link_training_clock_recovery(intel_dp);
intel_dp_set_link_train(intel_dp, &DP,
training_pattern |
@@ -3893,10 +3874,8 @@ intel_dp_link_training_channel_equalization(struct intel_dp *intel_dp)
intel_dp->DP = DP;
- if (channel_eq) {
- intel_dp->train_set_valid = true;
+ if (channel_eq)
DRM_DEBUG_KMS("Channel EQ done. DP Training successful\n");
- }
}
void intel_dp_stop_link_train(struct intel_dp *intel_dp)
@@ -5079,13 +5058,15 @@ static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
void intel_dp_encoder_reset(struct drm_encoder *encoder)
{
- struct intel_dp *intel_dp;
+ struct drm_i915_private *dev_priv = to_i915(encoder->dev);
+ struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+ if (!HAS_DDI(dev_priv))
+ intel_dp->DP = I915_READ(intel_dp->output_reg);
if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP)
return;
- intel_dp = enc_to_intel_dp(encoder);
-
pps_lock(intel_dp);
/*
@@ -5157,9 +5138,6 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
intel_display_power_get(dev_priv, power_domain);
if (long_hpd) {
- /* indicate that we need to restart link training */
- intel_dp->train_set_valid = false;
-
if (!intel_digital_port_connected(dev_priv, intel_dig_port))
goto mst_fail;
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index f34a219ec5c4..c5f11e0c5d5b 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -783,7 +783,6 @@ struct intel_dp {
bool has_aux_irq,
int send_bytes,
uint32_t aux_clock_divider);
- bool train_set_valid;
/* Displayport compliance testing */
unsigned long compliance_test_type;
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 4fd5fdfef6bd..c0c094d5b822 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -362,12 +362,12 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
uint64_t conn_configured = 0, mask;
int pass = 0;
- save_enabled = kcalloc(dev->mode_config.num_connector, sizeof(bool),
+ save_enabled = kcalloc(fb_helper->connector_count, sizeof(bool),
GFP_KERNEL);
if (!save_enabled)
return false;
- memcpy(save_enabled, enabled, dev->mode_config.num_connector);
+ memcpy(save_enabled, enabled, fb_helper->connector_count);
mask = (1 << fb_helper->connector_count) - 1;
retry:
for (i = 0; i < fb_helper->connector_count; i++) {
@@ -501,7 +501,7 @@ retry:
if (fallback) {
bail:
DRM_DEBUG_KMS("Not using firmware configuration\n");
- memcpy(enabled, save_enabled, dev->mode_config.num_connector);
+ memcpy(enabled, save_enabled, fb_helper->connector_count);
kfree(save_enabled);
return false;
}
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 0a68d2ec89dc..62284e45d531 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3880,6 +3880,8 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
if (IS_HASWELL(dev) || IS_BROADWELL(dev))
hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe));
+ memset(active, 0, sizeof(*active));
+
active->pipe_enabled = intel_crtc->active;
if (active->pipe_enabled) {
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 7b990b4e96d2..5378bdc3bbf9 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -26,6 +26,7 @@
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_of.h>
+#include <video/imx-ipu-v3.h>
#include "imx-drm.h"
@@ -504,6 +505,13 @@ static int compare_of(struct device *dev, void *data)
{
struct device_node *np = data;
+ /* Special case for DI, dev->of_node may not be set yet */
+ if (strcmp(dev->driver->name, "imx-ipuv3-crtc") == 0) {
+ struct ipu_client_platformdata *pdata = dev->platform_data;
+
+ return pdata->of_node == np;
+ }
+
/* Special case for LDB, one device for two channels */
if (of_node_cmp(np->name, "lvds-channel") == 0) {
np = of_get_parent(np);
diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
index 4ab841eebee1..9b0abd44b751 100644
--- a/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -369,7 +369,7 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
ret = imx_drm_add_crtc(drm, &ipu_crtc->base, &ipu_crtc->imx_crtc,
&ipu_crtc->plane[0]->base, &ipu_crtc_helper_funcs,
- ipu_crtc->dev->of_node);
+ pdata->of_node);
if (ret) {
dev_err(ipu_crtc->dev, "adding crtc failed with %d.\n", ret);
goto err_put_resources;
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index c99d3fe12881..e5bb40e58020 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -194,7 +194,7 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
}
}
- fvv = pllreffreq * testn / testm;
+ fvv = pllreffreq * (n + 1) / (m + 1);
fvv = (fvv - 800000) / 50000;
if (fvv > 15)
@@ -214,6 +214,14 @@ static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
WREG_DAC(MGA1064_PIX_PLLC_M, m);
WREG_DAC(MGA1064_PIX_PLLC_N, n);
WREG_DAC(MGA1064_PIX_PLLC_P, p);
+
+ if (mdev->unique_rev_id >= 0x04) {
+ WREG_DAC(0x1a, 0x09);
+ msleep(20);
+ WREG_DAC(0x1a, 0x01);
+
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 59f27e774acb..e40a1b07a014 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -557,6 +557,8 @@ nouveau_fbcon_init(struct drm_device *dev)
if (ret)
goto fini;
+ if (fbcon->helper.fbdev)
+ fbcon->helper.fbdev->pixmap.buf_align = 4;
return 0;
fini:
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
index 789dc2993b0d..8f715feadf56 100644
--- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c
@@ -82,7 +82,6 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
uint32_t fg;
uint32_t bg;
uint32_t dsize;
- uint32_t width;
uint32_t *data = (uint32_t *)image->data;
int ret;
@@ -93,9 +92,6 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
if (ret)
return ret;
- width = ALIGN(image->width, 8);
- dsize = ALIGN(width * image->height, 32) >> 5;
-
if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
fg = ((uint32_t *) info->pseudo_palette)[image->fg_color];
@@ -111,10 +107,11 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
((image->dx + image->width) & 0xffff));
OUT_RING(chan, bg);
OUT_RING(chan, fg);
- OUT_RING(chan, (image->height << 16) | width);
+ OUT_RING(chan, (image->height << 16) | image->width);
OUT_RING(chan, (image->height << 16) | image->width);
OUT_RING(chan, (image->dy << 16) | (image->dx & 0xffff));
+ dsize = ALIGN(image->width * image->height, 32) >> 5;
while (dsize) {
int iter_len = dsize > 128 ? 128 : dsize;
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
index e05499d6ed83..a4e259a00430 100644
--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
@@ -95,7 +95,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
struct nouveau_fbdev *nfbdev = info->par;
struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
struct nouveau_channel *chan = drm->channel;
- uint32_t width, dwords, *data = (uint32_t *)image->data;
+ uint32_t dwords, *data = (uint32_t *)image->data;
uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
uint32_t *palette = info->pseudo_palette;
int ret;
@@ -107,9 +107,6 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
if (ret)
return ret;
- width = ALIGN(image->width, 32);
- dwords = (width * image->height) >> 5;
-
BEGIN_NV04(chan, NvSub2D, 0x0814, 2);
if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -128,6 +125,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
OUT_RING(chan, 0);
OUT_RING(chan, image->dy);
+ dwords = ALIGN(image->width * image->height, 32) >> 5;
while (dwords) {
int push = dwords > 2047 ? 2047 : dwords;
diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
index c97395b4a312..f28315e865a5 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
@@ -95,7 +95,7 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
struct nouveau_fbdev *nfbdev = info->par;
struct nouveau_drm *drm = nouveau_drm(nfbdev->dev);
struct nouveau_channel *chan = drm->channel;
- uint32_t width, dwords, *data = (uint32_t *)image->data;
+ uint32_t dwords, *data = (uint32_t *)image->data;
uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
uint32_t *palette = info->pseudo_palette;
int ret;
@@ -107,9 +107,6 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
if (ret)
return ret;
- width = ALIGN(image->width, 32);
- dwords = (width * image->height) >> 5;
-
BEGIN_NVC0(chan, NvSub2D, 0x0814, 2);
if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
@@ -128,6 +125,7 @@ nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
OUT_RING (chan, 0);
OUT_RING (chan, image->dy);
+ dwords = ALIGN(image->width * image->height, 32) >> 5;
while (dwords) {
int push = dwords > 2047 ? 2047 : dwords;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
index b4b41b135643..2aaf0dd19a55 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
@@ -40,8 +40,8 @@ static int
gf119_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern)
{
struct nvkm_device *device = outp->base.disp->engine.subdev.device;
- const u32 loff = gf119_sor_loff(outp);
- nvkm_mask(device, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern);
+ const u32 soff = gf119_sor_soff(outp);
+ nvkm_mask(device, 0x61c110 + soff, 0x0f0f0f0f, 0x01010101 * pattern);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
index 36655a74c538..eeeea1c2ca23 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -874,22 +874,41 @@ gf100_gr_trap_gpc_rop(struct gf100_gr *gr, int gpc)
}
static const struct nvkm_enum gf100_mp_warp_error[] = {
- { 0x00, "NO_ERROR" },
- { 0x01, "STACK_MISMATCH" },
+ { 0x01, "STACK_ERROR" },
+ { 0x02, "API_STACK_ERROR" },
+ { 0x03, "RET_EMPTY_STACK_ERROR" },
+ { 0x04, "PC_WRAP" },
{ 0x05, "MISALIGNED_PC" },
- { 0x08, "MISALIGNED_GPR" },
- { 0x09, "INVALID_OPCODE" },
- { 0x0d, "GPR_OUT_OF_BOUNDS" },
- { 0x0e, "MEM_OUT_OF_BOUNDS" },
- { 0x0f, "UNALIGNED_MEM_ACCESS" },
+ { 0x06, "PC_OVERFLOW" },
+ { 0x07, "MISALIGNED_IMMC_ADDR" },
+ { 0x08, "MISALIGNED_REG" },
+ { 0x09, "ILLEGAL_INSTR_ENCODING" },
+ { 0x0a, "ILLEGAL_SPH_INSTR_COMBO" },
+ { 0x0b, "ILLEGAL_INSTR_PARAM" },
+ { 0x0c, "INVALID_CONST_ADDR" },
+ { 0x0d, "OOR_REG" },
+ { 0x0e, "OOR_ADDR" },
+ { 0x0f, "MISALIGNED_ADDR" },
{ 0x10, "INVALID_ADDR_SPACE" },
- { 0x11, "INVALID_PARAM" },
+ { 0x11, "ILLEGAL_INSTR_PARAM2" },
+ { 0x12, "INVALID_CONST_ADDR_LDC" },
+ { 0x13, "GEOMETRY_SM_ERROR" },
+ { 0x14, "DIVERGENT" },
+ { 0x15, "WARP_EXIT" },
{}
};
static const struct nvkm_bitfield gf100_mp_global_error[] = {
+ { 0x00000001, "SM_TO_SM_FAULT" },
+ { 0x00000002, "L1_ERROR" },
{ 0x00000004, "MULTIPLE_WARP_ERRORS" },
- { 0x00000008, "OUT_OF_STACK_SPACE" },
+ { 0x00000008, "PHYSICAL_STACK_OVERFLOW" },
+ { 0x00000010, "BPT_INT" },
+ { 0x00000020, "BPT_PAUSE" },
+ { 0x00000040, "SINGLE_STEP_COMPLETE" },
+ { 0x20000000, "ECC_SEC_ERROR" },
+ { 0x40000000, "ECC_DED_ERROR" },
+ { 0x80000000, "TIMEOUT" },
{}
};
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index c566993a2ec3..e2dd5d19c32c 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -630,6 +630,23 @@ void radeon_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
/*
* GPU helpers function.
*/
+
+/**
+ * radeon_device_is_virtual - check if we are running is a virtual environment
+ *
+ * Check if the asic has been passed through to a VM (all asics).
+ * Used at driver startup.
+ * Returns true if virtual or false if not.
+ */
+static bool radeon_device_is_virtual(void)
+{
+#ifdef CONFIG_X86
+ return boot_cpu_has(X86_FEATURE_HYPERVISOR);
+#else
+ return false;
+#endif
+}
+
/**
* radeon_card_posted - check if the hw has already been initialized
*
@@ -643,6 +660,10 @@ bool radeon_card_posted(struct radeon_device *rdev)
{
uint32_t reg;
+ /* for pass through, always force asic_init */
+ if (radeon_device_is_virtual())
+ return false;
+
/* required for EFI mode on macbook2,1 which uses an r5xx asic */
if (efi_enabled(EFI_BOOT) &&
(rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 745e996d2dbc..4ae8b56b1847 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -1004,9 +1004,9 @@ out_unlock:
return ret;
}
-static bool ttm_bo_mem_compat(struct ttm_placement *placement,
- struct ttm_mem_reg *mem,
- uint32_t *new_flags)
+bool ttm_bo_mem_compat(struct ttm_placement *placement,
+ struct ttm_mem_reg *mem,
+ uint32_t *new_flags)
{
int i;
@@ -1038,6 +1038,7 @@ static bool ttm_bo_mem_compat(struct ttm_placement *placement,
return false;
}
+EXPORT_SYMBOL(ttm_bo_mem_compat);
int ttm_bo_validate(struct ttm_buffer_object *bo,
struct ttm_placement *placement,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
index 299925a1f6c6..eadc981ee79a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c
@@ -49,6 +49,7 @@ int vmw_dmabuf_pin_in_placement(struct vmw_private *dev_priv,
{
struct ttm_buffer_object *bo = &buf->base;
int ret;
+ uint32_t new_flags;
ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
if (unlikely(ret != 0))
@@ -60,7 +61,12 @@ int vmw_dmabuf_pin_in_placement(struct vmw_private *dev_priv,
if (unlikely(ret != 0))
goto err;
- ret = ttm_bo_validate(bo, placement, interruptible, false);
+ if (buf->pin_count > 0)
+ ret = ttm_bo_mem_compat(placement, &bo->mem,
+ &new_flags) == true ? 0 : -EINVAL;
+ else
+ ret = ttm_bo_validate(bo, placement, interruptible, false);
+
if (!ret)
vmw_bo_pin_reserved(buf, true);
@@ -91,6 +97,7 @@ int vmw_dmabuf_pin_in_vram_or_gmr(struct vmw_private *dev_priv,
{
struct ttm_buffer_object *bo = &buf->base;
int ret;
+ uint32_t new_flags;
ret = ttm_write_lock(&dev_priv->reservation_sem, interruptible);
if (unlikely(ret != 0))
@@ -102,6 +109,12 @@ int vmw_dmabuf_pin_in_vram_or_gmr(struct vmw_private *dev_priv,
if (unlikely(ret != 0))
goto err;
+ if (buf->pin_count > 0) {
+ ret = ttm_bo_mem_compat(&vmw_vram_gmr_placement, &bo->mem,
+ &new_flags) == true ? 0 : -EINVAL;
+ goto out_unreserve;
+ }
+
ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, interruptible,
false);
if (likely(ret == 0) || ret == -ERESTARTSYS)
@@ -161,6 +174,7 @@ int vmw_dmabuf_pin_in_start_of_vram(struct vmw_private *dev_priv,
struct ttm_placement placement;
struct ttm_place place;
int ret = 0;
+ uint32_t new_flags;
place = vmw_vram_placement.placement[0];
place.lpfn = bo->num_pages;
@@ -185,10 +199,15 @@ int vmw_dmabuf_pin_in_start_of_vram(struct vmw_private *dev_priv,
*/
if (bo->mem.mem_type == TTM_PL_VRAM &&
bo->mem.start < bo->num_pages &&
- bo->mem.start > 0)
+ bo->mem.start > 0 &&
+ buf->pin_count == 0)
(void) ttm_bo_validate(bo, &vmw_sys_placement, false, false);
- ret = ttm_bo_validate(bo, &placement, interruptible, false);
+ if (buf->pin_count > 0)
+ ret = ttm_bo_mem_compat(&placement, &bo->mem,
+ &new_flags) == true ? 0 : -EINVAL;
+ else
+ ret = ttm_bo_validate(bo, &placement, interruptible, false);
/* For some reason we didn't end up at the start of vram */
WARN_ON(ret == 0 && bo->offset != 0);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 24fb348a44e1..f3f31f995878 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -227,6 +227,7 @@ static int vmw_force_iommu;
static int vmw_restrict_iommu;
static int vmw_force_coherent;
static int vmw_restrict_dma_mask;
+static int vmw_assume_16bpp;
static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
static void vmw_master_init(struct vmw_master *);
@@ -243,6 +244,8 @@ MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages");
module_param_named(force_coherent, vmw_force_coherent, int, 0600);
MODULE_PARM_DESC(restrict_dma_mask, "Restrict DMA mask to 44 bits with IOMMU");
module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, 0600);
+MODULE_PARM_DESC(assume_16bpp, "Assume 16-bpp when filtering modes");
+module_param_named(assume_16bpp, vmw_assume_16bpp, int, 0600);
static void vmw_print_capabilities(uint32_t capabilities)
@@ -652,6 +655,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
dev_priv->vram_start = pci_resource_start(dev->pdev, 1);
dev_priv->mmio_start = pci_resource_start(dev->pdev, 2);
+ dev_priv->assume_16bpp = !!vmw_assume_16bpp;
+
dev_priv->enable_fb = enable_fbdev;
vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
@@ -698,6 +703,13 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
vmw_read(dev_priv,
SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB);
+ /*
+ * Workaround for low memory 2D VMs to compensate for the
+ * allocation taken by fbdev
+ */
+ if (!(dev_priv->capabilities & SVGA_CAP_3D))
+ mem_size *= 2;
+
dev_priv->max_mob_pages = mem_size * 1024 / PAGE_SIZE;
dev_priv->prim_bb_mem =
vmw_read(dev_priv,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 469cdd520615..2e94fe27b3f6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -387,6 +387,7 @@ struct vmw_private {
spinlock_t hw_lock;
spinlock_t cap_lock;
bool has_dx;
+ bool assume_16bpp;
/*
* VGA registers.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 5da5de0cb522..4948c1529836 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -3273,19 +3273,19 @@ static const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = {
&vmw_cmd_dx_cid_check, true, false, true),
VMW_CMD_DEF(SVGA_3D_CMD_DX_DEFINE_QUERY, &vmw_cmd_dx_define_query,
true, false, true),
- VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_QUERY, &vmw_cmd_ok,
+ VMW_CMD_DEF(SVGA_3D_CMD_DX_DESTROY_QUERY, &vmw_cmd_dx_cid_check,
true, false, true),
VMW_CMD_DEF(SVGA_3D_CMD_DX_BIND_QUERY, &vmw_cmd_dx_bind_query,
true, false, true),
VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_QUERY_OFFSET,
- &vmw_cmd_ok, true, false, true),
- VMW_CMD_DEF(SVGA_3D_CMD_DX_BEGIN_QUERY, &vmw_cmd_ok,
+ &vmw_cmd_dx_cid_check, true, false, true),
+ VMW_CMD_DEF(SVGA_3D_CMD_DX_BEGIN_QUERY, &vmw_cmd_dx_cid_check,
true, false, true),
- VMW_CMD_DEF(SVGA_3D_CMD_DX_END_QUERY, &vmw_cmd_ok,
+ VMW_CMD_DEF(SVGA_3D_CMD_DX_END_QUERY, &vmw_cmd_dx_cid_check,
true, false, true),
VMW_CMD_DEF(SVGA_3D_CMD_DX_READBACK_QUERY, &vmw_cmd_invalid,
true, false, true),
- VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_PREDICATION, &vmw_cmd_invalid,
+ VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_PREDICATION, &vmw_cmd_dx_cid_check,
true, false, true),
VMW_CMD_DEF(SVGA_3D_CMD_DX_SET_VIEWPORTS, &vmw_cmd_dx_cid_check,
true, false, true),
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
index 3b1faf7862a5..d2d93959b119 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
@@ -517,28 +517,6 @@ static int vmw_fb_kms_framebuffer(struct fb_info *info)
par->set_fb = &vfb->base;
- if (!par->bo_ptr) {
- /*
- * Pin before mapping. Since we don't know in what placement
- * to pin, call into KMS to do it for us.
- */
- ret = vfb->pin(vfb);
- if (ret) {
- DRM_ERROR("Could not pin the fbdev framebuffer.\n");
- return ret;
- }
-
- ret = ttm_bo_kmap(&par->vmw_bo->base, 0,
- par->vmw_bo->base.num_pages, &par->map);
- if (ret) {
- vfb->unpin(vfb);
- DRM_ERROR("Could not map the fbdev framebuffer.\n");
- return ret;
- }
-
- par->bo_ptr = ttm_kmap_obj_virtual(&par->map, &par->bo_iowrite);
- }
-
return 0;
}
@@ -573,9 +551,9 @@ static int vmw_fb_set_par(struct fb_info *info)
mode = old_mode;
old_mode = NULL;
} else if (!vmw_kms_validate_mode_vram(vmw_priv,
- mode->hdisplay *
- (var->bits_per_pixel + 7) / 8,
- mode->vdisplay)) {
+ mode->hdisplay *
+ DIV_ROUND_UP(var->bits_per_pixel, 8),
+ mode->vdisplay)) {
drm_mode_destroy(vmw_priv->dev, mode);
return -EINVAL;
}
@@ -601,6 +579,31 @@ static int vmw_fb_set_par(struct fb_info *info)
if (ret)
goto out_unlock;
+ if (!par->bo_ptr) {
+ struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(set.fb);
+
+ /*
+ * Pin before mapping. Since we don't know in what placement
+ * to pin, call into KMS to do it for us.
+ */
+ ret = vfb->pin(vfb);
+ if (ret) {
+ DRM_ERROR("Could not pin the fbdev framebuffer.\n");
+ goto out_unlock;
+ }
+
+ ret = ttm_bo_kmap(&par->vmw_bo->base, 0,
+ par->vmw_bo->base.num_pages, &par->map);
+ if (ret) {
+ vfb->unpin(vfb);
+ DRM_ERROR("Could not map the fbdev framebuffer.\n");
+ goto out_unlock;
+ }
+
+ par->bo_ptr = ttm_kmap_obj_virtual(&par->map, &par->bo_iowrite);
+ }
+
+
vmw_fb_dirty_mark(par, par->fb_x, par->fb_y,
par->set_fb->width, par->set_fb->height);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 7c2e118a77b0..060e5c6f4446 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1538,14 +1538,10 @@ int vmw_du_connector_fill_modes(struct drm_connector *connector,
DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
};
int i;
- u32 assumed_bpp = 2;
+ u32 assumed_bpp = 4;
- /*
- * If using screen objects, then assume 32-bpp because that's what the
- * SVGA device is assuming
- */
- if (dev_priv->active_display_unit == vmw_du_screen_object)
- assumed_bpp = 4;
+ if (dev_priv->assume_16bpp)
+ assumed_bpp = 2;
if (dev_priv->active_display_unit == vmw_du_screen_target) {
max_width = min(max_width, dev_priv->stdu_max_width);
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index 0585fd2031dd..5030cba4a581 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -997,7 +997,7 @@ struct ipu_platform_reg {
};
/* These must be in the order of the corresponding device tree port nodes */
-static const struct ipu_platform_reg client_reg[] = {
+static struct ipu_platform_reg client_reg[] = {
{
.pdata = {
.csi = 0,
@@ -1048,7 +1048,7 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
mutex_unlock(&ipu_client_id_mutex);
for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
- const struct ipu_platform_reg *reg = &client_reg[i];
+ struct ipu_platform_reg *reg = &client_reg[i];
struct platform_device *pdev;
struct device_node *of_node;
@@ -1070,6 +1070,7 @@ static int ipu_add_client_devices(struct ipu_soc *ipu, unsigned long ipu_base)
pdev->dev.parent = dev;
+ reg->pdata.of_node = of_node;
ret = platform_device_add_data(pdev, &reg->pdata,
sizeof(reg->pdata));
if (!ret)
diff --git a/drivers/gpu/msm/a5xx_reg.h b/drivers/gpu/msm/a5xx_reg.h
index f3b4e6622043..436b6949c414 100644
--- a/drivers/gpu/msm/a5xx_reg.h
+++ b/drivers/gpu/msm/a5xx_reg.h
@@ -608,6 +608,7 @@
#define A5XX_PC_PERFCTR_PC_SEL_7 0xD17
/* HLSQ registers */
+#define A5XX_HLSQ_DBG_ECO_CNTL 0xE04
#define A5XX_HLSQ_ADDR_MODE_CNTL 0xE05
#define A5XX_HLSQ_PERFCTR_HLSQ_SEL_0 0xE10
#define A5XX_HLSQ_PERFCTR_HLSQ_SEL_1 0xE11
@@ -632,6 +633,7 @@
#define A5XX_VFD_PERFCTR_VFD_SEL_7 0xE57
/* VPC registers */
+#define A5XX_VPC_DBG_ECO_CNTL 0xE60
#define A5XX_VPC_ADDR_MODE_CNTL 0xE61
#define A5XX_VPC_PERFCTR_VPC_SEL_0 0xE64
#define A5XX_VPC_PERFCTR_VPC_SEL_1 0xE65
diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h
index 3615be45b6d9..a02ed40ba9d5 100644
--- a/drivers/gpu/msm/adreno-gpulist.h
+++ b/drivers/gpu/msm/adreno-gpulist.h
@@ -269,7 +269,7 @@ static const struct adreno_gpu_core adreno_gpulist[] = {
.patchid = ANY_ID,
.features = ADRENO_PREEMPTION | ADRENO_64BIT |
ADRENO_CONTENT_PROTECTION |
- ADRENO_GPMU | ADRENO_SPTP_PC,
+ ADRENO_GPMU | ADRENO_SPTP_PC | ADRENO_LM,
.pm4fw_name = "a530_pm4.fw",
.pfpfw_name = "a530_pfp.fw",
.zap_name = "a540_zap",
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 6160aa567fbf..11226472d801 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -843,6 +843,8 @@ static struct {
{ ADRENO_QUIRK_FAULT_DETECT_MASK, "qcom,gpu-quirk-fault-detect-mask" },
{ ADRENO_QUIRK_DISABLE_RB_DP2CLOCKGATING,
"qcom,gpu-quirk-dp2clockgating-disable" },
+ { ADRENO_QUIRK_DISABLE_LMLOADKILL,
+ "qcom,gpu-quirk-lmloadkill-disable" },
};
static int adreno_of_get_power(struct adreno_device *adreno_dev,
@@ -2109,8 +2111,6 @@ static int adreno_soft_reset(struct kgsl_device *device)
adreno_support_64bit(adreno_dev))
gpudev->enable_64bit(adreno_dev);
- /* Restore physical performance counter values after soft reset */
- adreno_perfcounter_restore(adreno_dev);
/* Reinitialize the GPU */
gpudev->start(adreno_dev);
@@ -2137,6 +2137,9 @@ static int adreno_soft_reset(struct kgsl_device *device)
set_bit(ADRENO_DEVICE_STARTED, &adreno_dev->priv);
}
+ /* Restore physical performance counter values after soft reset */
+ adreno_perfcounter_restore(adreno_dev);
+
return ret;
}
@@ -2291,9 +2294,9 @@ static void adreno_read(struct kgsl_device *device, void __iomem *base,
unsigned int mem_len)
{
- unsigned int __iomem *reg;
+ void __iomem *reg;
BUG_ON(offsetwords*sizeof(uint32_t) >= mem_len);
- reg = (unsigned int __iomem *)(base + (offsetwords << 2));
+ reg = (base + (offsetwords << 2));
if (!in_interrupt())
kgsl_pre_hwaccess(device);
@@ -2333,7 +2336,7 @@ static void adreno_regwrite(struct kgsl_device *device,
unsigned int offsetwords,
unsigned int value)
{
- unsigned int __iomem *reg;
+ void __iomem *reg;
BUG_ON(offsetwords*sizeof(uint32_t) >= device->reg_len);
@@ -2343,7 +2346,7 @@ static void adreno_regwrite(struct kgsl_device *device,
trace_kgsl_regwrite(device, offsetwords, value);
kgsl_cffdump_regwrite(device, offsetwords << 2, value);
- reg = (unsigned int __iomem *)(device->reg_virt + (offsetwords << 2));
+ reg = (device->reg_virt + (offsetwords << 2));
/*ensure previous writes post before this one,
* i.e. act like normal writel() */
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index a2af26c81f50..d81142db5b58 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -123,6 +123,8 @@
#define ADRENO_QUIRK_FAULT_DETECT_MASK BIT(3)
/* Disable RB sampler datapath clock gating optimization */
#define ADRENO_QUIRK_DISABLE_RB_DP2CLOCKGATING BIT(4)
+/* Disable local memory(LM) feature to avoid corner case error */
+#define ADRENO_QUIRK_DISABLE_LMLOADKILL BIT(5)
/* Flags to control command packet settings */
#define KGSL_CMD_FLAGS_NONE 0
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 3f5a9c6318f6..423071811b43 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -151,6 +151,43 @@ static const unsigned int _a3xx_pwron_fixup_fs_instructions[] = {
0x00000000, 0x03000000, 0x00000000, 0x00000000,
};
+static void a3xx_efuse_speed_bin(struct adreno_device *adreno_dev)
+{
+ unsigned int val;
+ unsigned int speed_bin[3];
+ struct kgsl_device *device = &adreno_dev->dev;
+
+ if (of_property_read_u32_array(device->pdev->dev.of_node,
+ "qcom,gpu-speed-bin", speed_bin, 3))
+ return;
+
+ adreno_efuse_read_u32(adreno_dev, speed_bin[0], &val);
+
+ adreno_dev->speed_bin = (val & speed_bin[1]) >> speed_bin[2];
+}
+
+static const struct {
+ int (*check)(struct adreno_device *adreno_dev);
+ void (*func)(struct adreno_device *adreno_dev);
+} a3xx_efuse_funcs[] = {
+ { adreno_is_a306a, a3xx_efuse_speed_bin },
+};
+
+static void a3xx_check_features(struct adreno_device *adreno_dev)
+{
+ unsigned int i;
+
+ if (adreno_efuse_map(adreno_dev))
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(a3xx_efuse_funcs); i++) {
+ if (a3xx_efuse_funcs[i].check(adreno_dev))
+ a3xx_efuse_funcs[i].func(adreno_dev);
+ }
+
+ adreno_efuse_unmap(adreno_dev);
+}
+
/**
* _a3xx_pwron_fixup() - Initialize a special command buffer to run a
* post-power collapse shader workaround
@@ -604,6 +641,9 @@ static void a3xx_platform_setup(struct adreno_device *adreno_dev)
gpudev->vbif_xin_halt_ctrl0_mask =
A30X_VBIF_XIN_HALT_CTRL0_MASK;
}
+
+ /* Check efuse bits for various capabilties */
+ a3xx_check_features(adreno_dev);
}
static int a3xx_send_me_init(struct adreno_device *adreno_dev,
diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c
index 860f6d2925f1..f652e955b07c 100644
--- a/drivers/gpu/msm/adreno_a5xx.c
+++ b/drivers/gpu/msm/adreno_a5xx.c
@@ -196,6 +196,8 @@ static void a5xx_platform_setup(struct adreno_device *adreno_dev)
/* A510 has 3 XIN ports in VBIF */
gpudev->vbif_xin_halt_ctrl0_mask =
A510_VBIF_XIN_HALT_CTRL0_MASK;
+ } else if (adreno_is_a540(adreno_dev)) {
+ gpudev->snapshot_data->sect_sizes->cp_merciu = 1024;
}
/* Calculate SP local and private mem addresses */
@@ -1534,12 +1536,12 @@ static void a5xx_clk_set_options(struct adreno_device *adreno_dev,
const char *name, struct clk *clk)
{
if (adreno_is_a540(adreno_dev)) {
- if (!strcmp(name, "mem_iface_clk"))
- clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH);
- clk_set_flags(clk, CLKFLAG_NORETAIN_MEM);
- if (!strcmp(name, "core_clk")) {
+ if (!strcmp(name, "mem_iface_clk")) {
clk_set_flags(clk, CLKFLAG_NORETAIN_PERIPH);
clk_set_flags(clk, CLKFLAG_NORETAIN_MEM);
+ } else if (!strcmp(name, "core_clk")) {
+ clk_set_flags(clk, CLKFLAG_RETAIN_PERIPH);
+ clk_set_flags(clk, CLKFLAG_RETAIN_MEM);
}
}
}
@@ -1781,11 +1783,11 @@ static void a5xx_start(struct adreno_device *adreno_dev)
set_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
gpudev->irq->mask |= (1 << A5XX_INT_MISC_HANG_DETECT);
/*
- * Set hang detection threshold to 1 million cycles
- * (0xFFFF*16)
+ * Set hang detection threshold to 4 million cycles
+ * (0x3FFFF*16)
*/
kgsl_regwrite(device, A5XX_RBBM_INTERFACE_HANG_INT_CNTL,
- (1 << 30) | 0xFFFF);
+ (1 << 30) | 0x3FFFF);
}
@@ -1944,6 +1946,16 @@ static void a5xx_start(struct adreno_device *adreno_dev)
}
+ /*
+ * VPC corner case with local memory load kill leads to corrupt
+ * internal state. Normal Disable does not work for all a5x chips.
+ * So do the following setting to disable it.
+ */
+ if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_DISABLE_LMLOADKILL)) {
+ kgsl_regrmw(device, A5XX_VPC_DBG_ECO_CNTL, 0, 0x1 << 23);
+ kgsl_regrmw(device, A5XX_HLSQ_DBG_ECO_CNTL, 0x1 << 18, 0);
+ }
+
a5xx_preemption_start(adreno_dev);
a5xx_protect_init(adreno_dev);
}
diff --git a/drivers/gpu/msm/adreno_perfcounter.c b/drivers/gpu/msm/adreno_perfcounter.c
index 42f8119ad8b4..f5f99c3ebb4a 100644
--- a/drivers/gpu/msm/adreno_perfcounter.c
+++ b/drivers/gpu/msm/adreno_perfcounter.c
@@ -522,12 +522,18 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev,
if (empty == -1)
return -EBUSY;
+ /* initialize the new counter */
+ group->regs[empty].countable = countable;
+
/* enable the new counter */
ret = adreno_perfcounter_enable(adreno_dev, groupid, empty, countable);
- if (ret)
+ if (ret) {
+ /* Put back the perfcounter */
+ if (!(group->flags & ADRENO_PERFCOUNTER_GROUP_FIXED))
+ group->regs[empty].countable =
+ KGSL_PERFCOUNTER_NOT_USED;
return ret;
- /* initialize the new counter */
- group->regs[empty].countable = countable;
+ }
/* set initial kernel and user count */
if (flags & PERFCOUNTER_FLAG_KERNEL) {
@@ -720,10 +726,22 @@ static int _perfcounter_enable_default(struct adreno_device *adreno_dev,
/* wait for the above commands submitted to complete */
ret = adreno_ringbuffer_waittimestamp(rb, rb->timestamp,
ADRENO_IDLE_TIMEOUT);
- if (ret)
- KGSL_DRV_ERR(device,
- "Perfcounter %u/%u/%u start via commands failed %d\n",
- group, counter, countable, ret);
+ if (ret) {
+ /*
+ * If we were woken up because of cancelling rb events
+ * either due to soft reset or adreno_stop, ignore the
+ * error and return 0 here. The perfcounter is already
+ * set up in software and it will be programmed in
+ * hardware when we wake up or come up after soft reset,
+ * by adreno_perfcounter_restore.
+ */
+ if (ret == -EAGAIN)
+ ret = 0;
+ else
+ KGSL_DRV_ERR(device,
+ "Perfcounter %u/%u/%u start via commands failed %d\n",
+ group, counter, countable, ret);
+ }
} else {
/* Select the desired perfcounter */
kgsl_regwrite(device, reg->select, countable);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index add4590bbb90..554eb2dffae4 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2507,6 +2507,8 @@ static int kgsl_setup_dma_buf(struct kgsl_device *device,
meta->dmabuf = dmabuf;
meta->attach = attach;
+ attach->priv = entry;
+
entry->priv_data = meta;
entry->memdesc.pagetable = pagetable;
entry->memdesc.size = 0;
@@ -2557,6 +2559,45 @@ out:
}
#endif
+#ifdef CONFIG_DMA_SHARED_BUFFER
+void kgsl_get_egl_counts(struct kgsl_mem_entry *entry,
+ int *egl_surface_count, int *egl_image_count)
+{
+ struct kgsl_dma_buf_meta *meta = entry->priv_data;
+ struct dma_buf *dmabuf = meta->dmabuf;
+ struct dma_buf_attachment *mem_entry_buf_attachment = meta->attach;
+ struct device *buf_attachment_dev = mem_entry_buf_attachment->dev;
+ struct dma_buf_attachment *attachment = NULL;
+
+ mutex_lock(&dmabuf->lock);
+ list_for_each_entry(attachment, &dmabuf->attachments, node) {
+ struct kgsl_mem_entry *scan_mem_entry = NULL;
+
+ if (attachment->dev != buf_attachment_dev)
+ continue;
+
+ scan_mem_entry = attachment->priv;
+ if (!scan_mem_entry)
+ continue;
+
+ switch (kgsl_memdesc_get_memtype(&scan_mem_entry->memdesc)) {
+ case KGSL_MEMTYPE_EGL_SURFACE:
+ (*egl_surface_count)++;
+ break;
+ case KGSL_MEMTYPE_EGL_IMAGE:
+ (*egl_image_count)++;
+ break;
+ }
+ }
+ mutex_unlock(&dmabuf->lock);
+}
+#else
+void kgsl_get_egl_counts(struct kgsl_mem_entry *entry,
+ int *egl_surface_count, int *egl_image_count)
+{
+}
+#endif
+
long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
@@ -3891,7 +3932,7 @@ kgsl_mmap_memstore(struct kgsl_device *device, struct vm_area_struct *vma)
return -EINVAL;
}
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
result = remap_pfn_range(vma, vma->vm_start,
device->memstore.physaddr >> PAGE_SHIFT,
@@ -4527,6 +4568,9 @@ int kgsl_device_platform_probe(struct kgsl_device *device)
if (status)
goto error_close_mmu;
+ /* Initialize the memory pools */
+ kgsl_init_page_pools(device->pdev);
+
status = kgsl_allocate_global(device, &device->memstore,
KGSL_MEMSTORE_SIZE, 0, KGSL_MEMDESC_CONTIG, "memstore");
@@ -4581,9 +4625,6 @@ int kgsl_device_platform_probe(struct kgsl_device *device)
/* Initialize common sysfs entries */
kgsl_pwrctrl_init_sysfs(device);
- /* Initialize the memory pools */
- kgsl_init_page_pools();
-
return 0;
error_free_memstore:
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 826c4edb3582..fbf9197b6d1b 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -435,6 +435,9 @@ long kgsl_ioctl_sparse_unbind(struct kgsl_device_private *dev_priv,
void kgsl_mem_entry_destroy(struct kref *kref);
+void kgsl_get_egl_counts(struct kgsl_mem_entry *entry,
+ int *egl_surface_count, int *egl_image_count);
+
struct kgsl_mem_entry * __must_check
kgsl_sharedmem_find(struct kgsl_process_private *private, uint64_t gpuaddr);
diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c
index 2f293e4da398..7758fc956055 100644
--- a/drivers/gpu/msm/kgsl_debugfs.c
+++ b/drivers/gpu/msm/kgsl_debugfs.c
@@ -125,13 +125,15 @@ static char get_cacheflag(const struct kgsl_memdesc *m)
}
-static int print_mem_entry(int id, void *ptr, void *data)
+static int print_mem_entry(void *data, void *ptr)
{
struct seq_file *s = data;
struct kgsl_mem_entry *entry = ptr;
char flags[10];
char usage[16];
struct kgsl_memdesc *m = &entry->memdesc;
+ unsigned int usermem_type = kgsl_memdesc_usermem_type(m);
+ int egl_surface_count = 0, egl_image_count = 0;
if (m->flags & KGSL_MEMFLAGS_SPARSE_VIRT)
return 0;
@@ -149,12 +151,17 @@ static int print_mem_entry(int id, void *ptr, void *data)
kgsl_get_memory_usage(usage, sizeof(usage), m->flags);
- seq_printf(s, "%pK %pK %16llu %5d %9s %10s %16s %5d %16llu",
+ if (usermem_type == KGSL_MEM_ENTRY_ION)
+ kgsl_get_egl_counts(entry, &egl_surface_count,
+ &egl_image_count);
+
+ seq_printf(s, "%pK %pK %16llu %5d %9s %10s %16s %5d %16llu %6d %6d",
(uint64_t *)(uintptr_t) m->gpuaddr,
(unsigned long *) m->useraddr,
m->size, entry->id, flags,
- memtype_str(kgsl_memdesc_usermem_type(m)),
- usage, (m->sgt ? m->sgt->nents : 0), m->mapsize);
+ memtype_str(usermem_type),
+ usage, (m->sgt ? m->sgt->nents : 0), m->mapsize,
+ egl_surface_count, egl_image_count);
if (entry->metadata[0] != 0)
seq_printf(s, " %s", entry->metadata);
@@ -164,25 +171,83 @@ static int print_mem_entry(int id, void *ptr, void *data)
return 0;
}
-static int process_mem_print(struct seq_file *s, void *unused)
+static struct kgsl_mem_entry *process_mem_seq_find(struct seq_file *s,
+ void *ptr, loff_t pos)
{
+ struct kgsl_mem_entry *entry = ptr;
struct kgsl_process_private *private = s->private;
+ int id = 0;
+ loff_t temp_pos = 1;
- seq_printf(s, "%16s %16s %16s %5s %9s %10s %16s %5s %16s\n",
- "gpuaddr", "useraddr", "size", "id", "flags", "type",
- "usage", "sglen", "mapsize");
+ if (entry != SEQ_START_TOKEN)
+ id = entry->id + 1;
spin_lock(&private->mem_lock);
- idr_for_each(&private->mem_idr, print_mem_entry, s);
+ for (entry = idr_get_next(&private->mem_idr, &id); entry;
+ id++, entry = idr_get_next(&private->mem_idr, &id),
+ temp_pos++) {
+ if (temp_pos == pos && kgsl_mem_entry_get(entry)) {
+ spin_unlock(&private->mem_lock);
+ goto found;
+ }
+ }
spin_unlock(&private->mem_lock);
- return 0;
+ entry = NULL;
+found:
+ if (ptr != SEQ_START_TOKEN)
+ kgsl_mem_entry_put(ptr);
+
+ return entry;
+}
+
+static void *process_mem_seq_start(struct seq_file *s, loff_t *pos)
+{
+ loff_t seq_file_offset = *pos;
+
+ if (seq_file_offset == 0)
+ return SEQ_START_TOKEN;
+ else
+ return process_mem_seq_find(s, SEQ_START_TOKEN,
+ seq_file_offset);
+}
+
+static void process_mem_seq_stop(struct seq_file *s, void *ptr)
+{
+ if (ptr && ptr != SEQ_START_TOKEN)
+ kgsl_mem_entry_put(ptr);
}
+static void *process_mem_seq_next(struct seq_file *s, void *ptr,
+ loff_t *pos)
+{
+ ++*pos;
+ return process_mem_seq_find(s, ptr, 1);
+}
+
+static int process_mem_seq_show(struct seq_file *s, void *ptr)
+{
+ if (ptr == SEQ_START_TOKEN) {
+ seq_printf(s, "%16s %16s %16s %5s %9s %10s %16s %5s %16s %6s %6s\n",
+ "gpuaddr", "useraddr", "size", "id", "flags", "type",
+ "usage", "sglen", "mapsize", "eglsrf", "eglimg");
+ return 0;
+ } else
+ return print_mem_entry(s, ptr);
+}
+
+static const struct seq_operations process_mem_seq_fops = {
+ .start = process_mem_seq_start,
+ .stop = process_mem_seq_stop,
+ .next = process_mem_seq_next,
+ .show = process_mem_seq_show,
+};
+
static int process_mem_open(struct inode *inode, struct file *file)
{
int ret;
pid_t pid = (pid_t) (unsigned long) inode->i_private;
+ struct seq_file *s = NULL;
struct kgsl_process_private *private = NULL;
private = kgsl_process_private_find(pid);
@@ -190,9 +255,13 @@ static int process_mem_open(struct inode *inode, struct file *file)
if (!private)
return -ENODEV;
- ret = single_open(file, process_mem_print, private);
+ ret = seq_open(file, &process_mem_seq_fops);
if (ret)
kgsl_process_private_put(private);
+ else {
+ s = file->private_data;
+ s->private = private;
+ }
return ret;
}
@@ -205,7 +274,7 @@ static int process_mem_release(struct inode *inode, struct file *file)
if (private)
kgsl_process_private_put(private);
- return single_release(inode, file);
+ return seq_release(inode, file);
}
static const struct file_operations process_mem_fops = {
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index ba564b2851f9..f516b7cd245a 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -390,6 +390,13 @@ kgsl_mmu_map(struct kgsl_pagetable *pagetable,
if (!memdesc->gpuaddr)
return -EINVAL;
+ if (!(memdesc->flags & (KGSL_MEMFLAGS_SPARSE_VIRT |
+ KGSL_MEMFLAGS_SPARSE_PHYS))) {
+ /* Only global mappings should be mapped multiple times */
+ if (!kgsl_memdesc_is_global(memdesc) &&
+ (KGSL_MEMDESC_MAPPED & memdesc->priv))
+ return -EINVAL;
+ }
size = kgsl_memdesc_footprint(memdesc);
@@ -403,6 +410,9 @@ kgsl_mmu_map(struct kgsl_pagetable *pagetable,
atomic_inc(&pagetable->stats.entries);
KGSL_STATS_ADD(size, &pagetable->stats.mapped,
&pagetable->stats.max_mapped);
+
+ /* This is needed for non-sparse mappings */
+ memdesc->priv |= KGSL_MEMDESC_MAPPED;
}
return 0;
@@ -455,6 +465,13 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
if (memdesc->size == 0)
return -EINVAL;
+ if (!(memdesc->flags & (KGSL_MEMFLAGS_SPARSE_VIRT |
+ KGSL_MEMFLAGS_SPARSE_PHYS))) {
+ /* Only global mappings should be mapped multiple times */
+ if (!(KGSL_MEMDESC_MAPPED & memdesc->priv))
+ return -EINVAL;
+ }
+
if (PT_OP_VALID(pagetable, mmu_unmap)) {
uint64_t size;
@@ -464,6 +481,9 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
atomic_dec(&pagetable->stats.entries);
atomic_long_sub(size, &pagetable->stats.mapped);
+
+ if (!kgsl_memdesc_is_global(memdesc))
+ memdesc->priv &= ~KGSL_MEMDESC_MAPPED;
}
return ret;
diff --git a/drivers/gpu/msm/kgsl_pool.c b/drivers/gpu/msm/kgsl_pool.c
index f5402fdc7e57..6ecbab466c7c 100644
--- a/drivers/gpu/msm/kgsl_pool.c
+++ b/drivers/gpu/msm/kgsl_pool.c
@@ -21,6 +21,10 @@
#include "kgsl_device.h"
#include "kgsl_pool.h"
+#define KGSL_MAX_POOLS 4
+#define KGSL_MAX_POOL_ORDER 8
+#define KGSL_MAX_RESERVED_PAGES 4096
+
/**
* struct kgsl_page_pool - Structure to hold information for the pool
* @pool_order: Page order describing the size of the page
@@ -40,41 +44,10 @@ struct kgsl_page_pool {
struct list_head page_list;
};
-static struct kgsl_page_pool kgsl_pools[] = {
- {
- .pool_order = 0,
- .reserved_pages = 2048,
- .allocation_allowed = true,
- .list_lock = __SPIN_LOCK_UNLOCKED(kgsl_pools[0].list_lock),
- .page_list = LIST_HEAD_INIT(kgsl_pools[0].page_list),
- },
-#ifndef CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS
- {
- .pool_order = 1,
- .reserved_pages = 1024,
- .allocation_allowed = true,
- .list_lock = __SPIN_LOCK_UNLOCKED(kgsl_pools[1].list_lock),
- .page_list = LIST_HEAD_INIT(kgsl_pools[1].page_list),
- },
- {
- .pool_order = 4,
- .reserved_pages = 256,
- .allocation_allowed = false,
- .list_lock = __SPIN_LOCK_UNLOCKED(kgsl_pools[2].list_lock),
- .page_list = LIST_HEAD_INIT(kgsl_pools[2].page_list),
- },
- {
- .pool_order = 8,
- .reserved_pages = 32,
- .allocation_allowed = false,
- .list_lock = __SPIN_LOCK_UNLOCKED(kgsl_pools[3].list_lock),
- .page_list = LIST_HEAD_INIT(kgsl_pools[3].page_list),
- },
+static struct kgsl_page_pool kgsl_pools[KGSL_MAX_POOLS];
+static int kgsl_num_pools;
+static int kgsl_pool_max_pages;
-#endif
-};
-
-#define KGSL_NUM_POOLS ARRAY_SIZE(kgsl_pools)
/* Returns KGSL pool corresponding to input page order*/
static struct kgsl_page_pool *
@@ -82,7 +55,7 @@ _kgsl_get_pool_from_order(unsigned int order)
{
int i;
- for (i = 0; i < KGSL_NUM_POOLS; i++) {
+ for (i = 0; i < kgsl_num_pools; i++) {
if (kgsl_pools[i].pool_order == order)
return &kgsl_pools[i];
}
@@ -154,7 +127,7 @@ static int kgsl_pool_size_total(void)
int i;
int total = 0;
- for (i = 0; i < KGSL_NUM_POOLS; i++)
+ for (i = 0; i < kgsl_num_pools; i++)
total += kgsl_pool_size(&kgsl_pools[i]);
return total;
}
@@ -207,7 +180,7 @@ kgsl_pool_reduce(unsigned int target_pages, bool exit)
total_pages = kgsl_pool_size_total();
- for (i = (KGSL_NUM_POOLS - 1); i >= 0; i--) {
+ for (i = (kgsl_num_pools - 1); i >= 0; i--) {
pool = &kgsl_pools[i];
/*
@@ -300,7 +273,7 @@ static int kgsl_pool_idx_lookup(unsigned int order)
{
int i;
- for (i = 0; i < KGSL_NUM_POOLS; i++)
+ for (i = 0; i < kgsl_num_pools; i++)
if (order == kgsl_pools[i].pool_order)
return i;
@@ -384,10 +357,13 @@ void kgsl_pool_free_page(struct page *page)
page_order = compound_order(page);
- pool = _kgsl_get_pool_from_order(page_order);
- if (pool != NULL) {
- _kgsl_pool_add_page(pool, page);
- return;
+ if (!kgsl_pool_max_pages ||
+ (kgsl_pool_size_total() < kgsl_pool_max_pages)) {
+ pool = _kgsl_get_pool_from_order(page_order);
+ if (pool != NULL) {
+ _kgsl_pool_add_page(pool, page);
+ return;
+ }
}
/* Give back to system as not added to pool */
@@ -398,7 +374,7 @@ static void kgsl_pool_reserve_pages(void)
{
int i, j;
- for (i = 0; i < KGSL_NUM_POOLS; i++) {
+ for (i = 0; i < kgsl_num_pools; i++) {
struct page *page;
for (j = 0; j < kgsl_pools[i].reserved_pages; j++) {
@@ -445,8 +421,76 @@ static struct shrinker kgsl_pool_shrinker = {
.batch = 0,
};
-void kgsl_init_page_pools(void)
+static void kgsl_pool_config(unsigned int order, unsigned int reserved_pages,
+ bool allocation_allowed)
{
+#ifdef CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS
+ if (order > 0) {
+ pr_info("%s: Pool order:%d not supprted.!!\n", __func__, order);
+ return;
+ }
+#endif
+ if ((order > KGSL_MAX_POOL_ORDER) ||
+ (reserved_pages > KGSL_MAX_RESERVED_PAGES))
+ return;
+
+ kgsl_pools[kgsl_num_pools].pool_order = order;
+ kgsl_pools[kgsl_num_pools].reserved_pages = reserved_pages;
+ kgsl_pools[kgsl_num_pools].allocation_allowed = allocation_allowed;
+ spin_lock_init(&kgsl_pools[kgsl_num_pools].list_lock);
+ INIT_LIST_HEAD(&kgsl_pools[kgsl_num_pools].page_list);
+ kgsl_num_pools++;
+}
+
+static void kgsl_of_parse_mempools(struct device_node *node)
+{
+ struct device_node *child;
+ unsigned int page_size, reserved_pages = 0;
+ bool allocation_allowed;
+
+ for_each_child_of_node(node, child) {
+ unsigned int index;
+
+ if (of_property_read_u32(child, "reg", &index))
+ return;
+
+ if (index >= KGSL_MAX_POOLS)
+ continue;
+
+ if (of_property_read_u32(child, "qcom,mempool-page-size",
+ &page_size))
+ return;
+
+ of_property_read_u32(child, "qcom,mempool-reserved",
+ &reserved_pages);
+
+ allocation_allowed = of_property_read_bool(child,
+ "qcom,mempool-allocate");
+
+ kgsl_pool_config(ilog2(page_size >> PAGE_SHIFT), reserved_pages,
+ allocation_allowed);
+ }
+}
+
+static void kgsl_of_get_mempools(struct device_node *parent)
+{
+ struct device_node *node;
+
+ node = of_find_compatible_node(parent, NULL, "qcom,gpu-mempools");
+ if (node != NULL) {
+ /* Get Max pages limit for mempool */
+ of_property_read_u32(node, "qcom,mempool-max-pages",
+ &kgsl_pool_max_pages);
+ kgsl_of_parse_mempools(node);
+ }
+}
+
+void kgsl_init_page_pools(struct platform_device *pdev)
+{
+
+ /* Get GPU mempools data and configure pools */
+ kgsl_of_get_mempools(pdev->dev.of_node);
+
/* Reserve the appropriate number of pages for each pool */
kgsl_pool_reserve_pages();
diff --git a/drivers/gpu/msm/kgsl_pool.h b/drivers/gpu/msm/kgsl_pool.h
index efbfa96f1498..d55e1ada123b 100644
--- a/drivers/gpu/msm/kgsl_pool.h
+++ b/drivers/gpu/msm/kgsl_pool.h
@@ -35,7 +35,7 @@ kgsl_gfp_mask(unsigned int page_order)
void kgsl_pool_free_sgt(struct sg_table *sgt);
void kgsl_pool_free_pages(struct page **pages, unsigned int page_count);
-void kgsl_init_page_pools(void);
+void kgsl_init_page_pools(struct platform_device *pdev);
void kgsl_exit_page_pools(void);
int kgsl_pool_alloc_page(int *page_size, struct page **pages,
unsigned int pages_len, unsigned int *align);
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index a2e4a909062f..13dc3017072d 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -1067,6 +1067,9 @@ void kgsl_snapshot_save_frozen_objs(struct work_struct *work)
size_t size = 0;
void *ptr;
+ if (IS_ERR_OR_NULL(device))
+ return;
+
kgsl_snapshot_process_ib_obj_list(snapshot);
list_for_each_entry(obj, &snapshot->obj_list, node) {
diff --git a/drivers/hid/hid-elo.c b/drivers/hid/hid-elo.c
index aad8c162a825..0cd4f7216239 100644
--- a/drivers/hid/hid-elo.c
+++ b/drivers/hid/hid-elo.c
@@ -261,7 +261,7 @@ static void elo_remove(struct hid_device *hdev)
struct elo_priv *priv = hid_get_drvdata(hdev);
hid_hw_stop(hdev);
- flush_workqueue(wq);
+ cancel_delayed_work_sync(&priv->work);
kfree(priv);
}
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 7ecd96bdf834..f62a9d6601cc 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -61,6 +61,7 @@ MODULE_LICENSE("GPL");
#define MT_QUIRK_ALWAYS_VALID (1 << 4)
#define MT_QUIRK_VALID_IS_INRANGE (1 << 5)
#define MT_QUIRK_VALID_IS_CONFIDENCE (1 << 6)
+#define MT_QUIRK_CONFIDENCE (1 << 7)
#define MT_QUIRK_SLOT_IS_CONTACTID_MINUS_ONE (1 << 8)
#define MT_QUIRK_NO_AREA (1 << 9)
#define MT_QUIRK_IGNORE_DUPLICATES (1 << 10)
@@ -78,6 +79,7 @@ struct mt_slot {
__s32 contactid; /* the device ContactID assigned to this slot */
bool touch_state; /* is the touch valid? */
bool inrange_state; /* is the finger in proximity of the sensor? */
+ bool confidence_state; /* is the touch made by a finger? */
};
struct mt_class {
@@ -450,16 +452,6 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON)
td->buttons_count++;
- /* Only map fields from TouchScreen or TouchPad collections.
- * We need to ignore fields that belong to other collections
- * such as Mouse that might have the same GenericDesktop usages. */
- if (field->application == HID_DG_TOUCHSCREEN)
- set_bit(INPUT_PROP_DIRECT, hi->input->propbit);
- else if (field->application == HID_DG_TOUCHPAD)
- set_bit(INPUT_PROP_POINTER, hi->input->propbit);
- else
- return 0;
-
if (usage->usage_index)
prev_usage = &field->usage[usage->usage_index - 1];
@@ -512,6 +504,9 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
mt_store_field(usage, td, hi);
return 1;
case HID_DG_CONFIDENCE:
+ if (cls->name == MT_CLS_WIN_8 &&
+ field->application == HID_DG_TOUCHPAD)
+ cls->quirks |= MT_QUIRK_CONFIDENCE;
mt_store_field(usage, td, hi);
return 1;
case HID_DG_TIPSWITCH:
@@ -624,6 +619,7 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
return;
if (td->curvalid || (td->mtclass.quirks & MT_QUIRK_ALWAYS_VALID)) {
+ int active;
int slotnum = mt_compute_slot(td, input);
struct mt_slot *s = &td->curdata;
struct input_mt *mt = input->mt;
@@ -638,10 +634,14 @@ static void mt_complete_slot(struct mt_device *td, struct input_dev *input)
return;
}
+ if (!(td->mtclass.quirks & MT_QUIRK_CONFIDENCE))
+ s->confidence_state = 1;
+ active = (s->touch_state || s->inrange_state) &&
+ s->confidence_state;
+
input_mt_slot(input, slotnum);
- input_mt_report_slot_state(input, MT_TOOL_FINGER,
- s->touch_state || s->inrange_state);
- if (s->touch_state || s->inrange_state) {
+ input_mt_report_slot_state(input, MT_TOOL_FINGER, active);
+ if (active) {
/* this finger is in proximity of the sensor */
int wide = (s->w > s->h);
/* divided by two to match visual scale of touch */
@@ -706,6 +706,8 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
td->curdata.touch_state = value;
break;
case HID_DG_CONFIDENCE:
+ if (quirks & MT_QUIRK_CONFIDENCE)
+ td->curdata.confidence_state = value;
if (quirks & MT_QUIRK_VALID_IS_CONFIDENCE)
td->curvalid = value;
break;
diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c
index 93ddc1c65b4c..3edd4ac36494 100644
--- a/drivers/hid/hid-steelseries.c
+++ b/drivers/hid/hid-steelseries.c
@@ -253,11 +253,6 @@ static int steelseries_srws1_probe(struct hid_device *hdev,
goto err_free;
}
- if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 16)) {
- ret = -ENODEV;
- goto err_free;
- }
-
ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
if (ret) {
hid_err(hdev, "hw start failed\n");
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c
index 2f1ddca6f2e0..700145b15088 100644
--- a/drivers/hid/usbhid/hiddev.c
+++ b/drivers/hid/usbhid/hiddev.c
@@ -516,13 +516,13 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,
goto inval;
} else if (uref->usage_index >= field->report_count)
goto inval;
-
- else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
- (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
- uref->usage_index + uref_multi->num_values > field->report_count))
- goto inval;
}
+ if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
+ (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
+ uref->usage_index + uref_multi->num_values > field->report_count))
+ goto inval;
+
switch (cmd) {
case HIDIOCGUSAGE:
uref->value = field->value[uref->usage_index];
diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c
index 6c99ee7bafa3..ee396ff167d9 100644
--- a/drivers/hwmon/ads7828.c
+++ b/drivers/hwmon/ads7828.c
@@ -120,6 +120,7 @@ static int ads7828_probe(struct i2c_client *client,
unsigned int vref_mv = ADS7828_INT_VREF_MV;
bool diff_input = false;
bool ext_vref = false;
+ unsigned int regval;
data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL);
if (!data)
@@ -154,6 +155,15 @@ static int ads7828_probe(struct i2c_client *client,
if (!diff_input)
data->cmd_byte |= ADS7828_CMD_SD_SE;
+ /*
+ * Datasheet specifies internal reference voltage is disabled by
+ * default. The internal reference voltage needs to be enabled and
+ * voltage needs to settle before getting valid ADC data. So perform a
+ * dummy read to enable the internal reference voltage.
+ */
+ if (!ext_vref)
+ regmap_read(data->regmap, data->cmd_byte, &regval);
+
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
data,
ads7828_groups);
diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c
index c43318d3416e..a9356a3dea92 100644
--- a/drivers/hwmon/dell-smm-hwmon.c
+++ b/drivers/hwmon/dell-smm-hwmon.c
@@ -66,11 +66,13 @@
static DEFINE_MUTEX(i8k_mutex);
static char bios_version[4];
+static char bios_machineid[16];
static struct device *i8k_hwmon_dev;
static u32 i8k_hwmon_flags;
static uint i8k_fan_mult = I8K_FAN_MULT;
static uint i8k_pwm_mult;
static uint i8k_fan_max = I8K_FAN_HIGH;
+static bool disallow_fan_type_call;
#define I8K_HWMON_HAVE_TEMP1 (1 << 0)
#define I8K_HWMON_HAVE_TEMP2 (1 << 1)
@@ -94,13 +96,13 @@ module_param(ignore_dmi, bool, 0);
MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
#if IS_ENABLED(CONFIG_I8K)
-static bool restricted;
+static bool restricted = true;
module_param(restricted, bool, 0);
-MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set");
+MODULE_PARM_DESC(restricted, "Restrict fan control and serial number to CAP_SYS_ADMIN (default: 1)");
static bool power_status;
module_param(power_status, bool, 0600);
-MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
+MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k (default: 0)");
#endif
static uint fan_mult;
@@ -235,14 +237,28 @@ static int i8k_get_fan_speed(int fan)
/*
* Read the fan type.
*/
-static int i8k_get_fan_type(int fan)
+static int _i8k_get_fan_type(int fan)
{
struct smm_regs regs = { .eax = I8K_SMM_GET_FAN_TYPE, };
+ if (disallow_fan_type_call)
+ return -EINVAL;
+
regs.ebx = fan & 0xff;
return i8k_smm(&regs) ? : regs.eax & 0xff;
}
+static int i8k_get_fan_type(int fan)
+{
+ /* I8K_SMM_GET_FAN_TYPE SMM call is expensive, so cache values */
+ static int types[2] = { INT_MIN, INT_MIN };
+
+ if (types[fan] == INT_MIN)
+ types[fan] = _i8k_get_fan_type(fan);
+
+ return types[fan];
+}
+
/*
* Read the fan nominal rpm for specific fan speed.
*/
@@ -392,9 +408,11 @@ i8k_ioctl_unlocked(struct file *fp, unsigned int cmd, unsigned long arg)
break;
case I8K_MACHINE_ID:
- memset(buff, 0, 16);
- strlcpy(buff, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
- sizeof(buff));
+ if (restricted && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ memset(buff, 0, sizeof(buff));
+ strlcpy(buff, bios_machineid, sizeof(buff));
break;
case I8K_FN_STATUS:
@@ -511,7 +529,7 @@ static int i8k_proc_show(struct seq_file *seq, void *offset)
seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
I8K_PROC_FMT,
bios_version,
- i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
+ (restricted && !capable(CAP_SYS_ADMIN)) ? "-1" : bios_machineid,
cpu_temp,
left_fan, right_fan, left_speed, right_speed,
ac_power, fn_key);
@@ -718,6 +736,9 @@ static struct attribute *i8k_attrs[] = {
static umode_t i8k_is_visible(struct kobject *kobj, struct attribute *attr,
int index)
{
+ if (disallow_fan_type_call &&
+ (index == 9 || index == 12))
+ return 0;
if (index >= 0 && index <= 1 &&
!(i8k_hwmon_flags & I8K_HWMON_HAVE_TEMP1))
return 0;
@@ -767,13 +788,17 @@ static int __init i8k_init_hwmon(void)
if (err >= 0)
i8k_hwmon_flags |= I8K_HWMON_HAVE_TEMP4;
- /* First fan attributes, if fan type is OK */
- err = i8k_get_fan_type(0);
+ /* First fan attributes, if fan status or type is OK */
+ err = i8k_get_fan_status(0);
+ if (err < 0)
+ err = i8k_get_fan_type(0);
if (err >= 0)
i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN1;
- /* Second fan attributes, if fan type is OK */
- err = i8k_get_fan_type(1);
+ /* Second fan attributes, if fan status or type is OK */
+ err = i8k_get_fan_status(1);
+ if (err < 0)
+ err = i8k_get_fan_type(1);
if (err >= 0)
i8k_hwmon_flags |= I8K_HWMON_HAVE_FAN2;
@@ -929,12 +954,14 @@ static struct dmi_system_id i8k_dmi_table[] __initdata = {
MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);
-static struct dmi_system_id i8k_blacklist_dmi_table[] __initdata = {
+/*
+ * On some machines once I8K_SMM_GET_FAN_TYPE is issued then CPU fan speed
+ * randomly going up and down due to bug in Dell SMM or BIOS. Here is blacklist
+ * of affected Dell machines for which we disallow I8K_SMM_GET_FAN_TYPE call.
+ * See bug: https://bugzilla.kernel.org/show_bug.cgi?id=100121
+ */
+static struct dmi_system_id i8k_blacklist_fan_type_dmi_table[] __initdata = {
{
- /*
- * CPU fan speed going up and down on Dell Studio XPS 8000
- * for unknown reasons.
- */
.ident = "Dell Studio XPS 8000",
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
@@ -942,16 +969,19 @@ static struct dmi_system_id i8k_blacklist_dmi_table[] __initdata = {
},
},
{
- /*
- * CPU fan speed going up and down on Dell Studio XPS 8100
- * for unknown reasons.
- */
.ident = "Dell Studio XPS 8100",
.matches = {
DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Studio XPS 8100"),
},
},
+ {
+ .ident = "Dell Inspiron 580",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Inspiron 580 "),
+ },
+ },
{ }
};
@@ -966,8 +996,7 @@ static int __init i8k_probe(void)
/*
* Get DMI information
*/
- if (!dmi_check_system(i8k_dmi_table) ||
- dmi_check_system(i8k_blacklist_dmi_table)) {
+ if (!dmi_check_system(i8k_dmi_table)) {
if (!ignore_dmi && !force)
return -ENODEV;
@@ -978,8 +1007,13 @@ static int __init i8k_probe(void)
i8k_get_dmi_data(DMI_BIOS_VERSION));
}
+ if (dmi_check_system(i8k_blacklist_fan_type_dmi_table))
+ disallow_fan_type_call = true;
+
strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION),
sizeof(bios_version));
+ strlcpy(bios_machineid, i8k_get_dmi_data(DMI_PRODUCT_SERIAL),
+ sizeof(bios_machineid));
/*
* Get SMM Dell signature
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index 5697ad3b1d13..a37b5ce9a6b2 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -2801,6 +2801,10 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
put_online_cpus();
+ ret = clk_set_rate(adev->pclk, CORESIGHT_CLK_RATE_TRACE);
+ if (ret)
+ return ret;
+
pm_runtime_put(&adev->dev);
mutex_lock(&drvdata->mutex);
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 294444d5f59e..cc8d957e0581 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -1545,8 +1545,8 @@ static ssize_t mem_size_store(struct device *dev,
mutex_lock(&drvdata->mem_lock);
if (kstrtoul(buf, 16, &val)) {
- return -EINVAL;
mutex_unlock(&drvdata->mem_lock);
+ return -EINVAL;
}
drvdata->mem_size = val;
@@ -1900,6 +1900,10 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4;
}
+ ret = clk_set_rate(adev->pclk, CORESIGHT_CLK_RATE_TRACE);
+ if (ret)
+ return ret;
+
pm_runtime_put(&adev->dev);
if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index 7baa1e750a23..3fd080b94069 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -162,6 +162,9 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
/* Disable tpiu to support older devices */
tpiu_disable_hw(drvdata);
+ ret = clk_set_rate(adev->pclk, CORESIGHT_CLK_RATE_TRACE);
+ if (ret)
+ return ret;
pm_runtime_put(&adev->dev);
diff --git a/drivers/hwtracing/stm/Kconfig b/drivers/hwtracing/stm/Kconfig
index e7a348807f0c..847a39b35307 100644
--- a/drivers/hwtracing/stm/Kconfig
+++ b/drivers/hwtracing/stm/Kconfig
@@ -9,6 +9,8 @@ config STM
Say Y here to enable System Trace Module device support.
+if STM
+
config STM_DUMMY
tristate "Dummy STM driver"
help
@@ -25,3 +27,16 @@ config STM_SOURCE_CONSOLE
If you want to send kernel console messages over STM devices,
say Y.
+
+config STM_SOURCE_HEARTBEAT
+ tristate "Heartbeat over STM devices"
+ help
+ This is a kernel space trace source that sends periodic
+ heartbeat messages to trace hosts over STM devices. It is
+ also useful for testing stm class drivers and the stm class
+ framework itself.
+
+ If you want to send heartbeat messages over STM devices,
+ say Y.
+
+endif
diff --git a/drivers/hwtracing/stm/Makefile b/drivers/hwtracing/stm/Makefile
index f9312c38dd7a..a9ce3d487e57 100644
--- a/drivers/hwtracing/stm/Makefile
+++ b/drivers/hwtracing/stm/Makefile
@@ -5,5 +5,7 @@ stm_core-y := core.o policy.o
obj-$(CONFIG_STM_DUMMY) += dummy_stm.o
obj-$(CONFIG_STM_SOURCE_CONSOLE) += stm_console.o
+obj-$(CONFIG_STM_SOURCE_HEARTBEAT) += stm_heartbeat.o
stm_console-y := console.o
+stm_heartbeat-y := heartbeat.o
diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index b6445d9e5453..02095410cb33 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -67,9 +67,24 @@ static ssize_t channels_show(struct device *dev,
static DEVICE_ATTR_RO(channels);
+static ssize_t hw_override_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct stm_device *stm = to_stm_device(dev);
+ int ret;
+
+ ret = sprintf(buf, "%u\n", stm->data->hw_override);
+
+ return ret;
+}
+
+static DEVICE_ATTR_RO(hw_override);
+
static struct attribute *stm_attrs[] = {
&dev_attr_masters.attr,
&dev_attr_channels.attr,
+ &dev_attr_hw_override.attr,
NULL,
};
@@ -113,6 +128,7 @@ struct stm_device *stm_find_device(const char *buf)
stm = to_stm_device(dev);
if (!try_module_get(stm->owner)) {
+ /* matches class_find_device() above */
put_device(dev);
return NULL;
}
@@ -125,7 +141,7 @@ struct stm_device *stm_find_device(const char *buf)
* @stm: stm device, previously acquired by stm_find_device()
*
* This drops the module reference and device reference taken by
- * stm_find_device().
+ * stm_find_device() or stm_char_open().
*/
void stm_put_device(struct stm_device *stm)
{
@@ -185,6 +201,9 @@ static void stm_output_claim(struct stm_device *stm, struct stm_output *output)
{
struct stp_master *master = stm_master(stm, output->master);
+ lockdep_assert_held(&stm->mc_lock);
+ lockdep_assert_held(&output->lock);
+
if (WARN_ON_ONCE(master->nr_free < output->nr_chans))
return;
@@ -199,6 +218,9 @@ stm_output_disclaim(struct stm_device *stm, struct stm_output *output)
{
struct stp_master *master = stm_master(stm, output->master);
+ lockdep_assert_held(&stm->mc_lock);
+ lockdep_assert_held(&output->lock);
+
bitmap_release_region(&master->chan_map[0], output->channel,
ilog2(output->nr_chans));
@@ -288,6 +310,7 @@ static int stm_output_assign(struct stm_device *stm, unsigned int width,
}
spin_lock(&stm->mc_lock);
+ spin_lock(&output->lock);
/* output is already assigned -- shouldn't happen */
if (WARN_ON_ONCE(output->nr_chans))
goto unlock;
@@ -304,6 +327,7 @@ static int stm_output_assign(struct stm_device *stm, unsigned int width,
ret = 0;
unlock:
+ spin_unlock(&output->lock);
spin_unlock(&stm->mc_lock);
return ret;
@@ -312,11 +336,18 @@ unlock:
static void stm_output_free(struct stm_device *stm, struct stm_output *output)
{
spin_lock(&stm->mc_lock);
+ spin_lock(&output->lock);
if (output->nr_chans)
stm_output_disclaim(stm, output);
+ spin_unlock(&output->lock);
spin_unlock(&stm->mc_lock);
}
+static void stm_output_init(struct stm_output *output)
+{
+ spin_lock_init(&output->lock);
+}
+
static int major_match(struct device *dev, const void *data)
{
unsigned int major = *(unsigned int *)data;
@@ -339,6 +370,7 @@ static int stm_char_open(struct inode *inode, struct file *file)
if (!stmf)
return -ENOMEM;
+ stm_output_init(&stmf->output);
stmf->stm = to_stm_device(dev);
if (!try_module_get(stmf->stm->owner))
@@ -349,6 +381,8 @@ static int stm_char_open(struct inode *inode, struct file *file)
return nonseekable_open(inode, file);
err_free:
+ /* matches class_find_device() above */
+ put_device(dev);
kfree(stmf);
return err;
@@ -357,9 +391,19 @@ err_free:
static int stm_char_release(struct inode *inode, struct file *file)
{
struct stm_file *stmf = file->private_data;
+ struct stm_device *stm = stmf->stm;
+
+ if (stm->data->unlink)
+ stm->data->unlink(stm->data, stmf->output.master,
+ stmf->output.channel);
+
+ stm_output_free(stm, &stmf->output);
- stm_output_free(stmf->stm, &stmf->output);
- stm_put_device(stmf->stm);
+ /*
+ * matches the stm_char_open()'s
+ * class_find_device() + try_module_get()
+ */
+ stm_put_device(stm);
kfree(stmf);
return 0;
@@ -380,8 +424,8 @@ static int stm_file_assign(struct stm_file *stmf, char *id, unsigned int width)
return ret;
}
-static void stm_write(struct stm_data *data, unsigned int master,
- unsigned int channel, const char *buf, size_t count)
+static ssize_t stm_write(struct stm_data *data, unsigned int master,
+ unsigned int channel, const char *buf, size_t count)
{
unsigned int flags = STP_PACKET_TIMESTAMPED;
const unsigned char *p = buf, nil = 0;
@@ -393,9 +437,14 @@ static void stm_write(struct stm_data *data, unsigned int master,
sz = data->packet(data, master, channel, STP_PACKET_DATA, flags,
sz, p);
flags = 0;
+
+ if (sz < 0)
+ break;
}
data->packet(data, master, channel, STP_PACKET_FLAG, 0, 0, &nil);
+
+ return pos;
}
static ssize_t stm_char_write(struct file *file, const char __user *buf,
@@ -406,6 +455,9 @@ static ssize_t stm_char_write(struct file *file, const char __user *buf,
char *kbuf;
int err;
+ if (count + 1 > PAGE_SIZE)
+ count = PAGE_SIZE - 1;
+
/*
* if no m/c have been assigned to this writer up to this
* point, use "default" policy entry
@@ -430,8 +482,8 @@ static ssize_t stm_char_write(struct file *file, const char __user *buf,
return -EFAULT;
}
- stm_write(stm->data, stmf->output.master, stmf->output.channel, kbuf,
- count);
+ count = stm_write(stm->data, stmf->output.master, stmf->output.channel,
+ kbuf, count);
kfree(kbuf);
@@ -509,16 +561,12 @@ static int stm_char_policy_set_ioctl(struct stm_file *stmf, void __user *arg)
if (ret)
goto err_free;
- ret = 0;
-
if (stm->data->link)
ret = stm->data->link(stm->data, stmf->output.master,
stmf->output.channel);
- if (ret) {
+ if (ret)
stm_output_free(stmf->stm, &stmf->output);
- stm_put_device(stmf->stm);
- }
err_free:
kfree(id);
@@ -633,17 +681,11 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data,
stm->dev.parent = parent;
stm->dev.release = stm_device_release;
- err = kobject_set_name(&stm->dev.kobj, "%s", stm_data->name);
- if (err)
- goto err_device;
-
- err = device_add(&stm->dev);
- if (err)
- goto err_device;
-
+ mutex_init(&stm->link_mutex);
spin_lock_init(&stm->link_lock);
INIT_LIST_HEAD(&stm->link_list);
+ /* initialize the object before it is accessible via sysfs */
spin_lock_init(&stm->mc_lock);
mutex_init(&stm->policy_mutex);
stm->sw_nmasters = nmasters;
@@ -651,9 +693,20 @@ int stm_register_device(struct device *parent, struct stm_data *stm_data,
stm->data = stm_data;
stm_data->stm = stm;
+ err = kobject_set_name(&stm->dev.kobj, "%s", stm_data->name);
+ if (err)
+ goto err_device;
+
+ err = device_add(&stm->dev);
+ if (err)
+ goto err_device;
+
return 0;
err_device:
+ unregister_chrdev(stm->major, stm_data->name);
+
+ /* matches device_initialize() above */
put_device(&stm->dev);
err_free:
kfree(stm);
@@ -662,20 +715,28 @@ err_free:
}
EXPORT_SYMBOL_GPL(stm_register_device);
-static void __stm_source_link_drop(struct stm_source_device *src,
- struct stm_device *stm);
+static int __stm_source_link_drop(struct stm_source_device *src,
+ struct stm_device *stm);
void stm_unregister_device(struct stm_data *stm_data)
{
struct stm_device *stm = stm_data->stm;
struct stm_source_device *src, *iter;
- int i;
+ int i, ret;
- spin_lock(&stm->link_lock);
+ mutex_lock(&stm->link_mutex);
list_for_each_entry_safe(src, iter, &stm->link_list, link_entry) {
- __stm_source_link_drop(src, stm);
+ ret = __stm_source_link_drop(src, stm);
+ /*
+ * src <-> stm link must not change under the same
+ * stm::link_mutex, so complain loudly if it has;
+ * also in this situation ret!=0 means this src is
+ * not connected to this stm and it should be otherwise
+ * safe to proceed with the tear-down of stm.
+ */
+ WARN_ON_ONCE(ret);
}
- spin_unlock(&stm->link_lock);
+ mutex_unlock(&stm->link_mutex);
synchronize_srcu(&stm_source_srcu);
@@ -694,6 +755,17 @@ void stm_unregister_device(struct stm_data *stm_data)
}
EXPORT_SYMBOL_GPL(stm_unregister_device);
+/*
+ * stm::link_list access serialization uses a spinlock and a mutex; holding
+ * either of them guarantees that the list is stable; modification requires
+ * holding both of them.
+ *
+ * Lock ordering is as follows:
+ * stm::link_mutex
+ * stm::link_lock
+ * src::link_lock
+ */
+
/**
* stm_source_link_add() - connect an stm_source device to an stm device
* @src: stm_source device
@@ -710,6 +782,7 @@ static int stm_source_link_add(struct stm_source_device *src,
char *id;
int err;
+ mutex_lock(&stm->link_mutex);
spin_lock(&stm->link_lock);
spin_lock(&src->link_lock);
@@ -719,6 +792,7 @@ static int stm_source_link_add(struct stm_source_device *src,
spin_unlock(&src->link_lock);
spin_unlock(&stm->link_lock);
+ mutex_unlock(&stm->link_mutex);
id = kstrdup(src->data->name, GFP_KERNEL);
if (id) {
@@ -753,9 +827,9 @@ static int stm_source_link_add(struct stm_source_device *src,
fail_free_output:
stm_output_free(stm, &src->output);
- stm_put_device(stm);
fail_detach:
+ mutex_lock(&stm->link_mutex);
spin_lock(&stm->link_lock);
spin_lock(&src->link_lock);
@@ -764,6 +838,7 @@ fail_detach:
spin_unlock(&src->link_lock);
spin_unlock(&stm->link_lock);
+ mutex_unlock(&stm->link_mutex);
return err;
}
@@ -776,28 +851,55 @@ fail_detach:
* If @stm is @src::link, disconnect them from one another and put the
* reference on the @stm device.
*
- * Caller must hold stm::link_lock.
+ * Caller must hold stm::link_mutex.
*/
-static void __stm_source_link_drop(struct stm_source_device *src,
- struct stm_device *stm)
+static int __stm_source_link_drop(struct stm_source_device *src,
+ struct stm_device *stm)
{
struct stm_device *link;
+ int ret = 0;
+
+ lockdep_assert_held(&stm->link_mutex);
+ /* for stm::link_list modification, we hold both mutex and spinlock */
+ spin_lock(&stm->link_lock);
spin_lock(&src->link_lock);
link = srcu_dereference_check(src->link, &stm_source_srcu, 1);
- if (WARN_ON_ONCE(link != stm)) {
- spin_unlock(&src->link_lock);
- return;
+
+ /*
+ * The linked device may have changed since we last looked, because
+ * we weren't holding the src::link_lock back then; if this is the
+ * case, tell the caller to retry.
+ */
+ if (link != stm) {
+ ret = -EAGAIN;
+ goto unlock;
}
stm_output_free(link, &src->output);
- /* caller must hold stm::link_lock */
list_del_init(&src->link_entry);
/* matches stm_find_device() from stm_source_link_store() */
stm_put_device(link);
rcu_assign_pointer(src->link, NULL);
+unlock:
spin_unlock(&src->link_lock);
+ spin_unlock(&stm->link_lock);
+
+ /*
+ * Call the unlink callbacks for both source and stm, when we know
+ * that we have actually performed the unlinking.
+ */
+ if (!ret) {
+ if (src->data->unlink)
+ src->data->unlink(src->data);
+
+ if (stm->data->unlink)
+ stm->data->unlink(stm->data, src->output.master,
+ src->output.channel);
+ }
+
+ return ret;
}
/**
@@ -813,21 +915,29 @@ static void __stm_source_link_drop(struct stm_source_device *src,
static void stm_source_link_drop(struct stm_source_device *src)
{
struct stm_device *stm;
- int idx;
+ int idx, ret;
+retry:
idx = srcu_read_lock(&stm_source_srcu);
+ /*
+ * The stm device will be valid for the duration of this
+ * read section, but the link may change before we grab
+ * the src::link_lock in __stm_source_link_drop().
+ */
stm = srcu_dereference(src->link, &stm_source_srcu);
+ ret = 0;
if (stm) {
- if (src->data->unlink)
- src->data->unlink(src->data);
-
- spin_lock(&stm->link_lock);
- __stm_source_link_drop(src, stm);
- spin_unlock(&stm->link_lock);
+ mutex_lock(&stm->link_mutex);
+ ret = __stm_source_link_drop(src, stm);
+ mutex_unlock(&stm->link_mutex);
}
srcu_read_unlock(&stm_source_srcu, idx);
+
+ /* if it did change, retry */
+ if (ret == -EAGAIN)
+ goto retry;
}
static ssize_t stm_source_link_show(struct device *dev,
@@ -862,8 +972,10 @@ static ssize_t stm_source_link_store(struct device *dev,
return -EINVAL;
err = stm_source_link_add(src, link);
- if (err)
+ if (err) {
+ /* matches the stm_find_device() above */
stm_put_device(link);
+ }
return err ? : count;
}
@@ -925,6 +1037,7 @@ int stm_source_register_device(struct device *parent,
if (err)
goto err;
+ stm_output_init(&src->output);
spin_lock_init(&src->link_lock);
INIT_LIST_HEAD(&src->link_entry);
src->data = data;
@@ -973,9 +1086,9 @@ int stm_source_write(struct stm_source_data *data, unsigned int chan,
stm = srcu_dereference(src->link, &stm_source_srcu);
if (stm)
- stm_write(stm->data, src->output.master,
- src->output.channel + chan,
- buf, count);
+ count = stm_write(stm->data, src->output.master,
+ src->output.channel + chan,
+ buf, count);
else
count = -ENODEV;
diff --git a/drivers/hwtracing/stm/dummy_stm.c b/drivers/hwtracing/stm/dummy_stm.c
index 3709bef0b21f..a86612d989f9 100644
--- a/drivers/hwtracing/stm/dummy_stm.c
+++ b/drivers/hwtracing/stm/dummy_stm.c
@@ -40,22 +40,71 @@ dummy_stm_packet(struct stm_data *stm_data, unsigned int master,
return size;
}
-static struct stm_data dummy_stm = {
- .name = "dummy_stm",
- .sw_start = 0x0000,
- .sw_end = 0xffff,
- .sw_nchannels = 0xffff,
- .packet = dummy_stm_packet,
-};
+#define DUMMY_STM_MAX 32
+
+static struct stm_data dummy_stm[DUMMY_STM_MAX];
+
+static int nr_dummies = 4;
+
+module_param(nr_dummies, int, 0400);
+
+static unsigned int fail_mode;
+
+module_param(fail_mode, int, 0600);
+
+static int dummy_stm_link(struct stm_data *data, unsigned int master,
+ unsigned int channel)
+{
+ if (fail_mode && (channel & fail_mode))
+ return -EINVAL;
+
+ return 0;
+}
static int dummy_stm_init(void)
{
- return stm_register_device(NULL, &dummy_stm, THIS_MODULE);
+ int i, ret = -ENOMEM;
+
+ if (nr_dummies < 0 || nr_dummies > DUMMY_STM_MAX)
+ return -EINVAL;
+
+ for (i = 0; i < nr_dummies; i++) {
+ dummy_stm[i].name = kasprintf(GFP_KERNEL, "dummy_stm.%d", i);
+ if (!dummy_stm[i].name)
+ goto fail_unregister;
+
+ dummy_stm[i].sw_start = 0x0000;
+ dummy_stm[i].sw_end = 0xffff;
+ dummy_stm[i].sw_nchannels = 0xffff;
+ dummy_stm[i].packet = dummy_stm_packet;
+ dummy_stm[i].link = dummy_stm_link;
+
+ ret = stm_register_device(NULL, &dummy_stm[i], THIS_MODULE);
+ if (ret)
+ goto fail_free;
+ }
+
+ return 0;
+
+fail_unregister:
+ for (i--; i >= 0; i--) {
+ stm_unregister_device(&dummy_stm[i]);
+fail_free:
+ kfree(dummy_stm[i].name);
+ }
+
+ return ret;
+
}
static void dummy_stm_exit(void)
{
- stm_unregister_device(&dummy_stm);
+ int i;
+
+ for (i = 0; i < nr_dummies; i++) {
+ stm_unregister_device(&dummy_stm[i]);
+ kfree(dummy_stm[i].name);
+ }
}
module_init(dummy_stm_init);
diff --git a/drivers/hwtracing/stm/heartbeat.c b/drivers/hwtracing/stm/heartbeat.c
new file mode 100644
index 000000000000..3da7b673aab2
--- /dev/null
+++ b/drivers/hwtracing/stm/heartbeat.c
@@ -0,0 +1,126 @@
+/*
+ * Simple heartbeat STM source driver
+ * Copyright (c) 2016, 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.
+ *
+ * Heartbeat STM source will send repetitive messages over STM devices to a
+ * trace host.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/hrtimer.h>
+#include <linux/slab.h>
+#include <linux/stm.h>
+
+#define STM_HEARTBEAT_MAX 32
+
+static int nr_devs = 4;
+static int interval_ms = 10;
+
+module_param(nr_devs, int, 0400);
+module_param(interval_ms, int, 0600);
+
+static struct stm_heartbeat {
+ struct stm_source_data data;
+ struct hrtimer hrtimer;
+ unsigned int active;
+} stm_heartbeat[STM_HEARTBEAT_MAX];
+
+static const char str[] = "heartbeat stm source driver is here to serve you";
+
+static enum hrtimer_restart stm_heartbeat_hrtimer_handler(struct hrtimer *hr)
+{
+ struct stm_heartbeat *heartbeat = container_of(hr, struct stm_heartbeat,
+ hrtimer);
+
+ stm_source_write(&heartbeat->data, 0, str, sizeof str);
+ if (heartbeat->active)
+ hrtimer_forward_now(hr, ms_to_ktime(interval_ms));
+
+ return heartbeat->active ? HRTIMER_RESTART : HRTIMER_NORESTART;
+}
+
+static int stm_heartbeat_link(struct stm_source_data *data)
+{
+ struct stm_heartbeat *heartbeat =
+ container_of(data, struct stm_heartbeat, data);
+
+ heartbeat->active = 1;
+ hrtimer_start(&heartbeat->hrtimer, ms_to_ktime(interval_ms),
+ HRTIMER_MODE_ABS);
+
+ return 0;
+}
+
+static void stm_heartbeat_unlink(struct stm_source_data *data)
+{
+ struct stm_heartbeat *heartbeat =
+ container_of(data, struct stm_heartbeat, data);
+
+ heartbeat->active = 0;
+ hrtimer_cancel(&heartbeat->hrtimer);
+}
+
+static int stm_heartbeat_init(void)
+{
+ int i, ret = -ENOMEM;
+
+ if (nr_devs < 0 || nr_devs > STM_HEARTBEAT_MAX)
+ return -EINVAL;
+
+ for (i = 0; i < nr_devs; i++) {
+ stm_heartbeat[i].data.name =
+ kasprintf(GFP_KERNEL, "heartbeat.%d", i);
+ if (!stm_heartbeat[i].data.name)
+ goto fail_unregister;
+
+ stm_heartbeat[i].data.nr_chans = 1;
+ stm_heartbeat[i].data.link = stm_heartbeat_link;
+ stm_heartbeat[i].data.unlink = stm_heartbeat_unlink;
+ hrtimer_init(&stm_heartbeat[i].hrtimer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_ABS);
+ stm_heartbeat[i].hrtimer.function =
+ stm_heartbeat_hrtimer_handler;
+
+ ret = stm_source_register_device(NULL, &stm_heartbeat[i].data);
+ if (ret)
+ goto fail_free;
+ }
+
+ return 0;
+
+fail_unregister:
+ for (i--; i >= 0; i--) {
+ stm_source_unregister_device(&stm_heartbeat[i].data);
+fail_free:
+ kfree(stm_heartbeat[i].data.name);
+ }
+
+ return ret;
+}
+
+static void stm_heartbeat_exit(void)
+{
+ int i;
+
+ for (i = 0; i < nr_devs; i++) {
+ stm_source_unregister_device(&stm_heartbeat[i].data);
+ kfree(stm_heartbeat[i].data.name);
+ }
+}
+
+module_init(stm_heartbeat_init);
+module_exit(stm_heartbeat_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("stm_heartbeat driver");
+MODULE_AUTHOR("Alexander Shishkin <alexander.shishkin@linux.intel.com>");
diff --git a/drivers/hwtracing/stm/policy.c b/drivers/hwtracing/stm/policy.c
index 11ab6d01adf6..1c061cb9bff0 100644
--- a/drivers/hwtracing/stm/policy.c
+++ b/drivers/hwtracing/stm/policy.c
@@ -272,13 +272,17 @@ void stp_policy_unbind(struct stp_policy *policy)
{
struct stm_device *stm = policy->stm;
+ /*
+ * stp_policy_release() will not call here if the policy is already
+ * unbound; other users should not either, as no link exists between
+ * this policy and anything else in that case
+ */
if (WARN_ON_ONCE(!policy->stm))
return;
- mutex_lock(&stm->policy_mutex);
- stm->policy = NULL;
- mutex_unlock(&stm->policy_mutex);
+ lockdep_assert_held(&stm->policy_mutex);
+ stm->policy = NULL;
policy->stm = NULL;
stm_put_device(stm);
@@ -287,8 +291,16 @@ void stp_policy_unbind(struct stp_policy *policy)
static void stp_policy_release(struct config_item *item)
{
struct stp_policy *policy = to_stp_policy(item);
+ struct stm_device *stm = policy->stm;
+ /* a policy *can* be unbound and still exist in configfs tree */
+ if (!stm)
+ return;
+
+ mutex_lock(&stm->policy_mutex);
stp_policy_unbind(policy);
+ mutex_unlock(&stm->policy_mutex);
+
kfree(policy);
}
@@ -320,16 +332,17 @@ stp_policies_make(struct config_group *group, const char *name)
/*
* node must look like <device_name>.<policy_name>, where
- * <device_name> is the name of an existing stm device and
- * <policy_name> is an arbitrary string
+ * <device_name> is the name of an existing stm device; may
+ * contain dots;
+ * <policy_name> is an arbitrary string; may not contain dots
*/
- p = strchr(devname, '.');
+ p = strrchr(devname, '.');
if (!p) {
kfree(devname);
return ERR_PTR(-EINVAL);
}
- *p++ = '\0';
+ *p = '\0';
stm = stm_find_device(devname);
kfree(devname);
diff --git a/drivers/hwtracing/stm/stm.h b/drivers/hwtracing/stm/stm.h
index 95ece0292c99..4e8c6926260f 100644
--- a/drivers/hwtracing/stm/stm.h
+++ b/drivers/hwtracing/stm/stm.h
@@ -45,6 +45,7 @@ struct stm_device {
int major;
unsigned int sw_nmasters;
struct stm_data *data;
+ struct mutex link_mutex;
spinlock_t link_lock;
struct list_head link_list;
/* master allocation */
@@ -56,6 +57,7 @@ struct stm_device {
container_of((_d), struct stm_device, dev)
struct stm_output {
+ spinlock_t lock;
unsigned int master;
unsigned int channel;
unsigned int nr_chans;
diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c
index 923f56598d4b..3a9f106787d2 100644
--- a/drivers/iio/accel/kxsd9.c
+++ b/drivers/iio/accel/kxsd9.c
@@ -81,7 +81,7 @@ static int kxsd9_write_scale(struct iio_dev *indio_dev, int micro)
mutex_lock(&st->buf_lock);
ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C));
- if (ret)
+ if (ret < 0)
goto error_ret;
st->tx[0] = KXSD9_WRITE(KXSD9_REG_CTRL_C);
st->tx[1] = (ret & ~KXSD9_FS_MASK) | i;
@@ -163,7 +163,7 @@ static int kxsd9_read_raw(struct iio_dev *indio_dev,
break;
case IIO_CHAN_INFO_SCALE:
ret = spi_w8r8(st->us, KXSD9_READ(KXSD9_REG_CTRL_C));
- if (ret)
+ if (ret < 0)
goto error_ret;
*val2 = kxsd9_micro_scales[ret & KXSD9_FS_MASK];
ret = IIO_VAL_INT_PLUS_MICRO;
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index 21e19b60e2b9..2123f0ac2e2a 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -396,8 +396,8 @@ static int ad7266_probe(struct spi_device *spi)
st = iio_priv(indio_dev);
- st->reg = devm_regulator_get(&spi->dev, "vref");
- if (!IS_ERR_OR_NULL(st->reg)) {
+ st->reg = devm_regulator_get_optional(&spi->dev, "vref");
+ if (!IS_ERR(st->reg)) {
ret = regulator_enable(st->reg);
if (ret)
return ret;
@@ -408,6 +408,9 @@ static int ad7266_probe(struct spi_device *spi)
st->vref_mv = ret / 1000;
} else {
+ /* Any other error indicates that the regulator does exist */
+ if (PTR_ERR(st->reg) != -ENODEV)
+ return PTR_ERR(st->reg);
/* Use internal reference */
st->vref_mv = 2500;
}
diff --git a/drivers/iio/humidity/hdc100x.c b/drivers/iio/humidity/hdc100x.c
index a7f61e881a49..dc5e7e70f951 100644
--- a/drivers/iio/humidity/hdc100x.c
+++ b/drivers/iio/humidity/hdc100x.c
@@ -55,7 +55,7 @@ static const struct {
},
{ /* IIO_HUMIDITYRELATIVE channel */
.shift = 8,
- .mask = 2,
+ .mask = 3,
},
};
@@ -164,14 +164,14 @@ static int hdc100x_get_measurement(struct hdc100x_data *data,
dev_err(&client->dev, "cannot read high byte measurement");
return ret;
}
- val = ret << 6;
+ val = ret << 8;
ret = i2c_smbus_read_byte(client);
if (ret < 0) {
dev_err(&client->dev, "cannot read low byte measurement");
return ret;
}
- val |= ret >> 2;
+ val |= ret;
return val;
}
@@ -211,18 +211,18 @@ static int hdc100x_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SCALE:
if (chan->type == IIO_TEMP) {
- *val = 165;
- *val2 = 65536 >> 2;
+ *val = 165000;
+ *val2 = 65536;
return IIO_VAL_FRACTIONAL;
} else {
- *val = 0;
- *val2 = 10000;
- return IIO_VAL_INT_PLUS_MICRO;
+ *val = 100;
+ *val2 = 65536;
+ return IIO_VAL_FRACTIONAL;
}
break;
case IIO_CHAN_INFO_OFFSET:
- *val = -3971;
- *val2 = 879096;
+ *val = -15887;
+ *val2 = 515151;
return IIO_VAL_INT_PLUS_MICRO;
default:
return -EINVAL;
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index ae2806aafb72..0c52dfe64977 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -210,22 +210,35 @@ static int iio_trigger_attach_poll_func(struct iio_trigger *trig,
/* Prevent the module from being removed whilst attached to a trigger */
__module_get(pf->indio_dev->info->driver_module);
+
+ /* Get irq number */
pf->irq = iio_trigger_get_irq(trig);
+ if (pf->irq < 0)
+ goto out_put_module;
+
+ /* Request irq */
ret = request_threaded_irq(pf->irq, pf->h, pf->thread,
pf->type, pf->name,
pf);
- if (ret < 0) {
- module_put(pf->indio_dev->info->driver_module);
- return ret;
- }
+ if (ret < 0)
+ goto out_put_irq;
+ /* Enable trigger in driver */
if (trig->ops && trig->ops->set_trigger_state && notinuse) {
ret = trig->ops->set_trigger_state(trig, true);
if (ret < 0)
- module_put(pf->indio_dev->info->driver_module);
+ goto out_free_irq;
}
return ret;
+
+out_free_irq:
+ free_irq(pf->irq, pf);
+out_put_irq:
+ iio_trigger_put_irq(trig, pf->irq);
+out_put_module:
+ module_put(pf->indio_dev->info->driver_module);
+ return ret;
}
static int iio_trigger_detach_poll_func(struct iio_trigger *trig,
diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c
index f6a07dc32ae4..4a6d9670e4cd 100644
--- a/drivers/iio/light/apds9960.c
+++ b/drivers/iio/light/apds9960.c
@@ -1005,6 +1005,7 @@ static int apds9960_probe(struct i2c_client *client,
iio_device_attach_buffer(indio_dev, buffer);
+ indio_dev->dev.parent = &client->dev;
indio_dev->info = &apds9960_info;
indio_dev->name = APDS9960_DRV_NAME;
indio_dev->channels = apds9960_channels;
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index b39a2fb0671c..5056bd68573f 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -28,15 +28,21 @@
#include <linux/iio/common/st_sensors.h>
#include "st_pressure.h"
+#define MCELSIUS_PER_CELSIUS 1000
+
+/* Default pressure sensitivity */
#define ST_PRESS_LSB_PER_MBAR 4096UL
#define ST_PRESS_KPASCAL_NANO_SCALE (100000000UL / \
ST_PRESS_LSB_PER_MBAR)
+
+/* Default temperature sensitivity */
#define ST_PRESS_LSB_PER_CELSIUS 480UL
-#define ST_PRESS_CELSIUS_NANO_SCALE (1000000000UL / \
- ST_PRESS_LSB_PER_CELSIUS)
+#define ST_PRESS_MILLI_CELSIUS_OFFSET 42500UL
+
#define ST_PRESS_NUMBER_DATA_CHANNELS 1
/* FULLSCALE */
+#define ST_PRESS_FS_AVL_1100MB 1100
#define ST_PRESS_FS_AVL_1260MB 1260
#define ST_PRESS_1_OUT_XL_ADDR 0x28
@@ -54,18 +60,20 @@
#define ST_PRESS_LPS331AP_PW_MASK 0x80
#define ST_PRESS_LPS331AP_FS_ADDR 0x23
#define ST_PRESS_LPS331AP_FS_MASK 0x30
-#define ST_PRESS_LPS331AP_FS_AVL_1260_VAL 0x00
-#define ST_PRESS_LPS331AP_FS_AVL_1260_GAIN ST_PRESS_KPASCAL_NANO_SCALE
-#define ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN ST_PRESS_CELSIUS_NANO_SCALE
#define ST_PRESS_LPS331AP_BDU_ADDR 0x20
#define ST_PRESS_LPS331AP_BDU_MASK 0x04
#define ST_PRESS_LPS331AP_DRDY_IRQ_ADDR 0x22
#define ST_PRESS_LPS331AP_DRDY_IRQ_INT1_MASK 0x04
#define ST_PRESS_LPS331AP_DRDY_IRQ_INT2_MASK 0x20
#define ST_PRESS_LPS331AP_MULTIREAD_BIT true
-#define ST_PRESS_LPS331AP_TEMP_OFFSET 42500
/* CUSTOM VALUES FOR LPS001WP SENSOR */
+
+/* LPS001WP pressure resolution */
+#define ST_PRESS_LPS001WP_LSB_PER_MBAR 16UL
+/* LPS001WP temperature resolution */
+#define ST_PRESS_LPS001WP_LSB_PER_CELSIUS 64UL
+
#define ST_PRESS_LPS001WP_WAI_EXP 0xba
#define ST_PRESS_LPS001WP_ODR_ADDR 0x20
#define ST_PRESS_LPS001WP_ODR_MASK 0x30
@@ -74,6 +82,8 @@
#define ST_PRESS_LPS001WP_ODR_AVL_13HZ_VAL 0x03
#define ST_PRESS_LPS001WP_PW_ADDR 0x20
#define ST_PRESS_LPS001WP_PW_MASK 0x40
+#define ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN \
+ (100000000UL / ST_PRESS_LPS001WP_LSB_PER_MBAR)
#define ST_PRESS_LPS001WP_BDU_ADDR 0x20
#define ST_PRESS_LPS001WP_BDU_MASK 0x04
#define ST_PRESS_LPS001WP_MULTIREAD_BIT true
@@ -90,18 +100,12 @@
#define ST_PRESS_LPS25H_ODR_AVL_25HZ_VAL 0x04
#define ST_PRESS_LPS25H_PW_ADDR 0x20
#define ST_PRESS_LPS25H_PW_MASK 0x80
-#define ST_PRESS_LPS25H_FS_ADDR 0x00
-#define ST_PRESS_LPS25H_FS_MASK 0x00
-#define ST_PRESS_LPS25H_FS_AVL_1260_VAL 0x00
-#define ST_PRESS_LPS25H_FS_AVL_1260_GAIN ST_PRESS_KPASCAL_NANO_SCALE
-#define ST_PRESS_LPS25H_FS_AVL_TEMP_GAIN ST_PRESS_CELSIUS_NANO_SCALE
#define ST_PRESS_LPS25H_BDU_ADDR 0x20
#define ST_PRESS_LPS25H_BDU_MASK 0x04
#define ST_PRESS_LPS25H_DRDY_IRQ_ADDR 0x23
#define ST_PRESS_LPS25H_DRDY_IRQ_INT1_MASK 0x01
#define ST_PRESS_LPS25H_DRDY_IRQ_INT2_MASK 0x10
#define ST_PRESS_LPS25H_MULTIREAD_BIT true
-#define ST_PRESS_LPS25H_TEMP_OFFSET 42500
#define ST_PRESS_LPS25H_OUT_XL_ADDR 0x28
#define ST_TEMP_LPS25H_OUT_L_ADDR 0x2b
@@ -153,7 +157,9 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = {
.storagebits = 16,
.endianness = IIO_LE,
},
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_separate =
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
.modified = 0,
},
{
@@ -169,7 +175,7 @@ static const struct iio_chan_spec st_press_lps001wp_channels[] = {
},
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_OFFSET),
+ BIT(IIO_CHAN_INFO_SCALE),
.modified = 0,
},
IIO_CHAN_SOFT_TIMESTAMP(1)
@@ -204,11 +210,14 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
.addr = ST_PRESS_LPS331AP_FS_ADDR,
.mask = ST_PRESS_LPS331AP_FS_MASK,
.fs_avl = {
+ /*
+ * Pressure and temperature sensitivity values
+ * as defined in table 3 of LPS331AP datasheet.
+ */
[0] = {
.num = ST_PRESS_FS_AVL_1260MB,
- .value = ST_PRESS_LPS331AP_FS_AVL_1260_VAL,
- .gain = ST_PRESS_LPS331AP_FS_AVL_1260_GAIN,
- .gain2 = ST_PRESS_LPS331AP_FS_AVL_TEMP_GAIN,
+ .gain = ST_PRESS_KPASCAL_NANO_SCALE,
+ .gain2 = ST_PRESS_LSB_PER_CELSIUS,
},
},
},
@@ -248,7 +257,17 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
},
.fs = {
- .addr = 0,
+ .fs_avl = {
+ /*
+ * Pressure and temperature resolution values
+ * as defined in table 3 of LPS001WP datasheet.
+ */
+ [0] = {
+ .num = ST_PRESS_FS_AVL_1100MB,
+ .gain = ST_PRESS_LPS001WP_FS_AVL_PRESS_GAIN,
+ .gain2 = ST_PRESS_LPS001WP_LSB_PER_CELSIUS,
+ },
+ },
},
.bdu = {
.addr = ST_PRESS_LPS001WP_BDU_ADDR,
@@ -285,14 +304,15 @@ static const struct st_sensor_settings st_press_sensors_settings[] = {
.value_off = ST_SENSORS_DEFAULT_POWER_OFF_VALUE,
},
.fs = {
- .addr = ST_PRESS_LPS25H_FS_ADDR,
- .mask = ST_PRESS_LPS25H_FS_MASK,
.fs_avl = {
+ /*
+ * Pressure and temperature sensitivity values
+ * as defined in table 3 of LPS25H datasheet.
+ */
[0] = {
.num = ST_PRESS_FS_AVL_1260MB,
- .value = ST_PRESS_LPS25H_FS_AVL_1260_VAL,
- .gain = ST_PRESS_LPS25H_FS_AVL_1260_GAIN,
- .gain2 = ST_PRESS_LPS25H_FS_AVL_TEMP_GAIN,
+ .gain = ST_PRESS_KPASCAL_NANO_SCALE,
+ .gain2 = ST_PRESS_LSB_PER_CELSIUS,
},
},
},
@@ -346,26 +366,26 @@ static int st_press_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
- *val = 0;
-
switch (ch->type) {
case IIO_PRESSURE:
+ *val = 0;
*val2 = press_data->current_fullscale->gain;
- break;
+ return IIO_VAL_INT_PLUS_NANO;
case IIO_TEMP:
+ *val = MCELSIUS_PER_CELSIUS;
*val2 = press_data->current_fullscale->gain2;
- break;
+ return IIO_VAL_FRACTIONAL;
default:
err = -EINVAL;
goto read_error;
}
- return IIO_VAL_INT_PLUS_NANO;
case IIO_CHAN_INFO_OFFSET:
switch (ch->type) {
case IIO_TEMP:
- *val = 425;
- *val2 = 10;
+ *val = ST_PRESS_MILLI_CELSIUS_OFFSET *
+ press_data->current_fullscale->gain2;
+ *val2 = MCELSIUS_PER_CELSIUS;
break;
default:
err = -EINVAL;
diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c
index f4d29d5dbd5f..e2f926cdcad2 100644
--- a/drivers/iio/proximity/as3935.c
+++ b/drivers/iio/proximity/as3935.c
@@ -64,6 +64,7 @@ struct as3935_state {
struct delayed_work work;
u32 tune_cap;
+ u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */
u8 buf[2] ____cacheline_aligned;
};
@@ -72,7 +73,8 @@ static const struct iio_chan_spec as3935_channels[] = {
.type = IIO_PROXIMITY,
.info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_PROCESSED),
+ BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_SCALE),
.scan_index = 0,
.scan_type = {
.sign = 'u',
@@ -181,7 +183,12 @@ static int as3935_read_raw(struct iio_dev *indio_dev,
/* storm out of range */
if (*val == AS3935_DATA_MASK)
return -EINVAL;
- *val *= 1000;
+
+ if (m == IIO_CHAN_INFO_PROCESSED)
+ *val *= 1000;
+ break;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 1000;
break;
default:
return -EINVAL;
@@ -206,10 +213,10 @@ static irqreturn_t as3935_trigger_handler(int irq, void *private)
ret = as3935_read(st, AS3935_DATA, &val);
if (ret)
goto err_read;
- val &= AS3935_DATA_MASK;
- val *= 1000;
- iio_push_to_buffers_with_timestamp(indio_dev, &val, pf->timestamp);
+ st->buffer[0] = val & AS3935_DATA_MASK;
+ iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer,
+ pf->timestamp);
err_read:
iio_trigger_notify_done(indio_dev->trig);
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index d6d2b3582910..4d8e7f18a9af 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -3430,14 +3430,14 @@ static int cm_establish(struct ib_cm_id *cm_id)
work->cm_event.event = IB_CM_USER_ESTABLISHED;
/* Check if the device started its remove_one */
- spin_lock_irq(&cm.lock);
+ spin_lock_irqsave(&cm.lock, flags);
if (!cm_dev->going_down) {
queue_delayed_work(cm.wq, &work->work, 0);
} else {
kfree(work);
ret = -ENODEV;
}
- spin_unlock_irq(&cm.lock);
+ spin_unlock_irqrestore(&cm.lock, flags);
out:
return ret;
diff --git a/drivers/infiniband/hw/mlx4/ah.c b/drivers/infiniband/hw/mlx4/ah.c
index 86af71351d9a..06da56bda201 100644
--- a/drivers/infiniband/hw/mlx4/ah.c
+++ b/drivers/infiniband/hw/mlx4/ah.c
@@ -47,6 +47,7 @@ static struct ib_ah *create_ib_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
ah->av.ib.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
ah->av.ib.g_slid = ah_attr->src_path_bits;
+ ah->av.ib.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
if (ah_attr->ah_flags & IB_AH_GRH) {
ah->av.ib.g_slid |= 0x80;
ah->av.ib.gid_index = ah_attr->grh.sgid_index;
@@ -64,7 +65,6 @@ static struct ib_ah *create_ib_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
!(1 << ah->av.ib.stat_rate & dev->caps.stat_rate_support))
--ah->av.ib.stat_rate;
}
- ah->av.ib.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
return &ah->ibah;
}
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 3db9a659719b..5f0f4fc58f43 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1519,7 +1519,7 @@ static int srp_map_idb(struct srp_rdma_ch *ch, struct srp_request *req,
if (dev->use_fast_reg) {
state.sg = idb_sg;
- sg_set_buf(idb_sg, req->indirect_desc, idb_len);
+ sg_init_one(idb_sg, req->indirect_desc, idb_len);
idb_sg->dma_address = req->indirect_dma_addr; /* hack! */
#ifdef CONFIG_NEED_SG_DMA_LENGTH
idb_sg->dma_length = idb_sg->length; /* hack^2 */
diff --git a/drivers/input/misc/pwm-beeper.c b/drivers/input/misc/pwm-beeper.c
index f2261ab54701..18663d4edae5 100644
--- a/drivers/input/misc/pwm-beeper.c
+++ b/drivers/input/misc/pwm-beeper.c
@@ -20,21 +20,40 @@
#include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/slab.h>
+#include <linux/workqueue.h>
struct pwm_beeper {
struct input_dev *input;
struct pwm_device *pwm;
+ struct work_struct work;
unsigned long period;
};
#define HZ_TO_NANOSECONDS(x) (1000000000UL/(x))
+static void __pwm_beeper_set(struct pwm_beeper *beeper)
+{
+ unsigned long period = beeper->period;
+
+ if (period) {
+ pwm_config(beeper->pwm, period / 2, period);
+ pwm_enable(beeper->pwm);
+ } else
+ pwm_disable(beeper->pwm);
+}
+
+static void pwm_beeper_work(struct work_struct *work)
+{
+ struct pwm_beeper *beeper =
+ container_of(work, struct pwm_beeper, work);
+
+ __pwm_beeper_set(beeper);
+}
+
static int pwm_beeper_event(struct input_dev *input,
unsigned int type, unsigned int code, int value)
{
- int ret = 0;
struct pwm_beeper *beeper = input_get_drvdata(input);
- unsigned long period;
if (type != EV_SND || value < 0)
return -EINVAL;
@@ -49,22 +68,31 @@ static int pwm_beeper_event(struct input_dev *input,
return -EINVAL;
}
- if (value == 0) {
- pwm_disable(beeper->pwm);
- } else {
- period = HZ_TO_NANOSECONDS(value);
- ret = pwm_config(beeper->pwm, period / 2, period);
- if (ret)
- return ret;
- ret = pwm_enable(beeper->pwm);
- if (ret)
- return ret;
- beeper->period = period;
- }
+ if (value == 0)
+ beeper->period = 0;
+ else
+ beeper->period = HZ_TO_NANOSECONDS(value);
+
+ schedule_work(&beeper->work);
return 0;
}
+static void pwm_beeper_stop(struct pwm_beeper *beeper)
+{
+ cancel_work_sync(&beeper->work);
+
+ if (beeper->period)
+ pwm_disable(beeper->pwm);
+}
+
+static void pwm_beeper_close(struct input_dev *input)
+{
+ struct pwm_beeper *beeper = input_get_drvdata(input);
+
+ pwm_beeper_stop(beeper);
+}
+
static int pwm_beeper_probe(struct platform_device *pdev)
{
unsigned long pwm_id = (unsigned long)dev_get_platdata(&pdev->dev);
@@ -87,6 +115,8 @@ static int pwm_beeper_probe(struct platform_device *pdev)
goto err_free;
}
+ INIT_WORK(&beeper->work, pwm_beeper_work);
+
beeper->input = input_allocate_device();
if (!beeper->input) {
dev_err(&pdev->dev, "Failed to allocate input device\n");
@@ -106,6 +136,7 @@ static int pwm_beeper_probe(struct platform_device *pdev)
beeper->input->sndbit[0] = BIT(SND_TONE) | BIT(SND_BELL);
beeper->input->event = pwm_beeper_event;
+ beeper->input->close = pwm_beeper_close;
input_set_drvdata(beeper->input, beeper);
@@ -135,7 +166,6 @@ static int pwm_beeper_remove(struct platform_device *pdev)
input_unregister_device(beeper->input);
- pwm_disable(beeper->pwm);
pwm_free(beeper->pwm);
kfree(beeper);
@@ -147,8 +177,7 @@ static int __maybe_unused pwm_beeper_suspend(struct device *dev)
{
struct pwm_beeper *beeper = dev_get_drvdata(dev);
- if (beeper->period)
- pwm_disable(beeper->pwm);
+ pwm_beeper_stop(beeper);
return 0;
}
@@ -157,10 +186,8 @@ static int __maybe_unused pwm_beeper_resume(struct device *dev)
{
struct pwm_beeper *beeper = dev_get_drvdata(dev);
- if (beeper->period) {
- pwm_config(beeper->pwm, beeper->period / 2, beeper->period);
- pwm_enable(beeper->pwm);
- }
+ if (beeper->period)
+ __pwm_beeper_set(beeper);
return 0;
}
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 5adbcedcb81c..2bb4c8633d3b 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -893,9 +893,15 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
#ifdef CONFIG_COMPAT
+
+#define UI_SET_PHYS_COMPAT _IOW(UINPUT_IOCTL_BASE, 108, compat_uptr_t)
+
static long uinput_compat_ioctl(struct file *file,
unsigned int cmd, unsigned long arg)
{
+ if (cmd == UI_SET_PHYS_COMPAT)
+ cmd = UI_SET_PHYS;
+
return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg));
}
#endif
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index bf4959f4225b..94f1bf772ec9 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -1363,13 +1363,23 @@ static int __init amd_iommu_init_pci(void)
break;
}
+ /*
+ * Order is important here to make sure any unity map requirements are
+ * fulfilled. The unity mappings are created and written to the device
+ * table during the amd_iommu_init_api() call.
+ *
+ * After that we call init_device_table_dma() to make sure any
+ * uninitialized DTE will block DMA, and in the end we flush the caches
+ * of all IOMMUs to make sure the changes to the device table are
+ * active.
+ */
+ ret = amd_iommu_init_api();
+
init_device_table_dma();
for_each_iommu(iommu)
iommu_flush_all_caches(iommu);
- ret = amd_iommu_init_api();
-
if (!ret)
print_iommu_info();
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 4e5118a4cd30..8487987458a1 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1919,6 +1919,7 @@ static struct iommu_ops arm_smmu_ops = {
.detach_dev = arm_smmu_detach_dev,
.map = arm_smmu_map,
.unmap = arm_smmu_unmap,
+ .map_sg = default_iommu_map_sg,
.iova_to_phys = arm_smmu_iova_to_phys,
.add_device = arm_smmu_add_device,
.remove_device = arm_smmu_remove_device,
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index a2e1b7f14df2..6763a4dfed94 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3169,11 +3169,6 @@ static int __init init_dmars(void)
}
}
- iommu_flush_write_buffer(iommu);
- iommu_set_root_entry(iommu);
- iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
- iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
-
if (!ecap_pass_through(iommu->ecap))
hw_pass_through = 0;
#ifdef CONFIG_INTEL_IOMMU_SVM
@@ -3182,6 +3177,18 @@ static int __init init_dmars(void)
#endif
}
+ /*
+ * Now that qi is enabled on all iommus, set the root entry and flush
+ * caches. This is required on some Intel X58 chipsets, otherwise the
+ * flush_context function will loop forever and the boot hangs.
+ */
+ for_each_active_iommu(iommu, drhd) {
+ iommu_flush_write_buffer(iommu);
+ iommu_set_root_entry(iommu);
+ iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
+ iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
+ }
+
if (iommu_pass_through)
iommu_identity_mapping |= IDENTMAP_ALL;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 50c8c92d575d..cfdc235c1d28 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -521,6 +521,13 @@ static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs
if (static_key_true(&supports_deactivate))
gic_write_dir(irqnr);
#ifdef CONFIG_SMP
+ /*
+ * Unlike GICv2, we don't need an smp_rmb() here.
+ * The control dependency from gic_read_iar to
+ * the ISB in gic_write_eoir is enough to ensure
+ * that any shared data read by handle_IPI will
+ * be read after the ACK.
+ */
handle_IPI(irqnr, regs);
#else
WARN_ONCE(true, "Unexpected SGI received!\n");
@@ -540,6 +547,15 @@ static void __init gic_dist_init(void)
writel_relaxed(0, base + GICD_CTLR);
gic_dist_wait_for_rwp();
+ /*
+ * Configure SPIs as non-secure Group-1. This will only matter
+ * if the GIC only has a single security state. This will not
+ * do the right thing if the kernel is running in secure mode,
+ * but that's not the intended use case anyway.
+ */
+ for (i = 32; i < gic_data.irq_nr; i += 32)
+ writel_relaxed(~0, base + GICD_IGROUPR + i / 8);
+
gic_dist_config(base, gic_data.irq_nr, gic_dist_wait_for_rwp);
/* Enable distributor with ARE, Group1 */
@@ -651,6 +667,9 @@ static void gic_cpu_init(void)
rbase = gic_data_rdist_sgi_base();
+ /* Configure SGIs/PPIs as non-secure Group-1 */
+ writel_relaxed(~0, rbase + GICR_IGROUPR0);
+
gic_cpu_config(rbase, gic_redist_wait_for_rwp);
/* Give LPIs a spin */
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index fb940e92b64e..10b73d9bea78 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -405,6 +405,14 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
if (static_key_true(&supports_deactivate))
writel_relaxed(irqstat, cpu_base + GIC_CPU_DEACTIVATE);
#ifdef CONFIG_SMP
+ /*
+ * Ensure any shared data written by the CPU sending
+ * the IPI is read after we've read the ACK register
+ * on the GIC.
+ *
+ * Pairs with the write barrier in gic_raise_softirq
+ */
+ smp_rmb();
handle_IPI(irqnr, regs);
#endif
continue;
diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c
index 004926955263..b0155b05cddb 100644
--- a/drivers/mcb/mcb-parse.c
+++ b/drivers/mcb/mcb-parse.c
@@ -57,7 +57,7 @@ static int chameleon_parse_gdd(struct mcb_bus *bus,
mdev->id = GDD_DEV(reg1);
mdev->rev = GDD_REV(reg1);
mdev->var = GDD_VAR(reg1);
- mdev->bar = GDD_BAR(reg1);
+ mdev->bar = GDD_BAR(reg2);
mdev->group = GDD_GRP(reg2);
mdev->inst = GDD_INS(reg2);
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
index d6bb18522e0c..6c09f3820dfd 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
+++ b/drivers/media/platform/msm/camera_v2/common/cam_soc_api.c
@@ -460,7 +460,7 @@ int msm_camera_set_clk_flags(struct clk *clk, unsigned long flags)
if (!clk)
return -EINVAL;
- CDBG("clk : %p, flags : %ld\n", clk, flags);
+ CDBG("clk : %pK, flags : %ld\n", clk, flags);
return clk_set_flags(clk, flags);
}
@@ -1040,8 +1040,11 @@ uint32_t msm_camera_unregister_bus_client(enum cam_bus_client id)
mutex_destroy(&g_cv[id].lock);
msm_bus_scale_unregister_client(g_cv[id].bus_client);
- msm_bus_cl_clear_pdata(g_cv[id].pdata);
- memset(&g_cv[id], 0, sizeof(struct msm_cam_bus_pscale_data));
+ g_cv[id].bus_client = 0;
+ g_cv[id].num_usecases = 0;
+ g_cv[id].num_paths = 0;
+ g_cv[id].vector_index = 0;
+ g_cv[id].dyn_vote = 0;
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 1529e2aa740c..96f9e61578f2 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -1027,7 +1027,7 @@ static int msm_vfe40_start_fetch_engine(struct vfe_device *vfe_dev,
rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
if (rc < 0 || !buf) {
- pr_err("%s: No fetch buffer rc= %d buf= %p\n",
+ pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
__func__, rc, buf);
return -EINVAL;
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index fdc98436a105..e8289f05d28f 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -67,7 +67,7 @@ static int msm_isp_axi_create_stream(struct vfe_device *vfe_dev,
} else {
/* check if the stream has been added for the vfe-device */
if (stream_info->vfe_mask & (1 << vfe_dev->pdev->id)) {
- pr_err("%s: stream %p/%x is already added for vfe dev %d vfe_mask %x\n",
+ pr_err("%s: stream %pK/%x is already added for vfe dev %d vfe_mask %x\n",
__func__, stream_info, stream_info->stream_id,
vfe_dev->pdev->id, stream_info->vfe_mask);
return -EINVAL;
@@ -1255,7 +1255,7 @@ int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg)
if (vfe_idx == -ENOTTY ||
stream_release_cmd->stream_handle !=
stream_info->stream_handle[vfe_idx]) {
- pr_err("%s: Invalid stream %p handle %x/%x vfe_idx %d vfe_dev %d num_isp %d\n",
+ pr_err("%s: Invalid stream %pK handle %x/%x vfe_idx %d vfe_dev %d num_isp %d\n",
__func__, stream_info,
stream_release_cmd->stream_handle,
vfe_idx != -ENOTTY ?
@@ -3483,7 +3483,7 @@ static int msm_isp_stream_axi_cfg_update(struct vfe_device *vfe_dev,
if (stream_info->update_vfe_mask) {
if (stream_info->update_vfe_mask & (1 << vfe_dev->pdev->id)) {
spin_unlock_irqrestore(&stream_info->lock, flags);
- pr_err("%s: Stream %p/%x Update already in progress for vfe %d\n",
+ pr_err("%s: Stream %pK/%x Update already in progress for vfe %d\n",
__func__, stream_info, stream_info->stream_src,
vfe_dev->pdev->id);
return -EINVAL;
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index df95e5cb9b99..094a7861831a 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -840,7 +840,7 @@ static uint16_t msm_ispif_get_cids_mask_from_cfg(
uint16_t cids_mask = 0;
BUG_ON(!entry);
- for (i = 0; i < entry->num_cids; i++)
+ for (i = 0; i < entry->num_cids && i < MAX_CID_CH_PARAM_ENTRY; i++)
cids_mask |= (1 << entry->cids[i]);
return cids_mask;
@@ -970,7 +970,7 @@ static void msm_ispif_intf_cmd(struct ispif_device *ispif, uint32_t cmd_bits,
pr_err("%s: invalid interface type\n", __func__);
return;
}
- if (params->entries[i].num_cids > MAX_CID_CH) {
+ if (params->entries[i].num_cids > MAX_CID_CH_PARAM_ENTRY) {
pr_err("%s: out of range of cid_num %d\n",
__func__, params->entries[i].num_cids);
return;
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
index 59135225cb15..c779ee46c19a 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
@@ -286,7 +286,7 @@ static int msm_vb2_put_buf(struct vb2_v4l2_buffer *vb, int session_id,
break;
}
if (vb2_v4l2_buf != vb) {
- pr_err("VB buffer is INVALID vb=%p, ses_id=%d, str_id=%d\n",
+ pr_err("VB buffer is INVALID vb=%pK, ses_id=%d, str_id=%d\n",
vb, session_id, stream_id);
spin_unlock_irqrestore(&stream->stream_lock, flags);
return -EINVAL;
@@ -329,7 +329,7 @@ static int msm_vb2_buf_done(struct vb2_v4l2_buffer *vb, int session_id,
break;
}
if (vb2_v4l2_buf != vb) {
- pr_err("VB buffer is INVALID ses_id=%d, str_id=%d, vb=%p\n",
+ pr_err("VB buffer is INVALID ses_id=%d, str_id=%d, vb=%pK\n",
session_id, stream_id, vb);
spin_unlock_irqrestore(&stream->stream_lock, flags);
return -EINVAL;
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 106d76aae3bb..ab074ffbcdfb 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -1074,6 +1074,13 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)
goto end;
}
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP,
+ CAM_AHB_NOMINAL_VOTE);
+ if (rc < 0) {
+ pr_err("%s:%d: failed to vote for AHB\n", __func__, __LINE__);
+ goto end;
+ }
+
msm_camera_io_w(0x1, cpp_dev->base + MSM_CPP_MICRO_CLKEN_CTL);
msm_camera_io_w(0x1, cpp_dev->base +
MSM_CPP_MICRO_BOOT_START);
@@ -1082,7 +1089,7 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)
if (rc) {
pr_err("%s:%d] poll command %x failed %d", __func__, __LINE__,
MSM_CPP_MSG_ID_CMD, rc);
- goto end;
+ goto vote;
}
msm_camera_io_w(0xFFFFFFFF, cpp_dev->base +
@@ -1092,7 +1099,7 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)
if (rc) {
pr_err("%s:%d] poll rx empty failed %d",
__func__, __LINE__, rc);
- goto end;
+ goto vote;
}
/*Start firmware loading*/
msm_cpp_write(MSM_CPP_CMD_FW_LOAD, cpp_dev->base);
@@ -1102,7 +1109,7 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)
if (rc) {
pr_err("%s:%d] poll rx empty failed %d",
__func__, __LINE__, rc);
- goto end;
+ goto vote;
}
for (i = 0; i < cpp_dev->fw->size/4; i++) {
msm_cpp_write(*ptr_bin, cpp_dev->base);
@@ -1111,7 +1118,7 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)
if (rc) {
pr_err("%s:%d] poll rx empty failed %d",
__func__, __LINE__, rc);
- goto end;
+ goto vote;
}
}
ptr_bin++;
@@ -1124,21 +1131,21 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)
if (rc) {
pr_err("%s:%d] poll command %x failed %d", __func__, __LINE__,
MSM_CPP_MSG_ID_OK, rc);
- goto end;
+ goto vote;
}
rc = msm_cpp_poll(cpp_dev->base, MSM_CPP_MSG_ID_CMD);
if (rc) {
pr_err("%s:%d] poll command %x failed %d", __func__, __LINE__,
MSM_CPP_MSG_ID_CMD, rc);
- goto end;
+ goto vote;
}
rc = msm_cpp_poll_rx_empty(cpp_dev->base);
if (rc) {
pr_err("%s:%d] poll rx empty failed %d",
__func__, __LINE__, rc);
- goto end;
+ goto vote;
}
/*Trigger MC to jump to start address*/
msm_cpp_write(MSM_CPP_CMD_EXEC_JUMP, cpp_dev->base);
@@ -1148,21 +1155,21 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)
if (rc) {
pr_err("%s:%d] poll command %x failed %d", __func__, __LINE__,
MSM_CPP_MSG_ID_CMD, rc);
- goto end;
+ goto vote;
}
rc = msm_cpp_poll(cpp_dev->base, 0x1);
if (rc) {
pr_err("%s:%d] poll command 0x1 failed %d", __func__, __LINE__,
rc);
- goto end;
+ goto vote;
}
rc = msm_cpp_poll(cpp_dev->base, MSM_CPP_MSG_ID_JUMP_ACK);
if (rc) {
pr_err("%s:%d] poll command %x failed %d", __func__, __LINE__,
MSM_CPP_MSG_ID_JUMP_ACK, rc);
- goto end;
+ goto vote;
}
rc = msm_cpp_poll(cpp_dev->base, MSM_CPP_MSG_ID_TRAILER);
@@ -1171,6 +1178,11 @@ static int32_t cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)
MSM_CPP_MSG_ID_JUMP_ACK, rc);
}
+vote:
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CPP,
+ CAM_AHB_SVS_VOTE);
+ if (rc < 0)
+ pr_err("%s:%d: failed to vote for AHB\n", __func__, __LINE__);
end:
return rc;
}
@@ -4186,7 +4198,7 @@ static int cpp_probe(struct platform_device *pdev)
cpp_dev->state = CPP_STATE_BOOT;
rc = cpp_init_hardware(cpp_dev);
if (rc < 0)
- goto cpp_probe_init_error;
+ goto bus_de_init;
media_entity_init(&cpp_dev->msm_sd.sd.entity, 0, NULL, 0);
cpp_dev->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
@@ -4225,7 +4237,7 @@ static int cpp_probe(struct platform_device *pdev)
if (!cpp_dev->work) {
pr_err("no enough memory\n");
rc = -ENOMEM;
- goto cpp_probe_init_error;
+ goto bus_de_init;
}
INIT_WORK((struct work_struct *)cpp_dev->work, msm_cpp_do_timeout_work);
@@ -4245,6 +4257,12 @@ static int cpp_probe(struct platform_device *pdev)
else
CPP_DBG("FAILED.");
return rc;
+
+bus_de_init:
+ if (cpp_dev->bus_master_flag)
+ msm_cpp_deinit_bandwidth_mgr(cpp_dev);
+ else
+ msm_isp_deinit_bandwidth_mgr(ISP_CPP);
cpp_probe_init_error:
media_entity_cleanup(&cpp_dev->msm_sd.sd.entity);
msm_sd_unregister(&cpp_dev->msm_sd);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
index 5f749bd46273..0d27de5c9b4b 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
@@ -645,7 +645,7 @@ static int32_t msm_flash_release(
static int32_t msm_flash_config(struct msm_flash_ctrl_t *flash_ctrl,
void __user *argp)
{
- int32_t rc = -EINVAL;
+ int32_t rc = 0;
struct msm_flash_cfg_data_t *flash_data =
(struct msm_flash_cfg_data_t *) argp;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c
index 25c152be2b71..5a330db0f9a5 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c
@@ -794,7 +794,7 @@ int32_t msm_camera_tz_i2c_register_sensor(
return -EINVAL;
}
- CDBG("id=%d, client=%p\n", s_ctrl->id, s_ctrl);
+ CDBG("id=%d, client=%pK\n", s_ctrl->id, s_ctrl);
sensor_info[s_ctrl->id].s_ctrl = s_ctrl;
sensor_info[s_ctrl->id].secure = s_ctrl->is_secure;
return 0;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
index 94223b557990..cf33bc6437cc 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
@@ -49,6 +49,10 @@
#define SDE_ROT_EVTLOG_BUF_ALIGN 32
#define SDE_ROT_DEBUG_BASE_MAX 10
+#define SDE_ROT_DEFAULT_BASE_REG_CNT 0x100
+#define GROUP_BYTES 4
+#define ROW_BYTES 16
+
static DEFINE_SPINLOCK(sde_rot_xlock);
/*
@@ -963,6 +967,273 @@ static const struct file_operations sde_rotator_raw_ops = {
.release = single_release
};
+static int sde_rotator_debug_base_open(struct inode *inode, struct file *file)
+{
+ /* non-seekable */
+ file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static int sde_rotator_debug_base_release(struct inode *inode,
+ struct file *file)
+{
+ struct sde_rotator_debug_base *dbg = file->private_data;
+
+ if (dbg && dbg->buf) {
+ kfree(dbg->buf);
+ dbg->buf_len = 0;
+ dbg->buf = NULL;
+ }
+ return 0;
+}
+
+static ssize_t sde_rotator_debug_base_offset_write(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ struct sde_rotator_debug_base *dbg = file->private_data;
+ u32 off = 0;
+ u32 cnt = SDE_ROT_DEFAULT_BASE_REG_CNT;
+ char buf[24];
+
+ if (!dbg)
+ return -ENODEV;
+
+ if (count >= sizeof(buf))
+ return -EFAULT;
+
+ if (copy_from_user(buf, user_buf, count))
+ return -EFAULT;
+
+ buf[count] = 0;
+
+ if (sscanf(buf, "%5x %x", &off, &cnt) < 2)
+ return -EINVAL;
+
+ if (off > dbg->max_offset)
+ return -EINVAL;
+
+ if (cnt > (dbg->max_offset - off))
+ cnt = dbg->max_offset - off;
+
+ dbg->off = off;
+ dbg->cnt = cnt;
+
+ SDEROT_DBG("offset=%x cnt=%x\n", off, cnt);
+
+ return count;
+}
+
+static ssize_t sde_rotator_debug_base_offset_read(struct file *file,
+ char __user *buff, size_t count, loff_t *ppos)
+{
+ struct sde_rotator_debug_base *dbg = file->private_data;
+ int len = 0;
+ char buf[24] = {'\0'};
+
+ if (!dbg)
+ return -ENODEV;
+
+ if (*ppos)
+ return 0; /* the end */
+
+ len = snprintf(buf, sizeof(buf), "0x%08zx %zx\n", dbg->off, dbg->cnt);
+ if (len < 0 || len >= sizeof(buf))
+ return 0;
+
+ if ((count < sizeof(buf)) || copy_to_user(buff, buf, len))
+ return -EFAULT;
+
+ *ppos += len; /* increase offset */
+
+ return len;
+}
+
+static ssize_t sde_rotator_debug_base_reg_write(struct file *file,
+ const char __user *user_buf, size_t count, loff_t *ppos)
+{
+ struct sde_rotator_debug_base *dbg = file->private_data;
+ size_t off;
+ u32 data, cnt;
+ char buf[24];
+
+ if (!dbg)
+ return -ENODEV;
+
+ if (count >= sizeof(buf))
+ return -EFAULT;
+
+ if (copy_from_user(buf, user_buf, count))
+ return -EFAULT;
+
+ buf[count] = 0;
+
+ cnt = sscanf(buf, "%zx %x", &off, &data);
+
+ if (cnt < 2)
+ return -EFAULT;
+
+ if (off >= dbg->max_offset)
+ return -EFAULT;
+
+ /* Enable Clock for register access */
+ sde_rotator_clk_ctrl(dbg->mgr, true);
+
+ writel_relaxed(data, dbg->base + off);
+
+ /* Disable Clock after register access */
+ sde_rotator_clk_ctrl(dbg->mgr, false);
+
+ SDEROT_DBG("addr=%zx data=%x\n", off, data);
+
+ return count;
+}
+
+static ssize_t sde_rotator_debug_base_reg_read(struct file *file,
+ char __user *user_buf, size_t count, loff_t *ppos)
+{
+ struct sde_rotator_debug_base *dbg = file->private_data;
+ size_t len;
+
+ if (!dbg) {
+ SDEROT_ERR("invalid handle\n");
+ return -ENODEV;
+ }
+
+ if (!dbg->buf) {
+ char dump_buf[64];
+ char *ptr;
+ int cnt, tot;
+
+ dbg->buf_len = sizeof(dump_buf) *
+ DIV_ROUND_UP(dbg->cnt, ROW_BYTES);
+ dbg->buf = kzalloc(dbg->buf_len, GFP_KERNEL);
+
+ if (!dbg->buf) {
+ SDEROT_ERR("not enough memory to hold reg dump\n");
+ return -ENOMEM;
+ }
+
+ ptr = dbg->base + dbg->off;
+ tot = 0;
+
+ /* Enable clock for register access */
+ sde_rotator_clk_ctrl(dbg->mgr, true);
+
+ for (cnt = dbg->cnt; cnt > 0; cnt -= ROW_BYTES) {
+ hex_dump_to_buffer(ptr, min(cnt, ROW_BYTES),
+ ROW_BYTES, GROUP_BYTES, dump_buf,
+ sizeof(dump_buf), false);
+ len = scnprintf(dbg->buf + tot, dbg->buf_len - tot,
+ "0x%08x: %s\n",
+ ((int) (unsigned long) ptr) -
+ ((int) (unsigned long) dbg->base),
+ dump_buf);
+
+ ptr += ROW_BYTES;
+ tot += len;
+ if (tot >= dbg->buf_len)
+ break;
+ }
+ /* Disable clock after register access */
+ sde_rotator_clk_ctrl(dbg->mgr, false);
+
+ dbg->buf_len = tot;
+ }
+
+ if (*ppos >= dbg->buf_len)
+ return 0; /* done reading */
+
+ len = min(count, dbg->buf_len - (size_t) *ppos);
+ if (copy_to_user(user_buf, dbg->buf + *ppos, len)) {
+ SDEROT_ERR("failed to copy to user\n");
+ return -EFAULT;
+ }
+
+ *ppos += len; /* increase offset */
+
+ return len;
+}
+
+static const struct file_operations sde_rotator_off_fops = {
+ .open = sde_rotator_debug_base_open,
+ .release = sde_rotator_debug_base_release,
+ .read = sde_rotator_debug_base_offset_read,
+ .write = sde_rotator_debug_base_offset_write,
+};
+
+static const struct file_operations sde_rotator_reg_fops = {
+ .open = sde_rotator_debug_base_open,
+ .release = sde_rotator_debug_base_release,
+ .read = sde_rotator_debug_base_reg_read,
+ .write = sde_rotator_debug_base_reg_write,
+};
+
+int sde_rotator_debug_register_base(struct sde_rotator_device *rot_dev,
+ struct dentry *debugfs_root,
+ const char *name,
+ struct sde_io_data *io_data)
+{
+ struct sde_rotator_debug_base *dbg;
+ struct dentry *ent_off, *ent_reg;
+ char dbgname[80] = "";
+ int prefix_len = 0;
+
+ if (!io_data)
+ return -EINVAL;
+
+ dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
+ if (!dbg)
+ return -ENOMEM;
+
+ if (name)
+ strlcpy(dbg->name, name, sizeof(dbg->name));
+ dbg->base = io_data->base;
+ dbg->max_offset = io_data->len;
+ dbg->off = 0;
+ dbg->cnt = SDE_ROT_DEFAULT_BASE_REG_CNT;
+
+ if (name) {
+ if (strcmp(name, "sde"))
+ prefix_len = snprintf(dbgname, sizeof(dbgname), "%s_",
+ name);
+ else
+ /*
+ * For SDE Rotator registers block, the IO base address
+ * is based on MDP IO address base. It is necessary to
+ * apply the initial offset to it from the first
+ * regdump setting.
+ */
+ dbg->base += rot_dev->mdata->regdump ?
+ rot_dev->mdata->regdump[0].offset : 0;
+ }
+
+ strlcpy(dbgname + prefix_len, "off", sizeof(dbgname) - prefix_len);
+ ent_off = debugfs_create_file(dbgname, 0644, debugfs_root, dbg,
+ &sde_rotator_off_fops);
+ if (IS_ERR_OR_NULL(ent_off)) {
+ SDEROT_ERR("debugfs_create_file: offset fail\n");
+ goto off_fail;
+ }
+
+ strlcpy(dbgname + prefix_len, "reg", sizeof(dbgname) - prefix_len);
+ ent_reg = debugfs_create_file(dbgname, 0644, debugfs_root, dbg,
+ &sde_rotator_reg_fops);
+ if (IS_ERR_OR_NULL(ent_reg)) {
+ SDEROT_ERR("debugfs_create_file: reg fail\n");
+ goto reg_fail;
+ }
+
+ dbg->mgr = rot_dev->mgr;
+
+ return 0;
+reg_fail:
+ debugfs_remove(ent_off);
+off_fail:
+ kfree(dbg);
+ return -ENODEV;
+}
+
/*
* sde_rotator_create_debugfs - Setup rotator debugfs directory structure.
* @rot_dev: Pointer to rotator device
@@ -1040,6 +1311,20 @@ struct dentry *sde_rotator_create_debugfs(
return NULL;
}
+ if (sde_rotator_debug_register_base(rot_dev, debugfs_root,
+ "sde", &rot_dev->mdata->sde_io)) {
+ SDEROT_ERR("fail create debug register for sde rotator\n");
+ debugfs_remove_recursive(debugfs_root);
+ return NULL;
+ }
+
+ if (sde_rotator_debug_register_base(rot_dev, debugfs_root,
+ "vbif_nrt", &rot_dev->mdata->vbif_nrt_io)) {
+ SDEROT_ERR("fail create debug register for sderot vbif_nrt\n");
+ debugfs_remove_recursive(debugfs_root);
+ return NULL;
+ }
+
return debugfs_root;
}
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h
index dcda54274fad..c2c6f9775602 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.h
@@ -44,6 +44,17 @@ void sde_rot_evtlog_tout_handler(bool queue, const char *name, ...);
struct sde_rotator_device;
+struct sde_rotator_debug_base {
+ char name[80];
+ void __iomem *base;
+ size_t off;
+ size_t cnt;
+ size_t max_offset;
+ char *buf;
+ size_t buf_len;
+ struct sde_rot_mgr *mgr;
+};
+
#if defined(CONFIG_DEBUG_FS)
struct dentry *sde_rotator_create_debugfs(
struct sde_rotator_device *rot_dev);
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index f071aae3ccab..0931242a5ec4 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -2940,7 +2940,10 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
case V4L2_CID_MPEG_VIDC_SET_PERF_LEVEL:
switch (ctrl->val) {
case V4L2_CID_MPEG_VIDC_PERF_LEVEL_NOMINAL:
- inst->flags &= ~VIDC_TURBO;
+ if (inst->flags & VIDC_TURBO) {
+ inst->flags &= ~VIDC_TURBO;
+ msm_dcvs_init_load(inst);
+ }
break;
case V4L2_CID_MPEG_VIDC_PERF_LEVEL_TURBO:
inst->flags |= VIDC_TURBO;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index e612c6ed11c7..fa2ad1754e77 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -5286,24 +5286,28 @@ void msm_comm_print_inst_info(struct msm_vidc_inst *inst)
int i = 0;
bool is_decode = false;
enum vidc_ports port;
+ bool is_secure = false;
if (!inst) {
- dprintk(VIDC_ERR, "%s - invalid param %p\n",
+ dprintk(VIDC_ERR, "%s - invalid param %pK\n",
__func__, inst);
return;
}
is_decode = inst->session_type == MSM_VIDC_DECODER;
port = is_decode ? OUTPUT_PORT : CAPTURE_PORT;
+ is_secure = inst->flags & VIDC_SECURE;
dprintk(VIDC_ERR,
- "%s session, Codec type: %s HxW: %d x %d fps: %d bitrate: %d bit-depth: %s\n",
- is_decode ? "Decode" : "Encode", inst->fmts[port].name,
+ "%s session, %s, Codec type: %s HxW: %d x %d fps: %d bitrate: %d bit-depth: %s\n",
+ is_decode ? "Decode" : "Encode",
+ is_secure ? "Secure" : "Non-Secure",
+ inst->fmts[port].name,
inst->prop.height[port], inst->prop.width[port],
inst->prop.fps, inst->prop.bitrate,
!inst->bit_depth ? "8" : "10");
dprintk(VIDC_ERR,
- "---Buffer details for inst: %p of type: %d---\n",
+ "---Buffer details for inst: %pK of type: %d---\n",
inst, inst->session_type);
mutex_lock(&inst->registeredbufs.lock);
dprintk(VIDC_ERR, "registered buffer list:\n");
@@ -5347,7 +5351,7 @@ static void msm_comm_print_debug_info(struct msm_vidc_inst *inst)
struct msm_vidc_inst *temp = NULL;
if (!inst || !inst->core) {
- dprintk(VIDC_ERR, "%s - invalid param %p %p\n",
+ dprintk(VIDC_ERR, "%s - invalid param %pK %pK\n",
__func__, inst, core);
return;
}
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 2764f43607c1..0e7d16fe84d4 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -1388,47 +1388,44 @@ static int uvc_v4l2_put_xu_query(const struct uvc_xu_control_query *kp,
static long uvc_v4l2_compat_ioctl32(struct file *file,
unsigned int cmd, unsigned long arg)
{
+ struct uvc_fh *handle = file->private_data;
union {
struct uvc_xu_control_mapping xmap;
struct uvc_xu_control_query xqry;
} karg;
void __user *up = compat_ptr(arg);
- mm_segment_t old_fs;
long ret;
switch (cmd) {
case UVCIOC_CTRL_MAP32:
- cmd = UVCIOC_CTRL_MAP;
ret = uvc_v4l2_get_xu_mapping(&karg.xmap, up);
+ if (ret)
+ return ret;
+ ret = uvc_ioctl_ctrl_map(handle->chain, &karg.xmap);
+ if (ret)
+ return ret;
+ ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up);
+ if (ret)
+ return ret;
+
break;
case UVCIOC_CTRL_QUERY32:
- cmd = UVCIOC_CTRL_QUERY;
ret = uvc_v4l2_get_xu_query(&karg.xqry, up);
+ if (ret)
+ return ret;
+ ret = uvc_xu_ctrl_query(handle->chain, &karg.xqry);
+ if (ret)
+ return ret;
+ ret = uvc_v4l2_put_xu_query(&karg.xqry, up);
+ if (ret)
+ return ret;
break;
default:
return -ENOIOCTLCMD;
}
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- ret = video_ioctl2(file, cmd, (unsigned long)&karg);
- set_fs(old_fs);
-
- if (ret < 0)
- return ret;
-
- switch (cmd) {
- case UVCIOC_CTRL_MAP:
- ret = uvc_v4l2_put_xu_mapping(&karg.xmap, up);
- break;
-
- case UVCIOC_CTRL_QUERY:
- ret = uvc_v4l2_put_xu_query(&karg.xqry, up);
- break;
- }
-
return ret;
}
#endif
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 2da7fd7deacd..2f1c03783414 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -280,7 +280,8 @@ static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user
static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
{
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
- copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)))
+ copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)) ||
+ copy_to_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
return -EFAULT;
return __put_v4l2_format32(&kp->format, &up->format);
}
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 6515dfc2b805..55cba89dbdb8 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -394,7 +394,7 @@ static void gpmc_cs_bool_timings(int cs, const struct gpmc_bool_timings *p)
gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
GPMC_CONFIG4_OEEXTRADELAY, p->oe_extra_delay);
gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG4,
- GPMC_CONFIG4_OEEXTRADELAY, p->we_extra_delay);
+ GPMC_CONFIG4_WEEXTRADELAY, p->we_extra_delay);
gpmc_cs_modify_reg(cs, GPMC_CS_CONFIG6,
GPMC_CONFIG6_CYCLE2CYCLESAMECSEN,
p->cycle2cyclesamecsen);
diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c
index 68aa31ae553a..88e80ec772f6 100644
--- a/drivers/mfd/intel-lpss.c
+++ b/drivers/mfd/intel-lpss.c
@@ -33,6 +33,7 @@
#define LPSS_DEV_SIZE 0x200
#define LPSS_PRIV_OFFSET 0x200
#define LPSS_PRIV_SIZE 0x100
+#define LPSS_PRIV_REG_COUNT (LPSS_PRIV_SIZE / 4)
#define LPSS_IDMA64_OFFSET 0x800
#define LPSS_IDMA64_SIZE 0x800
@@ -75,6 +76,7 @@ struct intel_lpss {
const struct mfd_cell *cell;
struct device *dev;
void __iomem *priv;
+ u32 priv_ctx[LPSS_PRIV_REG_COUNT];
int devid;
u32 caps;
u32 active_ltr;
@@ -485,6 +487,16 @@ EXPORT_SYMBOL_GPL(intel_lpss_prepare);
int intel_lpss_suspend(struct device *dev)
{
+ struct intel_lpss *lpss = dev_get_drvdata(dev);
+ unsigned int i;
+
+ /* Save device context */
+ for (i = 0; i < LPSS_PRIV_REG_COUNT; i++)
+ lpss->priv_ctx[i] = readl(lpss->priv + i * 4);
+
+ /* Put the device into reset state */
+ writel(0, lpss->priv + LPSS_PRIV_RESETS);
+
return 0;
}
EXPORT_SYMBOL_GPL(intel_lpss_suspend);
@@ -492,8 +504,13 @@ EXPORT_SYMBOL_GPL(intel_lpss_suspend);
int intel_lpss_resume(struct device *dev)
{
struct intel_lpss *lpss = dev_get_drvdata(dev);
+ unsigned int i;
- intel_lpss_init_dev(lpss);
+ intel_lpss_deassert_reset(lpss);
+
+ /* Restore device context */
+ for (i = 0; i < LPSS_PRIV_REG_COUNT; i++)
+ writel(lpss->priv_ctx[i], lpss->priv + i * 4);
return 0;
}
diff --git a/drivers/mfd/intel_soc_pmic_core.c b/drivers/mfd/intel_soc_pmic_core.c
index d9e15cf7c6c8..12d6ebb4ae5d 100644
--- a/drivers/mfd/intel_soc_pmic_core.c
+++ b/drivers/mfd/intel_soc_pmic_core.c
@@ -35,6 +35,7 @@ static struct gpiod_lookup_table panel_gpio_table = {
.table = {
/* Panel EN/DISABLE */
GPIO_LOOKUP("gpio_crystalcove", 94, "panel", GPIO_ACTIVE_HIGH),
+ { },
},
};
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index b7b3e8ee64f2..c30290f33430 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -269,6 +269,8 @@ static int usbtll_omap_probe(struct platform_device *pdev)
if (IS_ERR(tll->ch_clk[i]))
dev_dbg(dev, "can't get clock : %s\n", clkname);
+ else
+ clk_prepare(tll->ch_clk[i]);
}
pm_runtime_put_sync(dev);
@@ -301,9 +303,12 @@ static int usbtll_omap_remove(struct platform_device *pdev)
tll_dev = NULL;
spin_unlock(&tll_lock);
- for (i = 0; i < tll->nch; i++)
- if (!IS_ERR(tll->ch_clk[i]))
+ for (i = 0; i < tll->nch; i++) {
+ if (!IS_ERR(tll->ch_clk[i])) {
+ clk_unprepare(tll->ch_clk[i]);
clk_put(tll->ch_clk[i]);
+ }
+ }
pm_runtime_disable(&pdev->dev);
return 0;
@@ -420,7 +425,7 @@ int omap_tll_enable(struct usbhs_omap_platform_data *pdata)
if (IS_ERR(tll->ch_clk[i]))
continue;
- r = clk_prepare_enable(tll->ch_clk[i]);
+ r = clk_enable(tll->ch_clk[i]);
if (r) {
dev_err(tll_dev,
"Error enabling ch %d clock: %d\n", i, r);
@@ -448,7 +453,7 @@ int omap_tll_disable(struct usbhs_omap_platform_data *pdata)
for (i = 0; i < tll->nch; i++) {
if (omap_usb_mode_needs_tll(pdata->port_mode[i])) {
if (!IS_ERR(tll->ch_clk[i]))
- clk_disable_unprepare(tll->ch_clk[i]);
+ clk_disable(tll->ch_clk[i]);
}
}
diff --git a/drivers/mfd/wcd9xxx-utils.c b/drivers/mfd/wcd9xxx-utils.c
index fab594992df3..2b0a5f8ce7f2 100644
--- a/drivers/mfd/wcd9xxx-utils.c
+++ b/drivers/mfd/wcd9xxx-utils.c
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/regmap.h>
#include <linux/delay.h>
+#include <linux/sched.h>
#include <linux/mfd/core.h>
#include <linux/mfd/wcd9xxx/pdata.h>
#include <linux/mfd/wcd9xxx/core.h>
@@ -310,6 +311,7 @@ struct wcd9xxx_pdata *wcd9xxx_populate_dt_data(struct device *dev)
u32 ecpp_dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
u32 dmic_clk_drive = WCD9XXX_DMIC_CLK_DRIVE_UNDEFINED;
u32 prop_val;
+ int rc = 0;
if (!dev || !dev->of_node)
return NULL;
@@ -368,9 +370,13 @@ struct wcd9xxx_pdata *wcd9xxx_populate_dt_data(struct device *dev)
pdata->mclk_rate,
"mad_dmic_rate");
- if (!(wcd9xxx_read_of_property_u32(dev, "qcom,cdc-ecpp-dmic-rate",
- &prop_val)))
- ecpp_dmic_sample_rate = prop_val;
+ if (of_find_property(dev->of_node, "qcom,cdc-ecpp-dmic-rate", NULL)) {
+ rc = wcd9xxx_read_of_property_u32(dev,
+ "qcom,cdc-ecpp-dmic-rate",
+ &prop_val);
+ if (!rc)
+ ecpp_dmic_sample_rate = prop_val;
+ }
pdata->ecpp_dmic_sample_rate = wcd9xxx_validate_dmic_sample_rate(dev,
ecpp_dmic_sample_rate,
@@ -379,13 +385,14 @@ struct wcd9xxx_pdata *wcd9xxx_populate_dt_data(struct device *dev)
if (!(of_property_read_u32(dev->of_node,
"qcom,cdc-dmic-clk-drv-strength",
- &prop_val)))
+ &prop_val))) {
dmic_clk_drive = prop_val;
- if (dmic_clk_drive != 2 && dmic_clk_drive != 4 &&
- dmic_clk_drive != 8 && dmic_clk_drive != 16)
- dev_err(dev, "Invalid cdc-dmic-clk-drv-strength %d\n",
- dmic_clk_drive);
+ if (dmic_clk_drive != 2 && dmic_clk_drive != 4 &&
+ dmic_clk_drive != 8 && dmic_clk_drive != 16)
+ dev_err(dev, "Invalid cdc-dmic-clk-drv-strength %d\n",
+ dmic_clk_drive);
+ }
pdata->dmic_clk_drv = dmic_clk_drive;
diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c
index 76add503b6b8..69ec7127102c 100644
--- a/drivers/misc/hdcp.c
+++ b/drivers/misc/hdcp.c
@@ -160,43 +160,46 @@
static const struct hdcp_msg_data hdcp_msg_lookup[HDCP2P2_MAX_MESSAGES] = {
[AKE_INIT_MESSAGE_ID] = { 2,
- { {0x69000, 8}, {0x69008, 3} },
+ { {"rtx", 0x69000, 8}, {"TxCaps", 0x69008, 3} },
0 },
[AKE_SEND_CERT_MESSAGE_ID] = { 3,
- { {0x6900B, 522}, {0x69215, 8}, {0x6921D, 3} },
+ { {"cert-rx", 0x6900B, 522}, {"rrx", 0x69215, 8},
+ {"RxCaps", 0x6921D, 3} },
0 },
[AKE_NO_STORED_KM_MESSAGE_ID] = { 1,
- { {0x69220, 128} },
+ { {"Ekpub_km", 0x69220, 128} },
0 },
[AKE_STORED_KM_MESSAGE_ID] = { 2,
- { {0x692A0, 16}, {0x692B0, 16} },
+ { {"Ekh_km", 0x692A0, 16}, {"m", 0x692B0, 16} },
0 },
[AKE_SEND_H_PRIME_MESSAGE_ID] = { 1,
- { {0x692C0, 32} },
+ { {"H'", 0x692C0, 32} },
(1 << 1) },
[AKE_SEND_PAIRING_INFO_MESSAGE_ID] = { 1,
- { {0x692E0, 16} },
+ { {"Ekh_km", 0x692E0, 16} },
(1 << 2) },
[LC_INIT_MESSAGE_ID] = { 1,
- { {0x692F0, 8} },
+ { {"rn", 0x692F0, 8} },
0 },
[LC_SEND_L_PRIME_MESSAGE_ID] = { 1,
- { {0x692F8, 32} },
+ { {"L'", 0x692F8, 32} },
0 },
[SKE_SEND_EKS_MESSAGE_ID] = { 2,
- { {0x69318, 16}, {0x69328, 8} },
+ { {"Edkey_ks", 0x69318, 16}, {"riv", 0x69328, 8} },
0 },
[REPEATER_AUTH_SEND_RECEIVERID_LIST_MESSAGE_ID] = { 4,
- { {0x69330, 2}, {0x69332, 3}, {0x69335, 16}, {0x69345, 155} },
+ { {"RxInfo", 0x69330, 2}, {"seq_num_V", 0x69332, 3},
+ {"V'", 0x69335, 16}, {"ridlist", 0x69345, 155} },
(1 << 0) },
[REPEATER_AUTH_SEND_ACK_MESSAGE_ID] = { 1,
- { {0x693E0, 16} },
+ { {"V", 0x693E0, 16} },
0 },
[REPEATER_AUTH_STREAM_MANAGE_MESSAGE_ID] = { 3,
- { {0x693F0, 3}, {0x693F3, 2}, {0x693F5, 126} },
+ { {"seq_num_M", 0x693F0, 3}, {"k", 0x693F3, 2},
+ {"streamID_Type", 0x693F5, 126} },
0 },
[REPEATER_AUTH_STREAM_READY_MESSAGE_ID] = { 1,
- { {0x69473, 32} },
+ { {"M'", 0x69473, 32} },
0 }
};
@@ -616,36 +619,59 @@ static int hdcp_lib_get_next_message(struct hdcp_lib_handle *handle,
}
}
-static inline void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle,
- struct hdmi_hdcp_wakeup_data *data)
+static void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle,
+ struct hdmi_hdcp_wakeup_data *data)
{
- int rc = 0;
+ int rc = 0, i;
- if (handle && handle->client_ops && handle->client_ops->wakeup &&
- data && (data->cmd != HDMI_HDCP_WKUP_CMD_INVALID)) {
- data->abort_mask = REAUTH_REQ | LINK_INTEGRITY_FAILURE;
+ if (!handle || !handle->client_ops || !handle->client_ops->wakeup ||
+ !data || (data->cmd == HDMI_HDCP_WKUP_CMD_INVALID))
+ return;
- if (data->cmd == HDMI_HDCP_WKUP_CMD_SEND_MESSAGE ||
- data->cmd == HDMI_HDCP_WKUP_CMD_RECV_MESSAGE ||
- data->cmd == HDMI_HDCP_WKUP_CMD_LINK_POLL) {
- handle->last_msg =
- hdcp_lib_get_next_message(handle, data);
+ data->abort_mask = REAUTH_REQ | LINK_INTEGRITY_FAILURE;
- if (handle->last_msg > INVALID_MESSAGE_ID &&
- handle->last_msg < HDCP2P2_MAX_MESSAGES)
- data->message_data =
- &hdcp_msg_lookup[handle->last_msg];
- }
+ if (data->cmd == HDMI_HDCP_WKUP_CMD_SEND_MESSAGE ||
+ data->cmd == HDMI_HDCP_WKUP_CMD_RECV_MESSAGE ||
+ data->cmd == HDMI_HDCP_WKUP_CMD_LINK_POLL) {
+ handle->last_msg = hdcp_lib_get_next_message(handle, data);
- rc = handle->client_ops->wakeup(data);
- if (rc)
- pr_err("error sending %s to client\n",
- hdmi_hdcp_cmd_to_str(data->cmd));
+ pr_debug("lib->client: %s (%s)\n",
+ hdmi_hdcp_cmd_to_str(data->cmd),
+ hdcp_lib_message_name(handle->last_msg));
+
+ if (handle->last_msg > INVALID_MESSAGE_ID &&
+ handle->last_msg < HDCP2P2_MAX_MESSAGES) {
+ u32 msg_num, rx_status;
+ const struct hdcp_msg_part *msg;
+
+ data->message_data = &hdcp_msg_lookup[handle->last_msg];
+
+ msg_num = data->message_data->num_messages;
+ msg = data->message_data->messages;
+ rx_status = data->message_data->rx_status;
+
+ pr_debug("rxstatus 0x%x\n", rx_status);
+ pr_debug("%10s | %6s | %4s\n", "name", "offset", "len");
+
+ for (i = 0; i < msg_num; i++)
+ pr_debug("%10s | %6x | %4d\n",
+ msg[i].name, msg[i].offset,
+ msg[i].length);
+ }
+ } else {
+ pr_debug("lib->client: %s\n",
+ hdmi_hdcp_cmd_to_str(data->cmd));
}
+
+ rc = handle->client_ops->wakeup(data);
+ if (rc)
+ pr_err("error sending %s to client\n",
+ hdmi_hdcp_cmd_to_str(data->cmd));
}
static inline void hdcp_lib_send_message(struct hdcp_lib_handle *handle)
{
+ char msg_name[50];
struct hdmi_hdcp_wakeup_data cdata = {
HDMI_HDCP_WKUP_CMD_SEND_MESSAGE
};
@@ -655,6 +681,13 @@ static inline void hdcp_lib_send_message(struct hdcp_lib_handle *handle)
cdata.send_msg_len = handle->msglen;
cdata.timeout = handle->hdcp_timeout;
+ snprintf(msg_name, sizeof(msg_name), "%s: ",
+ hdcp_lib_message_name((int)cdata.send_msg_buf[0]));
+
+ print_hex_dump(KERN_DEBUG, msg_name,
+ DUMP_PREFIX_NONE, 16, 1, cdata.send_msg_buf,
+ cdata.send_msg_len, false);
+
hdcp_lib_wakeup_client(handle, &cdata);
}
@@ -1486,6 +1519,7 @@ static int hdcp_lib_check_valid_state(struct hdcp_lib_handle *handle)
if (handle->wakeup_cmd == HDCP_LIB_WKUP_CMD_START) {
if (!list_empty(&handle->worker.work_list)) {
+ pr_debug("error: queue not empty\n");
rc = -EBUSY;
goto exit;
}
@@ -1543,9 +1577,8 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
handle->wakeup_cmd = data->cmd;
handle->timeout_left = data->timeout;
- pr_debug("%s, timeout left: %dms, tethered %d\n",
- hdcp_lib_cmd_to_str(handle->wakeup_cmd),
- handle->timeout_left, handle->tethered);
+ pr_debug("client->lib: %s\n",
+ hdcp_lib_cmd_to_str(handle->wakeup_cmd));
rc = hdcp_lib_check_valid_state(handle);
if (rc)
@@ -1599,6 +1632,8 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data)
break;
case HDCP_LIB_WKUP_CMD_MSG_SEND_FAILED:
case HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED:
+ case HDCP_LIB_WKUP_CMD_LINK_FAILED:
+ handle->hdcp_state |= HDCP_STATE_ERROR;
HDCP_LIB_EXECUTE(clean);
break;
case HDCP_LIB_WKUP_CMD_MSG_RECV_SUCCESS:
@@ -1825,7 +1860,7 @@ static void hdcp_lib_clean(struct hdcp_lib_handle *handle)
if (!handle) {
pr_err("invalid input\n");
return;
- };
+ }
hdcp_lib_txmtr_deinit(handle);
if (!handle->legacy_app)
@@ -1859,6 +1894,7 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle)
struct hdcp_rcvd_msg_rsp *rsp_buf;
uint32_t msglen;
char *msg = NULL;
+ char msg_name[50];
uint32_t message_id_bytes = 0;
if (!handle || !handle->qseecom_handle ||
@@ -1907,8 +1943,11 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle)
mutex_unlock(&handle->msg_lock);
- pr_debug("msg received: %s from sink\n",
- hdcp_lib_message_name((int)msg[0]));
+ snprintf(msg_name, sizeof(msg_name), "%s: ",
+ hdcp_lib_message_name((int)msg[0]));
+
+ print_hex_dump(KERN_DEBUG, msg_name,
+ DUMP_PREFIX_NONE, 16, 1, msg, msglen, false);
/* send the message to QSEECOM */
req_buf = (struct hdcp_rcvd_msg_req *)(handle->qseecom_handle->sbuf);
@@ -1989,13 +2028,8 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle)
handle->hdcp_timeout = rsp_buf->timeout;
handle->msglen = rsp_buf->msglen;
- if (!atomic_read(&handle->hdcp_off)) {
- cdata.cmd = HDMI_HDCP_WKUP_CMD_SEND_MESSAGE;
- cdata.send_msg_buf = handle->listener_buf;
- cdata.send_msg_len = handle->msglen;
- cdata.timeout = handle->hdcp_timeout;
- }
-
+ if (!atomic_read(&handle->hdcp_off))
+ hdcp_lib_send_message(handle);
exit:
kzfree(msg);
@@ -2026,6 +2060,16 @@ static void hdcp_lib_topology_work(struct kthread_work *work)
return;
}
+ if (atomic_read(&handle->hdcp_off)) {
+ pr_debug("invalid state: hdcp off\n");
+ return;
+ }
+
+ if (handle->hdcp_state & HDCP_STATE_ERROR) {
+ pr_debug("invalid state: hdcp error\n");
+ return;
+ }
+
reinit_completion(&handle->topo_wait);
timeout = wait_for_completion_timeout(&handle->topo_wait, HZ * 3);
if (!timeout) {
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index cd0403f09267..e79c0371ee6f 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -417,8 +417,10 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl,
dev = cl->dev;
- if (dev->iamthif_state != MEI_IAMTHIF_READING)
+ if (dev->iamthif_state != MEI_IAMTHIF_READING) {
+ mei_irq_discard_msg(dev, mei_hdr);
return 0;
+ }
ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
if (ret)
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 1a173d0af694..a77643954523 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -222,17 +222,23 @@ EXPORT_SYMBOL_GPL(mei_cldev_recv);
static void mei_cl_bus_event_work(struct work_struct *work)
{
struct mei_cl_device *cldev;
+ struct mei_device *bus;
cldev = container_of(work, struct mei_cl_device, event_work);
+ bus = cldev->bus;
+
if (cldev->event_cb)
cldev->event_cb(cldev, cldev->events, cldev->event_context);
cldev->events = 0;
/* Prepare for the next read */
- if (cldev->events_mask & BIT(MEI_CL_EVENT_RX))
+ if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
+ mutex_lock(&bus->device_lock);
mei_cl_read_start(cldev->cl, 0, NULL);
+ mutex_unlock(&bus->device_lock);
+ }
}
/**
@@ -296,6 +302,7 @@ int mei_cldev_register_event_cb(struct mei_cl_device *cldev,
unsigned long events_mask,
mei_cldev_event_cb_t event_cb, void *context)
{
+ struct mei_device *bus = cldev->bus;
int ret;
if (cldev->event_cb)
@@ -308,15 +315,17 @@ int mei_cldev_register_event_cb(struct mei_cl_device *cldev,
INIT_WORK(&cldev->event_work, mei_cl_bus_event_work);
if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
+ mutex_lock(&bus->device_lock);
ret = mei_cl_read_start(cldev->cl, 0, NULL);
+ mutex_unlock(&bus->device_lock);
if (ret && ret != -EBUSY)
return ret;
}
if (cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)) {
- mutex_lock(&cldev->cl->dev->device_lock);
+ mutex_lock(&bus->device_lock);
ret = mei_cl_notify_request(cldev->cl, NULL, event_cb ? 1 : 0);
- mutex_unlock(&cldev->cl->dev->device_lock);
+ mutex_unlock(&bus->device_lock);
if (ret)
return ret;
}
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index a6c87c713193..958af84884b5 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -1735,6 +1735,10 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
wake_up(&cl->wait);
break;
+ case MEI_FOP_DISCONNECT_RSP:
+ mei_io_cb_free(cb);
+ mei_cl_set_disconnected(cl);
+ break;
default:
BUG_ON(0);
}
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index e7b7aad0999b..fd8a9f057ea6 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -873,8 +873,7 @@ static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT_RSP, NULL);
if (!cb)
return -ENOMEM;
- cl_dbg(dev, cl, "add disconnect response as first\n");
- list_add(&cb->list, &dev->ctrl_wr_list.list);
+ list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
}
return 0;
}
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 64b568a0268d..d1df797c7568 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -76,7 +76,6 @@ static inline int mei_cl_hbm_equal(struct mei_cl *cl,
* @dev: mei device
* @hdr: message header
*/
-static inline
void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr)
{
/*
@@ -184,10 +183,7 @@ static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
return -EMSGSIZE;
ret = mei_hbm_cl_disconnect_rsp(dev, cl);
- mei_cl_set_disconnected(cl);
- mei_io_cb_free(cb);
- mei_me_cl_put(cl->me_cl);
- cl->me_cl = NULL;
+ list_move_tail(&cb->list, &cmpl_list->list);
return ret;
}
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 4250555d5e72..1b06e2fd6858 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -782,6 +782,8 @@ bool mei_hbuf_acquire(struct mei_device *dev);
bool mei_write_is_idle(struct mei_device *dev);
+void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr);
+
#if IS_ENABLED(CONFIG_DEBUG_FS)
int mei_dbgfs_register(struct mei_device *dev, const char *name);
void mei_dbgfs_deregister(struct mei_device *dev);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index ff838ebefba6..7dc7271b05c1 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -131,6 +131,35 @@ static DEFINE_MUTEX(qsee_bw_mutex);
static DEFINE_MUTEX(app_access_lock);
static DEFINE_MUTEX(clk_access_lock);
+struct sglist_info {
+ uint32_t indexAndFlags;
+ uint32_t sizeOrCount;
+};
+
+/*
+ * The 31th bit indicates only one or multiple physical address inside
+ * the request buffer. If it is set, the index locates a single physical addr
+ * inside the request buffer, and `sizeOrCount` is the size of the memory being
+ * shared at that physical address.
+ * Otherwise, the index locates an array of {start, len} pairs (a
+ * "scatter/gather list"), and `sizeOrCount` gives the number of entries in
+ * that array.
+ *
+ * The 30th bit indicates 64 or 32bit address; when it is set, physical addr
+ * and scatter gather entry sizes are 64-bit values. Otherwise, 32-bit values.
+ *
+ * The bits [0:29] of `indexAndFlags` hold an offset into the request buffer.
+ */
+#define SGLISTINFO_SET_INDEX_FLAG(c, s, i) \
+ ((uint32_t)(((c & 1) << 31) | ((s & 1) << 30) | (i & 0x3fffffff)))
+
+#define SGLISTINFO_TABLE_SIZE (sizeof(struct sglist_info) * MAX_ION_FD)
+
+#define FEATURE_ID_WHITELIST 15 /*whitelist feature id*/
+
+#define MAKE_WHITELIST_VERSION(major, minor, patch) \
+ (((major & 0x3FF) << 22) | ((minor & 0x3FF) << 12) | (patch & 0xFFF))
+
struct qseecom_registered_listener_list {
struct list_head list;
struct qseecom_register_listener_req svc;
@@ -145,6 +174,8 @@ struct qseecom_registered_listener_list {
bool listener_in_use;
/* wq for thread blocked on this listener*/
wait_queue_head_t listener_block_app_wq;
+ struct sglist_info sglistinfo_ptr[MAX_ION_FD];
+ uint32_t sglist_cnt;
};
struct qseecom_registered_app_list {
@@ -268,30 +299,6 @@ struct qseecom_listener_handle {
static struct qseecom_control qseecom;
-struct sglist_info {
- uint32_t indexAndFlags;
- uint32_t sizeOrCount;
-};
-
-/*
- * The 31th bit indicates only one or multiple physical address inside
- * the request buffer. If it is set, the index locates a single physical addr
- * inside the request buffer, and `sizeOrCount` is the size of the memory being
- * shared at that physical address.
- * Otherwise, the index locates an array of {start, len} pairs (a
- * "scatter/gather list"), and `sizeOrCount` gives the number of entries in
- * that array.
- *
- * The 30th bit indicates 64 or 32bit address; when it is set, physical addr
- * and scatter gather entry sizes are 64-bit values. Otherwise, 32-bit values.
- *
- * The bits [0:29] of `indexAndFlags` hold an offset into the request buffer.
- */
-#define SGLISTINFO_SET_INDEX_FLAG(c, s, i) \
- ((uint32_t)(((c & 1) << 31) | ((s & 1) << 30) | (i & 0x3fffffff)))
-
-#define SGLISTINFO_TABLE_SIZE (sizeof(struct sglist_info) * MAX_ION_FD)
-
struct qseecom_dev_handle {
enum qseecom_client_handle_type type;
union {
@@ -305,8 +312,9 @@ struct qseecom_dev_handle {
bool perf_enabled;
bool fast_load_enabled;
enum qseecom_bandwidth_request_mode mode;
- struct sglist_info *sglistinfo_ptr;
+ struct sglist_info sglistinfo_ptr[MAX_ION_FD];
uint32_t sglist_cnt;
+ bool use_legacy_cmd;
};
struct qseecom_key_id_usage_desc {
@@ -584,6 +592,34 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id,
ret = scm_call2(smc_id, &desc);
break;
}
+ case QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST: {
+ struct qseecom_client_listener_data_irsp *req;
+ struct qseecom_client_listener_data_64bit_irsp *req_64;
+
+ smc_id =
+ TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID;
+ desc.arginfo =
+ TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_PARAM_ID;
+ if (qseecom.qsee_version < QSEE_VERSION_40) {
+ req =
+ (struct qseecom_client_listener_data_irsp *)
+ req_buf;
+ desc.args[0] = req->listener_id;
+ desc.args[1] = req->status;
+ desc.args[2] = req->sglistinfo_ptr;
+ desc.args[3] = req->sglistinfo_len;
+ } else {
+ req_64 =
+ (struct qseecom_client_listener_data_64bit_irsp *)
+ req_buf;
+ desc.args[0] = req_64->listener_id;
+ desc.args[1] = req_64->status;
+ desc.args[2] = req_64->sglistinfo_ptr;
+ desc.args[3] = req_64->sglistinfo_len;
+ }
+ ret = scm_call2(smc_id, &desc);
+ break;
+ }
case QSEOS_LOAD_EXTERNAL_ELF_COMMAND: {
struct qseecom_load_app_ireq *req;
struct qseecom_load_app_64bit_ireq *req_64bit;
@@ -1128,7 +1164,7 @@ static int qseecom_register_listener(struct qseecom_dev_handle *data,
return -EBUSY;
}
- new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
+ new_entry = kzalloc(sizeof(*new_entry), GFP_KERNEL);
if (!new_entry) {
pr_err("kmalloc failed\n");
return -ENOMEM;
@@ -1593,6 +1629,16 @@ static int __qseecom_qseos_fail_return_resp_tz(struct qseecom_dev_handle *data,
return ret;
}
+static void __qseecom_clean_listener_sglistinfo(
+ struct qseecom_registered_listener_list *ptr_svc)
+{
+ if (ptr_svc->sglist_cnt) {
+ memset(ptr_svc->sglistinfo_ptr, 0,
+ SGLISTINFO_TABLE_SIZE);
+ ptr_svc->sglist_cnt = 0;
+ }
+}
+
static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
struct qseecom_command_scm_resp *resp)
{
@@ -1601,9 +1647,14 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
uint32_t lstnr;
unsigned long flags;
struct qseecom_client_listener_data_irsp send_data_rsp;
+ struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit;
struct qseecom_registered_listener_list *ptr_svc = NULL;
sigset_t new_sigset;
sigset_t old_sigset;
+ uint32_t status;
+ void *cmd_buf = NULL;
+ size_t cmd_len;
+ struct sglist_info *table = NULL;
while (resp->result == QSEOS_RESULT_INCOMPLETE) {
lstnr = resp->data;
@@ -1677,15 +1728,42 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d",
data->client.app_id, lstnr, ret);
rc = -ENODEV;
- send_data_rsp.status = QSEOS_RESULT_FAILURE;
+ status = QSEOS_RESULT_FAILURE;
} else {
- send_data_rsp.status = QSEOS_RESULT_SUCCESS;
+ status = QSEOS_RESULT_SUCCESS;
}
qseecom.send_resp_flag = 0;
ptr_svc->send_resp_flag = 0;
- send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND;
- send_data_rsp.listener_id = lstnr;
+ table = ptr_svc->sglistinfo_ptr;
+ if (qseecom.qsee_version < QSEE_VERSION_40) {
+ send_data_rsp.listener_id = lstnr;
+ send_data_rsp.status = status;
+ send_data_rsp.sglistinfo_ptr =
+ (uint32_t)virt_to_phys(table);
+ send_data_rsp.sglistinfo_len =
+ SGLISTINFO_TABLE_SIZE;
+ dmac_flush_range((void *)table,
+ (void *)table + SGLISTINFO_TABLE_SIZE);
+ cmd_buf = (void *)&send_data_rsp;
+ cmd_len = sizeof(send_data_rsp);
+ } else {
+ send_data_rsp_64bit.listener_id = lstnr;
+ send_data_rsp_64bit.status = status;
+ send_data_rsp_64bit.sglistinfo_ptr =
+ virt_to_phys(table);
+ send_data_rsp_64bit.sglistinfo_len =
+ SGLISTINFO_TABLE_SIZE;
+ dmac_flush_range((void *)table,
+ (void *)table + SGLISTINFO_TABLE_SIZE);
+ cmd_buf = (void *)&send_data_rsp_64bit;
+ cmd_len = sizeof(send_data_rsp_64bit);
+ }
+ if (qseecom.whitelist_support == false)
+ *(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND;
+ else
+ *(uint32_t *)cmd_buf =
+ QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST;
if (ptr_svc)
msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle,
ptr_svc->sb_virt, ptr_svc->sb_length,
@@ -1695,10 +1773,9 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data,
__qseecom_enable_clk(CLK_QSEE);
ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
- (const void *)&send_data_rsp,
- sizeof(send_data_rsp), resp,
- sizeof(*resp));
+ cmd_buf, cmd_len, resp, sizeof(*resp));
ptr_svc->listener_in_use = false;
+ __qseecom_clean_listener_sglistinfo(ptr_svc);
if (ret) {
pr_err("scm_call() failed with err: %d (app_id = %d)\n",
ret, data->client.app_id);
@@ -1826,9 +1903,14 @@ static int __qseecom_reentrancy_process_incomplete_cmd(
uint32_t lstnr;
unsigned long flags;
struct qseecom_client_listener_data_irsp send_data_rsp;
+ struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit;
struct qseecom_registered_listener_list *ptr_svc = NULL;
sigset_t new_sigset;
sigset_t old_sigset;
+ uint32_t status;
+ void *cmd_buf = NULL;
+ size_t cmd_len;
+ struct sglist_info *table = NULL;
while (ret == 0 && rc == 0 && resp->result == QSEOS_RESULT_INCOMPLETE) {
lstnr = resp->data;
@@ -1891,13 +1973,38 @@ static int __qseecom_reentrancy_process_incomplete_cmd(
pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d",
data->client.app_id, lstnr, ret);
rc = -ENODEV;
- send_data_rsp.status = QSEOS_RESULT_FAILURE;
+ status = QSEOS_RESULT_FAILURE;
} else {
- send_data_rsp.status = QSEOS_RESULT_SUCCESS;
+ status = QSEOS_RESULT_SUCCESS;
}
-
- send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND;
- send_data_rsp.listener_id = lstnr;
+ table = ptr_svc->sglistinfo_ptr;
+ if (qseecom.qsee_version < QSEE_VERSION_40) {
+ send_data_rsp.listener_id = lstnr;
+ send_data_rsp.status = status;
+ send_data_rsp.sglistinfo_ptr =
+ (uint32_t)virt_to_phys(table);
+ send_data_rsp.sglistinfo_len = SGLISTINFO_TABLE_SIZE;
+ dmac_flush_range((void *)table,
+ (void *)table + SGLISTINFO_TABLE_SIZE);
+ cmd_buf = (void *)&send_data_rsp;
+ cmd_len = sizeof(send_data_rsp);
+ } else {
+ send_data_rsp_64bit.listener_id = lstnr;
+ send_data_rsp_64bit.status = status;
+ send_data_rsp_64bit.sglistinfo_ptr =
+ virt_to_phys(table);
+ send_data_rsp_64bit.sglistinfo_len =
+ SGLISTINFO_TABLE_SIZE;
+ dmac_flush_range((void *)table,
+ (void *)table + SGLISTINFO_TABLE_SIZE);
+ cmd_buf = (void *)&send_data_rsp_64bit;
+ cmd_len = sizeof(send_data_rsp_64bit);
+ }
+ if (qseecom.whitelist_support == false)
+ *(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND;
+ else
+ *(uint32_t *)cmd_buf =
+ QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST;
if (ptr_svc)
msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle,
ptr_svc->sb_virt, ptr_svc->sb_length,
@@ -1907,11 +2014,9 @@ static int __qseecom_reentrancy_process_incomplete_cmd(
__qseecom_enable_clk(CLK_QSEE);
ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
- (const void *)&send_data_rsp,
- sizeof(send_data_rsp), resp,
- sizeof(*resp));
-
+ cmd_buf, cmd_len, resp, sizeof(*resp));
ptr_svc->listener_in_use = false;
+ __qseecom_clean_listener_sglistinfo(ptr_svc);
wake_up_interruptible(&ptr_svc->listener_block_app_wq);
if (ret) {
@@ -2079,6 +2184,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
struct qseecom_load_app_64bit_ireq load_req_64bit;
void *cmd_buf = NULL;
size_t cmd_len;
+ bool first_time = false;
/* Copy the relevant information needed for loading the image */
if (copy_from_user(&load_img_req,
@@ -2150,6 +2256,7 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
&qseecom.registered_app_list_lock, flags);
ret = 0;
} else {
+ first_time = true;
pr_warn("App (%s) does'nt exist, loading apps for first time\n",
(char *)(load_img_req.img_name));
/* Get the handle of the shared fd */
@@ -2281,8 +2388,15 @@ static int qseecom_load_app(struct qseecom_dev_handle *data, void __user *argp)
load_img_req.app_id = app_id;
if (copy_to_user(argp, &load_img_req, sizeof(load_img_req))) {
pr_err("copy_to_user failed\n");
- kzfree(entry);
ret = -EFAULT;
+ if (first_time == true) {
+ spin_lock_irqsave(
+ &qseecom.registered_app_list_lock, flags);
+ list_del(&entry->list);
+ spin_unlock_irqrestore(
+ &qseecom.registered_app_list_lock, flags);
+ kzfree(entry);
+ }
}
loadapp_err:
@@ -2910,7 +3024,7 @@ static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq);
}
- if (qseecom.whitelist_support == false)
+ if (qseecom.whitelist_support == false || data->use_legacy_cmd == true)
*(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND;
else
*(uint32_t *)cmd_buf = QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST;
@@ -3015,6 +3129,8 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup,
struct qseecom_send_modfd_cmd_req *req = NULL;
struct qseecom_send_modfd_listener_resp *lstnr_resp = NULL;
struct qseecom_registered_listener_list *this_lstnr = NULL;
+ uint32_t offset;
+ struct sg_table *sg_ptr;
if ((data->type != QSEECOM_LISTENER_SERVICE) &&
(data->type != QSEECOM_CLIENT_APP))
@@ -3036,7 +3152,6 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup,
}
for (i = 0; i < MAX_ION_FD; i++) {
- struct sg_table *sg_ptr = NULL;
if ((data->type != QSEECOM_LISTENER_SERVICE) &&
(req->ifd_data[i].fd > 0)) {
ihandle = ion_import_dma_buf(qseecom.ion_clnt,
@@ -3178,14 +3293,25 @@ static int __qseecom_update_cmd_buf(void *msg, bool cleanup,
ihandle, NULL, len,
ION_IOC_CLEAN_INV_CACHES);
if (data->type == QSEECOM_CLIENT_APP) {
+ offset = req->ifd_data[i].cmd_buf_offset;
data->sglistinfo_ptr[i].indexAndFlags =
SGLISTINFO_SET_INDEX_FLAG(
- (sg_ptr->nents == 1), 0,
- req->ifd_data[i].cmd_buf_offset);
+ (sg_ptr->nents == 1), 0, offset);
data->sglistinfo_ptr[i].sizeOrCount =
(sg_ptr->nents == 1) ?
sg->length : sg_ptr->nents;
data->sglist_cnt = i + 1;
+ } else {
+ offset = (lstnr_resp->ifd_data[i].cmd_buf_offset
+ + (uintptr_t)lstnr_resp->resp_buf_ptr -
+ (uintptr_t)this_lstnr->sb_virt);
+ this_lstnr->sglistinfo_ptr[i].indexAndFlags =
+ SGLISTINFO_SET_INDEX_FLAG(
+ (sg_ptr->nents == 1), 0, offset);
+ this_lstnr->sglistinfo_ptr[i].sizeOrCount =
+ (sg_ptr->nents == 1) ?
+ sg->length : sg_ptr->nents;
+ this_lstnr->sglist_cnt = i + 1;
}
}
/* Deallocate the handle */
@@ -3258,6 +3384,8 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup,
struct qseecom_send_modfd_cmd_req *req = NULL;
struct qseecom_send_modfd_listener_resp *lstnr_resp = NULL;
struct qseecom_registered_listener_list *this_lstnr = NULL;
+ uint32_t offset;
+ struct sg_table *sg_ptr;
if ((data->type != QSEECOM_LISTENER_SERVICE) &&
(data->type != QSEECOM_CLIENT_APP))
@@ -3279,7 +3407,6 @@ static int __qseecom_update_cmd_buf_64(void *msg, bool cleanup,
}
for (i = 0; i < MAX_ION_FD; i++) {
- struct sg_table *sg_ptr = NULL;
if ((data->type != QSEECOM_LISTENER_SERVICE) &&
(req->ifd_data[i].fd > 0)) {
ihandle = ion_import_dma_buf(qseecom.ion_clnt,
@@ -3396,14 +3523,25 @@ cleanup:
ihandle, NULL, len,
ION_IOC_CLEAN_INV_CACHES);
if (data->type == QSEECOM_CLIENT_APP) {
+ offset = req->ifd_data[i].cmd_buf_offset;
data->sglistinfo_ptr[i].indexAndFlags =
SGLISTINFO_SET_INDEX_FLAG(
- (sg_ptr->nents == 1), 1,
- req->ifd_data[i].cmd_buf_offset);
+ (sg_ptr->nents == 1), 1, offset);
data->sglistinfo_ptr[i].sizeOrCount =
(sg_ptr->nents == 1) ?
sg->length : sg_ptr->nents;
data->sglist_cnt = i + 1;
+ } else {
+ offset = (lstnr_resp->ifd_data[i].cmd_buf_offset
+ + (uintptr_t)lstnr_resp->resp_buf_ptr -
+ (uintptr_t)this_lstnr->sb_virt);
+ this_lstnr->sglistinfo_ptr[i].indexAndFlags =
+ SGLISTINFO_SET_INDEX_FLAG(
+ (sg_ptr->nents == 1), 1, offset);
+ this_lstnr->sglistinfo_ptr[i].sizeOrCount =
+ (sg_ptr->nents == 1) ?
+ sg->length : sg_ptr->nents;
+ this_lstnr->sglist_cnt = i + 1;
}
}
/* Deallocate the handle */
@@ -4122,21 +4260,12 @@ int qseecom_start_app(struct qseecom_handle **handle,
data->client.user_virt_sb_base = 0;
data->client.ihandle = NULL;
- /* Allocate sglistinfo buffer for kernel client */
- data->sglistinfo_ptr = kzalloc(SGLISTINFO_TABLE_SIZE, GFP_KERNEL);
- if (!(data->sglistinfo_ptr)) {
- kfree(data);
- kfree(*handle);
- *handle = NULL;
- return -ENOMEM;
- }
init_waitqueue_head(&data->abort_wq);
data->client.ihandle = ion_alloc(qseecom.ion_clnt, size, 4096,
ION_HEAP(ION_QSECOM_HEAP_ID), 0);
if (IS_ERR_OR_NULL(data->client.ihandle)) {
pr_err("Ion client could not retrieve the handle\n");
- kfree(data->sglistinfo_ptr);
kfree(data);
kfree(*handle);
*handle = NULL;
@@ -4239,7 +4368,6 @@ int qseecom_start_app(struct qseecom_handle **handle,
return 0;
err:
- kfree(data->sglistinfo_ptr);
kfree(data);
kfree(*handle);
*handle = NULL;
@@ -4287,7 +4415,6 @@ int qseecom_shutdown_app(struct qseecom_handle **handle)
mutex_unlock(&app_access_lock);
if (ret == 0) {
- kzfree(data->sglistinfo_ptr);
kzfree(data);
kzfree(*handle);
kzfree(kclient);
@@ -4353,8 +4480,11 @@ int qseecom_send_command(struct qseecom_handle *handle, void *send_buf,
}
perf_enabled = true;
}
+ if (!strcmp(data->client.app_name, "securemm"))
+ data->use_legacy_cmd = true;
ret = __qseecom_send_cmd(data, &req);
+ data->use_legacy_cmd = false;
if (qseecom.support_bus_scaling)
__qseecom_add_bw_scale_down_timer(
QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
@@ -7030,6 +7160,7 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg)
wake_up_all(&data->abort_wq);
if (ret)
pr_err("failed qseecom_send_mod_resp: %d\n", ret);
+ __qseecom_clean_data_sglistinfo(data);
break;
}
case QSEECOM_QTEEC_IOCTL_OPEN_SESSION_REQ: {
@@ -7179,12 +7310,6 @@ static int qseecom_open(struct inode *inode, struct file *file)
data->mode = INACTIVE;
init_waitqueue_head(&data->abort_wq);
atomic_set(&data->ioctl_count, 0);
-
- data->sglistinfo_ptr = kzalloc(SGLISTINFO_TABLE_SIZE, GFP_KERNEL);
- if (!(data->sglistinfo_ptr)) {
- kzfree(data);
- return -ENOMEM;
- }
return ret;
}
@@ -7239,7 +7364,6 @@ static int qseecom_release(struct inode *inode, struct file *file)
if (data->perf_enabled == true)
qsee_disable_clock_vote(data, CLK_DFAB);
}
- kfree(data->sglistinfo_ptr);
kfree(data);
return ret;
@@ -7988,73 +8112,14 @@ out:
}
/*
- * Check if whitelist feature is supported by making a test scm_call
- * to send a whitelist command to an invalid app ID 0
+ * Check whitelist feature, and if TZ feature version is < 1.0.0,
+ * then whitelist feature is not supported.
*/
static int qseecom_check_whitelist_feature(void)
{
- struct qseecom_client_send_data_ireq send_data_req = {0};
- struct qseecom_client_send_data_64bit_ireq send_data_req_64bit = {0};
- struct qseecom_command_scm_resp resp;
- uint32_t buf_size = 128;
- void *buf = NULL;
- void *cmd_buf = NULL;
- size_t cmd_len;
- int ret = 0;
- phys_addr_t pa;
+ int version = scm_get_feat_version(FEATURE_ID_WHITELIST);
- buf = kzalloc(buf_size, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- pa = virt_to_phys(buf);
- if (qseecom.qsee_version < QSEE_VERSION_40) {
- send_data_req.qsee_cmd_id =
- QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST;
- send_data_req.app_id = 0;
- send_data_req.req_ptr = (uint32_t)pa;
- send_data_req.req_len = buf_size;
- send_data_req.rsp_ptr = (uint32_t)pa;
- send_data_req.rsp_len = buf_size;
- send_data_req.sglistinfo_ptr = (uint32_t)pa;
- send_data_req.sglistinfo_len = buf_size;
- cmd_buf = (void *)&send_data_req;
- cmd_len = sizeof(struct qseecom_client_send_data_ireq);
- } else {
- send_data_req_64bit.qsee_cmd_id =
- QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST;
- send_data_req_64bit.app_id = 0;
- send_data_req_64bit.req_ptr = (uint64_t)pa;
- send_data_req_64bit.req_len = buf_size;
- send_data_req_64bit.rsp_ptr = (uint64_t)pa;
- send_data_req_64bit.rsp_len = buf_size;
- send_data_req_64bit.sglistinfo_ptr = (uint64_t)pa;
- send_data_req_64bit.sglistinfo_len = buf_size;
- cmd_buf = (void *)&send_data_req_64bit;
- cmd_len = sizeof(struct qseecom_client_send_data_64bit_ireq);
- }
- ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
- cmd_buf, cmd_len,
- &resp, sizeof(resp));
-/*
- * If this cmd exists and whitelist is supported, scm_call return -2 (scm
- * driver remap it to -EINVAL) and resp.result 0xFFFFFFED(-19); Otherwise,
- * scm_call return -1 (remap to -EIO).
- */
- if (ret == -EIO) {
- qseecom.whitelist_support = false;
- ret = 0;
- } else if (ret == -EINVAL &&
- resp.result == QSEOS_RESULT_FAIL_SEND_CMD_NO_THREAD) {
- qseecom.whitelist_support = true;
- ret = 0;
- } else {
- pr_info("Check whitelist with ret = %d, result = 0x%x\n",
- ret, resp.result);
- qseecom.whitelist_support = false;
- ret = 0;
- }
- kfree(buf);
- return ret;
+ return version >= MAKE_WHITELIST_VERSION(1, 0, 0);
}
static int qseecom_probe(struct platform_device *pdev)
@@ -8305,11 +8370,7 @@ static int qseecom_probe(struct platform_device *pdev)
qseecom.qsee_perf_client = msm_bus_scale_register_client(
qseecom_platform_support);
- rc = qseecom_check_whitelist_feature();
- if (rc) {
- rc = -EINVAL;
- goto exit_destroy_ion_client;
- }
+ qseecom.whitelist_support = qseecom_check_whitelist_feature();
pr_warn("qseecom.whitelist_support = %d\n",
qseecom.whitelist_support);
diff --git a/drivers/misc/uid_stat.c b/drivers/misc/uid_stat.c
deleted file mode 100644
index 185c69c9738a..000000000000
--- a/drivers/misc/uid_stat.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/* drivers/misc/uid_stat.c
- *
- * Copyright (C) 2008 - 2009 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/atomic.h>
-
-#include <linux/err.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/stat.h>
-#include <linux/uid_stat.h>
-#include <net/activity_stats.h>
-
-static DEFINE_SPINLOCK(uid_lock);
-static LIST_HEAD(uid_list);
-static struct proc_dir_entry *parent;
-
-struct uid_stat {
- struct list_head link;
- uid_t uid;
- atomic_t tcp_rcv;
- atomic_t tcp_snd;
-};
-
-static struct uid_stat *find_uid_stat(uid_t uid) {
- struct uid_stat *entry;
-
- list_for_each_entry(entry, &uid_list, link) {
- if (entry->uid == uid) {
- return entry;
- }
- }
- return NULL;
-}
-
-static int uid_stat_atomic_int_show(struct seq_file *m, void *v)
-{
- unsigned int bytes;
- atomic_t *counter = m->private;
-
- bytes = (unsigned int) (atomic_read(counter) + INT_MIN);
- seq_printf(m, "%u\n", bytes);
- return seq_has_overflowed(m) ? -ENOSPC : 0;
-}
-
-static int uid_stat_read_atomic_int_open(struct inode *inode, struct file *file)
-{
- return single_open(file, uid_stat_atomic_int_show, PDE_DATA(inode));
-}
-
-static const struct file_operations uid_stat_read_atomic_int_fops = {
- .open = uid_stat_read_atomic_int_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-/* Create a new entry for tracking the specified uid. */
-static struct uid_stat *create_stat(uid_t uid) {
- struct uid_stat *new_uid;
- /* Create the uid stat struct and append it to the list. */
- new_uid = kmalloc(sizeof(struct uid_stat), GFP_ATOMIC);
- if (!new_uid)
- return NULL;
-
- new_uid->uid = uid;
- /* Counters start at INT_MIN, so we can track 4GB of network traffic. */
- atomic_set(&new_uid->tcp_rcv, INT_MIN);
- atomic_set(&new_uid->tcp_snd, INT_MIN);
-
- list_add_tail(&new_uid->link, &uid_list);
- return new_uid;
-}
-
-static void create_stat_proc(struct uid_stat *new_uid)
-{
- char uid_s[32];
- struct proc_dir_entry *entry;
- sprintf(uid_s, "%d", new_uid->uid);
- entry = proc_mkdir(uid_s, parent);
-
- /* Keep reference to uid_stat so we know what uid to read stats from. */
- proc_create_data("tcp_snd", S_IRUGO, entry,
- &uid_stat_read_atomic_int_fops, &new_uid->tcp_snd);
-
- proc_create_data("tcp_rcv", S_IRUGO, entry,
- &uid_stat_read_atomic_int_fops, &new_uid->tcp_rcv);
-}
-
-static struct uid_stat *find_or_create_uid_stat(uid_t uid)
-{
- struct uid_stat *entry;
- unsigned long flags;
- spin_lock_irqsave(&uid_lock, flags);
- entry = find_uid_stat(uid);
- if (entry) {
- spin_unlock_irqrestore(&uid_lock, flags);
- return entry;
- }
- entry = create_stat(uid);
- spin_unlock_irqrestore(&uid_lock, flags);
- if (entry)
- create_stat_proc(entry);
- return entry;
-}
-
-int uid_stat_tcp_snd(uid_t uid, int size) {
- struct uid_stat *entry;
- activity_stats_update();
- entry = find_or_create_uid_stat(uid);
- if (!entry)
- return -1;
- atomic_add(size, &entry->tcp_snd);
- return 0;
-}
-
-int uid_stat_tcp_rcv(uid_t uid, int size) {
- struct uid_stat *entry;
- activity_stats_update();
- entry = find_or_create_uid_stat(uid);
- if (!entry)
- return -1;
- atomic_add(size, &entry->tcp_rcv);
- return 0;
-}
-
-static int __init uid_stat_init(void)
-{
- parent = proc_mkdir("uid_stat", NULL);
- if (!parent) {
- pr_err("uid_stat: failed to create proc entry\n");
- return -1;
- }
- return 0;
-}
-
-__initcall(uid_stat_init);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 7547463928d6..6eee4aa0e574 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -4407,11 +4407,12 @@ static const struct mmc_fixup blk_fixups[] =
add_quirk_mmc, MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD),
/*
- * Some Micron MMC cards needs longer data read timeout than
- * indicated in CSD.
+ * Some MMC cards need longer data read timeout than indicated in CSD.
*/
MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc,
MMC_QUIRK_LONG_READ_TIME),
+ MMC_FIXUP("008GE0", CID_MANFID_TOSHIBA, CID_OEMID_ANY, add_quirk_mmc,
+ MMC_QUIRK_LONG_READ_TIME),
/*
* Some Samsung MMC cards need longer data read timeout than
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 3762f698e1ee..828d2b85f6e4 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1970,7 +1970,7 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
/*
* Some cards require longer data read timeout than indicated in CSD.
* Address this by setting the read timeout to a "reasonably high"
- * value. For the cards tested, 300ms has proven enough. If necessary,
+ * value. For the cards tested, 600ms has proven enough. If necessary,
* this value can be increased if other problematic cards require this.
* Certain Hynix 5.x cards giving read timeout even with 300ms.
* Increasing further to max value (4s).
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 5489f243a682..89288bd1eaa4 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -348,6 +348,9 @@ static void mmc_manage_gp_partitions(struct mmc_card *card, u8 *ext_csd)
}
}
+/* Minimum partition switch timeout in milliseconds */
+#define MMC_MIN_PART_SWITCH_TIME 300
+
/*
* Decode extended CSD.
*/
@@ -412,6 +415,10 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
/* EXT_CSD value is in units of 10ms, but we store in ms */
card->ext_csd.part_time = 10 * ext_csd[EXT_CSD_PART_SWITCH_TIME];
+ /* Some eMMC set the value too low so set a minimum */
+ if (card->ext_csd.part_time &&
+ card->ext_csd.part_time < MMC_MIN_PART_SWITCH_TIME)
+ card->ext_csd.part_time = MMC_MIN_PART_SWITCH_TIME;
/* Sleep / awake timeout in 100ns units */
if (sa_shift > 0 && sa_shift <= 0x17)
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index a5cda926d38e..8aea3fa6938b 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -233,7 +233,7 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_emmc = {
.chip = &sdhci_acpi_chip_int,
.caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR |
- MMC_CAP_BUS_WIDTH_TEST | MMC_CAP_WAIT_WHILE_BUSY,
+ MMC_CAP_WAIT_WHILE_BUSY,
.caps2 = MMC_CAP2_HC_ERASE_SZ,
.flags = SDHCI_ACPI_RUNTIME_PM,
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
@@ -248,7 +248,7 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = {
SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.quirks2 = SDHCI_QUIRK2_HOST_OFF_CARD_ON,
.caps = MMC_CAP_NONREMOVABLE | MMC_CAP_POWER_OFF_CARD |
- MMC_CAP_BUS_WIDTH_TEST | MMC_CAP_WAIT_WHILE_BUSY,
+ MMC_CAP_WAIT_WHILE_BUSY,
.flags = SDHCI_ACPI_RUNTIME_PM,
.pm_caps = MMC_PM_KEEP_POWER,
.probe_slot = sdhci_acpi_sdio_probe_slot,
@@ -260,7 +260,7 @@ static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = {
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
.quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON |
SDHCI_QUIRK2_STOP_WITH_TC,
- .caps = MMC_CAP_BUS_WIDTH_TEST | MMC_CAP_WAIT_WHILE_BUSY,
+ .caps = MMC_CAP_WAIT_WHILE_BUSY,
.probe_slot = sdhci_acpi_sd_probe_slot,
};
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 610154836d79..5ebe6eb6b89e 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -361,7 +361,6 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
{
slot->host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE |
MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR |
- MMC_CAP_BUS_WIDTH_TEST |
MMC_CAP_WAIT_WHILE_BUSY;
slot->host->mmc->caps2 |= MMC_CAP2_HC_ERASE_SZ;
slot->hw_reset = sdhci_pci_int_hw_reset;
@@ -377,15 +376,13 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot)
{
slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE |
- MMC_CAP_BUS_WIDTH_TEST |
MMC_CAP_WAIT_WHILE_BUSY;
return 0;
}
static int byt_sd_probe_slot(struct sdhci_pci_slot *slot)
{
- slot->host->mmc->caps |= MMC_CAP_BUS_WIDTH_TEST |
- MMC_CAP_WAIT_WHILE_BUSY;
+ slot->host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
slot->cd_con_id = NULL;
slot->cd_idx = 0;
slot->cd_override_level = true;
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 5b9834cf2820..4dd0391d2942 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -426,8 +426,25 @@ retry:
pnum, vol_id, lnum);
err = -EBADMSG;
} else {
- err = -EINVAL;
- ubi_ro_mode(ubi);
+ /*
+ * Ending up here in the non-Fastmap case
+ * is a clear bug as the VID header had to
+ * be present at scan time to have it referenced.
+ * With fastmap the story is more complicated.
+ * Fastmap has the mapping info without the need
+ * of a full scan. So the LEB could have been
+ * unmapped, Fastmap cannot know this and keeps
+ * the LEB referenced.
+ * This is valid and works as the layer above UBI
+ * has to do bookkeeping about used/referenced
+ * LEBs in any case.
+ */
+ if (ubi->fast_attach) {
+ err = -EBADMSG;
+ } else {
+ err = -EINVAL;
+ ubi_ro_mode(ubi);
+ }
}
}
goto out_free;
@@ -558,6 +575,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum,
int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0;
struct ubi_volume *vol = ubi->volumes[idx];
struct ubi_vid_hdr *vid_hdr;
+ uint32_t crc;
vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
if (!vid_hdr)
@@ -582,14 +600,8 @@ retry:
goto out_put;
}
- vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
- err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
- if (err) {
- up_read(&ubi->fm_eba_sem);
- goto write_error;
- }
+ ubi_assert(vid_hdr->vol_type == UBI_VID_DYNAMIC);
- data_size = offset + len;
mutex_lock(&ubi->buf_mutex);
memset(ubi->peb_buf + offset, 0xFF, len);
@@ -604,6 +616,19 @@ retry:
memcpy(ubi->peb_buf + offset, buf, len);
+ data_size = offset + len;
+ crc = crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size);
+ vid_hdr->sqnum = cpu_to_be64(ubi_next_sqnum(ubi));
+ vid_hdr->copy_flag = 1;
+ vid_hdr->data_size = cpu_to_be32(data_size);
+ vid_hdr->data_crc = cpu_to_be32(crc);
+ err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr);
+ if (err) {
+ mutex_unlock(&ubi->buf_mutex);
+ up_read(&ubi->fm_eba_sem);
+ goto write_error;
+ }
+
err = ubi_io_write_data(ubi, ubi->peb_buf, new_pnum, 0, data_size);
if (err) {
mutex_unlock(&ubi->buf_mutex);
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 263b439e21a8..990898b9dc72 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1058,6 +1058,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
ubi_msg(ubi, "fastmap WL pool size: %d",
ubi->fm_wl_pool.max_size);
ubi->fm_disabled = 0;
+ ubi->fast_attach = 1;
ubi_free_vid_hdr(ubi, vh);
kfree(ech);
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index fdb1931f66ed..bdb885d9d3fc 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -466,6 +466,7 @@ struct ubi_debug_info {
* @fm_eba_sem: allows ubi_update_fastmap() to block EBA table changes
* @fm_work: fastmap work queue
* @fm_work_scheduled: non-zero if fastmap work was scheduled
+ * @fast_attach: non-zero if UBI was attached by fastmap
*
* @used: RB-tree of used physical eraseblocks
* @erroneous: RB-tree of erroneous used physical eraseblocks
@@ -574,6 +575,7 @@ struct ubi_device {
size_t fm_size;
struct work_struct fm_work;
int fm_work_scheduled;
+ int fast_attach;
/* Wear-leveling sub-system's stuff */
struct rb_root used;
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 141c2a42d7ed..910c12e2638e 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -696,11 +696,17 @@ int can_change_mtu(struct net_device *dev, int new_mtu)
/* allow change of MTU according to the CANFD ability of the device */
switch (new_mtu) {
case CAN_MTU:
+ /* 'CANFD-only' controllers can not switch to CAN_MTU */
+ if (priv->ctrlmode_static & CAN_CTRLMODE_FD)
+ return -EINVAL;
+
priv->ctrlmode &= ~CAN_CTRLMODE_FD;
break;
case CANFD_MTU:
- if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD))
+ /* check for potential CANFD ability */
+ if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD) &&
+ !(priv->ctrlmode_static & CAN_CTRLMODE_FD))
return -EINVAL;
priv->ctrlmode |= CAN_CTRLMODE_FD;
@@ -782,6 +788,35 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
= { .len = sizeof(struct can_bittiming_const) },
};
+static int can_validate(struct nlattr *tb[], struct nlattr *data[])
+{
+ bool is_can_fd = false;
+
+ /* Make sure that valid CAN FD configurations always consist of
+ * - nominal/arbitration bittiming
+ * - data bittiming
+ * - control mode with CAN_CTRLMODE_FD set
+ */
+
+ if (data[IFLA_CAN_CTRLMODE]) {
+ struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
+
+ is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
+ }
+
+ if (is_can_fd) {
+ if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING])
+ return -EOPNOTSUPP;
+ }
+
+ if (data[IFLA_CAN_DATA_BITTIMING]) {
+ if (!is_can_fd || !data[IFLA_CAN_BITTIMING])
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
static int can_changelink(struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
{
@@ -813,19 +848,31 @@ static int can_changelink(struct net_device *dev,
if (data[IFLA_CAN_CTRLMODE]) {
struct can_ctrlmode *cm;
+ u32 ctrlstatic;
+ u32 maskedflags;
/* Do not allow changing controller mode while running */
if (dev->flags & IFF_UP)
return -EBUSY;
cm = nla_data(data[IFLA_CAN_CTRLMODE]);
+ ctrlstatic = priv->ctrlmode_static;
+ maskedflags = cm->flags & cm->mask;
+
+ /* check whether provided bits are allowed to be passed */
+ if (cm->mask & ~(priv->ctrlmode_supported | ctrlstatic))
+ return -EOPNOTSUPP;
+
+ /* do not check for static fd-non-iso if 'fd' is disabled */
+ if (!(maskedflags & CAN_CTRLMODE_FD))
+ ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO;
- /* check whether changed bits are allowed to be modified */
- if (cm->mask & ~priv->ctrlmode_supported)
+ /* make sure static options are provided by configuration */
+ if ((maskedflags & ctrlstatic) != ctrlstatic)
return -EOPNOTSUPP;
/* clear bits to be modified and copy the flag values */
priv->ctrlmode &= ~cm->mask;
- priv->ctrlmode |= (cm->flags & cm->mask);
+ priv->ctrlmode |= maskedflags;
/* CAN_CTRLMODE_FD can only be set when driver supports FD */
if (priv->ctrlmode & CAN_CTRLMODE_FD)
@@ -966,6 +1013,7 @@ static struct rtnl_link_ops can_link_ops __read_mostly = {
.maxtype = IFLA_CAN_MAX,
.policy = can_policy,
.setup = can_setup,
+ .validate = can_validate,
.newlink = can_newlink,
.changelink = can_changelink,
.get_size = can_get_size,
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 39cf911f7a1e..195f15edb32e 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -955,7 +955,7 @@ static struct net_device *alloc_m_can_dev(void)
priv->can.do_get_berr_counter = m_can_get_berr_counter;
/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.1 */
- priv->can.ctrlmode = CAN_CTRLMODE_FD_NON_ISO;
+ can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
/* CAN_CTRLMODE_FD_NON_ISO can not be changed with M_CAN IP v3.0.1 */
priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c
index bd377a6b067d..df54475d163b 100644
--- a/drivers/net/ethernet/atheros/alx/main.c
+++ b/drivers/net/ethernet/atheros/alx/main.c
@@ -86,9 +86,14 @@ static int alx_refill_rx_ring(struct alx_priv *alx, gfp_t gfp)
while (!cur_buf->skb && next != rxq->read_idx) {
struct alx_rfd *rfd = &rxq->rfd[cur];
- skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size, gfp);
+ skb = __netdev_alloc_skb(alx->dev, alx->rxbuf_size + 64, gfp);
if (!skb)
break;
+
+ /* Workround for the HW RX DMA overflow issue */
+ if (((unsigned long)skb->data & 0xfff) == 0xfc0)
+ skb_reserve(skb, 64);
+
dma = dma_map_single(&alx->hw.pdev->dev,
skb->data, alx->rxbuf_size,
DMA_FROM_DEVICE);
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index 169059c92f80..8d54e7b41bbf 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -2405,9 +2405,9 @@ static int macb_init(struct platform_device *pdev)
if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII)
val = GEM_BIT(RGMII);
else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII &&
- (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII))
+ (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII))
val = MACB_BIT(RMII);
- else if (!(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII))
+ else if (!(bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII))
val = MACB_BIT(MII);
if (bp->caps & MACB_CAPS_USRIO_HAS_CLKEN)
@@ -2738,7 +2738,7 @@ static int at91ether_init(struct platform_device *pdev)
}
static const struct macb_config at91sam9260_config = {
- .caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII,
+ .caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
.clk_init = macb_clk_init,
.init = macb_init,
};
@@ -2751,21 +2751,22 @@ static const struct macb_config pc302gem_config = {
};
static const struct macb_config sama5d2_config = {
- .caps = 0,
+ .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
.dma_burst_length = 16,
.clk_init = macb_clk_init,
.init = macb_init,
};
static const struct macb_config sama5d3_config = {
- .caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE,
+ .caps = MACB_CAPS_SG_DISABLED | MACB_CAPS_GIGABIT_MODE_AVAILABLE
+ | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
.dma_burst_length = 16,
.clk_init = macb_clk_init,
.init = macb_init,
};
static const struct macb_config sama5d4_config = {
- .caps = 0,
+ .caps = MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
.dma_burst_length = 4,
.clk_init = macb_clk_init,
.init = macb_init,
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index d83b0db77821..3f385ab94988 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -398,7 +398,7 @@
/* Capability mask bits */
#define MACB_CAPS_ISR_CLEAR_ON_WRITE 0x00000001
#define MACB_CAPS_USRIO_HAS_CLKEN 0x00000002
-#define MACB_CAPS_USRIO_DEFAULT_IS_MII 0x00000004
+#define MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII 0x00000004
#define MACB_CAPS_NO_GIGABIT_HALF 0x00000008
#define MACB_CAPS_FIFO_MODE 0x10000000
#define MACB_CAPS_GIGABIT_MODE_AVAILABLE 0x20000000
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index 2b34622a4bfe..3920c3eb6006 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -4475,7 +4475,7 @@ static int rocker_port_obj_add(struct net_device *dev,
fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj);
err = rocker_port_fib_ipv4(rocker_port, trans,
htonl(fib4->dst), fib4->dst_len,
- &fib4->fi, fib4->tb_id, 0);
+ fib4->fi, fib4->tb_id, 0);
break;
case SWITCHDEV_OBJ_ID_PORT_FDB:
err = rocker_port_fdb_add(rocker_port, trans,
@@ -4547,7 +4547,7 @@ static int rocker_port_obj_del(struct net_device *dev,
fib4 = SWITCHDEV_OBJ_IPV4_FIB(obj);
err = rocker_port_fib_ipv4(rocker_port, NULL,
htonl(fib4->dst), fib4->dst_len,
- &fib4->fi, fib4->tb_id,
+ fib4->fi, fib4->tb_id,
ROCKER_OP_FLAG_REMOVE);
break;
case SWITCHDEV_OBJ_ID_PORT_FDB:
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index e6a084a6be12..cbe9a330117a 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -619,6 +619,17 @@ fail:
return rc;
}
+static void efx_ef10_forget_old_piobufs(struct efx_nic *efx)
+{
+ struct efx_channel *channel;
+ struct efx_tx_queue *tx_queue;
+
+ /* All our existing PIO buffers went away */
+ efx_for_each_channel(channel, efx)
+ efx_for_each_channel_tx_queue(tx_queue, channel)
+ tx_queue->piobuf = NULL;
+}
+
#else /* !EFX_USE_PIO */
static int efx_ef10_alloc_piobufs(struct efx_nic *efx, unsigned int n)
@@ -635,6 +646,10 @@ static void efx_ef10_free_piobufs(struct efx_nic *efx)
{
}
+static void efx_ef10_forget_old_piobufs(struct efx_nic *efx)
+{
+}
+
#endif /* EFX_USE_PIO */
static void efx_ef10_remove(struct efx_nic *efx)
@@ -1018,6 +1033,7 @@ static void efx_ef10_reset_mc_allocations(struct efx_nic *efx)
nic_data->must_realloc_vis = true;
nic_data->must_restore_filters = true;
nic_data->must_restore_piobufs = true;
+ efx_ef10_forget_old_piobufs(efx);
nic_data->rx_rss_context = EFX_EF10_RSS_CONTEXT_INVALID;
/* Driver-created vswitches and vports must be re-created */
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 58efdec12f30..69e31e2a68fc 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -310,15 +310,15 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
/* Need Geneve and inner Ethernet header to be present */
if (unlikely(!pskb_may_pull(skb, GENEVE_BASE_HLEN)))
- goto error;
+ goto drop;
/* Return packets with reserved bits set */
geneveh = geneve_hdr(skb);
if (unlikely(geneveh->ver != GENEVE_VER))
- goto error;
+ goto drop;
if (unlikely(geneveh->proto_type != htons(ETH_P_TEB)))
- goto error;
+ goto drop;
opts_len = geneveh->opt_len * 4;
if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len,
@@ -336,10 +336,6 @@ drop:
/* Consume bad packet */
kfree_skb(skb);
return 0;
-
-error:
- /* Let the UDP layer deal with the skb */
- return 1;
}
static struct socket *geneve_create_sock(struct net *net, bool ipv6,
@@ -998,6 +994,17 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
return geneve_xmit_skb(skb, dev, info);
}
+static int geneve_change_mtu(struct net_device *dev, int new_mtu)
+{
+ /* GENEVE overhead is not fixed, so we can't enforce a more
+ * precise max MTU.
+ */
+ if (new_mtu < 68 || new_mtu > IP_MAX_MTU)
+ return -EINVAL;
+ dev->mtu = new_mtu;
+ return 0;
+}
+
static int geneve_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
{
struct ip_tunnel_info *info = skb_tunnel_info(skb);
@@ -1042,7 +1049,7 @@ static const struct net_device_ops geneve_netdev_ops = {
.ndo_stop = geneve_stop,
.ndo_start_xmit = geneve_xmit,
.ndo_get_stats64 = ip_tunnel_get_stats64,
- .ndo_change_mtu = eth_change_mtu,
+ .ndo_change_mtu = geneve_change_mtu,
.ndo_validate_addr = eth_validate_addr,
.ndo_set_mac_address = eth_mac_addr,
.ndo_fill_metadata_dst = geneve_fill_metadata_dst,
@@ -1349,11 +1356,21 @@ struct net_device *geneve_dev_create_fb(struct net *net, const char *name,
err = geneve_configure(net, dev, &geneve_remote_unspec,
0, 0, 0, htons(dst_port), true);
- if (err) {
- free_netdev(dev);
- return ERR_PTR(err);
- }
+ if (err)
+ goto err;
+
+ /* openvswitch users expect packet sizes to be unrestricted,
+ * so set the largest MTU we can.
+ */
+ err = geneve_change_mtu(dev, IP_MAX_MTU);
+ if (err)
+ goto err;
+
return dev;
+
+ err:
+ free_netdev(dev);
+ return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(geneve_dev_create_fb);
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 59fefca74263..a5f392ae30d5 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -969,7 +969,7 @@ static void team_port_disable(struct team *team,
NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
NETIF_F_HIGHDMA | NETIF_F_LRO)
-static void __team_compute_features(struct team *team)
+static void ___team_compute_features(struct team *team)
{
struct team_port *port;
u32 vlan_features = TEAM_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL;
@@ -993,15 +993,20 @@ static void __team_compute_features(struct team *team)
team->dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
if (dst_release_flag == (IFF_XMIT_DST_RELEASE | IFF_XMIT_DST_RELEASE_PERM))
team->dev->priv_flags |= IFF_XMIT_DST_RELEASE;
+}
+static void __team_compute_features(struct team *team)
+{
+ ___team_compute_features(team);
netdev_change_features(team->dev);
}
static void team_compute_features(struct team *team)
{
mutex_lock(&team->lock);
- __team_compute_features(team);
+ ___team_compute_features(team);
mutex_unlock(&team->lock);
+ netdev_change_features(team->dev);
}
static int team_port_enter(struct team *team, struct team_port *port)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 4b15d9ee5a54..935e0b45e151 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -567,11 +567,13 @@ static void tun_detach_all(struct net_device *dev)
for (i = 0; i < n; i++) {
tfile = rtnl_dereference(tun->tfiles[i]);
BUG_ON(!tfile);
+ tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN;
tfile->socket.sk->sk_data_ready(tfile->socket.sk);
RCU_INIT_POINTER(tfile->tun, NULL);
--tun->numqueues;
}
list_for_each_entry(tfile, &tun->disabled, next) {
+ tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN;
tfile->socket.sk->sk_data_ready(tfile->socket.sk);
RCU_INIT_POINTER(tfile->tun, NULL);
}
@@ -627,6 +629,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filte
goto out;
}
tfile->queue_index = tun->numqueues;
+ tfile->socket.sk->sk_shutdown &= ~RCV_SHUTDOWN;
rcu_assign_pointer(tfile->tun, tun);
rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
tun->numqueues++;
@@ -1412,9 +1415,6 @@ static ssize_t tun_do_read(struct tun_struct *tun, struct tun_file *tfile,
if (!iov_iter_count(to))
return 0;
- if (tun->dev->reg_state != NETREG_REGISTERED)
- return -EIO;
-
/* Read frames from queue */
skb = __skb_recv_datagram(tfile->socket.sk, noblock ? MSG_DONTWAIT : 0,
&peeked, &off, &err);
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index bd9acff1eb7b..7fbd8f044207 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -66,7 +66,7 @@ int asix_rx_fixup_internal(struct usbnet *dev, struct sk_buff *skb,
* buffer.
*/
if (rx->remaining && (rx->remaining + sizeof(u32) <= skb->len)) {
- offset = ((rx->remaining + 1) & 0xfffe) + sizeof(u32);
+ offset = ((rx->remaining + 1) & 0xfffe);
rx->header = get_unaligned_le32(skb->data + offset);
offset = 0;
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index b11fe09552bf..e0e94b855bbe 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -809,6 +809,13 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_
if (cdc_ncm_init(dev))
goto error2;
+ /* Some firmwares need a pause here or they will silently fail
+ * to set up the interface properly. This value was decided
+ * empirically on a Sierra Wireless MC7455 running 02.08.02.00
+ * firmware.
+ */
+ usleep_range(10000, 20000);
+
/* configure data interface */
temp = usb_set_interface(dev->udev, iface_no, data_altsetting);
if (temp) {
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 3c0df70e2f53..003780901628 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -1254,7 +1254,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
/* Need Vxlan and inner Ethernet header to be present */
if (!pskb_may_pull(skb, VXLAN_HLEN))
- goto error;
+ goto drop;
vxh = (struct vxlanhdr *)(udp_hdr(skb) + 1);
flags = ntohl(vxh->vx_flags);
@@ -1344,13 +1344,7 @@ drop:
bad_flags:
netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n",
ntohl(vxh->vx_flags), ntohl(vxh->vx_vni));
-
-error:
- if (tun_dst)
- dst_release((struct dst_entry *)tun_dst);
-
- /* Return non vxlan pkt */
- return 1;
+ goto drop;
}
static int arp_reduce(struct net_device *dev, struct sk_buff *skb)
@@ -2370,29 +2364,43 @@ static void vxlan_set_multicast_list(struct net_device *dev)
{
}
-static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
+static int __vxlan_change_mtu(struct net_device *dev,
+ struct net_device *lowerdev,
+ struct vxlan_rdst *dst, int new_mtu, bool strict)
{
- struct vxlan_dev *vxlan = netdev_priv(dev);
- struct vxlan_rdst *dst = &vxlan->default_dst;
- struct net_device *lowerdev;
- int max_mtu;
+ int max_mtu = IP_MAX_MTU;
- lowerdev = __dev_get_by_index(vxlan->net, dst->remote_ifindex);
- if (lowerdev == NULL)
- return eth_change_mtu(dev, new_mtu);
+ if (lowerdev)
+ max_mtu = lowerdev->mtu;
if (dst->remote_ip.sa.sa_family == AF_INET6)
- max_mtu = lowerdev->mtu - VXLAN6_HEADROOM;
+ max_mtu -= VXLAN6_HEADROOM;
else
- max_mtu = lowerdev->mtu - VXLAN_HEADROOM;
+ max_mtu -= VXLAN_HEADROOM;
- if (new_mtu < 68 || new_mtu > max_mtu)
+ if (new_mtu < 68)
return -EINVAL;
+ if (new_mtu > max_mtu) {
+ if (strict)
+ return -EINVAL;
+
+ new_mtu = max_mtu;
+ }
+
dev->mtu = new_mtu;
return 0;
}
+static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct vxlan_dev *vxlan = netdev_priv(dev);
+ struct vxlan_rdst *dst = &vxlan->default_dst;
+ struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
+ dst->remote_ifindex);
+ return __vxlan_change_mtu(dev, lowerdev, dst, new_mtu, true);
+}
+
static int egress_ipv4_tun_info(struct net_device *dev, struct sk_buff *skb,
struct ip_tunnel_info *info,
__be16 sport, __be16 dport)
@@ -2768,6 +2776,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
int err;
bool use_ipv6 = false;
__be16 default_port = vxlan->cfg.dst_port;
+ struct net_device *lowerdev = NULL;
vxlan->net = src_net;
@@ -2788,9 +2797,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
}
if (conf->remote_ifindex) {
- struct net_device *lowerdev
- = __dev_get_by_index(src_net, conf->remote_ifindex);
-
+ lowerdev = __dev_get_by_index(src_net, conf->remote_ifindex);
dst->remote_ifindex = conf->remote_ifindex;
if (!lowerdev) {
@@ -2814,6 +2821,12 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
needed_headroom = lowerdev->hard_header_len;
}
+ if (conf->mtu) {
+ err = __vxlan_change_mtu(dev, lowerdev, dst, conf->mtu, false);
+ if (err)
+ return err;
+ }
+
if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA)
needed_headroom += VXLAN6_HEADROOM;
else
@@ -2991,6 +3004,9 @@ static int vxlan_newlink(struct net *src_net, struct net_device *dev,
if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL])
conf.flags |= VXLAN_F_REMCSUM_NOPARTIAL;
+ if (tb[IFLA_MTU])
+ conf.mtu = nla_get_u32(tb[IFLA_MTU]);
+
err = vxlan_dev_configure(src_net, dev, &conf);
switch (err) {
case -ENODEV:
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 0947cc271e69..531de256d58d 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1681,6 +1681,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
goto err_hif_stop;
}
+ ar->free_vdev_map = (1LL << ar->max_num_vdevs) - 1;
+
+ INIT_LIST_HEAD(&ar->arvifs);
+
/* we don't care about HTT in UTF mode */
if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
status = ath10k_htt_setup(&ar->htt);
@@ -1694,10 +1698,6 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
if (status)
goto err_hif_stop;
- ar->free_vdev_map = (1LL << ar->max_num_vdevs) - 1;
-
- INIT_LIST_HEAD(&ar->arvifs);
-
return 0;
err_hif_stop:
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 6cc1aa3449c8..1a88a24ffeac 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1986,7 +1986,12 @@ static ssize_t ath10k_write_pktlog_filter(struct file *file,
goto out;
}
- if (filter && (filter != ar->debug.pktlog_filter)) {
+ if (filter == ar->debug.pktlog_filter) {
+ ret = count;
+ goto out;
+ }
+
+ if (filter) {
ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
if (ret) {
ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 95a55405ebf0..1e1bef349487 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4456,7 +4456,10 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
goto err_vdev_delete;
}
- if (ar->cfg_tx_chainmask) {
+ /* Configuring number of spatial stream for monitor interface is causing
+ * target assert in qca9888 and qca6174.
+ */
+ if (ar->cfg_tx_chainmask && (vif->type != NL80211_IFTYPE_MONITOR)) {
u16 nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
vdev_param = ar->wmi.vdev_param->nss;
@@ -6416,7 +6419,13 @@ ath10k_mac_update_rx_channel(struct ath10k *ar,
def = &vifs[0].new_ctx->def;
ar->rx_channel = def->chan;
- } else if (ctx && ath10k_mac_num_chanctxs(ar) == 0) {
+ } else if ((ctx && ath10k_mac_num_chanctxs(ar) == 0) ||
+ (ctx && (ar->state == ATH10K_STATE_RESTARTED))) {
+ /* During driver restart due to firmware assert, since mac80211
+ * already has valid channel context for given radio, channel
+ * context iteration return num_chanctx > 0. So fix rx_channel
+ * when restart is in progress.
+ */
ar->rx_channel = ctx->def.chan;
} else {
ar->rx_channel = NULL;
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 803030fd17d3..6a2a16856763 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -77,7 +77,7 @@ static const struct pci_device_id ath5k_led_devices[] = {
/* HP Compaq CQ60-206US (ddreggors@jumptv.com) */
{ ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) },
/* HP Compaq C700 (nitrousnrg@gmail.com) */
- { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) },
+ { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 0) },
/* LiteOn AR5BXB63 (magooz@salug.it) */
{ ATH_SDEVICE(PCI_VENDOR_ID_ATHEROS, 0x3067), ATH_LED(3, 0) },
/* IBM-specific AR5212 (all others) */
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 2e2b92ba96b8..1bdeacf7b257 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -49,6 +49,10 @@ int ath9k_led_blink;
module_param_named(blink, ath9k_led_blink, int, 0444);
MODULE_PARM_DESC(blink, "Enable LED blink on activity");
+static int ath9k_led_active_high = -1;
+module_param_named(led_active_high, ath9k_led_active_high, int, 0444);
+MODULE_PARM_DESC(led_active_high, "Invert LED polarity");
+
static int ath9k_btcoex_enable;
module_param_named(btcoex_enable, ath9k_btcoex_enable, int, 0444);
MODULE_PARM_DESC(btcoex_enable, "Enable wifi-BT coexistence");
@@ -600,6 +604,9 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
if (ret)
return ret;
+ if (ath9k_led_active_high != -1)
+ ah->config.led_active_high = ath9k_led_active_high == 1;
+
/*
* Enable WLAN/BT RX Antenna diversity only when:
*
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index e6fef1be9977..7cdaf40c3057 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -28,6 +28,16 @@ static const struct pci_device_id ath_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
+
+#ifdef CONFIG_ATH9K_PCOEM
+ /* Mini PCI AR9220 MB92 cards: Compex WLM200NX, Wistron DNMA-92 */
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
+ 0x0029,
+ PCI_VENDOR_ID_ATHEROS,
+ 0x2096),
+ .driver_data = ATH9K_PCI_LED_ACT_HI },
+#endif
+
{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
#ifdef CONFIG_ATH9K_PCOEM
diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c
index 5ca0307a3274..b9faae0278c9 100644
--- a/drivers/net/wireless/ath/wil6210/pmc.c
+++ b/drivers/net/wireless/ath/wil6210/pmc.c
@@ -54,6 +54,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
struct pmc_ctx *pmc = &wil->pmc;
struct device *dev = wil_to_dev(wil);
struct wmi_pmc_cmd pmc_cmd = {0};
+ int last_cmd_err = -ENOMEM;
mutex_lock(&pmc->lock);
@@ -62,6 +63,29 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
wil_err(wil, "%s: ERROR pmc is already allocated\n", __func__);
goto no_release_err;
}
+ if ((num_descriptors <= 0) || (descriptor_size <= 0)) {
+ wil_err(wil,
+ "Invalid params num_descriptors(%d), descriptor_size(%d)\n",
+ num_descriptors, descriptor_size);
+ last_cmd_err = -EINVAL;
+ goto no_release_err;
+ }
+
+ if (num_descriptors > (1 << WIL_RING_SIZE_ORDER_MAX)) {
+ wil_err(wil,
+ "num_descriptors(%d) exceeds max ring size %d\n",
+ num_descriptors, 1 << WIL_RING_SIZE_ORDER_MAX);
+ last_cmd_err = -EINVAL;
+ goto no_release_err;
+ }
+
+ if (num_descriptors > INT_MAX / descriptor_size) {
+ wil_err(wil,
+ "Overflow in num_descriptors(%d)*descriptor_size(%d)\n",
+ num_descriptors, descriptor_size);
+ last_cmd_err = -EINVAL;
+ goto no_release_err;
+ }
pmc->num_descriptors = num_descriptors;
pmc->descriptor_size = descriptor_size;
@@ -189,7 +213,7 @@ release_pmc_skb_list:
pmc->descriptors = NULL;
no_release_err:
- pmc->last_cmd_status = -ENOMEM;
+ pmc->last_cmd_status = last_cmd_err;
mutex_unlock(&pmc->lock);
}
@@ -295,7 +319,7 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count,
size_t retval = 0;
unsigned long long idx;
loff_t offset;
- size_t pmc_size = pmc->descriptor_size * pmc->num_descriptors;
+ size_t pmc_size;
mutex_lock(&pmc->lock);
@@ -306,6 +330,8 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count,
return -EPERM;
}
+ pmc_size = pmc->descriptor_size * pmc->num_descriptors;
+
wil_dbg_misc(wil,
"%s: size %u, pos %lld\n",
__func__, (unsigned)count, *f_pos);
@@ -345,7 +371,18 @@ loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence)
loff_t newpos;
struct wil6210_priv *wil = filp->private_data;
struct pmc_ctx *pmc = &wil->pmc;
- size_t pmc_size = pmc->descriptor_size * pmc->num_descriptors;
+ size_t pmc_size;
+
+ mutex_lock(&pmc->lock);
+
+ if (!wil_is_pmc_allocated(pmc)) {
+ wil_err(wil, "error, pmc is not allocated!\n");
+ pmc->last_cmd_status = -EPERM;
+ mutex_unlock(&pmc->lock);
+ return -EPERM;
+ }
+
+ pmc_size = pmc->descriptor_size * pmc->num_descriptors;
switch (whence) {
case 0: /* SEEK_SET */
@@ -361,15 +398,21 @@ loff_t wil_pmc_llseek(struct file *filp, loff_t off, int whence)
break;
default: /* can't happen */
- return -EINVAL;
+ newpos = -EINVAL;
+ goto out;
}
- if (newpos < 0)
- return -EINVAL;
+ if (newpos < 0) {
+ newpos = -EINVAL;
+ goto out;
+ }
if (newpos > pmc_size)
newpos = pmc_size;
filp->f_pos = newpos;
+out:
+ mutex_unlock(&pmc->lock);
+
return newpos;
}
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index c00a7daaa4bc..0cd95120bc78 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2723,6 +2723,7 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
if (!info->attrs[HWSIM_ATTR_ADDR_TRANSMITTER] ||
!info->attrs[HWSIM_ATTR_FLAGS] ||
!info->attrs[HWSIM_ATTR_COOKIE] ||
+ !info->attrs[HWSIM_ATTR_SIGNAL] ||
!info->attrs[HWSIM_ATTR_TX_INFO])
goto out;
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index 0517a4f2d3f2..7a40d8dffa36 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -1660,9 +1660,9 @@ void rtl_watchdog_wq_callback(void *data)
if (((rtlpriv->link_info.num_rx_inperiod +
rtlpriv->link_info.num_tx_inperiod) > 8) ||
(rtlpriv->link_info.num_rx_inperiod > 2))
- rtl_lps_enter(hw);
- else
rtl_lps_leave(hw);
+ else
+ rtl_lps_enter(hw);
}
rtlpriv->link_info.num_rx_inperiod = 0;
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
index f2b9d11adc9e..e85f1652ce55 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
@@ -1203,7 +1203,6 @@ static void btc8723b2ant_set_ant_path(struct btc_coexist *btcoexist,
/* Force GNT_BT to low */
btcoexist->btc_write_1byte_bitmask(btcoexist, 0x765, 0x18, 0x0);
- btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT) {
/* tell firmware "no antenna inverse" */
@@ -1211,19 +1210,25 @@ static void btc8723b2ant_set_ant_path(struct btc_coexist *btcoexist,
h2c_parameter[1] = 1; /* ext switch type */
btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
h2c_parameter);
+ btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
} else {
/* tell firmware "antenna inverse" */
h2c_parameter[0] = 1;
h2c_parameter[1] = 1; /* ext switch type */
btcoexist->btc_fill_h2c(btcoexist, 0x65, 2,
h2c_parameter);
+ btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280);
}
}
/* ext switch setting */
if (use_ext_switch) {
/* fixed internal switch S1->WiFi, S0->BT */
- btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
+ if (board_info->btdm_ant_pos == BTC_ANTENNA_AT_MAIN_PORT)
+ btcoexist->btc_write_2byte(btcoexist, 0x948, 0x0);
+ else
+ btcoexist->btc_write_2byte(btcoexist, 0x948, 0x280);
+
switch (antpos_type) {
case BTC_ANT_WIFI_AT_MAIN:
/* ext switch main at wifi */
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
index b2791c893417..babd1490f20c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c
@@ -965,13 +965,38 @@ void exhalbtc_set_chip_type(u8 chip_type)
}
}
-void exhalbtc_set_ant_num(u8 type, u8 ant_num)
+void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num)
{
if (BT_COEX_ANT_TYPE_PG == type) {
gl_bt_coexist.board_info.pg_ant_num = ant_num;
gl_bt_coexist.board_info.btdm_ant_num = ant_num;
+ /* The antenna position:
+ * Main (default) or Aux for pgAntNum=2 && btdmAntNum =1.
+ * The antenna position should be determined by
+ * auto-detect mechanism.
+ * The following is assumed to main,
+ * and those must be modified
+ * if y auto-detect mechanism is ready
+ */
+ if ((gl_bt_coexist.board_info.pg_ant_num == 2) &&
+ (gl_bt_coexist.board_info.btdm_ant_num == 1))
+ gl_bt_coexist.board_info.btdm_ant_pos =
+ BTC_ANTENNA_AT_MAIN_PORT;
+ else
+ gl_bt_coexist.board_info.btdm_ant_pos =
+ BTC_ANTENNA_AT_MAIN_PORT;
} else if (BT_COEX_ANT_TYPE_ANTDIV == type) {
gl_bt_coexist.board_info.btdm_ant_num = ant_num;
+ gl_bt_coexist.board_info.btdm_ant_pos =
+ BTC_ANTENNA_AT_MAIN_PORT;
+ } else if (type == BT_COEX_ANT_TYPE_DETECTED) {
+ gl_bt_coexist.board_info.btdm_ant_num = ant_num;
+ if (rtlpriv->cfg->mod_params->ant_sel == 1)
+ gl_bt_coexist.board_info.btdm_ant_pos =
+ BTC_ANTENNA_AT_AUX_PORT;
+ else
+ gl_bt_coexist.board_info.btdm_ant_pos =
+ BTC_ANTENNA_AT_MAIN_PORT;
}
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
index 0a903ea179ef..f41ca57dd8a7 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h
@@ -535,7 +535,7 @@ void exhalbtc_set_bt_patch_version(u16 bt_hci_version, u16 bt_patch_version);
void exhalbtc_update_min_bt_rssi(char bt_rssi);
void exhalbtc_set_bt_exist(bool bt_exist);
void exhalbtc_set_chip_type(u8 chip_type);
-void exhalbtc_set_ant_num(u8 type, u8 ant_num);
+void exhalbtc_set_ant_num(struct rtl_priv *rtlpriv, u8 type, u8 ant_num);
void exhalbtc_display_bt_coex_info(struct btc_coexist *btcoexist);
void exhalbtc_signal_compensation(struct btc_coexist *btcoexist,
u8 *rssi_wifi, u8 *rssi_bt);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
index b9b0cb7af8ea..d3fd9211b3a4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/rtl_btc.c
@@ -72,7 +72,10 @@ void rtl_btc_init_hal_vars(struct rtl_priv *rtlpriv)
__func__, bt_type);
exhalbtc_set_chip_type(bt_type);
- exhalbtc_set_ant_num(BT_COEX_ANT_TYPE_PG, ant_num);
+ if (rtlpriv->cfg->mod_params->ant_sel == 1)
+ exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_DETECTED, 1);
+ else
+ exhalbtc_set_ant_num(rtlpriv, BT_COEX_ANT_TYPE_PG, ant_num);
}
void rtl_btc_init_hw_config(struct rtl_priv *rtlpriv)
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 7f471bff435c..5b4048041147 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -1573,7 +1573,7 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw)
true,
HW_DESC_TXBUFF_ADDR),
skb->len, PCI_DMA_TODEVICE);
- kfree_skb(skb);
+ dev_kfree_skb_irq(skb);
ring->idx = (ring->idx + 1) % ring->entries;
}
ring->idx = 0;
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
index c983d2fe147f..5a3df9198ddf 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/hw.c
@@ -2684,6 +2684,7 @@ void rtl8723be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
bool auto_load_fail, u8 *hwinfo)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_mod_params *mod_params = rtlpriv->cfg->mod_params;
u8 value;
u32 tmpu_32;
@@ -2702,6 +2703,10 @@ void rtl8723be_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw,
rtlpriv->btcoexist.btc_info.ant_num = ANT_X2;
}
+ /* override ant_num / ant_path */
+ if (mod_params->ant_sel)
+ rtlpriv->btcoexist.btc_info.ant_num =
+ (mod_params->ant_sel == 1 ? ANT_X2 : ANT_X1);
}
void rtl8723be_bt_reg_init(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
index a78eaeda0008..2101793438ed 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
@@ -273,6 +273,7 @@ static struct rtl_mod_params rtl8723be_mod_params = {
.msi_support = false,
.disable_watchdog = false,
.debug = DBG_EMERG,
+ .ant_sel = 0,
};
static struct rtl_hal_cfg rtl8723be_hal_cfg = {
@@ -394,6 +395,7 @@ module_param_named(fwlps, rtl8723be_mod_params.fwctrl_lps, bool, 0444);
module_param_named(msi, rtl8723be_mod_params.msi_support, bool, 0444);
module_param_named(disable_watchdog, rtl8723be_mod_params.disable_watchdog,
bool, 0444);
+module_param_named(ant_sel, rtl8723be_mod_params.ant_sel, int, 0444);
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
@@ -402,6 +404,7 @@ MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 0)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
MODULE_PARM_DESC(disable_watchdog,
"Set to 1 to disable the watchdog (default 0)\n");
+MODULE_PARM_DESC(ant_sel, "Set to 1 or 2 to force antenna number (default 0)\n");
static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index 4544752a2ba8..b6faf624480e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -2252,6 +2252,9 @@ struct rtl_mod_params {
/* default 0: 1 means do not disable interrupts */
bool int_clear;
+
+ /* select antenna */
+ int ant_sel;
};
struct rtl_hal_usbint_cfg {
diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c
index e92f2639af2c..9fd3c6af0a61 100644
--- a/drivers/net/wireless/ti/wlcore/init.c
+++ b/drivers/net/wireless/ti/wlcore/init.c
@@ -549,6 +549,11 @@ static int wl12xx_init_ap_role(struct wl1271 *wl, struct wl12xx_vif *wlvif)
{
int ret;
+ /* Disable filtering */
+ ret = wl1271_acx_group_address_tbl(wl, wlvif, false, NULL, 0);
+ if (ret < 0)
+ return ret;
+
ret = wl1271_acx_ap_max_tx_retry(wl, wlvif);
if (ret < 0)
return ret;
diff --git a/drivers/nfc/nq-nci.c b/drivers/nfc/nq-nci.c
index 154310020997..2dd18dd78677 100644
--- a/drivers/nfc/nq-nci.c
+++ b/drivers/nfc/nq-nci.c
@@ -53,6 +53,7 @@ struct nqx_dev {
struct mutex read_mutex;
struct i2c_client *client;
struct miscdevice nqx_device;
+ union nqx_uinfo nqx_info;
/* NFC GPIO variables */
unsigned int irq_gpio;
unsigned int en_gpio;
@@ -467,6 +468,25 @@ int nfc_ioctl_core_reset_ntf(struct file *filp)
return nqx_dev->core_reset_ntf;
}
+/*
+ * Inside nfc_ioctl_nfcc_info
+ *
+ * @brief nfc_ioctl_nfcc_info
+ *
+ * Check the NQ Chipset and firmware version details
+ */
+unsigned int nfc_ioctl_nfcc_info(struct file *filp, unsigned long arg)
+{
+ unsigned int r = 0;
+ struct nqx_dev *nqx_dev = filp->private_data;
+
+ r = nqx_dev->nqx_info.i;
+ dev_dbg(&nqx_dev->client->dev,
+ "nqx nfc : nfc_ioctl_nfcc_info r = %d\n", r);
+
+ return r;
+}
+
static long nfc_ioctl(struct file *pfile, unsigned int cmd,
unsigned long arg)
{
@@ -489,6 +509,9 @@ static long nfc_ioctl(struct file *pfile, unsigned int cmd,
case NFCC_INITIAL_CORE_RESET_NTF:
r = nfc_ioctl_core_reset_ntf(pfile);
break;
+ case NFCC_GET_INFO:
+ r = nfc_ioctl_nfcc_info(pfile, arg);
+ break;
default:
r = -ENOIOCTLCMD;
}
@@ -508,13 +531,16 @@ static const struct file_operations nfc_dev_fops = {
};
/* Check for availability of NQ_ NFC controller hardware */
-static int nfcc_hw_check(struct i2c_client *client, unsigned int enable_gpio)
+static int nfcc_hw_check(struct i2c_client *client, struct nqx_dev *nqx_dev)
{
int ret = 0;
unsigned char raw_nci_reset_cmd[] = {0x20, 0x00, 0x01, 0x00};
+ unsigned char raw_nci_init_cmd[] = {0x20, 0x01, 0x00};
+ unsigned char nci_init_rsp[28];
unsigned char nci_reset_rsp[6];
-
+ unsigned char init_rsp_len = 0;
+ unsigned int enable_gpio = nqx_dev->en_gpio;
/* making sure that the NFCC starts in a clean state. */
gpio_set_value(enable_gpio, 0);/* ULPM: Disable */
/* hardware dependent delay */
@@ -536,16 +562,75 @@ static int nfcc_hw_check(struct i2c_client *client, unsigned int enable_gpio)
/* Read Response of RESET command */
ret = i2c_master_recv(client, nci_reset_rsp,
- sizeof(nci_reset_rsp));
+ sizeof(nci_reset_rsp));
dev_err(&client->dev,
- "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n",
- __func__, nci_reset_rsp[0],
- nci_reset_rsp[1], nci_reset_rsp[2]);
+ "%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n",
+ __func__, nci_reset_rsp[0],
+ nci_reset_rsp[1], nci_reset_rsp[2]);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "%s: - i2c_master_recv Error\n", __func__);
+ goto err_nfcc_hw_check;
+ }
+ ret = i2c_master_send(client, raw_nci_init_cmd,
+ sizeof(raw_nci_init_cmd));
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "%s: - i2c_master_send Error\n", __func__);
+ goto err_nfcc_hw_check;
+ }
+ /* hardware dependent delay */
+ msleep(30);
+ /* Read Response of INIT command */
+ ret = i2c_master_recv(client, nci_init_rsp,
+ sizeof(nci_init_rsp));
if (ret < 0) {
dev_err(&client->dev,
"%s: - i2c_master_recv Error\n", __func__);
goto err_nfcc_hw_check;
}
+ init_rsp_len = 2 + nci_init_rsp[2]; /*payload + len*/
+ if (init_rsp_len > PAYLOAD_HEADER_LENGTH) {
+ nqx_dev->nqx_info.info.chip_type =
+ nci_init_rsp[init_rsp_len - 3];
+ nqx_dev->nqx_info.info.rom_version =
+ nci_init_rsp[init_rsp_len - 2];
+ nqx_dev->nqx_info.info.fw_major =
+ nci_init_rsp[init_rsp_len - 1];
+ nqx_dev->nqx_info.info.fw_minor =
+ nci_init_rsp[init_rsp_len];
+ }
+ dev_dbg(&nqx_dev->client->dev, "NQ NFCC chip_type = %x\n",
+ nqx_dev->nqx_info.info.chip_type);
+ dev_dbg(&nqx_dev->client->dev, "NQ fw version = %x.%x.%x\n",
+ nqx_dev->nqx_info.info.rom_version,
+ nqx_dev->nqx_info.info.fw_major,
+ nqx_dev->nqx_info.info.fw_minor);
+
+ switch (nqx_dev->nqx_info.info.chip_type) {
+ case NFCC_NQ_210:
+ dev_dbg(&client->dev,
+ "%s: ## NFCC == NQ210 ##\n", __func__);
+ break;
+ case NFCC_NQ_220:
+ dev_dbg(&client->dev,
+ "%s: ## NFCC == NQ220 ##\n", __func__);
+ break;
+ case NFCC_NQ_310:
+ dev_dbg(&client->dev,
+ "%s: ## NFCC == NQ310 ##\n", __func__);
+ break;
+ case NFCC_NQ_330:
+ dev_dbg(&client->dev,
+ "%s: ## NFCC == NQ330 ##\n", __func__);
+ break;
+ default:
+ dev_err(&client->dev,
+ "%s: - NFCC HW not Supported\n", __func__);
+ break;
+ }
+
+ /*Disable NFC by default to save power on boot*/
gpio_set_value(enable_gpio, 0);/* ULPM: Disable */
ret = 0;
goto done;
@@ -566,9 +651,7 @@ done:
static int nqx_clock_select(struct nqx_dev *nqx_dev)
{
int r = 0;
-
- nqx_dev->s_clk =
- clk_get(&nqx_dev->client->dev, "ref_clk");
+ nqx_dev->s_clk = clk_get(&nqx_dev->client->dev, "ref_clk");
if (nqx_dev->s_clk == NULL)
goto err_clk;
@@ -867,8 +950,7 @@ static int nqx_probe(struct i2c_client *client,
* present before attempting further hardware initialisation.
*
*/
-
- r = nfcc_hw_check(client, platform_data->en_gpio);
+ r = nfcc_hw_check(client, nqx_dev);
if (r) {
/* make sure NFCC is not enabled */
gpio_set_value(platform_data->en_gpio, 0);
diff --git a/drivers/nfc/nq-nci.h b/drivers/nfc/nq-nci.h
index d62100c2d15a..c635e818b1f3 100644
--- a/drivers/nfc/nq-nci.h
+++ b/drivers/nfc/nq-nci.h
@@ -22,6 +22,7 @@
#include <linux/ioctl.h>
#include <linux/miscdevice.h>
+#include <linux/nfcinfo.h>
#define NFC_SET_PWR _IOW(0xE9, 0x01, unsigned int)
#define ESE_SET_PWR _IOW(0xE9, 0x02, unsigned int)
@@ -42,4 +43,12 @@ enum nfcc_initial_core_reset_ntf {
DEFAULT_INITIAL_CORE_RESET_NTF, /*2*/
};
+enum nfcc_chip_variant {
+ NFCC_NQ_210 = 0x48, /**< NFCC NQ210 */
+ NFCC_NQ_220 = 0x58, /**< NFCC NQ220 */
+ NFCC_NQ_310 = 0x40, /**< NFCC NQ310 */
+ NFCC_NQ_330 = 0x51, /**< NFCC NQ330 */
+ NFCC_NOT_SUPPORTED = 0xFF /**< NFCC is not supported */
+};
+
#endif
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 72a2c1969646..28da6242eb84 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -386,13 +386,13 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
EXPORT_SYMBOL_GPL(of_irq_to_resource);
/**
- * of_irq_get - Decode a node's IRQ and return it as a Linux irq number
+ * of_irq_get - Decode a node's IRQ and return it as a Linux IRQ number
* @dev: pointer to device tree node
- * @index: zero-based index of the irq
- *
- * Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain
- * is not yet created.
+ * @index: zero-based index of the IRQ
*
+ * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or
+ * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
+ * of any other failure.
*/
int of_irq_get(struct device_node *dev, int index)
{
@@ -413,12 +413,13 @@ int of_irq_get(struct device_node *dev, int index)
EXPORT_SYMBOL_GPL(of_irq_get);
/**
- * of_irq_get_byname - Decode a node's IRQ and return it as a Linux irq number
+ * of_irq_get_byname - Decode a node's IRQ and return it as a Linux IRQ number
* @dev: pointer to device tree node
- * @name: irq name
+ * @name: IRQ name
*
- * Returns Linux irq number on success, or -EPROBE_DEFER if the irq domain
- * is not yet created, or error code in case of any other failure.
+ * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or
+ * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
+ * of any other failure.
*/
int of_irq_get_byname(struct device_node *dev, const char *name)
{
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c
index 14af8ca66d1c..ce0752d3b535 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -5420,7 +5420,7 @@ static irqreturn_t handle_msi_irq(int irq, void *data)
struct msm_pcie_dev_t *dev = data;
void __iomem *ctrl_status;
- PCIE_DBG(dev, "irq=%d\n", irq);
+ PCIE_DUMP(dev, "irq: %d\n", irq);
/* check for set bits, clear it by setting that bit
and trigger corresponding irq */
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 7aafb5fb9336..9757cf9037a2 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -179,9 +179,6 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
u16 orig_cmd;
struct pci_bus_region region, inverted_region;
- if (dev->non_compliant_bars)
- return 0;
-
mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
/* No printks while decoding is disabled! */
@@ -322,6 +319,9 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
{
unsigned int pos, reg;
+ if (dev->non_compliant_bars)
+ return;
+
for (pos = 0; pos < howmany; pos++) {
struct resource *res = &dev->resource[pos];
reg = PCI_BASE_ADDRESS_0 + (pos << 2);
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index 3d8019eb3d84..181b35879ebd 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -1191,9 +1191,10 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)
const struct mtk_desc_pin *pin;
chained_irq_enter(chip, desc);
- for (eint_num = 0; eint_num < pctl->devdata->ap_num; eint_num += 32) {
+ for (eint_num = 0;
+ eint_num < pctl->devdata->ap_num;
+ eint_num += 32, reg += 4) {
status = readl(reg);
- reg += 4;
while (status) {
offset = __ffs(status);
index = eint_num + offset;
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos5440.c b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
index 82dc109f7ed4..3149a877c51f 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos5440.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos5440.c
@@ -107,6 +107,7 @@ struct exynos5440_pmx_func {
* @nr_groups: number of pin groups available.
* @pmx_functions: list of pin functions parsed from device tree.
* @nr_functions: number of pin functions available.
+ * @range: gpio range to register with pinctrl
*/
struct exynos5440_pinctrl_priv_data {
void __iomem *reg_base;
@@ -117,6 +118,7 @@ struct exynos5440_pinctrl_priv_data {
unsigned int nr_groups;
const struct exynos5440_pmx_func *pmx_functions;
unsigned int nr_functions;
+ struct pinctrl_gpio_range range;
};
/**
@@ -742,7 +744,6 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev,
struct pinctrl_desc *ctrldesc;
struct pinctrl_dev *pctl_dev;
struct pinctrl_pin_desc *pindesc, *pdesc;
- struct pinctrl_gpio_range grange;
char *pin_names;
int pin, ret;
@@ -794,12 +795,12 @@ static int exynos5440_pinctrl_register(struct platform_device *pdev,
return PTR_ERR(pctl_dev);
}
- grange.name = "exynos5440-pctrl-gpio-range";
- grange.id = 0;
- grange.base = 0;
- grange.npins = EXYNOS5440_MAX_PINS;
- grange.gc = priv->gc;
- pinctrl_add_gpio_range(pctl_dev, &grange);
+ priv->range.name = "exynos5440-pctrl-gpio-range";
+ priv->range.id = 0;
+ priv->range.base = 0;
+ priv->range.npins = EXYNOS5440_MAX_PINS;
+ priv->range.gc = priv->gc;
+ pinctrl_add_gpio_range(pctl_dev, &priv->range);
return 0;
}
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
index 3c2a6d4620ba..d51e9ac97fe0 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
@@ -18,6 +18,7 @@
#include "ipa_i.h"
#include "ipa_trace.h"
+#define IPA_WAN_AGGR_PKT_CNT 5
#define IPA_LAST_DESC_CNT 0xFFFF
#define POLLING_INACTIVITY_RX 40
#define POLLING_INACTIVITY_TX 40
@@ -1099,16 +1100,18 @@ int ipa2_rx_poll(u32 clnt_hdl, int weight)
break;
ipa_wq_rx_common(ep->sys, iov.size);
- cnt += 5;
+ cnt += IPA_WAN_AGGR_PKT_CNT;
};
- if (cnt == 0) {
+ if (cnt == 0 || cnt < weight) {
ep->inactive_cycles++;
ep->client_notify(ep->priv, IPA_CLIENT_COMP_NAPI, 0);
if (ep->inactive_cycles > 3 || ep->sys->len == 0) {
ep->switch_to_intr = true;
delay = 0;
+ } else if (cnt < weight) {
+ delay = 0;
}
queue_delayed_work(ep->sys->wq,
&ep->sys->switch_to_intr_work, msecs_to_jiffies(delay));
@@ -1165,8 +1168,11 @@ void ipa_update_repl_threshold(enum ipa_client_type ipa_client)
* Determine how many buffers/descriptors remaining will
* cause to drop below the yellow WM bar.
*/
- ep->rx_replenish_threshold = ipa_get_sys_yellow_wm(ep->sys)
- / ep->sys->rx_buff_sz;
+ if (ep->sys->rx_buff_sz)
+ ep->rx_replenish_threshold = ipa_get_sys_yellow_wm(ep->sys)
+ / ep->sys->rx_buff_sz;
+ else
+ ep->rx_replenish_threshold = 0;
}
/**
@@ -1361,8 +1367,11 @@ int ipa2_setup_sys_pipe(struct ipa_sys_connect_params *sys_in, u32 *clnt_hdl)
* Determine how many buffers/descriptors remaining will
* cause to drop below the yellow WM bar.
*/
- ep->rx_replenish_threshold = ipa_get_sys_yellow_wm(ep->sys)
- / ep->sys->rx_buff_sz;
+ if (ep->sys->rx_buff_sz)
+ ep->rx_replenish_threshold =
+ ipa_get_sys_yellow_wm(ep->sys) / ep->sys->rx_buff_sz;
+ else
+ ep->rx_replenish_threshold = 0;
/* Only when the WAN pipes are setup, actual threshold will
* be read from the register. So update LAN_CONS ep again with
* right value.
@@ -3162,14 +3171,9 @@ static int ipa_assign_policy_v2(struct ipa_sys_connect_params *in,
sys->repl_hdlr =
ipa_replenish_rx_cache;
}
- if (in->napi_enabled) {
- sys->rx_pool_sz =
- IPA_WAN_NAPI_CONS_RX_POOL_SZ;
- if (in->recycle_enabled) {
- sys->repl_hdlr =
- ipa_replenish_rx_cache_recycle;
- }
- }
+ if (in->napi_enabled && in->recycle_enabled)
+ sys->repl_hdlr =
+ ipa_replenish_rx_cache_recycle;
sys->ep->wakelock_client =
IPA_WAKELOCK_REF_CLIENT_WAN_RX;
in->ipa_ep_cfg.aggr.aggr_sw_eof_active
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index 73206abf9cfd..866170d3324d 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -51,8 +51,6 @@
#define IPA_UC_FINISH_MAX 6
#define IPA_UC_WAIT_MIN_SLEEP 1000
#define IPA_UC_WAII_MAX_SLEEP 1200
-#define IPA_WAN_NAPI_CONS_RX_POOL_SZ (IPA_GENERIC_RX_POOL_SZ*3)
-#define IPA_WAN_CONS_DESC_FIFO_SZ (IPA_SYS_DESC_FIFO_SZ*3)
#define IPA_MAX_STATUS_STAT_NUM 30
diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
index 520f139ee38a..c2e43a62ab69 100644
--- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
@@ -62,6 +62,7 @@
#define IPA_UEVENT_NUM_EVNP 4 /* number of event pointers */
#define NAPI_WEIGHT 60
+#define IPA_WWAN_CONS_DESC_FIFO_SZ 1024
static struct net_device *ipa_netdevs[IPA_WWAN_DEVICE_COUNT];
static struct ipa_sys_connect_params apps_to_ipa_ep_cfg, ipa_to_apps_ep_cfg;
@@ -100,6 +101,7 @@ struct ipa_rmnet_plat_drv_res {
bool ipa_loaduC;
bool ipa_advertise_sg_support;
bool ipa_napi_enable;
+ u32 wan_rx_desc_size;
};
static struct ipa_rmnet_plat_drv_res ipa_rmnet_res;
@@ -1291,10 +1293,8 @@ static int handle_ingress_format(struct net_device *dev,
ipa_to_apps_ep_cfg.priv = dev;
ipa_to_apps_ep_cfg.napi_enabled = ipa_rmnet_res.ipa_napi_enable;
- if (ipa_to_apps_ep_cfg.napi_enabled)
- ipa_to_apps_ep_cfg.desc_fifo_sz = IPA_WAN_CONS_DESC_FIFO_SZ;
- else
- ipa_to_apps_ep_cfg.desc_fifo_sz = IPA_SYS_DESC_FIFO_SZ;
+ ipa_to_apps_ep_cfg.desc_fifo_sz =
+ ipa_rmnet_res.wan_rx_desc_size * sizeof(struct sps_iovec);
mutex_lock(&ipa_to_apps_pipe_handle_guard);
if (atomic_read(&is_ssr)) {
@@ -1925,6 +1925,9 @@ static struct notifier_block ssr_notifier = {
static int get_ipa_rmnet_dts_configuration(struct platform_device *pdev,
struct ipa_rmnet_plat_drv_res *ipa_rmnet_drv_res)
{
+ int result;
+
+ ipa_rmnet_drv_res->wan_rx_desc_size = IPA_WWAN_CONS_DESC_FIFO_SZ;
ipa_rmnet_drv_res->ipa_rmnet_ssr =
of_property_read_bool(pdev->dev.of_node,
"qcom,rmnet-ipa-ssr");
@@ -1947,6 +1950,18 @@ static int get_ipa_rmnet_dts_configuration(struct platform_device *pdev,
"qcom,ipa-napi-enable");
pr_info("IPA Napi Enable = %s\n",
ipa_rmnet_drv_res->ipa_napi_enable ? "True" : "False");
+
+ /* Get IPA WAN RX desc fifo size */
+ result = of_property_read_u32(pdev->dev.of_node,
+ "qcom,wan-rx-desc-size",
+ &ipa_rmnet_drv_res->wan_rx_desc_size);
+ if (result)
+ pr_info("using default for wan-rx-desc-size = %u\n",
+ ipa_rmnet_drv_res->wan_rx_desc_size);
+ else
+ IPAWANDBG(": found ipa_drv_res->wan-rx-desc-size = %u\n",
+ ipa_rmnet_drv_res->wan_rx_desc_size);
+
return 0;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index cc1cb456ab8a..4b0cd46082a3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -21,6 +21,7 @@
#include "ipahal/ipahal.h"
#include "ipahal/ipahal_fltrt.h"
+#define IPA_WAN_AGGR_PKT_CNT 5
#define IPA_LAST_DESC_CNT 0xFFFF
#define POLLING_INACTIVITY_RX 40
#define POLLING_MIN_SLEEP_RX 1010
@@ -60,7 +61,6 @@
#define IPA_ODU_RX_POOL_SZ 64
#define IPA_SIZE_DL_CSUM_META_TRAILER 8
-#define IPA_GSI_EVT_RING_LEN 4096
#define IPA_GSI_MAX_CH_LOW_WEIGHT 15
#define IPA_GSI_EVT_RING_INT_MODT 3200 /* 0.1s under 32KHz clock */
@@ -3298,9 +3298,6 @@ static int ipa3_assign_policy(struct ipa_sys_connect_params *in,
sys->repl_hdlr =
ipa3_replenish_rx_cache;
}
- if (in->napi_enabled)
- sys->rx_pool_sz =
- IPA_WAN_NAPI_CONS_RX_POOL_SZ;
if (in->napi_enabled && in->recycle_enabled)
sys->repl_hdlr =
ipa3_replenish_rx_cache_recycle;
@@ -3965,13 +3962,19 @@ static int ipa_gsi_setup_channel(struct ipa_sys_connect_params *in,
gsi_evt_ring_props.re_size =
GSI_EVT_RING_RE_SIZE_16B;
- gsi_evt_ring_props.ring_len = IPA_GSI_EVT_RING_LEN;
+ /*
+ * GSI ring length is calculated based on the desc_fifo_sz
+ * which was meant to define the BAM desc fifo. GSI descriptors
+ * are 16B as opposed to 8B for BAM.
+ */
+ gsi_evt_ring_props.ring_len = 2 * in->desc_fifo_sz;
+
gsi_evt_ring_props.ring_base_vaddr =
- dma_alloc_coherent(ipa3_ctx->pdev, IPA_GSI_EVT_RING_LEN,
- &evt_dma_addr, GFP_KERNEL);
+ dma_alloc_coherent(ipa3_ctx->pdev,
+ gsi_evt_ring_props.ring_len, &evt_dma_addr, GFP_KERNEL);
if (!gsi_evt_ring_props.ring_base_vaddr) {
IPAERR("fail to dma alloc %u bytes\n",
- IPA_GSI_EVT_RING_LEN);
+ gsi_evt_ring_props.ring_len);
return -ENOMEM;
}
gsi_evt_ring_props.ring_base_addr = evt_dma_addr;
@@ -4098,7 +4101,7 @@ fail_get_gsi_ep_info:
}
fail_alloc_evt_ring:
if (gsi_evt_ring_props.ring_base_vaddr)
- dma_free_coherent(ipa3_ctx->pdev, IPA_GSI_EVT_RING_LEN,
+ dma_free_coherent(ipa3_ctx->pdev, gsi_evt_ring_props.ring_len,
gsi_evt_ring_props.ring_base_vaddr, evt_dma_addr);
IPAERR("Return with err: %d\n", result);
return result;
@@ -4280,16 +4283,18 @@ int ipa3_rx_poll(u32 clnt_hdl, int weight)
break;
ipa3_wq_rx_common(ep->sys, mem_info.size);
- cnt += 5;
+ cnt += IPA_WAN_AGGR_PKT_CNT;
};
- if (cnt == 0) {
+ if (cnt == 0 || cnt < weight) {
ep->inactive_cycles++;
ep->client_notify(ep->priv, IPA_CLIENT_COMP_NAPI, 0);
if (ep->inactive_cycles > 3 || ep->sys->len == 0) {
ep->switch_to_intr = true;
delay = 0;
+ } else if (cnt < weight) {
+ delay = 0;
}
queue_delayed_work(ep->sys->wq,
&ep->sys->switch_to_intr_work, msecs_to_jiffies(delay));
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 40f1e93653f9..1b78835cda6b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -53,8 +53,6 @@
#define IPA_UC_FINISH_MAX 6
#define IPA_UC_WAIT_MIN_SLEEP 1000
#define IPA_UC_WAII_MAX_SLEEP 1200
-#define IPA_WAN_NAPI_CONS_RX_POOL_SZ (IPA_GENERIC_RX_POOL_SZ*3)
-#define IPA_WAN_CONS_DESC_FIFO_SZ (IPA_SYS_DESC_FIFO_SZ*3)
#define IPA_MAX_STATUS_STAT_NUM 30
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index 8f6c303d2867..0419249890e9 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -65,6 +65,7 @@
((rmnet_ipa3_ctx && rmnet_ipa3_ctx->wwan_priv) ? \
rmnet_ipa3_ctx->wwan_priv->net : NULL)
+#define IPA_WWAN_CONS_DESC_FIFO_SZ 256
static int ipa3_wwan_add_ul_flt_rule_to_ipa(void);
static int ipa3_wwan_del_ul_flt_rule_to_ipa(void);
@@ -89,6 +90,7 @@ struct ipa3_rmnet_plat_drv_res {
bool ipa_loaduC;
bool ipa_advertise_sg_support;
bool ipa_napi_enable;
+ u32 wan_rx_desc_size;
};
/**
@@ -1275,7 +1277,7 @@ static int handle3_ingress_format(struct net_device *dev,
ipa_wan_ep_cfg->ipa_ep_cfg.aggr.aggr_pkt_limit =
in->u.ingress_format.agg_count;
- if (ipa_wan_ep_cfg->napi_enabled) {
+ if (ipa3_rmnet_res.ipa_napi_enable) {
ipa_wan_ep_cfg->recycle_enabled = true;
ep_cfg = (struct rmnet_phys_ep_conf_s *)
rcu_dereference(dev->rx_handler_data);
@@ -1303,10 +1305,8 @@ static int handle3_ingress_format(struct net_device *dev,
ipa_wan_ep_cfg->priv = dev;
ipa_wan_ep_cfg->napi_enabled = ipa3_rmnet_res.ipa_napi_enable;
- if (ipa_wan_ep_cfg->napi_enabled)
- ipa_wan_ep_cfg->desc_fifo_sz = IPA_WAN_CONS_DESC_FIFO_SZ;
- else
- ipa_wan_ep_cfg->desc_fifo_sz = IPA_SYS_DESC_FIFO_SZ;
+ ipa_wan_ep_cfg->desc_fifo_sz =
+ ipa3_rmnet_res.wan_rx_desc_size * sizeof(struct sps_iovec);
mutex_lock(&rmnet_ipa3_ctx->ipa_to_apps_pipe_handle_guard);
@@ -1957,6 +1957,9 @@ static struct notifier_block ipa3_ssr_notifier = {
static int get_ipa_rmnet_dts_configuration(struct platform_device *pdev,
struct ipa3_rmnet_plat_drv_res *ipa_rmnet_drv_res)
{
+ int result;
+
+ ipa_rmnet_drv_res->wan_rx_desc_size = IPA_WWAN_CONS_DESC_FIFO_SZ;
ipa_rmnet_drv_res->ipa_rmnet_ssr =
of_property_read_bool(pdev->dev.of_node,
"qcom,rmnet-ipa-ssr");
@@ -1979,6 +1982,18 @@ static int get_ipa_rmnet_dts_configuration(struct platform_device *pdev,
"qcom,ipa-napi-enable");
pr_info("IPA Napi Enable = %s\n",
ipa_rmnet_drv_res->ipa_napi_enable ? "True" : "False");
+
+ /* Get IPA WAN RX desc fifo size */
+ result = of_property_read_u32(pdev->dev.of_node,
+ "qcom,wan-rx-desc-size",
+ &ipa_rmnet_drv_res->wan_rx_desc_size);
+ if (result)
+ pr_info("using default for wan-rx-desc-size = %u\n",
+ ipa_rmnet_drv_res->wan_rx_desc_size);
+ else
+ IPAWANDBG(": found ipa_drv_res->wan-rx-desc-size = %u\n",
+ ipa_rmnet_drv_res->wan_rx_desc_size);
+
return 0;
}
diff --git a/drivers/platform/msm/msm_11ad/msm_11ad.c b/drivers/platform/msm/msm_11ad/msm_11ad.c
index 45fedfa72bda..5810f7bf7f2f 100644
--- a/drivers/platform/msm/msm_11ad/msm_11ad.c
+++ b/drivers/platform/msm/msm_11ad/msm_11ad.c
@@ -51,6 +51,9 @@
#define VDDIO_MAX_UV 2040000
#define VDDIO_MAX_UA 70300
+#define DISABLE_PCIE_L1_MASK 0xFFFFFFFD
+#define PCIE20_CAP_LINKCTRLSTATUS 0x80
+
struct device;
static const char * const gpio_en_name = "qcom,wigig-en";
@@ -505,6 +508,7 @@ static int ops_resume(void *handle)
int rc;
struct msm11ad_ctx *ctx = handle;
struct pci_dev *pcidev;
+ u32 val;
pr_info("%s(%p)\n", __func__, handle);
if (!ctx) {
@@ -548,6 +552,27 @@ static int ops_resume(void *handle)
goto err_suspend_rc;
}
+ /* Disable L1 */
+ rc = pci_read_config_dword(ctx->pcidev,
+ PCIE20_CAP_LINKCTRLSTATUS, &val);
+ if (rc) {
+ dev_err(ctx->dev,
+ "reading PCIE20_CAP_LINKCTRLSTATUS failed:%d\n",
+ rc);
+ goto err_suspend_rc;
+ }
+ val &= DISABLE_PCIE_L1_MASK; /* disable bit 1 */
+ dev_dbg(ctx->dev, "writing PCIE20_CAP_LINKCTRLSTATUS (val 0x%x)\n",
+ val);
+ rc = pci_write_config_dword(ctx->pcidev,
+ PCIE20_CAP_LINKCTRLSTATUS, val);
+ if (rc) {
+ dev_err(ctx->dev,
+ "writing PCIE20_CAP_LINKCTRLSTATUS (val 0x%x) failed:%d\n",
+ val, rc);
+ goto err_suspend_rc;
+ }
+
return 0;
err_suspend_rc:
@@ -792,6 +817,7 @@ static int msm_11ad_probe(struct platform_device *pdev)
struct device_node *rc_node;
struct pci_dev *pcidev = NULL;
int rc;
+ u32 val;
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
@@ -907,6 +933,28 @@ static int msm_11ad_probe(struct platform_device *pdev)
goto out_rc;
}
ctx->pcidev = pcidev;
+
+ /* Disable L1 */
+ rc = pci_read_config_dword(ctx->pcidev,
+ PCIE20_CAP_LINKCTRLSTATUS, &val);
+ if (rc) {
+ dev_err(ctx->dev,
+ "reading PCIE20_CAP_LINKCTRLSTATUS failed:%d\n",
+ rc);
+ goto out_rc;
+ }
+ val &= DISABLE_PCIE_L1_MASK; /* disable bit 1 */
+ dev_dbg(ctx->dev, "writing PCIE20_CAP_LINKCTRLSTATUS (val 0x%x)\n",
+ val);
+ rc = pci_write_config_dword(ctx->pcidev,
+ PCIE20_CAP_LINKCTRLSTATUS, val);
+ if (rc) {
+ dev_err(ctx->dev,
+ "writing PCIE20_CAP_LINKCTRLSTATUS (val 0x%x) failed:%d\n",
+ val, rc);
+ goto out_rc;
+ }
+
rc = pci_save_state(pcidev);
if (rc) {
dev_err(ctx->dev, "pci_save_state failed :%d\n", rc);
diff --git a/drivers/platform/x86/dell-rbtn.c b/drivers/platform/x86/dell-rbtn.c
index cd410e392550..d33e9ad3218f 100644
--- a/drivers/platform/x86/dell-rbtn.c
+++ b/drivers/platform/x86/dell-rbtn.c
@@ -28,6 +28,7 @@ struct rbtn_data {
enum rbtn_type type;
struct rfkill *rfkill;
struct input_dev *input_dev;
+ bool suspended;
};
@@ -220,9 +221,55 @@ static const struct acpi_device_id rbtn_ids[] = {
{ "", 0 },
};
+#ifdef CONFIG_PM_SLEEP
+static void ACPI_SYSTEM_XFACE rbtn_clear_suspended_flag(void *context)
+{
+ struct rbtn_data *rbtn_data = context;
+
+ rbtn_data->suspended = false;
+}
+
+static int rbtn_suspend(struct device *dev)
+{
+ struct acpi_device *device = to_acpi_device(dev);
+ struct rbtn_data *rbtn_data = acpi_driver_data(device);
+
+ rbtn_data->suspended = true;
+
+ return 0;
+}
+
+static int rbtn_resume(struct device *dev)
+{
+ struct acpi_device *device = to_acpi_device(dev);
+ struct rbtn_data *rbtn_data = acpi_driver_data(device);
+ acpi_status status;
+
+ /*
+ * Upon resume, some BIOSes send an ACPI notification thet triggers
+ * an unwanted input event. In order to ignore it, we use a flag
+ * that we set at suspend and clear once we have received the extra
+ * ACPI notification. Since ACPI notifications are delivered
+ * asynchronously to drivers, we clear the flag from the workqueue
+ * used to deliver the notifications. This should be enough
+ * to have the flag cleared only after we received the extra
+ * notification, if any.
+ */
+ status = acpi_os_execute(OSL_NOTIFY_HANDLER,
+ rbtn_clear_suspended_flag, rbtn_data);
+ if (ACPI_FAILURE(status))
+ rbtn_clear_suspended_flag(rbtn_data);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(rbtn_pm_ops, rbtn_suspend, rbtn_resume);
+
static struct acpi_driver rbtn_driver = {
.name = "dell-rbtn",
.ids = rbtn_ids,
+ .drv.pm = &rbtn_pm_ops,
.ops = {
.add = rbtn_add,
.remove = rbtn_remove,
@@ -384,6 +431,15 @@ static void rbtn_notify(struct acpi_device *device, u32 event)
{
struct rbtn_data *rbtn_data = device->driver_data;
+ /*
+ * Some BIOSes send a notification at resume.
+ * Ignore it to prevent unwanted input events.
+ */
+ if (rbtn_data->suspended) {
+ dev_dbg(&device->dev, "ACPI notification ignored\n");
+ return;
+ }
+
if (event != 0x80) {
dev_info(&device->dev, "Received unknown event (0x%x)\n",
event);
diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h
index a703b208f6e4..3f67f49377b4 100644
--- a/drivers/power/qcom-charger/fg-core.h
+++ b/drivers/power/qcom-charger/fg-core.h
@@ -222,7 +222,6 @@ struct fg_batt_props {
int float_volt_uv;
int vbatt_full_mv;
int fastchg_curr_ma;
- int batt_id_kohm;
};
struct fg_cyc_ctr_data {
@@ -260,6 +259,7 @@ struct fg_chip {
struct power_supply *batt_psy;
struct power_supply *usb_psy;
struct power_supply *dc_psy;
+ struct power_supply *parallel_psy;
struct iio_channel *batt_id_chan;
struct fg_memif *sram;
struct fg_irq_info *irqs;
@@ -278,7 +278,7 @@ struct fg_chip {
u32 batt_soc_base;
u32 batt_info_base;
u32 mem_if_base;
- int batt_id;
+ int batt_id_kohms;
int status;
int charge_done;
int last_soc;
@@ -291,6 +291,7 @@ struct fg_chip {
bool charge_full;
bool recharge_soc_adjusted;
bool ki_coeff_dischg_en;
+ bool esr_fcc_ctrl_en;
struct completion soc_update;
struct completion soc_ready;
struct delayed_work profile_load_work;
@@ -340,6 +341,8 @@ extern int fg_read(struct fg_chip *chip, int addr, u8 *val, int len);
extern int fg_write(struct fg_chip *chip, int addr, u8 *val, int len);
extern int fg_masked_write(struct fg_chip *chip, int addr, u8 mask, u8 val);
extern int fg_ima_init(struct fg_chip *chip);
+extern int fg_clear_ima_errors_if_any(struct fg_chip *chip, bool check_hw_sts);
+extern int fg_clear_dma_errors_if_any(struct fg_chip *chip);
extern int fg_debugfs_create(struct fg_chip *chip);
extern void fill_string(char *str, size_t str_len, u8 *buf, int buf_len);
extern int64_t twos_compliment_extend(int64_t val, int s_bit_pos);
diff --git a/drivers/power/qcom-charger/fg-memif.c b/drivers/power/qcom-charger/fg-memif.c
index c271b24adfc4..a98ff7d765e3 100644
--- a/drivers/power/qcom-charger/fg-memif.c
+++ b/drivers/power/qcom-charger/fg-memif.c
@@ -64,44 +64,90 @@ static int fg_config_access_mode(struct fg_chip *chip, bool access, bool burst)
static int fg_run_iacs_clear_sequence(struct fg_chip *chip)
{
- u8 tmp;
- int rc;
+ u8 val, hw_sts, exp_sts;
+ int rc, tries = 250;
/*
* Values to write for running IACS clear sequence comes from
* hardware documentation.
*/
- rc = fg_masked_write(chip, MEM_IF_IMA_CFG(chip), IACS_CLR_BIT,
- IACS_CLR_BIT);
+ rc = fg_masked_write(chip, MEM_IF_IMA_CFG(chip),
+ IACS_CLR_BIT | STATIC_CLK_EN_BIT,
+ IACS_CLR_BIT | STATIC_CLK_EN_BIT);
if (rc < 0) {
pr_err("failed to write 0x%04x, rc=%d\n", MEM_IF_IMA_CFG(chip),
rc);
return rc;
}
- tmp = 0x4;
- rc = fg_write(chip, MEM_IF_ADDR_MSB(chip), &tmp, 1);
+ rc = fg_config_access_mode(chip, FG_READ, false);
if (rc < 0) {
- pr_err("failed to write 0x%04x, rc=%d\n", MEM_IF_ADDR_LSB(chip),
- rc);
+ pr_err("failed to write to 0x%04x, rc=%d\n",
+ MEM_IF_IMA_CTL(chip), rc);
return rc;
}
- tmp = 0x0;
- rc = fg_write(chip, MEM_IF_WR_DATA3(chip), &tmp, 1);
+ rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
+ MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT,
+ MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT);
if (rc < 0) {
- pr_err("failed to write 0x%04x, rc=%d\n", MEM_IF_WR_DATA3(chip),
- rc);
+ pr_err("failed to set ima_req_access bit rc=%d\n", rc);
return rc;
}
- rc = fg_read(chip, MEM_IF_RD_DATA3(chip), &tmp, 1);
- if (rc < 0) {
- pr_err("failed to read 0x%04x, rc=%d\n", MEM_IF_RD_DATA3(chip),
- rc);
- return rc;
+ /* Delay for the clock to reach FG */
+ usleep_range(35, 40);
+
+ while (1) {
+ val = 0;
+ rc = fg_write(chip, MEM_IF_ADDR_MSB(chip), &val, 1);
+ if (rc < 0) {
+ pr_err("failed to write 0x%04x, rc=%d\n",
+ MEM_IF_ADDR_MSB(chip), rc);
+ return rc;
+ }
+
+ val = 0;
+ rc = fg_write(chip, MEM_IF_WR_DATA3(chip), &val, 1);
+ if (rc < 0) {
+ pr_err("failed to write 0x%04x, rc=%d\n",
+ MEM_IF_WR_DATA3(chip), rc);
+ return rc;
+ }
+
+ rc = fg_read(chip, MEM_IF_RD_DATA3(chip), &val, 1);
+ if (rc < 0) {
+ pr_err("failed to read 0x%04x, rc=%d\n",
+ MEM_IF_RD_DATA3(chip), rc);
+ return rc;
+ }
+
+ /* Delay for IMA hardware to clear */
+ usleep_range(35, 40);
+
+ rc = fg_read(chip, MEM_IF_IMA_HW_STS(chip), &hw_sts, 1);
+ if (rc < 0) {
+ pr_err("failed to read ima_hw_sts rc=%d\n", rc);
+ return rc;
+ }
+
+ if (hw_sts != 0)
+ continue;
+
+ rc = fg_read(chip, MEM_IF_IMA_EXP_STS(chip), &exp_sts, 1);
+ if (rc < 0) {
+ pr_err("failed to read ima_exp_sts rc=%d\n", rc);
+ return rc;
+ }
+
+ if (exp_sts == 0 || !(--tries))
+ break;
}
+ if (!tries)
+ pr_err("Failed to clear the error? hw_sts: %x exp_sts: %d\n",
+ hw_sts, exp_sts);
+
rc = fg_masked_write(chip, MEM_IF_IMA_CFG(chip), IACS_CLR_BIT, 0);
if (rc < 0) {
pr_err("failed to write 0x%04x, rc=%d\n", MEM_IF_IMA_CFG(chip),
@@ -109,14 +155,65 @@ static int fg_run_iacs_clear_sequence(struct fg_chip *chip)
return rc;
}
+ udelay(5);
+
+ rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
+ MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, 0);
+ if (rc < 0) {
+ pr_err("failed to write to 0x%04x, rc=%d\n",
+ MEM_IF_MEM_INTF_CFG(chip), rc);
+ return rc;
+ }
+
+ /* Delay before next transaction is attempted */
+ usleep_range(35, 40);
fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "IACS clear sequence complete\n");
return rc;
}
-static int fg_check_for_ima_errors(struct fg_chip *chip)
+int fg_clear_dma_errors_if_any(struct fg_chip *chip)
+{
+ int rc;
+ u8 dma_sts;
+
+ rc = fg_read(chip, MEM_IF_DMA_STS(chip), &dma_sts, 1);
+ if (rc < 0) {
+ pr_err("failed to read addr=0x%04x, rc=%d\n",
+ MEM_IF_DMA_STS(chip), rc);
+ return rc;
+ }
+ fg_dbg(chip, FG_STATUS, "dma_sts: %x\n", dma_sts);
+
+ if (dma_sts & (DMA_WRITE_ERROR_BIT | DMA_READ_ERROR_BIT)) {
+ rc = fg_masked_write(chip, MEM_IF_DMA_CTL(chip),
+ DMA_CLEAR_LOG_BIT, DMA_CLEAR_LOG_BIT);
+ if (rc < 0) {
+ pr_err("failed to write addr=0x%04x, rc=%d\n",
+ MEM_IF_DMA_CTL(chip), rc);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+int fg_clear_ima_errors_if_any(struct fg_chip *chip, bool check_hw_sts)
{
int rc = 0;
u8 err_sts, exp_sts = 0, hw_sts = 0;
+ bool run_err_clr_seq = false;
+
+ rc = fg_read(chip, MEM_IF_IMA_EXP_STS(chip), &exp_sts, 1);
+ if (rc < 0) {
+ pr_err("failed to read ima_exp_sts rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = fg_read(chip, MEM_IF_IMA_HW_STS(chip), &hw_sts, 1);
+ if (rc < 0) {
+ pr_err("failed to read ima_hw_sts rc=%d\n", rc);
+ return rc;
+ }
rc = fg_read(chip, MEM_IF_IMA_ERR_STS(chip), &err_sts, 1);
if (rc < 0) {
@@ -124,22 +221,30 @@ static int fg_check_for_ima_errors(struct fg_chip *chip)
return rc;
}
- if (err_sts & (ADDR_STBL_ERR_BIT | WR_ACS_ERR_BIT | RD_ACS_ERR_BIT)) {
- rc = fg_read(chip, MEM_IF_IMA_EXP_STS(chip), &exp_sts, 1);
- if (rc < 0) {
- pr_err("failed to read ima_exp_sts rc=%d\n", rc);
- return rc;
- }
+ fg_dbg(chip, FG_SRAM_READ | FG_SRAM_WRITE, "ima_err_sts=%x ima_exp_sts=%x ima_hw_sts=%x\n",
+ err_sts, exp_sts, hw_sts);
- rc = fg_read(chip, MEM_IF_IMA_HW_STS(chip), &hw_sts, 1);
- if (rc < 0) {
- pr_err("failed to read ima_hw_sts rc=%d\n", rc);
- return rc;
+ if (check_hw_sts) {
+ /*
+ * Lower nibble should be equal to upper nibble before SRAM
+ * transactions begins from SW side. If they are unequal, then
+ * the error clear sequence should be run irrespective of IMA
+ * exception errors.
+ */
+ if ((hw_sts & 0x0F) != hw_sts >> 4) {
+ pr_err("IMA HW not in correct state, hw_sts=%x\n",
+ hw_sts);
+ run_err_clr_seq = true;
}
+ }
- pr_err("ima_err_sts=%x ima_exp_sts=%x ima_hw_sts=%x\n",
- err_sts, exp_sts, hw_sts);
+ if (exp_sts & (IACS_ERR_BIT | XCT_TYPE_ERR_BIT | DATA_RD_ERR_BIT |
+ DATA_WR_ERR_BIT | ADDR_BURST_WRAP_BIT | ADDR_STABLE_ERR_BIT)) {
+ pr_err("IMA exception bit set, exp_sts=%x\n", exp_sts);
+ run_err_clr_seq = true;
+ }
+ if (run_err_clr_seq) {
/* clear the error */
rc = fg_run_iacs_clear_sequence(chip);
if (rc < 0) {
@@ -156,7 +261,7 @@ static int fg_check_for_ima_errors(struct fg_chip *chip)
static int fg_check_iacs_ready(struct fg_chip *chip)
{
- int rc = 0, timeout = 250;
+ int rc = 0, tries = 250;
u8 ima_opr_sts = 0;
/*
@@ -176,17 +281,17 @@ static int fg_check_iacs_ready(struct fg_chip *chip)
if (ima_opr_sts & IACS_RDY_BIT)
break;
- if (!(--timeout))
+ if (!(--tries))
break;
/* delay for iacs_ready to be asserted */
usleep_range(5000, 7000);
}
- if (!timeout) {
+ if (!tries) {
pr_err("IACS_RDY not set\n");
-
- rc = fg_check_for_ima_errors(chip);
+ /* check for error condition */
+ rc = fg_clear_ima_errors_if_any(chip, false);
if (rc < 0) {
pr_err("Failed to check for ima errors rc=%d\n", rc);
return rc;
@@ -250,7 +355,7 @@ static int __fg_interleaved_mem_write(struct fg_chip *chip, u16 address,
}
/* check for error condition */
- rc = fg_check_for_ima_errors(chip);
+ rc = fg_clear_ima_errors_if_any(chip, false);
if (rc < 0) {
pr_err("Failed to check for ima errors rc=%d\n", rc);
return rc;
@@ -296,7 +401,7 @@ static int __fg_interleaved_mem_read(struct fg_chip *chip, u16 address,
offset = 0;
/* check for error condition */
- rc = fg_check_for_ima_errors(chip);
+ rc = fg_clear_ima_errors_if_any(chip, false);
if (rc < 0) {
pr_err("Failed to check for ima errors rc=%d\n", rc);
return rc;
@@ -581,5 +686,19 @@ int fg_ima_init(struct fg_chip *chip)
return rc;
}
+ /* Clear DMA errors if any before clearing IMA errors */
+ rc = fg_clear_dma_errors_if_any(chip);
+ if (rc < 0) {
+ pr_err("Error in checking DMA errors rc:%d\n", rc);
+ return rc;
+ }
+
+ /* Clear IMA errors if any before SRAM transactions can begin */
+ rc = fg_clear_ima_errors_if_any(chip, true);
+ if (rc < 0 && rc != -EAGAIN) {
+ pr_err("Error in checking IMA errors rc:%d\n", rc);
+ return rc;
+ }
+
return 0;
}
diff --git a/drivers/power/qcom-charger/fg-reg.h b/drivers/power/qcom-charger/fg-reg.h
index 431e28a7eb1f..ffc46f328f91 100644
--- a/drivers/power/qcom-charger/fg-reg.h
+++ b/drivers/power/qcom-charger/fg-reg.h
@@ -26,6 +26,9 @@
#define BATT_SOC_LOW_PWR_CFG(chip) (chip->batt_soc_base + 0x52)
#define BATT_SOC_LOW_PWR_STS(chip) (chip->batt_soc_base + 0x56)
+/* BATT_SOC_INT_RT_STS */
+#define MSOC_EMPTY_BIT BIT(5)
+
/* BATT_SOC_EN_CTL */
#define FG_ALGORITHM_EN_BIT BIT(7)
@@ -258,6 +261,7 @@
#define ESR_REQ_CTL_EN_BIT BIT(0)
/* FG_MEM_IF register and bit definitions */
+#define MEM_IF_INT_RT_STS(chip) ((chip->mem_if_base) + 0x10)
#define MEM_IF_MEM_INTF_CFG(chip) ((chip->mem_if_base) + 0x50)
#define MEM_IF_IMA_CTL(chip) ((chip->mem_if_base) + 0x51)
#define MEM_IF_IMA_CFG(chip) ((chip->mem_if_base) + 0x52)
@@ -273,6 +277,11 @@
#define MEM_IF_WR_DATA3(chip) ((chip->mem_if_base) + 0x66)
#define MEM_IF_RD_DATA0(chip) ((chip->mem_if_base) + 0x67)
#define MEM_IF_RD_DATA3(chip) ((chip->mem_if_base) + 0x6A)
+#define MEM_IF_DMA_STS(chip) ((chip->mem_if_base) + 0x70)
+#define MEM_IF_DMA_CTL(chip) ((chip->mem_if_base) + 0x71)
+
+/* MEM_IF_INT_RT_STS */
+#define MEM_XCP_BIT BIT(1)
/* MEM_IF_MEM_INTF_CFG */
#define MEM_ACCESS_REQ_BIT BIT(7)
@@ -286,10 +295,19 @@
/* MEM_IF_IMA_CFG */
#define IACS_CLR_BIT BIT(2)
#define IACS_INTR_SRC_SLCT_BIT BIT(3)
+#define STATIC_CLK_EN_BIT BIT(4)
/* MEM_IF_IMA_OPR_STS */
#define IACS_RDY_BIT BIT(1)
+/* MEM_IF_IMA_EXP_STS */
+#define IACS_ERR_BIT BIT(0)
+#define XCT_TYPE_ERR_BIT BIT(1)
+#define DATA_RD_ERR_BIT BIT(3)
+#define DATA_WR_ERR_BIT BIT(4)
+#define ADDR_BURST_WRAP_BIT BIT(5)
+#define ADDR_STABLE_ERR_BIT BIT(7)
+
/* MEM_IF_IMA_ERR_STS */
#define ADDR_STBL_ERR_BIT BIT(7)
#define WR_ACS_ERR_BIT BIT(6)
@@ -297,4 +315,11 @@
/* MEM_IF_FG_BEAT_COUNT */
#define BEAT_COUNT_MASK GENMASK(3, 0)
+
+/* MEM_IF_DMA_STS */
+#define DMA_WRITE_ERROR_BIT BIT(1)
+#define DMA_READ_ERROR_BIT BIT(2)
+
+/* MEM_IF_DMA_CTL */
+#define DMA_CLEAR_LOG_BIT BIT(0)
#endif
diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c
index 4ee94b990382..dfbf1adc5a38 100644
--- a/drivers/power/qcom-charger/qpnp-fg-gen3.c
+++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c
@@ -655,12 +655,71 @@ static int fg_get_msoc_raw(struct fg_chip *chip, int *val)
return 0;
}
+static bool is_batt_empty(struct fg_chip *chip)
+{
+ u8 status;
+ int rc, vbatt_uv, msoc;
+
+ rc = fg_read(chip, BATT_SOC_INT_RT_STS(chip), &status, 1);
+ if (rc < 0) {
+ pr_err("failed to read addr=0x%04x, rc=%d\n",
+ BATT_SOC_INT_RT_STS(chip), rc);
+ return false;
+ }
+
+ if (!(status & MSOC_EMPTY_BIT))
+ return false;
+
+ rc = fg_get_battery_voltage(chip, &vbatt_uv);
+ if (rc < 0) {
+ pr_err("failed to get battery voltage, rc=%d\n", rc);
+ return false;
+ }
+
+ rc = fg_get_msoc_raw(chip, &msoc);
+ if (!rc)
+ pr_warn("batt_soc_rt_sts: %x vbatt: %d uV msoc:%d\n", status,
+ vbatt_uv, msoc);
+
+ return ((vbatt_uv < chip->dt.cutoff_volt_mv * 1000) ? true : false);
+}
+
+#define DEBUG_BATT_ID_KOHMS 7
+static bool is_debug_batt_id(struct fg_chip *chip)
+{
+ int batt_id_delta = 0;
+
+ if (!chip->batt_id_kohms)
+ return false;
+
+ batt_id_delta = abs(chip->batt_id_kohms - DEBUG_BATT_ID_KOHMS);
+ if (batt_id_delta <= 1) {
+ fg_dbg(chip, FG_POWER_SUPPLY, "Debug battery id: %dKohms\n",
+ chip->batt_id_kohms);
+ return true;
+ }
+
+ return false;
+}
+
#define FULL_CAPACITY 100
#define FULL_SOC_RAW 255
+#define DEBUG_BATT_SOC 67
+#define EMPTY_SOC 0
static int fg_get_prop_capacity(struct fg_chip *chip, int *val)
{
int rc, msoc;
+ if (is_debug_batt_id(chip)) {
+ *val = DEBUG_BATT_SOC;
+ return 0;
+ }
+
+ if (is_batt_empty(chip)) {
+ *val = EMPTY_SOC;
+ return 0;
+ }
+
if (chip->charge_full) {
*val = FULL_CAPACITY;
return 0;
@@ -725,7 +784,7 @@ static int fg_get_batt_profile(struct fg_chip *chip)
}
batt_id /= 1000;
- chip->batt_id = batt_id;
+ chip->batt_id_kohms = batt_id;
batt_node = of_find_node_by_name(node, "qcom,battery-data");
if (!batt_node) {
pr_err("Batterydata not available\n");
@@ -879,6 +938,17 @@ static bool is_charger_available(struct fg_chip *chip)
return true;
}
+static bool is_parallel_charger_available(struct fg_chip *chip)
+{
+ if (!chip->parallel_psy)
+ chip->parallel_psy = power_supply_get_by_name("parallel");
+
+ if (!chip->parallel_psy)
+ return false;
+
+ return true;
+}
+
static int fg_save_learned_cap_to_sram(struct fg_chip *chip)
{
int16_t cc_mah;
@@ -1351,6 +1421,72 @@ static int fg_adjust_recharge_soc(struct fg_chip *chip)
return 0;
}
+static int fg_esr_fcc_config(struct fg_chip *chip)
+{
+ union power_supply_propval prop = {0, };
+ int rc;
+ bool parallel_en = false;
+
+ if (is_parallel_charger_available(chip)) {
+ rc = power_supply_get_property(chip->parallel_psy,
+ POWER_SUPPLY_PROP_CHARGING_ENABLED, &prop);
+ if (rc < 0) {
+ pr_err("Error in reading charging_enabled from parallel_psy, rc=%d\n",
+ rc);
+ return rc;
+ }
+ parallel_en = prop.intval;
+ }
+
+ fg_dbg(chip, FG_POWER_SUPPLY, "status: %d parallel_en: %d esr_fcc_ctrl_en: %d\n",
+ chip->status, parallel_en, chip->esr_fcc_ctrl_en);
+
+ if (chip->status == POWER_SUPPLY_STATUS_CHARGING && parallel_en) {
+ if (chip->esr_fcc_ctrl_en)
+ return 0;
+
+ /*
+ * When parallel charging is enabled, configure ESR FCC to
+ * 300mA to trigger an ESR pulse. Without this, FG can ask
+ * the main charger to increase FCC when it is supposed to
+ * decrease it.
+ */
+ rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip),
+ ESR_FAST_CRG_IVAL_MASK |
+ ESR_FAST_CRG_CTL_EN_BIT,
+ ESR_FCC_300MA | ESR_FAST_CRG_CTL_EN_BIT);
+ if (rc < 0) {
+ pr_err("Error in writing to %04x, rc=%d\n",
+ BATT_INFO_ESR_FAST_CRG_CFG(chip), rc);
+ return rc;
+ }
+
+ chip->esr_fcc_ctrl_en = true;
+ } else {
+ if (!chip->esr_fcc_ctrl_en)
+ return 0;
+
+ /*
+ * If we're here, then it means either the device is not in
+ * charging state or parallel charging is disabled. Disable
+ * ESR fast charge current control in SW.
+ */
+ rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip),
+ ESR_FAST_CRG_CTL_EN_BIT, 0);
+ if (rc < 0) {
+ pr_err("Error in writing to %04x, rc=%d\n",
+ BATT_INFO_ESR_FAST_CRG_CFG(chip), rc);
+ return rc;
+ }
+
+ chip->esr_fcc_ctrl_en = false;
+ }
+
+ fg_dbg(chip, FG_STATUS, "esr_fcc_ctrl_en set to %d\n",
+ chip->esr_fcc_ctrl_en);
+ return 0;
+}
+
static void status_change_work(struct work_struct *work)
{
struct fg_chip *chip = container_of(work,
@@ -1398,6 +1534,10 @@ static void status_change_work(struct work_struct *work)
rc = fg_adjust_ki_coeff_dischg(chip);
if (rc < 0)
pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
+
+ rc = fg_esr_fcc_config(chip);
+ if (rc < 0)
+ pr_err("Error in adjusting FCC for ESR, rc=%d\n", rc);
out:
pm_relax(chip->dev);
}
@@ -1556,6 +1696,10 @@ static void dump_sram(u8 *buf, int len)
}
}
+#define PROFILE_LOAD_BIT BIT(0)
+#define BOOTLOADER_LOAD_BIT BIT(1)
+#define BOOTLOADER_RESTART_BIT BIT(2)
+#define HLOS_RESTART_BIT BIT(3)
static bool is_profile_load_required(struct fg_chip *chip)
{
u8 buf[PROFILE_COMP_LEN], val;
@@ -1570,7 +1714,7 @@ static bool is_profile_load_required(struct fg_chip *chip)
}
/* Check if integrity bit is set */
- if (val == 0x01) {
+ if (val & PROFILE_LOAD_BIT) {
fg_dbg(chip, FG_STATUS, "Battery profile integrity bit is set\n");
rc = fg_sram_read(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
buf, PROFILE_COMP_LEN, FG_IMA_DEFAULT);
@@ -1728,7 +1872,7 @@ static void profile_load_work(struct work_struct *work)
fg_dbg(chip, FG_STATUS, "SOC is ready\n");
/* Set the profile integrity bit */
- val = 0x1;
+ val = HLOS_RESTART_BIT | PROFILE_LOAD_BIT;
rc = fg_sram_write(chip, PROFILE_INTEGRITY_WORD,
PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
if (rc < 0) {
@@ -2152,6 +2296,37 @@ static int fg_memif_init(struct fg_chip *chip)
/* INTERRUPT HANDLERS STAY HERE */
+static irqreturn_t fg_mem_xcp_irq_handler(int irq, void *data)
+{
+ struct fg_chip *chip = data;
+ u8 status;
+ int rc;
+
+ rc = fg_read(chip, MEM_IF_INT_RT_STS(chip), &status, 1);
+ if (rc < 0) {
+ pr_err("failed to read addr=0x%04x, rc=%d\n",
+ MEM_IF_INT_RT_STS(chip), rc);
+ return IRQ_HANDLED;
+ }
+
+ fg_dbg(chip, FG_IRQ, "irq %d triggered, status:%d\n", irq, status);
+ if (status & MEM_XCP_BIT) {
+ rc = fg_clear_dma_errors_if_any(chip);
+ if (rc < 0) {
+ pr_err("Error in clearing DMA error, rc=%d\n", rc);
+ return IRQ_HANDLED;
+ }
+
+ mutex_lock(&chip->sram_rw_lock);
+ rc = fg_clear_ima_errors_if_any(chip, true);
+ if (rc < 0 && rc != -EAGAIN)
+ pr_err("Error in checking IMA errors rc:%d\n", rc);
+ mutex_unlock(&chip->sram_rw_lock);
+ }
+
+ return IRQ_HANDLED;
+}
+
static irqreturn_t fg_vbatt_low_irq_handler(int irq, void *data)
{
struct fg_chip *chip = data;
@@ -2248,14 +2423,10 @@ static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data)
struct fg_chip *chip = data;
int rc;
+ fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
if (chip->cyc_ctr.en)
schedule_work(&chip->cycle_count_work);
- if (is_charger_available(chip))
- power_supply_changed(chip->batt_psy);
-
- fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
-
if (chip->cl.active)
fg_cap_learning_update(chip);
@@ -2267,6 +2438,9 @@ static irqreturn_t fg_delta_soc_irq_handler(int irq, void *data)
if (rc < 0)
pr_err("Error in adjusting ki_coeff_dischg, rc=%d\n", rc);
+ if (is_charger_available(chip))
+ power_supply_changed(chip->batt_psy);
+
return IRQ_HANDLED;
}
@@ -2274,10 +2448,10 @@ static irqreturn_t fg_empty_soc_irq_handler(int irq, void *data)
{
struct fg_chip *chip = data;
+ fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
if (is_charger_available(chip))
power_supply_changed(chip->batt_psy);
- fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
return IRQ_HANDLED;
}
@@ -2291,9 +2465,7 @@ static irqreturn_t fg_soc_irq_handler(int irq, void *data)
static irqreturn_t fg_dummy_irq_handler(int irq, void *data)
{
- struct fg_chip *chip = data;
-
- fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
+ pr_debug("irq %d triggered\n", irq);
return IRQ_HANDLED;
}
@@ -2367,7 +2539,7 @@ static struct fg_irq_info fg_irqs[FG_IRQ_MAX] = {
},
[MEM_XCP_IRQ] = {
.name = "mem-xcp",
- .handler = fg_dummy_irq_handler,
+ .handler = fg_mem_xcp_irq_handler,
},
[IMA_RDY_IRQ] = {
.name = "ima-rdy",
@@ -2495,7 +2667,7 @@ static int fg_parse_ki_coefficients(struct fg_chip *chip)
}
#define DEFAULT_CUTOFF_VOLT_MV 3200
-#define DEFAULT_EMPTY_VOLT_MV 3100
+#define DEFAULT_EMPTY_VOLT_MV 2800
#define DEFAULT_CHG_TERM_CURR_MA 100
#define DEFAULT_SYS_TERM_CURR_MA -125
#define DEFAULT_DELTA_SOC_THR 1
@@ -2612,7 +2784,7 @@ static int fg_parse_dt(struct fg_chip *chip)
rc = fg_get_batt_profile(chip);
if (rc < 0)
pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n",
- chip->batt_id, rc);
+ chip->batt_id_kohms, rc);
/* Read all the optional properties below */
rc = of_property_read_u32(node, "qcom,fg-cutoff-voltage", &temp);
@@ -2783,7 +2955,7 @@ static int fg_gen3_probe(struct platform_device *pdev)
{
struct fg_chip *chip;
struct power_supply_config fg_psy_cfg;
- int rc;
+ int rc, msoc, volt_uv, batt_temp;
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
@@ -2876,11 +3048,22 @@ static int fg_gen3_probe(struct platform_device *pdev)
goto exit;
}
+ rc = fg_get_battery_voltage(chip, &volt_uv);
+ if (!rc)
+ rc = fg_get_prop_capacity(chip, &msoc);
+
+ if (!rc)
+ rc = fg_get_battery_temp(chip, &batt_temp);
+
+ if (!rc)
+ pr_info("battery SOC:%d voltage: %duV temp: %d id: %dKOhms\n",
+ msoc, volt_uv, batt_temp, chip->batt_id_kohms);
+
+ device_init_wakeup(chip->dev, true);
if (chip->profile_available)
schedule_delayed_work(&chip->profile_load_work, 0);
- device_init_wakeup(chip->dev, true);
- pr_debug("FG GEN3 driver successfully probed\n");
+ pr_debug("FG GEN3 driver probed successfully\n");
return 0;
exit:
fg_cleanup(chip);
diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c
index f9d76c56aa2e..a00ad8343a88 100644
--- a/drivers/power/qcom-charger/qpnp-smb2.c
+++ b/drivers/power/qcom-charger/qpnp-smb2.c
@@ -225,6 +225,7 @@ struct smb_dt_props {
s32 step_cc_delta[STEP_CHARGING_MAX_STEPS];
struct device_node *revid_dev_node;
int float_option;
+ int chg_inhibit_thr_mv;
bool hvdcp_disable;
};
@@ -335,6 +336,14 @@ static int smb2_parse_dt(struct smb2 *chip)
chip->dt.hvdcp_disable = of_property_read_bool(node,
"qcom,hvdcp-disable");
+ of_property_read_u32(node, "qcom,chg-inhibit-threshold-mv",
+ &chip->dt.chg_inhibit_thr_mv);
+ if ((chip->dt.chg_inhibit_thr_mv < 0 ||
+ chip->dt.chg_inhibit_thr_mv > 300)) {
+ pr_err("qcom,chg-inhibit-threshold-mv is incorrect\n");
+ return -EINVAL;
+ }
+
return 0;
}
@@ -1213,6 +1222,40 @@ static int smb2_init_hw(struct smb2 *chip)
return rc;
}
+ switch (chip->dt.chg_inhibit_thr_mv) {
+ case 50:
+ rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
+ CHARGE_INHIBIT_THRESHOLD_MASK,
+ CHARGE_INHIBIT_THRESHOLD_50MV);
+ break;
+ case 100:
+ rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
+ CHARGE_INHIBIT_THRESHOLD_MASK,
+ CHARGE_INHIBIT_THRESHOLD_100MV);
+ break;
+ case 200:
+ rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
+ CHARGE_INHIBIT_THRESHOLD_MASK,
+ CHARGE_INHIBIT_THRESHOLD_200MV);
+ break;
+ case 300:
+ rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
+ CHARGE_INHIBIT_THRESHOLD_MASK,
+ CHARGE_INHIBIT_THRESHOLD_300MV);
+ break;
+ case 0:
+ rc = smblib_masked_write(chg, CHGR_CFG2_REG,
+ CHARGER_INHIBIT_BIT, 0);
+ default:
+ break;
+ }
+
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't configure charge inhibit threshold rc=%d\n",
+ rc);
+ return rc;
+ }
+
return rc;
}
@@ -1241,6 +1284,7 @@ static int smb2_setup_wa_flags(struct smb2 *chip)
switch (pmic_rev_id->pmic_subtype) {
case PMICOBALT_SUBTYPE:
+ chip->chg.wa_flags |= BOOST_BACK_WA;
if (pmic_rev_id->rev4 == PMICOBALT_V1P1_REV4) /* PMI rev 1.1 */
chg->wa_flags |= QC_CHARGER_DETECTION_WA_BIT;
break;
@@ -1451,7 +1495,8 @@ static struct smb2_irq_info smb2_irqs[] = {
},
{
.name = "switcher-power-ok",
- .handler = smblib_handle_debug,
+ .handler = smblib_handle_switcher_power_ok,
+ .storm_data = {true, 1000, 3},
},
};
@@ -1746,6 +1791,16 @@ static int smb2_remove(struct platform_device *pdev)
return 0;
}
+static void smb2_shutdown(struct platform_device *pdev)
+{
+ struct smb2 *chip = platform_get_drvdata(pdev);
+ struct smb_charger *chg = &chip->chg;
+
+ smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
+ HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT, 0);
+ smblib_write(chg, CMD_HVDCP_2_REG, FORCE_5V_BIT);
+}
+
static const struct of_device_id match_table[] = {
{ .compatible = "qcom,qpnp-smb2", },
{ },
@@ -1759,6 +1814,7 @@ static struct platform_driver smb2_driver = {
},
.probe = smb2_probe,
.remove = smb2_remove,
+ .shutdown = smb2_shutdown,
};
module_platform_driver(smb2_driver);
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c
index 198e77469bbe..144169ea4930 100644
--- a/drivers/power/qcom-charger/smb-lib.c
+++ b/drivers/power/qcom-charger/smb-lib.c
@@ -490,7 +490,7 @@ static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg)
/* ensure hvdcp is enabled */
if (!get_effective_result(chg->hvdcp_disable_votable)) {
apsd_result = smblib_get_apsd_result(chg);
- if (apsd_result->pst == POWER_SUPPLY_TYPE_USB_HVDCP) {
+ if (apsd_result->bit & (QC_2P0_BIT | QC_3P0_BIT)) {
/* rerun APSD */
smblib_dbg(chg, PR_MISC, "rerun APSD\n");
smblib_masked_write(chg, CMD_APSD_REG,
@@ -596,7 +596,11 @@ static int smblib_usb_suspend_vote_callback(struct votable *votable, void *data,
{
struct smb_charger *chg = data;
- return smblib_set_usb_suspend(chg, suspend);
+ /* resume input if suspend is invalid */
+ if (suspend < 0)
+ suspend = 0;
+
+ return smblib_set_usb_suspend(chg, (bool)suspend);
}
static int smblib_dc_suspend_vote_callback(struct votable *votable, void *data,
@@ -604,10 +608,11 @@ static int smblib_dc_suspend_vote_callback(struct votable *votable, void *data,
{
struct smb_charger *chg = data;
+ /* resume input if suspend is invalid */
if (suspend < 0)
- suspend = false;
+ suspend = 0;
- return smblib_set_dc_suspend(chg, suspend);
+ return smblib_set_dc_suspend(chg, (bool)suspend);
}
static int smblib_fcc_max_vote_callback(struct votable *votable, void *data,
@@ -956,12 +961,13 @@ static int smblib_apsd_disable_vote_callback(struct votable *votable,
* OTG REGULATOR *
*****************/
-#define OTG_SOFT_START_DELAY_MS 20
+#define MAX_SOFTSTART_TRIES 2
int smblib_vbus_regulator_enable(struct regulator_dev *rdev)
{
struct smb_charger *chg = rdev_get_drvdata(rdev);
u8 stat;
int rc = 0;
+ int tries = MAX_SOFTSTART_TRIES;
rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG,
ENG_BUCKBOOST_HALT1_8_MODE_BIT,
@@ -978,14 +984,25 @@ int smblib_vbus_regulator_enable(struct regulator_dev *rdev)
return rc;
}
- msleep(OTG_SOFT_START_DELAY_MS);
- rc = smblib_read(chg, OTG_STATUS_REG, &stat);
- if (rc < 0) {
- smblib_err(chg, "Couldn't read OTG_STATUS_REG rc=%d\n", rc);
- return rc;
- }
- if (stat & BOOST_SOFTSTART_DONE_BIT)
- smblib_otg_cl_config(chg, chg->otg_cl_ua);
+ /* waiting for boost readiness, usually ~1ms, 2ms in worst case */
+ do {
+ usleep_range(1000, 1100);
+
+ rc = smblib_read(chg, OTG_STATUS_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read OTG_STATUS_REG rc=%d\n",
+ rc);
+ return rc;
+ }
+ if (stat & BOOST_SOFTSTART_DONE_BIT) {
+ smblib_otg_cl_config(chg, chg->otg_cl_ua);
+ break;
+ }
+ } while (--tries);
+
+ if (tries == 0)
+ smblib_err(chg, "Timeout waiting for boost softstart rc=%d\n",
+ rc);
return rc;
}
@@ -1997,6 +2014,45 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
"Couldn't enable vconn on CC line rc=%d\n", rc);
return rc;
}
+
+ rc = vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n",
+ rc);
+ return rc;
+ }
+
+ rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
+ USBIN_MODE_CHG_BIT, USBIN_MODE_CHG_BIT);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't change USB mode rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = smblib_masked_write(chg, CMD_APSD_REG,
+ ICL_OVERRIDE_BIT, ICL_OVERRIDE_BIT);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't override APSD rc=%d\n", rc);
+ return rc;
+ }
+ } else {
+ rc = smblib_masked_write(chg, CMD_APSD_REG,
+ ICL_OVERRIDE_BIT, 0);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't override APSD rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
+ USBIN_MODE_CHG_BIT, 0);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't change USB mode rc=%d\n", rc);
+ return rc;
+ }
}
/* CC pin selection s/w override in PD session; h/w otherwise. */
@@ -2027,6 +2083,52 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
return rc;
}
+int smblib_reg_block_update(struct smb_charger *chg,
+ struct reg_info *entry)
+{
+ int rc = 0;
+
+ while (entry && entry->reg) {
+ rc = smblib_read(chg, entry->reg, &entry->bak);
+ if (rc < 0) {
+ dev_err(chg->dev, "Error in reading %s rc=%d\n",
+ entry->desc, rc);
+ break;
+ }
+ entry->bak &= entry->mask;
+
+ rc = smblib_masked_write(chg, entry->reg,
+ entry->mask, entry->val);
+ if (rc < 0) {
+ dev_err(chg->dev, "Error in writing %s rc=%d\n",
+ entry->desc, rc);
+ break;
+ }
+ entry++;
+ }
+
+ return rc;
+}
+
+int smblib_reg_block_restore(struct smb_charger *chg,
+ struct reg_info *entry)
+{
+ int rc = 0;
+
+ while (entry && entry->reg) {
+ rc = smblib_masked_write(chg, entry->reg,
+ entry->mask, entry->bak);
+ if (rc < 0) {
+ dev_err(chg->dev, "Error in writing %s rc=%d\n",
+ entry->desc, rc);
+ break;
+ }
+ entry++;
+ }
+
+ return rc;
+}
+
int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
const union power_supply_propval *val)
{
@@ -2230,11 +2332,8 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
}
}
- if (!chg->dpdm_reg)
- goto skip_dpdm_float;
-
if (chg->vbus_present) {
- if (!regulator_is_enabled(chg->dpdm_reg)) {
+ if (chg->dpdm_reg && !regulator_is_enabled(chg->dpdm_reg)) {
smblib_dbg(chg, PR_MISC, "enabling DPDM regulator\n");
rc = regulator_enable(chg->dpdm_reg);
if (rc < 0)
@@ -2242,7 +2341,14 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
rc);
}
} else {
- if (regulator_is_enabled(chg->dpdm_reg)) {
+ if (chg->wa_flags & BOOST_BACK_WA) {
+ vote(chg->usb_suspend_votable,
+ BOOST_BACK_VOTER, false, 0);
+ vote(chg->dc_suspend_votable,
+ BOOST_BACK_VOTER, false, 0);
+ }
+
+ if (chg->dpdm_reg && regulator_is_enabled(chg->dpdm_reg)) {
smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n");
rc = regulator_disable(chg->dpdm_reg);
if (rc < 0)
@@ -2251,7 +2357,6 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
}
}
-skip_dpdm_float:
power_supply_changed(chg->usb_psy);
smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s %s\n",
irq_data->name, chg->vbus_present ? "attached" : "detached");
@@ -2683,6 +2788,39 @@ irqreturn_t smblib_handle_high_duty_cycle(int irq, void *data)
return IRQ_HANDLED;
}
+irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data)
+{
+ struct smb_irq_data *irq_data = data;
+ struct smb_charger *chg = irq_data->parent_data;
+ int rc;
+ u8 stat;
+
+ if (!(chg->wa_flags & BOOST_BACK_WA))
+ return IRQ_HANDLED;
+
+ rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n", rc);
+ return IRQ_HANDLED;
+ }
+
+ if ((stat & USE_USBIN_BIT) &&
+ get_effective_result(chg->usb_suspend_votable))
+ return IRQ_HANDLED;
+
+ if ((stat & USE_DCIN_BIT) &&
+ get_effective_result(chg->dc_suspend_votable))
+ return IRQ_HANDLED;
+
+ if (is_storming(&irq_data->storm_data)) {
+ smblib_dbg(chg, PR_MISC, "reverse boost detected; suspending input\n");
+ vote(chg->usb_suspend_votable, BOOST_BACK_VOTER, true, 0);
+ vote(chg->dc_suspend_votable, BOOST_BACK_VOTER, true, 0);
+ }
+
+ return IRQ_HANDLED;
+}
+
/***************
* Work Queues *
***************/
@@ -2743,7 +2881,9 @@ static void smblib_pl_taper_work(struct work_struct *work)
union power_supply_propval pval = {0, };
int rc;
+ smblib_dbg(chg, PR_PARALLEL, "starting parallel taper work\n");
if (chg->pl.slave_fcc_ua < MINIMUM_PARALLEL_FCC_UA) {
+ smblib_dbg(chg, PR_PARALLEL, "parallel taper is done\n");
vote(chg->pl_disable_votable, TAPER_END_VOTER, true, 0);
goto done;
}
@@ -2755,6 +2895,7 @@ static void smblib_pl_taper_work(struct work_struct *work)
}
if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) {
+ smblib_dbg(chg, PR_PARALLEL, "master is taper charging; reducing slave FCC\n");
vote(chg->awake_votable, PL_TAPER_WORK_RUNNING_VOTER, true, 0);
/* Reduce the taper percent by 25 percent */
chg->pl.taper_pct = chg->pl.taper_pct
@@ -2768,6 +2909,8 @@ static void smblib_pl_taper_work(struct work_struct *work)
/*
* Master back to Fast Charge, get out of this round of taper reduction
*/
+ smblib_dbg(chg, PR_PARALLEL, "master is fast charging; waiting for next taper\n");
+
done:
vote(chg->awake_votable, PL_TAPER_WORK_RUNNING_VOTER, false, 0);
}
diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h
index 4be06ffcfb25..2809ddadbd90 100644
--- a/drivers/power/qcom-charger/smb-lib.h
+++ b/drivers/power/qcom-charger/smb-lib.h
@@ -46,6 +46,7 @@ enum print_reason {
#define VBUS_CC_SHORT_VOTER "VBUS_CC_SHORT_VOTER"
#define LEGACY_CABLE_VOTER "LEGACY_CABLE_VOTER"
#define PD_INACTIVE_VOTER "PD_INACTIVE_VOTER"
+#define BOOST_BACK_VOTER "BOOST_BACK_VOTER"
enum smb_mode {
PARALLEL_MASTER = 0,
@@ -55,6 +56,7 @@ enum smb_mode {
enum {
QC_CHARGER_DETECTION_WA_BIT = BIT(0),
+ BOOST_BACK_WA = BIT(1),
};
struct smb_regulator {
@@ -116,6 +118,14 @@ struct smb_iio {
struct iio_channel *batt_i_chan;
};
+struct reg_info {
+ u16 reg;
+ u8 mask;
+ u8 val;
+ u8 bak;
+ const char *desc;
+};
+
struct smb_charger {
struct device *dev;
char *name;
@@ -240,6 +250,7 @@ irqreturn_t smblib_handle_icl_change(int irq, void *data);
irqreturn_t smblib_handle_usb_typec_change(int irq, void *data);
irqreturn_t smblib_handle_dc_plugin(int irq, void *data);
irqreturn_t smblib_handle_high_duty_cycle(int irq, void *data);
+irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data);
int smblib_get_prop_input_suspend(struct smb_charger *chg,
union power_supply_propval *val);
diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h
index a74fcf730a8c..2aed4cf294a2 100644
--- a/drivers/power/qcom-charger/smb-reg.h
+++ b/drivers/power/qcom-charger/smb-reg.h
@@ -184,6 +184,10 @@ enum {
#define CHARGE_INHIBIT_THRESHOLD_CFG_REG (CHGR_BASE + 0x72)
#define CHARGE_INHIBIT_THRESHOLD_MASK GENMASK(1, 0)
+#define CHARGE_INHIBIT_THRESHOLD_50MV 0
+#define CHARGE_INHIBIT_THRESHOLD_100MV 1
+#define CHARGE_INHIBIT_THRESHOLD_200MV 2
+#define CHARGE_INHIBIT_THRESHOLD_300MV 3
#define RECHARGE_THRESHOLD_CFG_REG (CHGR_BASE + 0x73)
#define RECHARGE_THRESHOLD_MASK GENMASK(1, 0)
diff --git a/drivers/power/qcom-charger/smb138x-charger.c b/drivers/power/qcom-charger/smb138x-charger.c
index 9a87ff5fb081..9dc528a6bb45 100644
--- a/drivers/power/qcom-charger/smb138x-charger.c
+++ b/drivers/power/qcom-charger/smb138x-charger.c
@@ -397,6 +397,7 @@ static int smb138x_init_batt_psy(struct smb138x *chip)
*****************************/
static enum power_supply_property smb138x_parallel_props[] = {
+ POWER_SUPPLY_PROP_CHARGE_TYPE,
POWER_SUPPLY_PROP_CHARGING_ENABLED,
POWER_SUPPLY_PROP_PIN_ENABLED,
POWER_SUPPLY_PROP_INPUT_SUSPEND,
@@ -417,6 +418,9 @@ static int smb138x_parallel_get_prop(struct power_supply *psy,
u8 temp;
switch (prop) {
+ case POWER_SUPPLY_PROP_CHARGE_TYPE:
+ rc = smblib_get_prop_batt_charge_type(chg, val);
+ break;
case POWER_SUPPLY_PROP_CHARGING_ENABLED:
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_5_REG,
&temp);
diff --git a/drivers/regulator/cprh-kbss-regulator.c b/drivers/regulator/cprh-kbss-regulator.c
index 953ea5f33f40..5661ae75843c 100644
--- a/drivers/regulator/cprh-kbss-regulator.c
+++ b/drivers/regulator/cprh-kbss-regulator.c
@@ -257,7 +257,7 @@ msmcobalt_v2_kbss_fuse_ref_volt[2][MSMCOBALT_KBSS_FUSE_CORNERS] = {
#define MSMCOBALT_KBSS_POWER_TEMP_SENSOR_ID_START 1
#define MSMCOBALT_KBSS_POWER_TEMP_SENSOR_ID_END 5
#define MSMCOBALT_KBSS_PERFORMANCE_TEMP_SENSOR_ID_START 6
-#define MSMCOBALT_KBSS_PERFORMANCE_TEMP_SENSOR_ID_END 11
+#define MSMCOBALT_KBSS_PERFORMANCE_TEMP_SENSOR_ID_END 10
#define MSMCOBALT_KBSS_POWER_AGING_SENSOR_ID 0
#define MSMCOBALT_KBSS_POWER_AGING_BYPASS_MASK0 0
diff --git a/drivers/regulator/qpnp-labibb-regulator.c b/drivers/regulator/qpnp-labibb-regulator.c
index 2e41401f8580..3d0be1f8a5b5 100644
--- a/drivers/regulator/qpnp-labibb-regulator.c
+++ b/drivers/regulator/qpnp-labibb-regulator.c
@@ -32,6 +32,7 @@
#define QPNP_LABIBB_REGULATOR_DRIVER_NAME "qcom,qpnp-labibb-regulator"
+#define REG_REVISION_2 0x01
#define REG_PERPH_TYPE 0x04
#define QPNP_LAB_TYPE 0x24
@@ -60,6 +61,7 @@
#define REG_LAB_PRECHARGE_CTL 0x5E
#define REG_LAB_SOFT_START_CTL 0x5F
#define REG_LAB_SPARE_CTL 0x60
+#define REG_LAB_PFM_CTL 0x62
/* LAB register bits definitions */
@@ -91,9 +93,9 @@
#define LAB_IBB_EN_RDY_EN BIT(7)
/* REG_LAB_CURRENT_LIMIT */
-#define LAB_CURRENT_LIMIT_BITS 3
-#define LAB_CURRENT_LIMIT_MASK ((1 << LAB_CURRENT_LIMIT_BITS) - 1)
-#define LAB_CURRENT_LIMIT_EN BIT(7)
+#define LAB_CURRENT_LIMIT_MASK GENMASK(2, 0)
+#define LAB_CURRENT_LIMIT_EN_BIT BIT(7)
+#define LAB_OVERRIDE_CURRENT_MAX_BIT BIT(3)
/* REG_LAB_CURRENT_SENSE */
#define LAB_CURRENT_SENSE_GAIN_BITS 2
@@ -129,6 +131,9 @@
#define LAB_SPARE_TOUCH_WAKE_BIT BIT(3)
#define LAB_SPARE_DISABLE_SCP_BIT BIT(0)
+/* REG_LAB_PFM_CTL */
+#define LAB_PFM_EN_BIT BIT(7)
+
/* IBB register offset definitions */
#define REG_IBB_REVISION4 0x03
#define REG_IBB_STATUS1 0x08
@@ -253,12 +258,6 @@
#define SWIRE_DEFAULT_2ND_CMD_DLY_MS 20
#define SWIRE_DEFAULT_IBB_PS_ENABLE_DLY_MS 200
-enum pmic_subtype {
- PMI8994 = 10,
- PMI8950 = 17,
- PMI8996 = 19,
-};
-
/**
* enum qpnp_labibb_mode - working mode of LAB/IBB regulators
* %QPNP_LABIBB_LCD_MODE: configure LAB and IBB regulators
@@ -350,6 +349,10 @@ static const int lab_current_limit_plan[] = {
400,
600,
800,
+ 1000,
+ 1200,
+ 1400,
+ 1600,
};
static const char * const lab_current_sense_plan[] = {
@@ -477,6 +480,8 @@ struct qpnp_labibb {
struct pmic_revid_data *pmic_rev_id;
u16 lab_base;
u16 ibb_base;
+ u8 lab_dig_major;
+ u8 ibb_dig_major;
struct lab_regulator lab_vreg;
struct ibb_regulator ibb_vreg;
enum qpnp_labibb_mode mode;
@@ -487,6 +492,7 @@ struct qpnp_labibb {
bool swire_control;
bool ttw_force_lab_on;
bool skip_2nd_swire_cmd;
+ bool pfm_enable;
u32 swire_2nd_cmd_delay;
u32 swire_ibb_ps_enable_delay;
};
@@ -539,60 +545,58 @@ static struct settings lab_settings[LAB_SETTINGS_MAX] = {
SETTING(LAB_RDSON_MNGMNT, false),
};
-static int
-qpnp_labibb_read(struct qpnp_labibb *labibb, u8 *val,
- u16 base, int count)
+static int qpnp_labibb_read(struct qpnp_labibb *labibb, u8 *val, u16 address,
+ int count)
{
int rc = 0;
struct platform_device *pdev = labibb->pdev;
- if (base == 0) {
- pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
- base, to_spmi_device(pdev->dev.parent)->usid, rc);
+ if (address == 0) {
+ pr_err("address cannot be zero address=0x%02x sid=0x%02x rc=%d\n",
+ address, to_spmi_device(pdev->dev.parent)->usid, rc);
return -EINVAL;
}
- rc = regmap_bulk_read(labibb->regmap, base, val, count);
+ rc = regmap_bulk_read(labibb->regmap, address, val, count);
if (rc) {
- pr_err("SPMI read failed base=0x%02x sid=0x%02x rc=%d\n", base,
- to_spmi_device(pdev->dev.parent)->usid, rc);
+ pr_err("SPMI read failed address=0x%02x sid=0x%02x rc=%d\n",
+ address, to_spmi_device(pdev->dev.parent)->usid, rc);
return rc;
}
+
return 0;
}
-static int
-qpnp_labibb_write(struct qpnp_labibb *labibb, u16 base,
- u8 *val, int count)
+static int qpnp_labibb_write(struct qpnp_labibb *labibb, u16 address, u8 *val,
+ int count)
{
int rc = 0;
struct platform_device *pdev = labibb->pdev;
- if (base == 0) {
- pr_err("base cannot be zero base=0x%02x sid=0x%02x rc=%d\n",
- base, to_spmi_device(pdev->dev.parent)->usid, rc);
+ if (address == 0) {
+ pr_err("address cannot be zero address=0x%02x sid=0x%02x rc=%d\n",
+ address, to_spmi_device(pdev->dev.parent)->usid, rc);
return -EINVAL;
}
- rc = regmap_bulk_write(labibb->regmap, base, val, count);
+ rc = regmap_bulk_write(labibb->regmap, address, val, count);
if (rc) {
- pr_err("write failed base=0x%02x sid=0x%02x rc=%d\n",
- base, to_spmi_device(pdev->dev.parent)->usid, rc);
+ pr_err("write failed address=0x%02x sid=0x%02x rc=%d\n",
+ address, to_spmi_device(pdev->dev.parent)->usid, rc);
return rc;
}
return 0;
}
-static int
-qpnp_labibb_masked_write(struct qpnp_labibb *labibb, u16 base,
- u8 mask, u8 val)
+static int qpnp_labibb_masked_write(struct qpnp_labibb *labibb, u16 address,
+ u8 mask, u8 val)
{
int rc;
- rc = regmap_update_bits(labibb->regmap, base, mask, val);
+ rc = regmap_update_bits(labibb->regmap, address, mask, val);
if (rc) {
- pr_err("spmi write failed: addr=%03X, rc=%d\n", base, rc);
+ pr_err("spmi write failed: addr=%03X, rc=%d\n", address, rc);
return rc;
}
@@ -709,18 +713,24 @@ static int qpnp_lab_dt_init(struct qpnp_labibb *labibb,
u8 i, val;
u32 tmp;
- if (labibb->mode == QPNP_LABIBB_LCD_MODE)
- val = REG_LAB_IBB_LCD_MODE;
- else
- val = REG_LAB_IBB_AMOLED_MODE;
+ /*
+ * Do not configure LCD_AMOLED_SEL for pmicobalt as it will be done by
+ * GPIO selector.
+ */
+ if (labibb->pmic_rev_id->pmic_subtype != PMICOBALT_SUBTYPE) {
+ if (labibb->mode == QPNP_LABIBB_LCD_MODE)
+ val = REG_LAB_IBB_LCD_MODE;
+ else
+ val = REG_LAB_IBB_AMOLED_MODE;
- rc = qpnp_labibb_sec_write(labibb, labibb->lab_base,
- REG_LAB_LCD_AMOLED_SEL, &val, 1);
+ rc = qpnp_labibb_sec_write(labibb, labibb->lab_base,
+ REG_LAB_LCD_AMOLED_SEL, &val, 1);
- if (rc) {
- pr_err("qpnp_lab_sec_write register %x failed rc = %d\n",
- REG_LAB_LCD_AMOLED_SEL, rc);
- return rc;
+ if (rc) {
+ pr_err("qpnp_lab_sec_write register %x failed rc = %d\n",
+ REG_LAB_LCD_AMOLED_SEL, rc);
+ return rc;
+ }
}
val = 0;
@@ -785,7 +795,7 @@ static int qpnp_lab_dt_init(struct qpnp_labibb *labibb,
if (of_property_read_bool(of_node,
"qcom,qpnp-lab-limit-max-current-enable"))
- val |= LAB_CURRENT_LIMIT_EN;
+ val |= LAB_CURRENT_LIMIT_EN_BIT;
rc = qpnp_labibb_write(labibb, labibb->lab_base +
REG_LAB_CURRENT_LIMIT, &val, 1);
@@ -938,6 +948,88 @@ static int qpnp_lab_dt_init(struct qpnp_labibb *labibb,
return rc;
}
+#define LAB_CURRENT_MAX_1600MA 0x7
+#define LAB_CURRENT_MAX_400MA 0x1
+static int qpnp_lab_pfm_disable(struct qpnp_labibb *labibb)
+{
+ int rc = 0;
+ u8 val, mask;
+
+ mutex_lock(&(labibb->lab_vreg.lab_mutex));
+ if (!labibb->pfm_enable) {
+ pr_debug("PFM already disabled\n");
+ goto out;
+ }
+
+ val = 0;
+ mask = LAB_PFM_EN_BIT;
+ rc = qpnp_labibb_masked_write(labibb, labibb->lab_base +
+ REG_LAB_PFM_CTL, mask, val);
+ if (rc < 0) {
+ pr_err("Write register %x failed rc = %d\n",
+ REG_LAB_PFM_CTL, rc);
+ goto out;
+ }
+
+ val = LAB_CURRENT_MAX_1600MA;
+ mask = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_LIMIT_MASK;
+ rc = qpnp_labibb_masked_write(labibb, labibb->lab_base +
+ REG_LAB_CURRENT_LIMIT, mask, val);
+ if (rc < 0) {
+ pr_err("Write register %x failed rc = %d\n",
+ REG_LAB_CURRENT_LIMIT, rc);
+ goto out;
+ }
+
+ labibb->pfm_enable = false;
+out:
+ mutex_unlock(&(labibb->lab_vreg.lab_mutex));
+ return rc;
+}
+
+static int qpnp_lab_pfm_enable(struct qpnp_labibb *labibb)
+{
+ int rc = 0;
+ u8 val, mask;
+
+ mutex_lock(&(labibb->lab_vreg.lab_mutex));
+ if (labibb->pfm_enable) {
+ pr_debug("PFM already enabled\n");
+ goto out;
+ }
+
+ /* Wait for ~100uS */
+ usleep_range(100, 105);
+
+ val = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_MAX_400MA;
+ mask = LAB_OVERRIDE_CURRENT_MAX_BIT | LAB_CURRENT_LIMIT_MASK;
+ rc = qpnp_labibb_masked_write(labibb, labibb->lab_base +
+ REG_LAB_CURRENT_LIMIT, mask, val);
+ if (rc < 0) {
+ pr_err("Write register %x failed rc = %d\n",
+ REG_LAB_CURRENT_LIMIT, rc);
+ goto out;
+ }
+
+ /* Wait for ~100uS */
+ usleep_range(100, 105);
+
+ val = LAB_PFM_EN_BIT;
+ mask = LAB_PFM_EN_BIT;
+ rc = qpnp_labibb_masked_write(labibb, labibb->lab_base +
+ REG_LAB_PFM_CTL, mask, val);
+ if (rc < 0) {
+ pr_err("Write register %x failed rc = %d\n",
+ REG_LAB_PFM_CTL, rc);
+ goto out;
+ }
+
+ labibb->pfm_enable = true;
+out:
+ mutex_unlock(&(labibb->lab_vreg.lab_mutex));
+ return rc;
+}
+
static int qpnp_labibb_restore_settings(struct qpnp_labibb *labibb)
{
int rc, i;
@@ -1172,7 +1264,7 @@ static int qpnp_labibb_regulator_ttw_mode_enter(struct qpnp_labibb *labibb)
}
val = LAB_SPARE_DISABLE_SCP_BIT;
- if (labibb->pmic_rev_id->pmic_subtype != PMI8950)
+ if (labibb->pmic_rev_id->pmic_subtype != PMI8950_SUBTYPE)
val |= LAB_SPARE_TOUCH_WAKE_BIT;
rc = qpnp_labibb_write(labibb, labibb->lab_base +
REG_LAB_SPARE_CTL, &val, 1);
@@ -1199,10 +1291,10 @@ static int qpnp_labibb_regulator_ttw_mode_enter(struct qpnp_labibb *labibb)
}
switch (labibb->pmic_rev_id->pmic_subtype) {
- case PMI8996:
+ case PMI8996_SUBTYPE:
rc = qpnp_labibb_ttw_enter_ibb_pmi8996(labibb);
break;
- case PMI8950:
+ case PMI8950_SUBTYPE:
rc = qpnp_labibb_ttw_enter_ibb_pmi8950(labibb);
break;
}
@@ -1282,9 +1374,9 @@ static int qpnp_labibb_regulator_ttw_mode_exit(struct qpnp_labibb *labibb)
}
switch (labibb->pmic_rev_id->pmic_subtype) {
- case PMI8996:
- case PMI8994:
- case PMI8950:
+ case PMI8996_SUBTYPE:
+ case PMI8994_SUBTYPE:
+ case PMI8950_SUBTYPE:
rc = qpnp_labibb_ttw_exit_ibb_common(labibb);
break;
}
@@ -1437,6 +1529,15 @@ static int qpnp_labibb_regulator_disable(struct qpnp_labibb *labibb)
return -EINVAL;
}
+ if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE &&
+ labibb->mode == QPNP_LABIBB_LCD_MODE) {
+ rc = qpnp_lab_pfm_disable(labibb);
+ if (rc < 0) {
+ pr_err("Error in disabling PFM, rc=%d\n", rc);
+ return rc;
+ }
+ }
+
labibb->lab_vreg.vreg_enabled = 0;
labibb->ibb_vreg.vreg_enabled = 0;
@@ -1646,9 +1747,17 @@ static irqreturn_t lab_vreg_ok_handler(int irq, void *_labibb)
struct qpnp_labibb *labibb = _labibb;
int rc;
- rc = qpnp_skip_swire_command(labibb);
- if (rc)
- pr_err("Failed in 'qpnp_skip_swire_command' rc=%d\n", rc);
+ if (labibb->skip_2nd_swire_cmd && labibb->lab_dig_major < 2) {
+ rc = qpnp_skip_swire_command(labibb);
+ if (rc < 0)
+ pr_err("Failed in 'qpnp_skip_swire_command' rc=%d\n",
+ rc);
+ } else if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE &&
+ labibb->mode == QPNP_LABIBB_LCD_MODE) {
+ rc = qpnp_lab_pfm_enable(labibb);
+ if (rc < 0)
+ pr_err("Failed to config PFM, rc=%d\n", rc);
+ }
return IRQ_HANDLED;
}
@@ -1663,6 +1772,23 @@ static int qpnp_lab_regulator_get_voltage(struct regulator_dev *rdev)
return labibb->lab_vreg.curr_volt;
}
+static bool is_lab_vreg_ok_irq_available(struct qpnp_labibb *labibb)
+{
+ /*
+ * LAB VREG_OK interrupt is used only to skip 2nd SWIRE command in
+ * dig_major < 2 targets. For pmicobalt, it is used to enable PFM in
+ * LCD mode.
+ */
+ if (labibb->skip_2nd_swire_cmd && labibb->lab_dig_major < 2)
+ return true;
+
+ if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE &&
+ labibb->mode == QPNP_LABIBB_LCD_MODE)
+ return true;
+
+ return false;
+}
+
static struct regulator_ops qpnp_lab_ops = {
.enable = qpnp_lab_regulator_enable,
.disable = qpnp_lab_regulator_disable,
@@ -1784,16 +1910,16 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb,
}
if (of_find_property(of_node,
- "qpnp,qpnp-lab-current-sense", NULL)) {
+ "qcom,qpnp-lab-current-sense", NULL)) {
config_current_sense = true;
rc = of_property_read_string(of_node,
- "qpnp,qpnp-lab-current-sense",
+ "qcom,qpnp-lab-current-sense",
&current_sense_str);
if (!rc) {
val = qpnp_labibb_get_matching_idx(
current_sense_str);
} else {
- pr_err("qpnp,qpnp-lab-current-sense configured incorrectly rc = %d\n",
+ pr_err("qcom,qpnp-lab-current-sense configured incorrectly rc = %d\n",
rc);
return rc;
}
@@ -1811,19 +1937,6 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb,
}
}
- if (labibb->skip_2nd_swire_cmd) {
- rc = devm_request_threaded_irq(labibb->dev,
- labibb->lab_vreg.lab_vreg_ok_irq, NULL,
- lab_vreg_ok_handler,
- IRQF_ONESHOT | IRQF_TRIGGER_RISING,
- "lab-vreg-ok", labibb);
- if (rc) {
- pr_err("Failed to register 'lab-vreg-ok' irq rc=%d\n",
- rc);
- return rc;
- }
- }
-
val = (labibb->standalone) ? 0 : LAB_IBB_EN_RDY_EN;
rc = qpnp_labibb_sec_write(labibb, labibb->lab_base,
REG_LAB_IBB_EN_RDY, &val, 1);
@@ -1901,6 +2014,19 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb,
labibb->lab_vreg.vreg_enabled = 1;
}
+ if (is_lab_vreg_ok_irq_available(labibb)) {
+ rc = devm_request_threaded_irq(labibb->dev,
+ labibb->lab_vreg.lab_vreg_ok_irq, NULL,
+ lab_vreg_ok_handler,
+ IRQF_ONESHOT | IRQF_TRIGGER_RISING,
+ "lab-vreg-ok", labibb);
+ if (rc) {
+ pr_err("Failed to register 'lab-vreg-ok' irq rc=%d\n",
+ rc);
+ return rc;
+ }
+ }
+
rc = qpnp_labibb_read(labibb, &val,
labibb->lab_base + REG_LAB_MODULE_RDY, 1);
if (rc) {
@@ -1955,7 +2081,6 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb,
return -EINVAL;
}
- mutex_init(&(labibb->lab_vreg.lab_mutex));
return 0;
}
@@ -1966,18 +2091,37 @@ static int qpnp_ibb_dt_init(struct qpnp_labibb *labibb,
u32 i, tmp;
u8 val;
- if (labibb->mode == QPNP_LABIBB_LCD_MODE)
- val = REG_LAB_IBB_LCD_MODE;
- else
- val = REG_LAB_IBB_AMOLED_MODE;
+ /*
+ * Do not configure LCD_AMOLED_SEL for pmicobalt as it will be done by
+ * GPIO selector. Override the labibb->mode with what was configured
+ * by the bootloader.
+ */
+ if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE) {
+ rc = qpnp_labibb_read(labibb, &val,
+ labibb->ibb_base + REG_IBB_LCD_AMOLED_SEL, 1);
+ if (rc) {
+ pr_err("qpnp_labibb_read register %x failed rc = %d\n",
+ REG_IBB_LCD_AMOLED_SEL, rc);
+ return rc;
+ }
- rc = qpnp_labibb_sec_write(labibb, labibb->ibb_base,
- REG_LAB_LCD_AMOLED_SEL, &val, 1);
+ if (val == REG_LAB_IBB_AMOLED_MODE)
+ labibb->mode = QPNP_LABIBB_AMOLED_MODE;
+ else
+ labibb->mode = QPNP_LABIBB_LCD_MODE;
+ } else {
+ if (labibb->mode == QPNP_LABIBB_LCD_MODE)
+ val = REG_LAB_IBB_LCD_MODE;
+ else
+ val = REG_LAB_IBB_AMOLED_MODE;
- if (rc) {
- pr_err("qpnp_labibb_sec_write register %x failed rc = %d\n",
- REG_IBB_LCD_AMOLED_SEL, rc);
- return rc;
+ rc = qpnp_labibb_sec_write(labibb, labibb->ibb_base,
+ REG_LAB_LCD_AMOLED_SEL, &val, 1);
+ if (rc) {
+ pr_err("qpnp_labibb_sec_write register %x failed rc = %d\n",
+ REG_IBB_LCD_AMOLED_SEL, rc);
+ return rc;
+ }
}
rc = of_property_read_u32(of_node, "qcom,qpnp-ibb-lab-pwrdn-delay",
@@ -2482,6 +2626,13 @@ static int register_qpnp_ibb_regulator(struct qpnp_labibb *labibb,
return rc;
}
+ /*
+ * For pmicobalt, override swire_control with what was configured
+ * before by the bootloader.
+ */
+ if (labibb->pmic_rev_id->pmic_subtype == PMICOBALT_SUBTYPE)
+ labibb->swire_control = val & IBB_ENABLE_CTL_SWIRE_RDY;
+
if (ibb_enable_ctl &
(IBB_ENABLE_CTL_SWIRE_RDY | IBB_ENABLE_CTL_MODULE_EN)) {
/* SWIRE_RDY or IBB_MODULE_EN enabled */
@@ -2659,14 +2810,13 @@ static int register_qpnp_ibb_regulator(struct qpnp_labibb *labibb,
return -EINVAL;
}
- mutex_init(&(labibb->ibb_vreg.ibb_mutex));
return 0;
}
static int qpnp_lab_register_irq(struct device_node *child,
struct qpnp_labibb *labibb)
{
- if (labibb->skip_2nd_swire_cmd) {
+ if (is_lab_vreg_ok_irq_available(labibb)) {
labibb->lab_vreg.lab_vreg_ok_irq =
of_irq_get_byname(child, "lab-vreg-ok");
if (labibb->lab_vreg.lab_vreg_ok_irq < 0) {
@@ -2684,7 +2834,7 @@ static int qpnp_labibb_check_ttw_supported(struct qpnp_labibb *labibb)
u8 val;
switch (labibb->pmic_rev_id->pmic_subtype) {
- case PMI8996:
+ case PMI8996_SUBTYPE:
rc = qpnp_labibb_read(labibb, &val,
labibb->ibb_base + REG_IBB_REVISION4, 1);
if (rc) {
@@ -2702,7 +2852,7 @@ static int qpnp_labibb_check_ttw_supported(struct qpnp_labibb *labibb)
/* FORCE_LAB_ON in TTW is not required for PMI8996 */
labibb->ttw_force_lab_on = false;
break;
- case PMI8950:
+ case PMI8950_SUBTYPE:
/* TTW supported for all revisions */
break;
default:
@@ -2721,7 +2871,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
unsigned int base;
struct device_node *child, *revid_dev_node;
const char *mode_name;
- u8 type;
+ u8 type, revision;
int rc = 0;
labibb = devm_kzalloc(&pdev->dev,
@@ -2739,6 +2889,9 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
labibb->dev = &(pdev->dev);
labibb->pdev = pdev;
+ mutex_init(&(labibb->lab_vreg.lab_mutex));
+ mutex_init(&(labibb->ibb_vreg.ibb_mutex));
+
revid_dev_node = of_parse_phandle(labibb->dev->of_node,
"qcom,pmic-revid", 0);
if (!revid_dev_node) {
@@ -2753,19 +2906,19 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
}
rc = of_property_read_string(labibb->dev->of_node,
- "qpnp,qpnp-labibb-mode", &mode_name);
+ "qcom,qpnp-labibb-mode", &mode_name);
if (!rc) {
if (strcmp("lcd", mode_name) == 0) {
labibb->mode = QPNP_LABIBB_LCD_MODE;
} else if (strcmp("amoled", mode_name) == 0) {
labibb->mode = QPNP_LABIBB_AMOLED_MODE;
} else {
- pr_err("Invalid device property in qpnp,qpnp-labibb-mode: %s\n",
+ pr_err("Invalid device property in qcom,qpnp-labibb-mode: %s\n",
mode_name);
return -EINVAL;
}
} else {
- pr_err("qpnp_labibb: qpnp,qpnp-labibb-mode is missing.\n");
+ pr_err("qpnp_labibb: qcom,qpnp-labibb-mode is missing.\n");
return rc;
}
@@ -2783,15 +2936,17 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
labibb->dev->of_node, "qcom,labibb-ttw-force-lab-on");
labibb->swire_control = of_property_read_bool(labibb->dev->of_node,
- "qpnp,swire-control");
+ "qcom,swire-control");
if (labibb->swire_control && labibb->mode != QPNP_LABIBB_AMOLED_MODE) {
pr_err("Invalid mode for SWIRE control\n");
return -EINVAL;
}
+
if (labibb->swire_control) {
labibb->skip_2nd_swire_cmd =
of_property_read_bool(labibb->dev->of_node,
"qcom,skip-2nd-swire-cmd");
+
rc = of_property_read_u32(labibb->dev->of_node,
"qcom,swire-2nd-cmd-delay",
&labibb->swire_2nd_cmd_delay);
@@ -2811,6 +2966,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
pr_err("no child nodes\n");
return -ENXIO;
}
+
for_each_available_child_of_node(pdev->dev.of_node, child) {
rc = of_property_read_u32(child, "reg", &base);
if (rc < 0) {
@@ -2820,6 +2976,13 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
return rc;
}
+ rc = qpnp_labibb_read(labibb, &revision, base + REG_REVISION_2,
+ 1);
+ if (rc) {
+ pr_err("Reading REVISION_2 failed rc=%d\n", rc);
+ goto fail_registration;
+ }
+
rc = qpnp_labibb_read(labibb, &type,
base + REG_PERPH_TYPE, 1);
if (rc) {
@@ -2830,6 +2993,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
switch (type) {
case QPNP_LAB_TYPE:
labibb->lab_base = base;
+ labibb->lab_dig_major = revision;
rc = qpnp_lab_register_irq(child, labibb);
if (rc) {
pr_err("Failed to register LAB IRQ rc=%d\n",
@@ -2843,6 +3007,7 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
case QPNP_IBB_TYPE:
labibb->ibb_base = base;
+ labibb->ibb_dig_major = revision;
rc = register_qpnp_ibb_regulator(labibb, child);
if (rc)
goto fail_registration;
diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c
index d4c285688ce9..3ddc85e6efd6 100644
--- a/drivers/scsi/53c700.c
+++ b/drivers/scsi/53c700.c
@@ -1122,7 +1122,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
} else {
struct scsi_cmnd *SCp;
- SCp = scsi_host_find_tag(SDp->host, SCSI_NO_TAG);
+ SCp = SDp->current_cmnd;
if(unlikely(SCp == NULL)) {
sdev_printk(KERN_ERR, SDp,
"no saved request for untagged cmd\n");
@@ -1826,7 +1826,7 @@ NCR_700_queuecommand_lck(struct scsi_cmnd *SCp, void (*done)(struct scsi_cmnd *)
slot->tag, slot);
} else {
slot->tag = SCSI_NO_TAG;
- /* must populate current_cmnd for scsi_host_find_tag to work */
+ /* save current command for reselection */
SCp->device->current_cmnd = SCp;
}
/* sanity check: some of the commands generated by the mid-layer
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index d044f3f273be..467773033a20 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -29,6 +29,7 @@ enum {
#define AAC_INT_MODE_MSI (1<<1)
#define AAC_INT_MODE_AIF (1<<2)
#define AAC_INT_MODE_SYNC (1<<3)
+#define AAC_INT_MODE_MSIX (1<<16)
#define AAC_INT_ENABLE_TYPE1_INTX 0xfffffffb
#define AAC_INT_ENABLE_TYPE1_MSIX 0xfffffffa
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 0e954e37f0b5..0d351cd3191b 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -37,6 +37,7 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/blkdev.h>
+#include <linux/delay.h>
#include <linux/completion.h>
#include <linux/mm.h>
#include <scsi/scsi_host.h>
@@ -47,6 +48,20 @@ struct aac_common aac_config = {
.irq_mod = 1
};
+static inline int aac_is_msix_mode(struct aac_dev *dev)
+{
+ u32 status;
+
+ status = src_readl(dev, MUnit.OMR);
+ return (status & AAC_INT_MODE_MSIX);
+}
+
+static inline void aac_change_to_intx(struct aac_dev *dev)
+{
+ aac_src_access_devreg(dev, AAC_DISABLE_MSIX);
+ aac_src_access_devreg(dev, AAC_ENABLE_INTX);
+}
+
static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign)
{
unsigned char *base;
@@ -425,6 +440,15 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
dev->comm_interface = AAC_COMM_PRODUCER;
dev->raw_io_interface = dev->raw_io_64 = 0;
+
+ /*
+ * Enable INTX mode, if not done already Enabled
+ */
+ if (aac_is_msix_mode(dev)) {
+ aac_change_to_intx(dev);
+ dev_info(&dev->pdev->dev, "Changed firmware to INTX mode");
+ }
+
if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
0, 0, 0, 0, 0, 0,
status+0, status+1, status+2, status+3, NULL)) &&
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 4cbf54928640..8c758c36fc70 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -611,10 +611,10 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
}
return -EFAULT;
}
- /* We used to udelay() here but that absorbed
- * a CPU when a timeout occured. Not very
- * useful. */
- cpu_relax();
+ /*
+ * Allow other processes / CPUS to use core
+ */
+ schedule();
}
} else if (down_interruptible(&fibptr->event_wait)) {
/* Do nothing ... satisfy
@@ -1970,6 +1970,10 @@ int aac_command_thread(void *data)
if (difference <= 0)
difference = 1;
set_current_state(TASK_INTERRUPTIBLE);
+
+ if (kthread_should_stop())
+ break;
+
schedule_timeout(difference);
if (kthread_should_stop())
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index da2e068ee47d..93cbefa75b26 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -227,6 +227,7 @@ static struct {
{"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN},
{"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC},
{"Promise", "", NULL, BLIST_SPARSELUN},
+ {"QEMU", "QEMU CD-ROM", NULL, BLIST_SKIP_VPD_PAGES},
{"QNAP", "iSCSI Storage", NULL, BLIST_MAX_1024},
{"SYNOLOGY", "iSCSI Storage", NULL, BLIST_MAX_1024},
{"QUANTUM", "XP34301", "1071", BLIST_NOTQ},
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 984ddcb4786d..1b9c049bd5c5 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1127,7 +1127,6 @@ static int scsi_eh_action(struct scsi_cmnd *scmd, int rtn)
*/
void scsi_eh_finish_cmd(struct scsi_cmnd *scmd, struct list_head *done_q)
{
- scmd->device->host->host_failed--;
scmd->eh_eflags = 0;
list_move_tail(&scmd->eh_entry, done_q);
}
@@ -2226,6 +2225,9 @@ int scsi_error_handler(void *data)
else
scsi_unjam_host(shost);
+ /* All scmds have been handled */
+ shost->host_failed = 0;
+
/*
* Note - if the above fails completely, the action is to take
* individual devices offline and flush the queue of any
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index dd8ad2a44510..cf5b99e1f12b 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -910,9 +910,12 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
}
/*
- * If we finished all bytes in the request we are done now.
+ * special case: failed zero length commands always need to
+ * drop down into the retry code. Otherwise, if we finished
+ * all bytes in the request we are done now.
*/
- if (!scsi_end_request(req, error, good_bytes, 0))
+ if (!(blk_rq_bytes(req) == 0 && error) &&
+ !scsi_end_request(req, error, good_bytes, 0))
return;
/*
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 7808ef94ff07..87b35b78d879 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -314,6 +314,7 @@ static void scsi_target_destroy(struct scsi_target *starget)
struct Scsi_Host *shost = dev_to_shost(dev->parent);
unsigned long flags;
+ BUG_ON(starget->state == STARGET_DEL);
starget->state = STARGET_DEL;
transport_destroy_device(dev);
spin_lock_irqsave(shost->host_lock, flags);
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index d2a0ae4971ed..d47624000edf 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1193,18 +1193,18 @@ static void __scsi_remove_target(struct scsi_target *starget)
void scsi_remove_target(struct device *dev)
{
struct Scsi_Host *shost = dev_to_shost(dev->parent);
- struct scsi_target *starget, *last_target = NULL;
+ struct scsi_target *starget;
unsigned long flags;
restart:
spin_lock_irqsave(shost->host_lock, flags);
list_for_each_entry(starget, &shost->__targets, siblings) {
if (starget->state == STARGET_DEL ||
- starget == last_target)
+ starget->state == STARGET_REMOVE)
continue;
if (starget->dev.parent == dev || &starget->dev == dev) {
kref_get(&starget->reap_ref);
- last_target = starget;
+ starget->state = STARGET_REMOVE;
spin_unlock_irqrestore(shost->host_lock, flags);
__scsi_remove_target(starget);
scsi_target_reap(starget);
diff --git a/drivers/soc/qcom/memshare/msm_memshare.c b/drivers/soc/qcom/memshare/msm_memshare.c
index 00cc5e12709b..dcca82fc25c6 100644
--- a/drivers/soc/qcom/memshare/msm_memshare.c
+++ b/drivers/soc/qcom/memshare/msm_memshare.c
@@ -39,6 +39,7 @@ static DECLARE_DELAYED_WORK(work_recv_msg, mem_share_svc_recv_msg);
static struct workqueue_struct *mem_share_svc_workqueue;
static uint64_t bootup_request;
static void *memshare_ramdump_dev[MAX_CLIENTS];
+static struct device *memshare_dev[MAX_CLIENTS];
/* Memshare Driver Structure */
struct memshare_driver {
@@ -145,9 +146,14 @@ static int mem_share_configure_ramdump(void)
}
snprintf(client_name, 18, "memshare_%s", clnt);
-
- memshare_ramdump_dev[num_clients] = create_ramdump_device(client_name,
- NULL);
+ if (memshare_dev[num_clients]) {
+ memshare_ramdump_dev[num_clients] =
+ create_ramdump_device(client_name,
+ memshare_dev[num_clients]);
+ } else {
+ pr_err("memshare:%s: invalid memshare device\n", __func__);
+ return -ENODEV;
+ }
if (IS_ERR_OR_NULL(memshare_ramdump_dev[num_clients])) {
pr_err("memshare: %s: Unable to create memshare ramdump device.\n",
__func__);
@@ -957,6 +963,8 @@ static int memshare_child_probe(struct platform_device *pdev)
* memshare clients
*/
+ memshare_dev[num_clients] = &pdev->dev;
+
if (!memblock[num_clients].file_created) {
rc = mem_share_configure_ramdump();
if (rc)
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_dbg_voter.c b/drivers/soc/qcom/msm_bus/msm_bus_dbg_voter.c
index e4c8f1f446df..a876484859eb 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_dbg_voter.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_dbg_voter.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
*
* This program is Mree 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 @@ static ssize_t bus_floor_vote_store_api(struct device *dev,
return 0;
}
- if (sscanf(buf, "%s %llu", name, &vote_khz) != 2) {
+ if (sscanf(buf, "%9s %llu", name, &vote_khz) != 2) {
pr_err("%s:return error", __func__);
return -EINVAL;
}
diff --git a/drivers/soc/qcom/pil-q6v5-mss.c b/drivers/soc/qcom/pil-q6v5-mss.c
index 31a5ae89174e..bf6b11194111 100644
--- a/drivers/soc/qcom/pil-q6v5-mss.c
+++ b/drivers/soc/qcom/pil-q6v5-mss.c
@@ -277,7 +277,8 @@ static int pil_mss_loadable_init(struct modem_data *drv,
q6->restart_reg_sec = true;
}
- q6->restart_reg = devm_ioremap_resource(&pdev->dev, res);
+ q6->restart_reg = devm_ioremap(&pdev->dev,
+ res->start, resource_size(res));
if (!q6->restart_reg)
return -ENOMEM;
diff --git a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
index e8969a5e533b..45ac48eb2241 100644
--- a/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
+++ b/drivers/soc/qcom/qdsp6v2/apr_tal_glink.c
@@ -35,6 +35,7 @@
struct apr_tx_buf {
struct list_head list;
+ struct apr_pkt_priv pkt_priv;
char buf[APR_MAX_BUF];
};
@@ -67,29 +68,28 @@ static char *svc_names[APR_DEST_MAX][APR_CLIENT_MAX] = {
static struct apr_svc_ch_dev
apr_svc_ch[APR_DL_MAX][APR_DEST_MAX][APR_CLIENT_MAX];
-static int apr_get_free_buf(int len, void **buf)
+static struct apr_tx_buf *apr_get_free_buf(int len)
{
struct apr_tx_buf *tx_buf;
unsigned long flags;
- if (!buf || len > APR_MAX_BUF) {
+ if (len > APR_MAX_BUF) {
pr_err("%s: buf too large [%d]\n", __func__, len);
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
spin_lock_irqsave(&buf_list.lock, flags);
if (list_empty(&buf_list.list)) {
spin_unlock_irqrestore(&buf_list.lock, flags);
pr_err("%s: No buf available\n", __func__);
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
tx_buf = list_first_entry(&buf_list.list, struct apr_tx_buf, list);
list_del(&tx_buf->list);
spin_unlock_irqrestore(&buf_list.lock, flags);
- *buf = tx_buf->buf;
- return 0;
+ return tx_buf;
}
static void apr_buf_add_tail(const void *buf)
@@ -130,16 +130,22 @@ int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
{
int rc = 0, retries = 0;
void *pkt_data = NULL;
+ struct apr_tx_buf *tx_buf;
+ struct apr_pkt_priv *pkt_priv_ptr = pkt_priv;
if (!apr_ch->handle || !pkt_priv)
return -EINVAL;
if (pkt_priv->pkt_owner == APR_PKT_OWNER_DRIVER) {
- rc = apr_get_free_buf(len, &pkt_data);
- if (rc)
+ tx_buf = apr_get_free_buf(len);
+ if (IS_ERR_OR_NULL(tx_buf)) {
+ rc = -EINVAL;
goto exit;
-
- memcpy(pkt_data, data, len);
+ }
+ memcpy(tx_buf->buf, data, len);
+ memcpy(&tx_buf->pkt_priv, pkt_priv, sizeof(tx_buf->pkt_priv));
+ pkt_priv_ptr = &tx_buf->pkt_priv;
+ pkt_data = tx_buf->buf;
} else {
pkt_data = data;
}
@@ -148,7 +154,7 @@ int apr_tal_write(struct apr_svc_ch_dev *apr_ch, void *data,
if (rc == -EAGAIN)
udelay(50);
- rc = __apr_tal_write(apr_ch, pkt_data, pkt_priv, len);
+ rc = __apr_tal_write(apr_ch, pkt_data, pkt_priv_ptr, len);
} while (rc == -EAGAIN && retries++ < APR_MAXIMUM_NUM_OF_RETRIES);
if (rc < 0) {
@@ -180,6 +186,28 @@ void apr_tal_notify_rx(void *handle, const void *priv, const void *pkt_priv,
glink_rx_done(apr_ch->handle, ptr, true);
}
+static void apr_tal_notify_tx_abort(void *handle, const void *priv,
+ const void *pkt_priv)
+{
+ struct apr_pkt_priv *apr_pkt_priv_ptr =
+ (struct apr_pkt_priv *)pkt_priv;
+ struct apr_tx_buf *list_node;
+
+ if (!apr_pkt_priv_ptr) {
+ pr_err("%s: Invalid pkt_priv\n", __func__);
+ return;
+ }
+
+ pr_debug("%s: tx_abort received for apr_pkt_priv_ptr:%pK\n",
+ __func__, apr_pkt_priv_ptr);
+
+ if (apr_pkt_priv_ptr->pkt_owner == APR_PKT_OWNER_DRIVER) {
+ list_node = container_of(apr_pkt_priv_ptr,
+ struct apr_tx_buf, pkt_priv);
+ apr_buf_add_tail(list_node->buf);
+ }
+}
+
void apr_tal_notify_tx_done(void *handle, const void *priv,
const void *pkt_priv, const void *ptr)
{
@@ -315,6 +343,7 @@ struct apr_svc_ch_dev *apr_tal_open(uint32_t clnt, uint32_t dest, uint32_t dl,
open_cfg.notify_state = apr_tal_notify_state;
open_cfg.notify_rx_intent_req = apr_tal_notify_rx_intent_req;
open_cfg.notify_remote_rx_intent = apr_tal_notify_remote_rx_intent;
+ open_cfg.notify_tx_abort = apr_tal_notify_tx_abort;
open_cfg.priv = apr_ch;
open_cfg.transport = "smem";
diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c
index 24018c544b06..2b708732760f 100644
--- a/drivers/soc/qcom/service-locator.c
+++ b/drivers/soc/qcom/service-locator.c
@@ -149,7 +149,7 @@ static void service_locator_recv_msg(struct work_struct *work)
do {
pr_debug("Notified about a Receive event\n");
ret = qmi_recv_msg(service_locator.clnt_handle);
- if (ret != -ENOMSG)
+ if (ret < 0)
pr_err("Error receiving message rc:%d. Retrying...\n",
ret);
} while (ret == 0);
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index 8cba88742cb8..a244bc168136 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -162,7 +162,7 @@ static void root_service_clnt_recv_msg(struct work_struct *work)
data->instance_id);
} while ((ret = qmi_recv_msg(data->clnt_handle)) == 0);
- pr_info("Notified about a Receive event (instance-id: %d)\n",
+ pr_debug("Notified about a Receive event (instance-id: %d)\n",
data->instance_id);
}
@@ -227,7 +227,8 @@ static void root_service_service_ind_cb(struct qmi_handle *handle,
struct qmi_client_info *data = (struct qmi_client_info *)ind_cb_priv;
struct service_notif_info *service_notif;
struct msg_desc ind_desc;
- struct qmi_servreg_notif_state_updated_ind_msg_v01 ind_msg;
+ struct qmi_servreg_notif_state_updated_ind_msg_v01 ind_msg = {
+ QMI_STATE_MIN_VAL, "", 0xFFFF };
int rc;
ind_desc.msg_id = SERVREG_NOTIF_STATE_UPDATED_IND_MSG;
diff --git a/drivers/soc/qcom/sysmon.c b/drivers/soc/qcom/sysmon.c
index 8a12341a6f91..f8d0f10b1173 100644
--- a/drivers/soc/qcom/sysmon.c
+++ b/drivers/soc/qcom/sysmon.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-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
@@ -206,7 +206,7 @@ int sysmon_send_shutdown_no_qmi(struct subsys_desc *dest_desc)
return -ENODEV;
mutex_lock(&ss->lock);
- ret = sysmon_send_msg(ss, tx_buf, ARRAY_SIZE(tx_buf));
+ ret = sysmon_send_msg(ss, tx_buf, strlen(tx_buf));
if (ret) {
pr_err("Message sending failed %d\n", ret);
goto out;
@@ -257,7 +257,7 @@ int sysmon_get_reason_no_qmi(struct subsys_desc *dest_desc,
return -ENODEV;
mutex_lock(&ss->lock);
- ret = sysmon_send_msg(ss, tx_buf, ARRAY_SIZE(tx_buf));
+ ret = sysmon_send_msg(ss, tx_buf, strlen(tx_buf));
if (ret) {
pr_err("Message sending failed %d\n", ret);
goto out;
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index c0b936d802ef..0ae654a921f8 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spmi.h>
+#include <linux/syscore_ops.h>
/* PMIC Arbiter configuration registers */
#define PMIC_ARB_VERSION 0x0000
@@ -159,6 +160,7 @@ struct spmi_pmic_arb {
u16 last_apid;
struct apid_data apid_data[PMIC_ARB_MAX_PERIPHS];
};
+static struct spmi_pmic_arb *the_pa;
/**
* pmic_arb_ver: version dependent functionality.
@@ -525,7 +527,7 @@ static void cleanup_irq(struct spmi_pmic_arb *pa, u16 apid, int id)
irq_mask, ppid);
}
-static void periph_interrupt(struct spmi_pmic_arb *pa, u16 apid)
+static void periph_interrupt(struct spmi_pmic_arb *pa, u16 apid, bool show)
{
unsigned int irq;
u32 status;
@@ -542,22 +544,32 @@ static void periph_interrupt(struct spmi_pmic_arb *pa, u16 apid)
cleanup_irq(pa, apid, id);
continue;
}
- generic_handle_irq(irq);
+ if (show) {
+ struct irq_desc *desc;
+ const char *name = "null";
+
+ desc = irq_to_desc(irq);
+ if (desc == NULL)
+ name = "stray irq";
+ else if (desc->action && desc->action->name)
+ name = desc->action->name;
+
+ pr_warn("spmi_show_resume_irq: %d triggered [0x%01x, 0x%02x, 0x%01x] %s\n",
+ irq, sid, per, id, name);
+ } else {
+ generic_handle_irq(irq);
+ }
}
}
-static void pmic_arb_chained_irq(struct irq_desc *desc)
+static void __pmic_arb_chained_irq(struct spmi_pmic_arb *pa, bool show)
{
- struct spmi_pmic_arb *pa = irq_desc_get_handler_data(desc);
- struct irq_chip *chip = irq_desc_get_chip(desc);
void __iomem *intr = pa->intr;
int first = pa->min_apid >> 5;
int last = pa->max_apid >> 5;
u32 status, enable;
int i, id, apid;
- chained_irq_enter(chip, desc);
-
for (i = first; i <= last; ++i) {
status = readl_relaxed(intr +
pa->ver_ops->owner_acc_status(pa->ee, i));
@@ -568,10 +580,18 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
enable = readl_relaxed(intr +
pa->ver_ops->acc_enable(apid));
if (enable & SPMI_PIC_ACC_ENABLE_BIT)
- periph_interrupt(pa, apid);
+ periph_interrupt(pa, apid, show);
}
}
+}
+
+static void pmic_arb_chained_irq(struct irq_desc *desc)
+{
+ struct spmi_pmic_arb *pa = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ chained_irq_enter(chip, desc);
+ __pmic_arb_chained_irq(pa, false);
chained_irq_exit(chip, desc);
}
@@ -988,6 +1008,16 @@ static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
.xlate = qpnpint_irq_domain_dt_translate,
};
+static void spmi_pmic_arb_resume(void)
+{
+ if (spmi_show_resume_irq())
+ __pmic_arb_chained_irq(the_pa, true);
+}
+
+static struct syscore_ops spmi_pmic_arb_syscore_ops = {
+ .resume = spmi_pmic_arb_resume,
+};
+
static int spmi_pmic_arb_probe(struct platform_device *pdev)
{
struct spmi_pmic_arb *pa;
@@ -1153,6 +1183,8 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
if (err)
goto err_domain_remove;
+ the_pa = pa;
+ register_syscore_ops(&spmi_pmic_arb_syscore_ops);
return 0;
err_domain_remove:
@@ -1167,8 +1199,11 @@ static int spmi_pmic_arb_remove(struct platform_device *pdev)
{
struct spmi_controller *ctrl = platform_get_drvdata(pdev);
struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);
+
spmi_controller_remove(ctrl);
irq_set_chained_handler_and_data(pa->irq, NULL, NULL);
+ unregister_syscore_ops(&spmi_pmic_arb_syscore_ops);
+ the_pa = NULL;
irq_domain_remove(pa->domain);
spmi_controller_put(ctrl);
return 0;
diff --git a/drivers/staging/android/fiq_debugger/Kconfig b/drivers/staging/android/fiq_debugger/Kconfig
index 56f7f999377e..60fc224d4efc 100644
--- a/drivers/staging/android/fiq_debugger/Kconfig
+++ b/drivers/staging/android/fiq_debugger/Kconfig
@@ -42,6 +42,15 @@ config FIQ_DEBUGGER_CONSOLE_DEFAULT_ENABLE
If enabled, this puts the fiq debugger into console mode by default.
Otherwise, the fiq debugger will start out in debug mode.
+config FIQ_DEBUGGER_UART_OVERLAY
+ bool "Install uart DT overlay"
+ depends on FIQ_DEBUGGER
+ select OF_OVERLAY
+ default n
+ help
+ If enabled, fiq debugger is calling fiq_debugger_uart_overlay()
+ that will apply overlay uart_overlay@0 to disable proper uart.
+
config FIQ_WATCHDOG
bool
select FIQ_DEBUGGER
diff --git a/drivers/staging/android/fiq_debugger/fiq_debugger.c b/drivers/staging/android/fiq_debugger/fiq_debugger.c
index 7f056831dbff..b132cff14f01 100644
--- a/drivers/staging/android/fiq_debugger/fiq_debugger.c
+++ b/drivers/staging/android/fiq_debugger/fiq_debugger.c
@@ -39,6 +39,10 @@
#include <asm/fiq_glue.h>
#endif
+#ifdef CONFIG_FIQ_DEBUGGER_UART_OVERLAY
+#include <linux/of.h>
+#endif
+
#include <linux/uaccess.h>
#include "fiq_debugger.h"
@@ -119,11 +123,13 @@ static bool initial_console_enable;
#endif
static bool fiq_kgdb_enable;
+static bool fiq_debugger_disable;
module_param_named(no_sleep, initial_no_sleep, bool, 0644);
module_param_named(debug_enable, initial_debug_enable, bool, 0644);
module_param_named(console_enable, initial_console_enable, bool, 0644);
module_param_named(kgdb_enable, fiq_kgdb_enable, bool, 0644);
+module_param_named(disable, fiq_debugger_disable, bool, 0644);
#ifdef CONFIG_FIQ_DEBUGGER_WAKEUP_IRQ_ALWAYS_ON
static inline
@@ -1201,11 +1207,41 @@ static struct platform_driver fiq_debugger_driver = {
},
};
+#if defined(CONFIG_FIQ_DEBUGGER_UART_OVERLAY)
+int fiq_debugger_uart_overlay(void)
+{
+ struct device_node *onp = of_find_node_by_path("/uart_overlay@0");
+ int ret;
+
+ if (!onp) {
+ pr_err("serial_debugger: uart overlay not found\n");
+ return -ENODEV;
+ }
+
+ ret = of_overlay_create(onp);
+ if (ret < 0) {
+ pr_err("serial_debugger: fail to create overlay: %d\n", ret);
+ of_node_put(onp);
+ return ret;
+ }
+
+ pr_info("serial_debugger: uart overlay applied\n");
+ return 0;
+}
+#endif
+
static int __init fiq_debugger_init(void)
{
+ if (fiq_debugger_disable) {
+ pr_err("serial_debugger: disabled\n");
+ return -ENODEV;
+ }
#if defined(CONFIG_FIQ_DEBUGGER_CONSOLE)
fiq_debugger_tty_init();
#endif
+#if defined(CONFIG_FIQ_DEBUGGER_UART_OVERLAY)
+ fiq_debugger_uart_overlay();
+#endif
return platform_driver_register(&fiq_debugger_driver);
}
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index 940781183fac..3be10963f98b 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -567,14 +567,17 @@ static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
struct comedi_isadma_desc *desc;
int i;
- outb(0x0, dev->iobase + DAS1800_STATUS); /* disable conversions */
- outb(0x0, dev->iobase + DAS1800_CONTROL_B); /* disable interrupts and dma */
- outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* disable and clear fifo and stop triggering */
-
- for (i = 0; i < 2; i++) {
- desc = &dma->desc[i];
- if (desc->chan)
- comedi_isadma_disable(desc->chan);
+ /* disable and stop conversions */
+ outb(0x0, dev->iobase + DAS1800_STATUS);
+ outb(0x0, dev->iobase + DAS1800_CONTROL_B);
+ outb(0x0, dev->iobase + DAS1800_CONTROL_A);
+
+ if (dma) {
+ for (i = 0; i < 2; i++) {
+ desc = &dma->desc[i];
+ if (desc->chan)
+ comedi_isadma_disable(desc->chan);
+ }
}
return 0;
@@ -934,13 +937,14 @@ static void das1800_ai_setup_dma(struct comedi_device *dev,
{
struct das1800_private *devpriv = dev->private;
struct comedi_isadma *dma = devpriv->dma;
- struct comedi_isadma_desc *desc = &dma->desc[0];
+ struct comedi_isadma_desc *desc;
unsigned int bytes;
if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
return;
dma->cur_dma = 0;
+ desc = &dma->desc[0];
/* determine a dma transfer size to fill buffer in 0.3 sec */
bytes = das1800_ai_transfer_size(dev, s, desc->maxsize, 300000000);
diff --git a/drivers/staging/iio/accel/sca3000_core.c b/drivers/staging/iio/accel/sca3000_core.c
index 02e930c55570..e4839ee4ca61 100644
--- a/drivers/staging/iio/accel/sca3000_core.c
+++ b/drivers/staging/iio/accel/sca3000_core.c
@@ -595,7 +595,7 @@ static ssize_t sca3000_read_frequency(struct device *dev,
goto error_ret_mut;
ret = sca3000_read_ctrl_reg(st, SCA3000_REG_CTRL_SEL_OUT_CTRL);
mutex_unlock(&st->lock);
- if (ret)
+ if (ret < 0)
goto error_ret;
val = ret;
if (base_freq > 0)
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 560c5c72daeb..65c7033e0df0 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -879,14 +879,6 @@ __cpufreq_cooling_register(struct device_node *np,
goto free_power_table;
}
- snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
- cpufreq_dev->id);
-
- cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev,
- &cpufreq_cooling_ops);
- if (IS_ERR(cool_dev))
- goto remove_idr;
-
/* Fill freq-table in descending order of frequencies */
for (i = 0, freq = -1; i <= cpufreq_dev->max_level; i++) {
freq = find_next_max(table, freq);
@@ -899,6 +891,14 @@ __cpufreq_cooling_register(struct device_node *np,
pr_debug("%s: freq:%u KHz\n", __func__, freq);
}
+ snprintf(dev_name, sizeof(dev_name), "thermal-cpufreq-%d",
+ cpufreq_dev->id);
+
+ cool_dev = thermal_of_cooling_device_register(np, dev_name, cpufreq_dev,
+ &cpufreq_cooling_ops);
+ if (IS_ERR(cool_dev))
+ goto remove_idr;
+
cpufreq_dev->clipped_freq = cpufreq_dev->freq_table[0];
cpufreq_dev->cool_dev = cool_dev;
diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
index 0dde34e3a7c5..545c60c826a1 100644
--- a/drivers/thunderbolt/eeprom.c
+++ b/drivers/thunderbolt/eeprom.c
@@ -444,6 +444,7 @@ int tb_drom_read(struct tb_switch *sw)
return tb_drom_parse_entries(sw);
err:
kfree(sw->drom);
+ sw->drom = NULL;
return -EIO;
}
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index c3fe026d3168..9aff37186246 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -2045,7 +2045,9 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm)
}
}
spin_unlock(&gsm_mux_lock);
- WARN_ON(i == MAX_MUX);
+ /* open failed before registering => nothing to do */
+ if (i == MAX_MUX)
+ return;
/* In theory disconnecting DLCI 0 is sufficient but for some
modems this is apparently not the case. */
diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c
index bbc4ce66c2c1..644ddb841d9f 100644
--- a/drivers/tty/n_hdlc.c
+++ b/drivers/tty/n_hdlc.c
@@ -600,7 +600,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
add_wait_queue(&tty->read_wait, &wait);
for (;;) {
- if (test_bit(TTY_OTHER_DONE, &tty->flags)) {
+ if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
ret = -EIO;
break;
}
@@ -828,7 +828,7 @@ static unsigned int n_hdlc_tty_poll(struct tty_struct *tty, struct file *filp,
/* set bits for operations that won't block */
if (n_hdlc->rx_buf_list.head)
mask |= POLLIN | POLLRDNORM; /* readable */
- if (test_bit(TTY_OTHER_DONE, &tty->flags))
+ if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
mask |= POLLHUP;
if (tty_hung_up_p(filp))
mask |= POLLHUP;
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index cf000b331eed..84e71bd19082 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -1955,18 +1955,6 @@ static inline int input_available_p(struct tty_struct *tty, int poll)
return ldata->commit_head - ldata->read_tail >= amt;
}
-static inline int check_other_done(struct tty_struct *tty)
-{
- int done = test_bit(TTY_OTHER_DONE, &tty->flags);
- if (done) {
- /* paired with cmpxchg() in check_other_closed(); ensures
- * read buffer head index is not stale
- */
- smp_mb__after_atomic();
- }
- return done;
-}
-
/**
* copy_from_read_buf - copy read data directly
* @tty: terminal device
@@ -2171,7 +2159,7 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
struct n_tty_data *ldata = tty->disc_data;
unsigned char __user *b = buf;
DEFINE_WAIT_FUNC(wait, woken_wake_function);
- int c, done;
+ int c;
int minimum, time;
ssize_t retval = 0;
long timeout;
@@ -2239,32 +2227,35 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
((minimum - (b - buf)) >= 1))
ldata->minimum_to_wake = (minimum - (b - buf));
- done = check_other_done(tty);
-
if (!input_available_p(tty, 0)) {
- if (done) {
- retval = -EIO;
- break;
- }
- if (tty_hung_up_p(file))
- break;
- if (!timeout)
- break;
- if (file->f_flags & O_NONBLOCK) {
- retval = -EAGAIN;
- break;
- }
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
up_read(&tty->termios_rwsem);
+ tty_buffer_flush_work(tty->port);
+ down_read(&tty->termios_rwsem);
+ if (!input_available_p(tty, 0)) {
+ if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
+ retval = -EIO;
+ break;
+ }
+ if (tty_hung_up_p(file))
+ break;
+ if (!timeout)
+ break;
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ break;
+ }
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ break;
+ }
+ up_read(&tty->termios_rwsem);
- timeout = wait_woken(&wait, TASK_INTERRUPTIBLE,
- timeout);
+ timeout = wait_woken(&wait, TASK_INTERRUPTIBLE,
+ timeout);
- down_read(&tty->termios_rwsem);
- continue;
+ down_read(&tty->termios_rwsem);
+ continue;
+ }
}
if (ldata->icanon && !L_EXTPROC(tty)) {
@@ -2446,12 +2437,17 @@ static unsigned int n_tty_poll(struct tty_struct *tty, struct file *file,
poll_wait(file, &tty->read_wait, wait);
poll_wait(file, &tty->write_wait, wait);
- if (check_other_done(tty))
- mask |= POLLHUP;
if (input_available_p(tty, 1))
mask |= POLLIN | POLLRDNORM;
+ else {
+ tty_buffer_flush_work(tty->port);
+ if (input_available_p(tty, 1))
+ mask |= POLLIN | POLLRDNORM;
+ }
if (tty->packet && tty->link->ctrl_status)
mask |= POLLPRI | POLLIN | POLLRDNORM;
+ if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
+ mask |= POLLHUP;
if (tty_hung_up_p(file))
mask |= POLLHUP;
if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) {
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 78e983677339..7865228f664f 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -59,7 +59,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
if (!tty->link)
return;
set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
- tty_flip_buffer_push(tty->link->port);
+ wake_up_interruptible(&tty->link->read_wait);
wake_up_interruptible(&tty->link->write_wait);
if (tty->driver->subtype == PTY_TYPE_MASTER) {
set_bit(TTY_OTHER_CLOSED, &tty->flags);
@@ -247,9 +247,7 @@ static int pty_open(struct tty_struct *tty, struct file *filp)
goto out;
clear_bit(TTY_IO_ERROR, &tty->flags);
- /* TTY_OTHER_CLOSED must be cleared before TTY_OTHER_DONE */
clear_bit(TTY_OTHER_CLOSED, &tty->link->flags);
- clear_bit(TTY_OTHER_DONE, &tty->link->flags);
set_bit(TTY_THROTTLED, &tty->flags);
return 0;
diff --git a/drivers/tty/serial/8250/8250_mid.c b/drivers/tty/serial/8250/8250_mid.c
index 88531a36b69c..ed489880e62b 100644
--- a/drivers/tty/serial/8250/8250_mid.c
+++ b/drivers/tty/serial/8250/8250_mid.c
@@ -14,6 +14,7 @@
#include <linux/pci.h>
#include <linux/dma/hsu.h>
+#include <linux/8250_pci.h>
#include "8250.h"
@@ -24,6 +25,7 @@
#define PCI_DEVICE_ID_INTEL_DNV_UART 0x19d8
/* Intel MID Specific registers */
+#define INTEL_MID_UART_DNV_FISR 0x08
#define INTEL_MID_UART_PS 0x30
#define INTEL_MID_UART_MUL 0x34
#define INTEL_MID_UART_DIV 0x38
@@ -31,6 +33,7 @@
struct mid8250;
struct mid8250_board {
+ unsigned int flags;
unsigned long freq;
unsigned int base_baud;
int (*setup)(struct mid8250 *, struct uart_port *p);
@@ -88,16 +91,16 @@ static int tng_setup(struct mid8250 *mid, struct uart_port *p)
static int dnv_handle_irq(struct uart_port *p)
{
struct mid8250 *mid = p->private_data;
- int ret;
-
- ret = hsu_dma_irq(&mid->dma_chip, 0);
- ret |= hsu_dma_irq(&mid->dma_chip, 1);
-
- /* For now, letting the HW generate separate interrupt for the UART */
- if (ret)
- return ret;
-
- return serial8250_handle_irq(p, serial_port_in(p, UART_IIR));
+ unsigned int fisr = serial_port_in(p, INTEL_MID_UART_DNV_FISR);
+ int ret = IRQ_NONE;
+
+ if (fisr & BIT(2))
+ ret |= hsu_dma_irq(&mid->dma_chip, 1);
+ if (fisr & BIT(1))
+ ret |= hsu_dma_irq(&mid->dma_chip, 0);
+ if (fisr & BIT(0))
+ ret |= serial8250_handle_irq(p, serial_port_in(p, UART_IIR));
+ return ret;
}
#define DNV_DMA_CHAN_OFFSET 0x80
@@ -106,12 +109,13 @@ static int dnv_setup(struct mid8250 *mid, struct uart_port *p)
{
struct hsu_dma_chip *chip = &mid->dma_chip;
struct pci_dev *pdev = to_pci_dev(p->dev);
+ unsigned int bar = FL_GET_BASE(mid->board->flags);
int ret;
chip->dev = &pdev->dev;
chip->irq = pdev->irq;
chip->regs = p->membase;
- chip->length = pci_resource_len(pdev, 0);
+ chip->length = pci_resource_len(pdev, bar);
chip->offset = DNV_DMA_CHAN_OFFSET;
/* Falling back to PIO mode if DMA probing fails */
@@ -217,6 +221,7 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct uart_8250_port uart;
struct mid8250 *mid;
+ unsigned int bar;
int ret;
ret = pcim_enable_device(pdev);
@@ -230,6 +235,7 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return -ENOMEM;
mid->board = (struct mid8250_board *)id->driver_data;
+ bar = FL_GET_BASE(mid->board->flags);
memset(&uart, 0, sizeof(struct uart_8250_port));
@@ -242,8 +248,8 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE;
uart.port.set_termios = mid8250_set_termios;
- uart.port.mapbase = pci_resource_start(pdev, 0);
- uart.port.membase = pcim_iomap(pdev, 0, 0);
+ uart.port.mapbase = pci_resource_start(pdev, bar);
+ uart.port.membase = pcim_iomap(pdev, bar, 0);
if (!uart.port.membase)
return -ENOMEM;
@@ -282,18 +288,21 @@ static void mid8250_remove(struct pci_dev *pdev)
}
static const struct mid8250_board pnw_board = {
+ .flags = FL_BASE0,
.freq = 50000000,
.base_baud = 115200,
.setup = pnw_setup,
};
static const struct mid8250_board tng_board = {
+ .flags = FL_BASE0,
.freq = 38400000,
.base_baud = 1843200,
.setup = tng_setup,
};
static const struct mid8250_board dnv_board = {
+ .flags = FL_BASE1,
.freq = 133333333,
.base_baud = 115200,
.setup = dnv_setup,
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 7cd6f9a90542..c1d4a8fa9be8 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1401,6 +1401,9 @@ byt_set_termios(struct uart_port *p, struct ktermios *termios,
unsigned long m, n;
u32 reg;
+ /* Gracefully handle the B0 case: fall back to B9600 */
+ fuart = fuart ? fuart : 9600 * 16;
+
/* Get Fuart closer to Fref */
fuart *= rounddown_pow_of_two(fref / fuart);
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 94294558943c..7bbadd176c74 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -277,6 +277,13 @@ static bool atmel_use_dma_rx(struct uart_port *port)
return atmel_port->use_dma_rx;
}
+static bool atmel_use_fifo(struct uart_port *port)
+{
+ struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+
+ return atmel_port->fifo_size;
+}
+
static unsigned int atmel_get_lines_status(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
@@ -2169,7 +2176,12 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
mode |= ATMEL_US_USMODE_RS485;
} else if (termios->c_cflag & CRTSCTS) {
/* RS232 with hardware handshake (RTS/CTS) */
- mode |= ATMEL_US_USMODE_HWHS;
+ if (atmel_use_dma_rx(port) && !atmel_use_fifo(port)) {
+ dev_info(port->dev, "not enabling hardware flow control because DMA is used");
+ termios->c_cflag &= ~CRTSCTS;
+ } else {
+ mode |= ATMEL_US_USMODE_HWHS;
+ }
} else {
/* RS232 without hadware handshake */
mode |= ATMEL_US_USMODE_NORMAL;
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index fd9c47f2f29f..c8ab5370670d 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1263,6 +1263,8 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
/* check to see if we need to change clock source */
if (ourport->baudclk != clk) {
+ clk_prepare_enable(clk);
+
s3c24xx_serial_setsource(port, clk_sel);
if (!IS_ERR(ourport->baudclk)) {
@@ -1270,8 +1272,6 @@ static void s3c24xx_serial_set_termios(struct uart_port *port,
ourport->baudclk = ERR_PTR(-EINVAL);
}
- clk_prepare_enable(clk);
-
ourport->baudclk = clk;
ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
}
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
index 73190f5d2832..71d26c8e1b8f 100644
--- a/drivers/tty/serial/ucc_uart.c
+++ b/drivers/tty/serial/ucc_uart.c
@@ -1478,6 +1478,9 @@ static const struct of_device_id ucc_uart_match[] = {
.type = "serial",
.compatible = "ucc_uart",
},
+ {
+ .compatible = "fsl,t1040-ucc-uart",
+ },
{},
};
MODULE_DEVICE_TABLE(of, ucc_uart_match);
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 3cd31e0d4bd9..fb31eecb708d 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -37,29 +37,6 @@
#define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF)
-/*
- * If all tty flip buffers have been processed by flush_to_ldisc() or
- * dropped by tty_buffer_flush(), check if the linked pty has been closed.
- * If so, wake the reader/poll to process
- */
-static inline void check_other_closed(struct tty_struct *tty)
-{
- unsigned long flags, old;
-
- /* transition from TTY_OTHER_CLOSED => TTY_OTHER_DONE must be atomic */
- for (flags = ACCESS_ONCE(tty->flags);
- test_bit(TTY_OTHER_CLOSED, &flags);
- ) {
- old = flags;
- __set_bit(TTY_OTHER_DONE, &flags);
- flags = cmpxchg(&tty->flags, old, flags);
- if (old == flags) {
- wake_up_interruptible(&tty->read_wait);
- break;
- }
- }
-}
-
/**
* tty_buffer_lock_exclusive - gain exclusive access to buffer
* tty_buffer_unlock_exclusive - release exclusive access
@@ -254,8 +231,6 @@ void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld)
if (ld && ld->ops->flush_buffer)
ld->ops->flush_buffer(tty);
- check_other_closed(tty);
-
atomic_dec(&buf->priority);
mutex_unlock(&buf->lock);
}
@@ -505,10 +480,8 @@ static void flush_to_ldisc(struct work_struct *work)
*/
count = smp_load_acquire(&head->commit) - head->read;
if (!count) {
- if (next == NULL) {
- check_other_closed(tty);
+ if (next == NULL)
break;
- }
buf->head = next;
tty_buffer_free(port, head);
continue;
@@ -597,3 +570,8 @@ bool tty_buffer_cancel_work(struct tty_port *port)
{
return cancel_work_sync(&port->buf.work);
}
+
+void tty_buffer_flush_work(struct tty_port *port)
+{
+ flush_work(&port->buf.work);
+}
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 6f0336fff501..41987a55a538 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -366,34 +366,22 @@ static void to_utf8(struct vc_data *vc, uint c)
static void do_compute_shiftstate(void)
{
- unsigned int i, j, k, sym, val;
+ unsigned int k, sym, val;
shift_state = 0;
memset(shift_down, 0, sizeof(shift_down));
- for (i = 0; i < ARRAY_SIZE(key_down); i++) {
-
- if (!key_down[i])
+ for_each_set_bit(k, key_down, min(NR_KEYS, KEY_CNT)) {
+ sym = U(key_maps[0][k]);
+ if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
continue;
- k = i * BITS_PER_LONG;
-
- for (j = 0; j < BITS_PER_LONG; j++, k++) {
-
- if (!test_bit(k, key_down))
- continue;
+ val = KVAL(sym);
+ if (val == KVAL(K_CAPSSHIFT))
+ val = KVAL(K_SHIFT);
- sym = U(key_maps[0][k]);
- if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
- continue;
-
- val = KVAL(sym);
- if (val == KVAL(K_CAPSSHIFT))
- val = KVAL(K_SHIFT);
-
- shift_down[val]++;
- shift_state |= (1 << val);
- }
+ shift_down[val]++;
+ shift_state |= BIT(val);
}
}
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 4462d167900c..136ebaaa9cc0 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -750,6 +750,7 @@ static void visual_init(struct vc_data *vc, int num, int init)
vc->vc_complement_mask = 0;
vc->vc_can_do_color = 0;
vc->vc_panic_force_write = false;
+ vc->vc_cur_blink_ms = DEFAULT_CURSOR_BLINK_MS;
vc->vc_sw->con_init(vc, init);
if (!vc->vc_complement_mask)
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
@@ -3583,9 +3584,10 @@ static int do_register_con_driver(const struct consw *csw, int first, int last)
goto err;
desc = csw->con_startup();
-
- if (!desc)
+ if (!desc) {
+ retval = -ENODEV;
goto err;
+ }
retval = -EINVAL;
diff --git a/drivers/usb/common/usb-otg-fsm.c b/drivers/usb/common/usb-otg-fsm.c
index 61d538aa2346..4f4f06a5889f 100644
--- a/drivers/usb/common/usb-otg-fsm.c
+++ b/drivers/usb/common/usb-otg-fsm.c
@@ -21,6 +21,7 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/mutex.h>
@@ -365,3 +366,4 @@ int otg_statemachine(struct otg_fsm *fsm)
return state_changed;
}
EXPORT_SYMBOL_GPL(otg_statemachine);
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 2057d91d8336..dadd1e8dfe09 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -284,7 +284,7 @@ static int usb_probe_interface(struct device *dev)
struct usb_device *udev = interface_to_usbdev(intf);
const struct usb_device_id *id;
int error = -ENODEV;
- int lpm_disable_error;
+ int lpm_disable_error = -ENODEV;
dev_dbg(dev, "%s\n", __func__);
@@ -336,12 +336,14 @@ static int usb_probe_interface(struct device *dev)
* setting during probe, that should also be fine. usb_set_interface()
* will attempt to disable LPM, and fail if it can't disable it.
*/
- lpm_disable_error = usb_unlocked_disable_lpm(udev);
- if (lpm_disable_error && driver->disable_hub_initiated_lpm) {
- dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n.",
- __func__, driver->name);
- error = lpm_disable_error;
- goto err;
+ if (driver->disable_hub_initiated_lpm) {
+ lpm_disable_error = usb_unlocked_disable_lpm(udev);
+ if (lpm_disable_error) {
+ dev_err(&intf->dev, "%s Failed to disable LPM for driver %s\n.",
+ __func__, driver->name);
+ error = lpm_disable_error;
+ goto err;
+ }
}
/* Carry out a deferred switch to altsetting 0 */
@@ -391,7 +393,8 @@ static int usb_unbind_interface(struct device *dev)
struct usb_interface *intf = to_usb_interface(dev);
struct usb_host_endpoint *ep, **eps = NULL;
struct usb_device *udev;
- int i, j, error, r, lpm_disable_error;
+ int i, j, error, r;
+ int lpm_disable_error = -ENODEV;
intf->condition = USB_INTERFACE_UNBINDING;
@@ -399,12 +402,13 @@ static int usb_unbind_interface(struct device *dev)
udev = interface_to_usbdev(intf);
error = usb_autoresume_device(udev);
- /* Hub-initiated LPM policy may change, so attempt to disable LPM until
+ /* If hub-initiated LPM policy may change, attempt to disable LPM until
* the driver is unbound. If LPM isn't disabled, that's fine because it
* wouldn't be enabled unless all the bound interfaces supported
* hub-initiated LPM.
*/
- lpm_disable_error = usb_unlocked_disable_lpm(udev);
+ if (driver->disable_hub_initiated_lpm)
+ lpm_disable_error = usb_unlocked_disable_lpm(udev);
/*
* Terminate all URBs for this interface unless the driver
@@ -505,7 +509,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,
struct device *dev;
struct usb_device *udev;
int retval = 0;
- int lpm_disable_error;
+ int lpm_disable_error = -ENODEV;
if (!iface)
return -ENODEV;
@@ -526,12 +530,14 @@ int usb_driver_claim_interface(struct usb_driver *driver,
iface->condition = USB_INTERFACE_BOUND;
- /* Disable LPM until this driver is bound. */
- lpm_disable_error = usb_unlocked_disable_lpm(udev);
- if (lpm_disable_error && driver->disable_hub_initiated_lpm) {
- dev_err(&iface->dev, "%s Failed to disable LPM for driver %s\n.",
- __func__, driver->name);
- return -ENOMEM;
+ /* See the comment about disabling LPM in usb_probe_interface(). */
+ if (driver->disable_hub_initiated_lpm) {
+ lpm_disable_error = usb_unlocked_disable_lpm(udev);
+ if (lpm_disable_error) {
+ dev_err(&iface->dev, "%s Failed to disable LPM for driver %s\n.",
+ __func__, driver->name);
+ return -ENOMEM;
+ }
}
/* Claimed interfaces are initially inactive (suspended) and
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 269c1ee2da44..5839111ab4e0 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -48,6 +48,11 @@ static void hub_event(struct work_struct *work);
/* synchronize hub-port add/remove and peering operations */
DEFINE_MUTEX(usb_port_peer_mutex);
+static bool skip_extended_resume_delay = 1;
+module_param(skip_extended_resume_delay, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(skip_extended_resume_delay,
+ "removes extra delay added to finish bus resume");
+
/* cycle leds on hubs that aren't blinking for attention */
static bool blinkenlights = 0;
module_param(blinkenlights, bool, S_IRUGO);
@@ -3434,7 +3439,9 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
/* drive resume for USB_RESUME_TIMEOUT msec */
dev_dbg(&udev->dev, "usb %sresume\n",
(PMSG_IS_AUTO(msg) ? "auto-" : ""));
- msleep(USB_RESUME_TIMEOUT);
+ if (!skip_extended_resume_delay)
+ usleep_range(USB_RESUME_TIMEOUT * 1000,
+ (USB_RESUME_TIMEOUT + 1) * 1000);
/* Virtual root hubs can trigger on GET_PORT_STATUS to
* stop resume signaling. Then finish the resume
@@ -3443,7 +3450,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
status = hub_port_status(hub, port1, &portstatus, &portchange);
/* TRSMRCY = 10 msec */
- msleep(10);
+ usleep_range(10000, 10500);
}
SuspendCleared:
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 6dc810bce295..944a6dca0fcb 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -44,6 +44,9 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Creative SB Audigy 2 NX */
{ USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* USB3503 */
+ { USB_DEVICE(0x0424, 0x3503), .driver_info = USB_QUIRK_RESET_RESUME },
+
/* Microsoft Wireless Laser Mouse 6000 Receiver */
{ USB_DEVICE(0x045e, 0x00e1), .driver_info = USB_QUIRK_RESET_RESUME },
@@ -173,6 +176,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* MAYA44USB sound device */
{ USB_DEVICE(0x0a92, 0x0091), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* ASUS Base Station(T100) */
+ { USB_DEVICE(0x0b05, 0x17e0), .driver_info =
+ USB_QUIRK_IGNORE_REMOTE_WAKEUP },
+
/* Action Semiconductor flash disk */
{ USB_DEVICE(0x10d6, 0x2200), .driver_info =
USB_QUIRK_STRING_FETCH_255 },
@@ -188,26 +195,22 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x1908, 0x1315), .driver_info =
USB_QUIRK_HONOR_BNUMINTERFACES },
- /* INTEL VALUE SSD */
- { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
-
- /* USB3503 */
- { USB_DEVICE(0x0424, 0x3503), .driver_info = USB_QUIRK_RESET_RESUME },
-
- /* ASUS Base Station(T100) */
- { USB_DEVICE(0x0b05, 0x17e0), .driver_info =
- USB_QUIRK_IGNORE_REMOTE_WAKEUP },
-
/* Protocol and OTG Electrical Test Device */
{ USB_DEVICE(0x1a0a, 0x0200), .driver_info =
USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
+ /* Acer C120 LED Projector */
+ { USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM },
+
/* Blackmagic Design Intensity Shuttle */
{ USB_DEVICE(0x1edb, 0xbd3b), .driver_info = USB_QUIRK_NO_LPM },
/* Blackmagic Design UltraStudio SDI */
{ USB_DEVICE(0x1edb, 0xbd4f), .driver_info = USB_QUIRK_NO_LPM },
+ /* INTEL VALUE SSD */
+ { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
+
{ } /* terminating entry must be last */
};
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index a66d3cb62b65..a738a68d2292 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -44,6 +44,17 @@
#include <linux/usb/phy.h>
#include "hw.h"
+#ifdef CONFIG_MIPS
+/*
+ * There are some MIPS machines that can run in either big-endian
+ * or little-endian mode and that use the dwc2 register without
+ * a byteswap in both ways.
+ * Unlike other architectures, MIPS apparently does not require a
+ * barrier before the __raw_writel() to synchronize with DMA but does
+ * require the barrier after the __raw_writel() to serialize a set of
+ * writes. This set of operations was added specifically for MIPS and
+ * should only be used there.
+ */
static inline u32 dwc2_readl(const void __iomem *addr)
{
u32 value = __raw_readl(addr);
@@ -70,6 +81,22 @@ static inline void dwc2_writel(u32 value, void __iomem *addr)
pr_info("INFO:: wrote %08x to %p\n", value, addr);
#endif
}
+#else
+/* Normal architectures just use readl/write */
+static inline u32 dwc2_readl(const void __iomem *addr)
+{
+ return readl(addr);
+}
+
+static inline void dwc2_writel(u32 value, void __iomem *addr)
+{
+ writel(value, addr);
+
+#ifdef DWC2_LOG_WRITES
+ pr_info("info:: wrote %08x to %p\n", value, addr);
+#endif
+}
+#endif
/* Maximum number of Endpoints/HostChannels */
#define MAX_EPS_CHANNELS 16
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index dd5cb5577dca..2f1fb7e7aa54 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -128,12 +128,6 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, exynos);
- ret = dwc3_exynos_register_phys(exynos);
- if (ret) {
- dev_err(dev, "couldn't register PHYs\n");
- return ret;
- }
-
exynos->dev = dev;
exynos->clk = devm_clk_get(dev, "usbdrd30");
@@ -183,20 +177,29 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
goto err3;
}
+ ret = dwc3_exynos_register_phys(exynos);
+ if (ret) {
+ dev_err(dev, "couldn't register PHYs\n");
+ goto err4;
+ }
+
if (node) {
ret = of_platform_populate(node, NULL, NULL, dev);
if (ret) {
dev_err(dev, "failed to add dwc3 core\n");
- goto err4;
+ goto err5;
}
} else {
dev_err(dev, "no device node, failed to add dwc3 core\n");
ret = -ENODEV;
- goto err4;
+ goto err5;
}
return 0;
+err5:
+ platform_device_unregister(exynos->usb2_phy);
+ platform_device_unregister(exynos->usb3_phy);
err4:
regulator_disable(exynos->vdd10);
err3:
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 5db4fe9e3cdf..be29dc4bef89 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1528,7 +1528,14 @@ static int android_setup(struct usb_gadget *gadget,
static void android_disconnect(struct usb_gadget *gadget)
{
struct usb_composite_dev *cdev = get_gadget_data(gadget);
- struct gadget_info *gi = container_of(cdev, struct gadget_info, cdev);
+ struct gadget_info *gi;
+
+ if (!cdev) {
+ pr_err("%s: gadget is not connected\n", __func__);
+ return;
+ }
+
+ gi = container_of(cdev, struct gadget_info, cdev);
/* accessory HID support can be active while the
accessory function is not actually enabled,
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 20fe358387be..eb2409dda50d 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -717,7 +717,7 @@ static void ffs_user_copy_worker(struct work_struct *work)
if (io_data->read && ret > 0) {
use_mm(io_data->mm);
ret = copy_to_iter(io_data->buf, ret, &io_data->data);
- if (iov_iter_count(&io_data->data))
+ if (ret != io_data->req->actual && iov_iter_count(&io_data->data))
ret = -EFAULT;
unuse_mm(io_data->mm);
}
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index b135da661fc9..f3715d85aedc 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -2981,25 +2981,6 @@ void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn,
}
EXPORT_SYMBOL_GPL(fsg_common_set_inquiry_string);
-int fsg_common_run_thread(struct fsg_common *common)
-{
- common->state = FSG_STATE_IDLE;
- /* Tell the thread to start working */
- common->thread_task =
- kthread_create(fsg_main_thread, common, "file-storage");
- if (IS_ERR(common->thread_task)) {
- common->state = FSG_STATE_TERMINATED;
- return PTR_ERR(common->thread_task);
- }
-
- DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task));
-
- wake_up_process(common->thread_task);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(fsg_common_run_thread);
-
static void fsg_common_release(struct kref *ref)
{
struct fsg_common *common = container_of(ref, struct fsg_common, ref);
@@ -3009,6 +2990,7 @@ static void fsg_common_release(struct kref *ref)
if (common->state != FSG_STATE_TERMINATED) {
raise_exception(common, FSG_STATE_EXIT);
wait_for_completion(&common->thread_notifier);
+ common->thread_task = NULL;
}
for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
@@ -3054,9 +3036,21 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
if (ret)
return ret;
fsg_common_set_inquiry_string(fsg->common, NULL, NULL);
- ret = fsg_common_run_thread(fsg->common);
- if (ret)
+ }
+
+ if (!common->thread_task) {
+ common->state = FSG_STATE_IDLE;
+ common->thread_task =
+ kthread_create(fsg_main_thread, common, "file-storage");
+ if (IS_ERR(common->thread_task)) {
+ int ret = PTR_ERR(common->thread_task);
+ common->thread_task = NULL;
+ common->state = FSG_STATE_TERMINATED;
return ret;
+ }
+ DBG(common, "I/O thread pid: %d\n",
+ task_pid_nr(common->thread_task));
+ wake_up_process(common->thread_task);
}
fsg->gadget = gadget;
diff --git a/drivers/usb/gadget/function/f_mass_storage.h b/drivers/usb/gadget/function/f_mass_storage.h
index 445df6775609..b6a9918eaefb 100644
--- a/drivers/usb/gadget/function/f_mass_storage.h
+++ b/drivers/usb/gadget/function/f_mass_storage.h
@@ -153,8 +153,6 @@ int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg);
void fsg_common_set_inquiry_string(struct fsg_common *common, const char *vn,
const char *pn);
-int fsg_common_run_thread(struct fsg_common *common);
-
void fsg_config_from_params(struct fsg_config *cfg,
const struct fsg_module_parameters *params,
unsigned int fsg_num_buffers);
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 98d5908c1e2f..8919cc26b98e 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -1141,6 +1141,7 @@ static void f_midi_free(struct usb_function *f)
kfree(midi->in_port[i]);
opts->func_inst.f = NULL;
kfree(midi);
+ opts->func_inst.f = NULL;
--opts->refcnt;
mutex_unlock(&opts->lock);
}
diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c
index 5e50fe245a59..ea0f433f989c 100644
--- a/drivers/usb/gadget/function/f_mtp.c
+++ b/drivers/usb/gadget/function/f_mtp.c
@@ -753,8 +753,8 @@ static ssize_t mtp_write(struct file *fp, const char __user *buf,
break;
}
- if (count > MTP_BULK_BUFFER_SIZE)
- xfer = MTP_BULK_BUFFER_SIZE;
+ if (count > mtp_tx_req_len)
+ xfer = mtp_tx_req_len;
else
xfer = count;
if (xfer && copy_from_user(req->buf, buf, xfer)) {
@@ -850,8 +850,8 @@ static void send_file_work(struct work_struct *data)
break;
}
- if (count > MTP_BULK_BUFFER_SIZE)
- xfer = MTP_BULK_BUFFER_SIZE;
+ if (count > mtp_tx_req_len)
+ xfer = mtp_tx_req_len;
else
xfer = count;
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index dd73dfe5dcab..74e9f5b5a45d 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -863,8 +863,6 @@ static int eth_stop(struct net_device *net)
/*-------------------------------------------------------------------------*/
-static u8 host_ethaddr[ETH_ALEN];
-
static int get_ether_addr(const char *str, u8 *dev_addr)
{
if (str) {
@@ -895,17 +893,6 @@ static int get_ether_addr_str(u8 dev_addr[ETH_ALEN], char *str, int len)
return 18;
}
-static int get_host_ether_addr(u8 *str, u8 *dev_addr)
-{
- memcpy(dev_addr, str, ETH_ALEN);
- if (is_valid_ether_addr(dev_addr))
- return 0;
-
- random_ether_addr(dev_addr);
- memcpy(str, dev_addr, ETH_ALEN);
- return 1;
-}
-
static const struct net_device_ops eth_netdev_ops = {
.ndo_open = eth_open,
.ndo_stop = eth_stop,
@@ -963,11 +950,9 @@ struct eth_dev *gether_setup_name(struct usb_gadget *g,
if (get_ether_addr(dev_addr, net->dev_addr))
dev_warn(&g->dev,
"using random %s ethernet address\n", "self");
-
- if (get_host_ether_addr(host_ethaddr, dev->host_mac))
- dev_warn(&g->dev, "using random %s ethernet address\n", "host");
- else
- dev_warn(&g->dev, "using previous %s ethernet address\n", "host");
+ if (get_ether_addr(host_addr, dev->host_mac))
+ dev_warn(&g->dev,
+ "using random %s ethernet address\n", "host");
if (ethaddr)
memcpy(ethaddr, dev->host_mac, ETH_ALEN);
diff --git a/drivers/usb/gadget/legacy/acm_ms.c b/drivers/usb/gadget/legacy/acm_ms.c
index 4b158e2d1e57..64b2cbb0bc6b 100644
--- a/drivers/usb/gadget/legacy/acm_ms.c
+++ b/drivers/usb/gadget/legacy/acm_ms.c
@@ -133,10 +133,6 @@ static int acm_ms_do_config(struct usb_configuration *c)
if (status < 0)
goto put_msg;
- status = fsg_common_run_thread(opts->common);
- if (status)
- goto remove_acm;
-
status = usb_add_function(c, f_msg);
if (status)
goto remove_acm;
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c
index f454c7af489c..55386619a0f1 100644
--- a/drivers/usb/gadget/legacy/inode.c
+++ b/drivers/usb/gadget/legacy/inode.c
@@ -937,8 +937,11 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
struct usb_ep *ep = dev->gadget->ep0;
struct usb_request *req = dev->req;
- if ((retval = setup_req (ep, req, 0)) == 0)
- retval = usb_ep_queue (ep, req, GFP_ATOMIC);
+ if ((retval = setup_req (ep, req, 0)) == 0) {
+ spin_unlock_irq (&dev->lock);
+ retval = usb_ep_queue (ep, req, GFP_KERNEL);
+ spin_lock_irq (&dev->lock);
+ }
dev->state = STATE_DEV_CONNECTED;
/* assume that was SET_CONFIGURATION */
@@ -1456,8 +1459,11 @@ delegate:
w_length);
if (value < 0)
break;
+
+ spin_unlock (&dev->lock);
value = usb_ep_queue (gadget->ep0, dev->req,
- GFP_ATOMIC);
+ GFP_KERNEL);
+ spin_lock (&dev->lock);
if (value < 0) {
clean_req (gadget->ep0, dev->req);
break;
@@ -1480,11 +1486,14 @@ delegate:
if (value >= 0 && dev->state != STATE_DEV_SETUP) {
req->length = value;
req->zero = value < w_length;
- value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
+
+ spin_unlock (&dev->lock);
+ value = usb_ep_queue (gadget->ep0, req, GFP_KERNEL);
if (value < 0) {
DBG (dev, "ep_queue --> %d\n", value);
req->status = 0;
}
+ return value;
}
/* device stalls when value < 0 */
diff --git a/drivers/usb/gadget/legacy/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c
index bda3c519110f..99aa22c81770 100644
--- a/drivers/usb/gadget/legacy/mass_storage.c
+++ b/drivers/usb/gadget/legacy/mass_storage.c
@@ -132,10 +132,6 @@ static int msg_do_config(struct usb_configuration *c)
if (IS_ERR(f_msg))
return PTR_ERR(f_msg);
- ret = fsg_common_run_thread(opts->common);
- if (ret)
- goto put_func;
-
ret = usb_add_function(c, f_msg);
if (ret)
goto put_func;
diff --git a/drivers/usb/gadget/legacy/multi.c b/drivers/usb/gadget/legacy/multi.c
index 4fe794ddcd49..09c7c28f32f7 100644
--- a/drivers/usb/gadget/legacy/multi.c
+++ b/drivers/usb/gadget/legacy/multi.c
@@ -137,7 +137,6 @@ static struct usb_function *f_msg_rndis;
static int rndis_do_config(struct usb_configuration *c)
{
- struct fsg_opts *fsg_opts;
int ret;
if (gadget_is_otg(c->cdev->gadget)) {
@@ -169,11 +168,6 @@ static int rndis_do_config(struct usb_configuration *c)
goto err_fsg;
}
- fsg_opts = fsg_opts_from_func_inst(fi_msg);
- ret = fsg_common_run_thread(fsg_opts->common);
- if (ret)
- goto err_run;
-
ret = usb_add_function(c, f_msg_rndis);
if (ret)
goto err_run;
@@ -225,7 +219,6 @@ static struct usb_function *f_msg_multi;
static int cdc_do_config(struct usb_configuration *c)
{
- struct fsg_opts *fsg_opts;
int ret;
if (gadget_is_otg(c->cdev->gadget)) {
@@ -258,11 +251,6 @@ static int cdc_do_config(struct usb_configuration *c)
goto err_fsg;
}
- fsg_opts = fsg_opts_from_func_inst(fi_msg);
- ret = fsg_common_run_thread(fsg_opts->common);
- if (ret)
- goto err_run;
-
ret = usb_add_function(c, f_msg_multi);
if (ret)
goto err_run;
diff --git a/drivers/usb/gadget/legacy/nokia.c b/drivers/usb/gadget/legacy/nokia.c
index 8b3f6fb1825d..05d3f79e768d 100644
--- a/drivers/usb/gadget/legacy/nokia.c
+++ b/drivers/usb/gadget/legacy/nokia.c
@@ -152,7 +152,6 @@ static int nokia_bind_config(struct usb_configuration *c)
struct usb_function *f_ecm;
struct usb_function *f_obex2 = NULL;
struct usb_function *f_msg;
- struct fsg_opts *fsg_opts;
int status = 0;
int obex1_stat = -1;
int obex2_stat = -1;
@@ -222,12 +221,6 @@ static int nokia_bind_config(struct usb_configuration *c)
goto err_ecm;
}
- fsg_opts = fsg_opts_from_func_inst(fi_msg);
-
- status = fsg_common_run_thread(fsg_opts->common);
- if (status)
- goto err_msg;
-
status = usb_add_function(c, f_msg);
if (status)
goto err_msg;
diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
index c148a4fdfe99..476ac5e511a4 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -71,7 +71,7 @@ int usb_gadget_map_request(struct usb_gadget *gadget,
mapped = dma_map_sg(dev, req->sg, req->num_sgs,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (mapped == 0) {
- dev_err(&gadget->dev, "failed to map SGs\n");
+ dev_err(dev, "failed to map SGs\n");
return -EFAULT;
}
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index 4031b372008e..c1c1024a054c 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -89,7 +89,7 @@ static int tegra_reset_usb_controller(struct platform_device *pdev)
if (!usb1_reset_attempted) {
struct reset_control *usb1_reset;
- usb1_reset = of_reset_control_get(phy_np, "usb");
+ usb1_reset = of_reset_control_get(phy_np, "utmi-pads");
if (IS_ERR(usb1_reset)) {
dev_warn(&pdev->dev,
"can't get utmi-pads reset from the PHY\n");
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 0f51d078416e..a7b055bc279a 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1165,7 +1165,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
xhci_set_link_state(xhci, port_array, wIndex,
XDEV_RESUME);
spin_unlock_irqrestore(&xhci->lock, flags);
- msleep(20);
+ usleep_range(21000, 21500);
spin_lock_irqsave(&xhci->lock, flags);
xhci_set_link_state(xhci, port_array, wIndex,
XDEV_U0);
@@ -1409,7 +1409,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
if (need_usb2_u3_exit) {
spin_unlock_irqrestore(&xhci->lock, flags);
- msleep(20);
+ usleep_range(21000, 21500);
spin_lock_irqsave(&xhci->lock, flags);
}
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index ac298e632d73..29dc6ab252b1 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1789,6 +1789,8 @@ void xhci_free_command(struct xhci_hcd *xhci,
int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned intr_num)
{
int size;
+ u32 iman_reg;
+ u64 erdp_reg;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct device *dev = xhci_to_hcd(xhci)->self.controller;
@@ -1800,14 +1802,38 @@ int xhci_sec_event_ring_cleanup(struct usb_hcd *hcd, unsigned intr_num)
size =
sizeof(struct xhci_erst_entry)*(xhci->sec_erst[intr_num].num_entries);
- if (xhci->sec_erst[intr_num].entries)
+ if (xhci->sec_erst[intr_num].entries) {
+ /*
+ * disable irq, ack pending interrupt and clear EHB for xHC to
+ * generate interrupt again when new event ring is setup
+ */
+ iman_reg =
+ readl_relaxed(&xhci->sec_ir_set[intr_num]->irq_pending);
+ iman_reg &= ~IMAN_IE;
+ writel_relaxed(iman_reg,
+ &xhci->sec_ir_set[intr_num]->irq_pending);
+ iman_reg =
+ readl_relaxed(&xhci->sec_ir_set[intr_num]->irq_pending);
+ if (iman_reg & IMAN_IP)
+ writel_relaxed(iman_reg,
+ &xhci->sec_ir_set[intr_num]->irq_pending);
+ /* make sure IP gets cleared before clearing EHB */
+ mb();
+
+ erdp_reg = xhci_read_64(xhci,
+ &xhci->sec_ir_set[intr_num]->erst_dequeue);
+ xhci_write_64(xhci, erdp_reg | ERST_EHB,
+ &xhci->sec_ir_set[intr_num]->erst_dequeue);
+
dma_free_coherent(dev, size, xhci->sec_erst[intr_num].entries,
xhci->sec_erst[intr_num].erst_dma_addr);
- xhci->sec_erst[intr_num].entries = NULL;
+ xhci->sec_erst[intr_num].entries = NULL;
+ }
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Freed SEC ERST#%d",
intr_num);
if (xhci->sec_event_ring[intr_num])
xhci_ring_free(xhci, xhci->sec_event_ring[intr_num]);
+
xhci->sec_event_ring[intr_num] = NULL;
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Freed sec event ring");
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index ea4fb4b0cd44..de644e56aa3b 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -37,6 +37,7 @@
/* Device for a quirk */
#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
+#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1009 0x1009
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400 0x1400
#define PCI_VENDOR_ID_ETRON 0x1b6f
@@ -115,6 +116,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
}
+ if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
+ pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1009)
+ xhci->quirks |= XHCI_BROKEN_STREAMS;
+
if (pdev->vendor == PCI_VENDOR_ID_NEC)
xhci->quirks |= XHCI_NEC_HOST;
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 5193bf5eb8c3..084dbbc81a6d 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -186,6 +186,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
ret = clk_prepare_enable(clk);
if (ret)
goto put_hcd;
+ } else if (PTR_ERR(clk) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto put_hcd;
}
if (pdev->dev.parent)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 2b63969c2bbf..34cd23724bed 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -289,6 +289,14 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
+
+ /*
+ * Writing the CMD_RING_ABORT bit should cause a cmd completion event,
+ * however on some host hw the CMD_RING_RUNNING bit is correctly cleared
+ * but the completion event in never sent. Use the cmd timeout timer to
+ * handle those cases. Use twice the time to cover the bit polling retry
+ */
+ mod_timer(&xhci->cmd_timer, jiffies + (2 * XHCI_CMD_DEFAULT_TIMEOUT));
xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
&xhci->op_regs->cmd_ring);
@@ -313,6 +321,7 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
xhci_err(xhci, "Stopped the command ring failed, "
"maybe the host is dead\n");
+ del_timer(&xhci->cmd_timer);
xhci->xhc_state |= XHCI_STATE_DYING;
xhci_quiesce(xhci);
xhci_halt(xhci);
@@ -1252,22 +1261,21 @@ void xhci_handle_command_timeout(unsigned long data)
int ret;
unsigned long flags;
u64 hw_ring_state;
- struct xhci_command *cur_cmd = NULL;
+ bool second_timeout = false;
xhci = (struct xhci_hcd *) data;
/* mark this command to be cancelled */
spin_lock_irqsave(&xhci->lock, flags);
if (xhci->current_cmd) {
- cur_cmd = xhci->current_cmd;
- cur_cmd->status = COMP_CMD_ABORT;
+ if (xhci->current_cmd->status == COMP_CMD_ABORT)
+ second_timeout = true;
+ xhci->current_cmd->status = COMP_CMD_ABORT;
}
-
/* Make sure command ring is running before aborting it */
hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
(hw_ring_state & CMD_RING_RUNNING)) {
-
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_dbg(xhci, "Command timeout\n");
ret = xhci_abort_cmd_ring(xhci);
@@ -1279,6 +1287,15 @@ void xhci_handle_command_timeout(unsigned long data)
}
return;
}
+
+ /* command ring failed to restart, or host removed. Bail out */
+ if (second_timeout || xhci->xhc_state & XHCI_STATE_REMOVING) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ xhci_dbg(xhci, "command timed out twice, ring start fail?\n");
+ xhci_cleanup_command_queue(xhci);
+ return;
+ }
+
/* command timeout on stopped ring, ring can't be aborted */
xhci_dbg(xhci, "Command timeout on stopped ring\n");
xhci_handle_stopped_cmd_ring(xhci, xhci->current_cmd);
@@ -2727,7 +2744,8 @@ hw_died:
writel(irq_pending, &xhci->ir_set->irq_pending);
}
- if (xhci->xhc_state & XHCI_STATE_DYING) {
+ if (xhci->xhc_state & XHCI_STATE_DYING ||
+ xhci->xhc_state & XHCI_STATE_HALTED) {
xhci_dbg(xhci, "xHCI dying, ignoring interrupt. "
"Shouldn't IRQs be disabled?\n");
/* Clear the event handler busy flag (RW1C);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 5fc20c7c51f8..a37b219a8dc5 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -692,20 +692,23 @@ void xhci_stop(struct usb_hcd *hcd)
u32 temp;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
- if (xhci->xhc_state & XHCI_STATE_HALTED)
- return;
-
mutex_lock(&xhci->mutex);
- spin_lock_irq(&xhci->lock);
- xhci->xhc_state |= XHCI_STATE_HALTED;
- xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
- /* Make sure the xHC is halted for a USB3 roothub
- * (xhci_stop() could be called as part of failed init).
- */
- xhci_halt(xhci);
- xhci_reset(xhci);
- spin_unlock_irq(&xhci->lock);
+ if (!(xhci->xhc_state & XHCI_STATE_HALTED)) {
+ spin_lock_irq(&xhci->lock);
+
+ xhci->xhc_state |= XHCI_STATE_HALTED;
+ xhci->cmd_ring_state = CMD_RING_STATE_STOPPED;
+ xhci_halt(xhci);
+ xhci_reset(xhci);
+
+ spin_unlock_irq(&xhci->lock);
+ }
+
+ if (!usb_hcd_is_primary_hcd(hcd)) {
+ mutex_unlock(&xhci->mutex);
+ return;
+ }
xhci_cleanup_msix(xhci);
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 637f3f7cfce8..1a812eafe670 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -505,6 +505,7 @@ static struct scatterlist *
alloc_sglist(int nents, int max, int vary, struct usbtest_dev *dev, int pipe)
{
struct scatterlist *sg;
+ unsigned int n_size = 0;
unsigned i;
unsigned size = max;
unsigned maxpacket =
@@ -537,7 +538,8 @@ alloc_sglist(int nents, int max, int vary, struct usbtest_dev *dev, int pipe)
break;
case 1:
for (j = 0; j < size; j++)
- *buf++ = (u8) ((j % maxpacket) % 63);
+ *buf++ = (u8) (((j + n_size) % maxpacket) % 63);
+ n_size += size;
break;
}
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index ee9ff7028b92..00eed5d66fda 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2401,7 +2401,8 @@ static void musb_restore_context(struct musb *musb)
musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe);
musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe);
musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);
- musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
+ if (musb->context.devctl & MUSB_DEVCTL_SESSION)
+ musb_writeb(musb_base, MUSB_DEVCTL, musb->context.devctl);
for (i = 0; i < musb->config->num_eps; ++i) {
struct musb_hw_ep *hw_ep;
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 795a45b1b25b..59a63a0b7985 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -594,14 +594,13 @@ musb_rx_reinit(struct musb *musb, struct musb_qh *qh, u8 epnum)
musb_writew(ep->regs, MUSB_TXCSR, 0);
/* scrub all previous state, clearing toggle */
- } else {
- csr = musb_readw(ep->regs, MUSB_RXCSR);
- if (csr & MUSB_RXCSR_RXPKTRDY)
- WARNING("rx%d, packet/%d ready?\n", ep->epnum,
- musb_readw(ep->regs, MUSB_RXCOUNT));
-
- musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
}
+ csr = musb_readw(ep->regs, MUSB_RXCSR);
+ if (csr & MUSB_RXCSR_RXPKTRDY)
+ WARNING("rx%d, packet/%d ready?\n", ep->epnum,
+ musb_readw(ep->regs, MUSB_RXCOUNT));
+
+ musb_h_flush_rxfifo(ep, MUSB_RXCSR_CLRDATATOG);
/* target addr and (for multipoint) hub addr/port */
if (musb->is_multipoint) {
@@ -995,9 +994,15 @@ static void musb_bulk_nak_timeout(struct musb *musb, struct musb_hw_ep *ep,
if (is_in) {
dma = is_dma_capable() ? ep->rx_channel : NULL;
- /* clear nak timeout bit */
+ /*
+ * Need to stop the transaction by clearing REQPKT first
+ * then the NAK Timeout bit ref MUSBMHDRC USB 2.0 HIGH-SPEED
+ * DUAL-ROLE CONTROLLER Programmer's Guide, section 9.2.2
+ */
rx_csr = musb_readw(epio, MUSB_RXCSR);
rx_csr |= MUSB_RXCSR_H_WZC_BITS;
+ rx_csr &= ~MUSB_RXCSR_H_REQPKT;
+ musb_writew(epio, MUSB_RXCSR, rx_csr);
rx_csr &= ~MUSB_RXCSR_DATAERROR;
musb_writew(epio, MUSB_RXCSR, rx_csr);
@@ -1551,7 +1556,7 @@ static int musb_rx_dma_iso_cppi41(struct dma_controller *dma,
struct urb *urb,
size_t len)
{
- struct dma_channel *channel = hw_ep->tx_channel;
+ struct dma_channel *channel = hw_ep->rx_channel;
void __iomem *epio = hw_ep->regs;
dma_addr_t *buf;
u32 length, res;
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index c0866971db2b..1947ea0e0988 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -2856,14 +2856,16 @@ static int edge_startup(struct usb_serial *serial)
/* not set up yet, so do it now */
edge_serial->interrupt_read_urb =
usb_alloc_urb(0, GFP_KERNEL);
- if (!edge_serial->interrupt_read_urb)
- return -ENOMEM;
+ if (!edge_serial->interrupt_read_urb) {
+ response = -ENOMEM;
+ break;
+ }
edge_serial->interrupt_in_buffer =
kmalloc(buffer_size, GFP_KERNEL);
if (!edge_serial->interrupt_in_buffer) {
- usb_free_urb(edge_serial->interrupt_read_urb);
- return -ENOMEM;
+ response = -ENOMEM;
+ break;
}
edge_serial->interrupt_in_endpoint =
endpoint->bEndpointAddress;
@@ -2891,14 +2893,16 @@ static int edge_startup(struct usb_serial *serial)
/* not set up yet, so do it now */
edge_serial->read_urb =
usb_alloc_urb(0, GFP_KERNEL);
- if (!edge_serial->read_urb)
- return -ENOMEM;
+ if (!edge_serial->read_urb) {
+ response = -ENOMEM;
+ break;
+ }
edge_serial->bulk_in_buffer =
kmalloc(buffer_size, GFP_KERNEL);
if (!edge_serial->bulk_in_buffer) {
- usb_free_urb(edge_serial->read_urb);
- return -ENOMEM;
+ response = -ENOMEM;
+ break;
}
edge_serial->bulk_in_endpoint =
endpoint->bEndpointAddress;
@@ -2924,9 +2928,22 @@ static int edge_startup(struct usb_serial *serial)
}
}
- if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) {
- dev_err(ddev, "Error - the proper endpoints were not found!\n");
- return -ENODEV;
+ if (response || !interrupt_in_found || !bulk_in_found ||
+ !bulk_out_found) {
+ if (!response) {
+ dev_err(ddev, "expected endpoints not found\n");
+ response = -ENODEV;
+ }
+
+ usb_free_urb(edge_serial->interrupt_read_urb);
+ kfree(edge_serial->interrupt_in_buffer);
+
+ usb_free_urb(edge_serial->read_urb);
+ kfree(edge_serial->bulk_in_buffer);
+
+ kfree(edge_serial);
+
+ return response;
}
/* start interrupt read for this edgeport this interrupt will
@@ -2949,16 +2966,9 @@ static void edge_disconnect(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
- /* stop reads and writes on all ports */
- /* free up our endpoint stuff */
if (edge_serial->is_epic) {
usb_kill_urb(edge_serial->interrupt_read_urb);
- usb_free_urb(edge_serial->interrupt_read_urb);
- kfree(edge_serial->interrupt_in_buffer);
-
usb_kill_urb(edge_serial->read_urb);
- usb_free_urb(edge_serial->read_urb);
- kfree(edge_serial->bulk_in_buffer);
}
}
@@ -2971,6 +2981,16 @@ static void edge_release(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+ if (edge_serial->is_epic) {
+ usb_kill_urb(edge_serial->interrupt_read_urb);
+ usb_free_urb(edge_serial->interrupt_read_urb);
+ kfree(edge_serial->interrupt_in_buffer);
+
+ usb_kill_urb(edge_serial->read_urb);
+ usb_free_urb(edge_serial->read_urb);
+ kfree(edge_serial->bulk_in_buffer);
+ }
+
kfree(edge_serial);
}
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c
index e07b15ed5814..7faa901ee47f 100644
--- a/drivers/usb/serial/keyspan.c
+++ b/drivers/usb/serial/keyspan.c
@@ -2376,6 +2376,10 @@ static void keyspan_release(struct usb_serial *serial)
s_priv = usb_get_serial_data(serial);
+ /* Make sure to unlink the URBs submitted in attach. */
+ usb_kill_urb(s_priv->instat_urb);
+ usb_kill_urb(s_priv->indat_urb);
+
usb_free_urb(s_priv->instat_urb);
usb_free_urb(s_priv->indat_urb);
usb_free_urb(s_priv->glocont_urb);
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c
index 78b4f64c6b00..06c7dbc1c802 100644
--- a/drivers/usb/serial/mos7720.c
+++ b/drivers/usb/serial/mos7720.c
@@ -2007,6 +2007,7 @@ static void mos7720_release(struct usb_serial *serial)
urblist_entry)
usb_unlink_urb(urbtrack->urb);
spin_unlock_irqrestore(&mos_parport->listlock, flags);
+ parport_del_port(mos_parport->pp);
kref_put(&mos_parport->ref_count, destroy_mos_parport);
}
diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c
index 31a8b47f1ac6..c6596cbcc4b6 100644
--- a/drivers/usb/serial/mxuport.c
+++ b/drivers/usb/serial/mxuport.c
@@ -1259,6 +1259,15 @@ static int mxuport_attach(struct usb_serial *serial)
return 0;
}
+static void mxuport_release(struct usb_serial *serial)
+{
+ struct usb_serial_port *port0 = serial->port[0];
+ struct usb_serial_port *port1 = serial->port[1];
+
+ usb_serial_generic_close(port1);
+ usb_serial_generic_close(port0);
+}
+
static int mxuport_open(struct tty_struct *tty, struct usb_serial_port *port)
{
struct mxuport_port *mxport = usb_get_serial_port_data(port);
@@ -1361,6 +1370,7 @@ static struct usb_serial_driver mxuport_device = {
.probe = mxuport_probe,
.port_probe = mxuport_port_probe,
.attach = mxuport_attach,
+ .release = mxuport_release,
.calc_num_ports = mxuport_calc_num_ports,
.open = mxuport_open,
.close = mxuport_close,
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index c6f497f16526..d96d423d00e6 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -375,18 +375,22 @@ static void option_instat_callback(struct urb *urb);
#define HAIER_PRODUCT_CE81B 0x10f8
#define HAIER_PRODUCT_CE100 0x2009
-/* Cinterion (formerly Siemens) products */
-#define SIEMENS_VENDOR_ID 0x0681
-#define CINTERION_VENDOR_ID 0x1e2d
+/* Gemalto's Cinterion products (formerly Siemens) */
+#define SIEMENS_VENDOR_ID 0x0681
+#define CINTERION_VENDOR_ID 0x1e2d
+#define CINTERION_PRODUCT_HC25_MDMNET 0x0040
#define CINTERION_PRODUCT_HC25_MDM 0x0047
-#define CINTERION_PRODUCT_HC25_MDMNET 0x0040
+#define CINTERION_PRODUCT_HC28_MDMNET 0x004A /* same for HC28J */
#define CINTERION_PRODUCT_HC28_MDM 0x004C
-#define CINTERION_PRODUCT_HC28_MDMNET 0x004A /* same for HC28J */
#define CINTERION_PRODUCT_EU3_E 0x0051
#define CINTERION_PRODUCT_EU3_P 0x0052
#define CINTERION_PRODUCT_PH8 0x0053
#define CINTERION_PRODUCT_AHXX 0x0055
#define CINTERION_PRODUCT_PLXX 0x0060
+#define CINTERION_PRODUCT_PH8_2RMNET 0x0082
+#define CINTERION_PRODUCT_PH8_AUDIO 0x0083
+#define CINTERION_PRODUCT_AHXX_2RMNET 0x0084
+#define CINTERION_PRODUCT_AHXX_AUDIO 0x0085
/* Olivetti products */
#define OLIVETTI_VENDOR_ID 0x0b3c
@@ -633,6 +637,10 @@ static const struct option_blacklist_info telit_le922_blacklist_usbcfg3 = {
.reserved = BIT(1) | BIT(2) | BIT(3),
};
+static const struct option_blacklist_info cinterion_rmnet2_blacklist = {
+ .reserved = BIT(4) | BIT(5),
+};
+
static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -1602,7 +1610,79 @@ static const struct usb_device_id option_ids[] = {
.driver_info = (kernel_ulong_t)&net_intf3_blacklist },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&net_intf3_blacklist },
- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffe9, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff42, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff43, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff44, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff45, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff46, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff47, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff48, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff49, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff4a, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff4b, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff4c, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff4d, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff4e, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff4f, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff50, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff51, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff52, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff53, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff54, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff55, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff56, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff57, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff58, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff59, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff5a, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff5b, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff5c, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff5d, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff5e, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff5f, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff60, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff61, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff62, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff63, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff64, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff65, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff66, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff67, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff68, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff69, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff6a, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff6b, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff6c, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff6d, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff6e, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff6f, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff70, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff71, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff72, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff73, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff74, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff75, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff76, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff77, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff78, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff79, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff7a, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff7b, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff7c, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff7d, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff7e, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff7f, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff80, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff81, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff82, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff83, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff84, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff85, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff86, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff87, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff88, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff89, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff8a, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff8b, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff8c, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff8d, 0xff, 0xff, 0xff) },
@@ -1613,6 +1693,61 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff92, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff93, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff94, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff9f, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa0, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa1, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa2, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa3, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa4, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa5, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa6, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa7, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa8, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffa9, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffaa, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffab, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffac, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffae, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffaf, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb0, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb1, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb2, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb3, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb4, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb5, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb6, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb7, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb8, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffb9, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffba, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffbb, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffbc, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffbd, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffbe, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffbf, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc0, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc1, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc2, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc3, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc4, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc5, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc6, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc7, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc8, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffc9, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffca, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffcb, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffcc, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffcd, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffce, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffcf, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffd0, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffd1, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffd2, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffd3, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffd4, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffd5, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffe9, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffec, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffee, 0xff, 0xff, 0xff) },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xfff6, 0xff, 0xff, 0xff) },
@@ -1712,7 +1847,13 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX, 0xff) },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
- { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) },
+ { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8_2RMNET, 0xff),
+ .driver_info = (kernel_ulong_t)&cinterion_rmnet2_blacklist },
+ { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8_AUDIO, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+ { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX_2RMNET, 0xff) },
+ { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX_AUDIO, 0xff) },
+ { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) },
{ USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDMNET) },
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c
index 504f5bff79c0..b18974cbd995 100644
--- a/drivers/usb/serial/quatech2.c
+++ b/drivers/usb/serial/quatech2.c
@@ -141,6 +141,7 @@ static void qt2_release(struct usb_serial *serial)
serial_priv = usb_get_serial_data(serial);
+ usb_kill_urb(serial_priv->read_urb);
usb_free_urb(serial_priv->read_urb);
kfree(serial_priv->read_buffer);
kfree(serial_priv);
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 9baf081174ce..e26e32169a36 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -811,6 +811,7 @@ static int uas_slave_configure(struct scsi_device *sdev)
if (devinfo->flags & US_FL_BROKEN_FUA)
sdev->broken_fua = 1;
+ scsi_change_queue_depth(sdev, devinfo->qdepth - 2);
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index 1e93a5b2e9ba..5a24a1995af9 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -178,6 +178,7 @@ enum mdss_hw_capabilities {
MDSS_CAPS_CWB_SUPPORTED,
MDSS_CAPS_MDP_VOTE_CLK_NOT_SUPPORTED,
MDSS_CAPS_AVR_SUPPORTED,
+ MDSS_CAPS_SEC_DETACH_SMMU,
MDSS_CAPS_MAX,
};
@@ -221,6 +222,7 @@ struct mdss_smmu_client {
bool domain_attached;
bool handoff_pending;
void __iomem *mmu_base;
+ int domain;
};
struct mdss_mdp_qseed3_lut_tbl {
@@ -327,6 +329,7 @@ struct mdss_data_type {
u32 wfd_mode;
u32 has_no_lut_read;
atomic_t sd_client_count;
+ atomic_t sc_client_count;
u8 has_wb_ad;
u8 has_non_scalar_rgb;
bool has_src_split;
@@ -519,6 +522,8 @@ struct mdss_data_type {
u32 max_dest_scaler_input_width;
u32 max_dest_scaler_output_width;
struct mdss_mdp_destination_scaler *ds;
+ u32 sec_disp_en;
+ u32 sec_cam_en;
};
extern struct mdss_data_type *mdss_res;
@@ -579,6 +584,14 @@ static inline int mdss_get_sd_client_cnt(void)
return atomic_read(&mdss_res->sd_client_count);
}
+static inline int mdss_get_sc_client_cnt(void)
+{
+ if (!mdss_res)
+ return 0;
+ else
+ return atomic_read(&mdss_res->sc_client_count);
+}
+
static inline void mdss_set_quirk(struct mdss_data_type *mdata,
enum mdss_hw_quirk bit)
{
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index fa2e47e06503..75e42ca8cd88 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -57,6 +57,10 @@ static u32 supported_modes[] = {
HDMI_VFRMT_4096x2160p60_256_135, HDMI_EVFRMT_4096x2160p24_16_9
};
+static int mdss_dp_off_irq(struct mdss_dp_drv_pdata *dp_drv);
+static void mdss_dp_mainlink_push_idle(struct mdss_panel_data *pdata);
+static inline void mdss_dp_link_retraining(struct mdss_dp_drv_pdata *dp);
+
static void mdss_dp_put_dt_clk_data(struct device *dev,
struct dss_module_power *module_power)
{
@@ -902,8 +906,6 @@ static int dp_audio_info_setup(struct platform_device *pdev,
mdss_dp_set_safe_to_exit_level(&dp_ctrl->ctrl_io, dp_ctrl->lane_cnt);
mdss_dp_audio_enable(&dp_ctrl->ctrl_io, true);
- dp_ctrl->wait_for_audio_comp = true;
-
return rc;
} /* dp_audio_info_setup */
@@ -926,17 +928,6 @@ static int dp_get_audio_edid_blk(struct platform_device *pdev,
return rc;
} /* dp_get_audio_edid_blk */
-static void dp_audio_codec_teardown_done(struct platform_device *pdev)
-{
- struct mdss_dp_drv_pdata *dp = platform_get_drvdata(pdev);
-
- if (!dp)
- pr_err("invalid input\n");
-
- pr_debug("audio codec teardown done\n");
- complete_all(&dp->audio_comp);
-}
-
static int mdss_dp_init_ext_disp(struct mdss_dp_drv_pdata *dp)
{
int ret = 0;
@@ -958,8 +949,6 @@ static int mdss_dp_init_ext_disp(struct mdss_dp_drv_pdata *dp)
dp_get_audio_edid_blk;
dp->ext_audio_data.codec_ops.cable_status =
dp_get_cable_status;
- dp->ext_audio_data.codec_ops.teardown_done =
- dp_audio_codec_teardown_done;
if (!dp->pdev->dev.of_node) {
pr_err("%s cannot find dp dev.of_node\n", __func__);
@@ -1040,12 +1029,10 @@ static int dp_init_panel_info(struct mdss_dp_drv_pdata *dp_drv, u32 vic)
return 0;
} /* dp_init_panel_info */
-static inline void mdss_dp_set_audio_switch_node(
- struct mdss_dp_drv_pdata *dp, int val)
+static inline void mdss_dp_ack_state(struct mdss_dp_drv_pdata *dp, int val)
{
if (dp && dp->ext_audio_data.intf_ops.notify)
- dp->ext_audio_data.intf_ops.notify(dp->ext_pdev,
- val);
+ dp->ext_audio_data.intf_ops.notify(dp->ext_pdev, val);
}
/**
@@ -1156,19 +1143,27 @@ static void mdss_dp_configure_source_params(struct mdss_dp_drv_pdata *dp,
*
* Initiates training of the DP main link and checks the state of the main
* link after the training is complete.
+ *
+ * Return: error code. -EINVAL if any invalid data or -EAGAIN if retraining
+ * is required.
*/
-static void mdss_dp_train_main_link(struct mdss_dp_drv_pdata *dp)
+static int mdss_dp_train_main_link(struct mdss_dp_drv_pdata *dp)
{
+ int ret = 0;
int ready = 0;
pr_debug("enter\n");
+ ret = mdss_dp_link_train(dp);
+ if (ret)
+ goto end;
- mdss_dp_link_train(dp);
mdss_dp_wait4train(dp);
ready = mdss_dp_mainlink_ready(dp, BIT(0));
pr_debug("main link %s\n", ready ? "READY" : "NOT READY");
+end:
+ return ret;
}
static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv)
@@ -1178,33 +1173,43 @@ static int mdss_dp_on_irq(struct mdss_dp_drv_pdata *dp_drv)
struct lane_mapping ln_map;
/* wait until link training is completed */
- mutex_lock(&dp_drv->train_mutex);
-
pr_debug("enter\n");
- orientation = usbpd_get_plug_orientation(dp_drv->pd);
- pr_debug("plug orientation = %d\n", orientation);
+ do {
+ if (ret == -EAGAIN) {
+ mdss_dp_mainlink_push_idle(&dp_drv->panel_data);
+ mdss_dp_off_irq(dp_drv);
+ }
- ret = mdss_dp_get_lane_mapping(dp_drv, orientation, &ln_map);
- if (ret)
- goto exit;
+ mutex_lock(&dp_drv->train_mutex);
- mdss_dp_phy_share_lane_config(&dp_drv->phy_io,
- orientation, dp_drv->dpcd.max_lane_count);
+ orientation = usbpd_get_plug_orientation(dp_drv->pd);
+ pr_debug("plug orientation = %d\n", orientation);
- ret = mdss_dp_enable_mainlink_clocks(dp_drv);
- if (ret)
- goto exit;
+ ret = mdss_dp_get_lane_mapping(dp_drv, orientation, &ln_map);
+ if (ret)
+ goto exit;
- mdss_dp_mainlink_reset(&dp_drv->ctrl_io);
+ mdss_dp_phy_share_lane_config(&dp_drv->phy_io,
+ orientation, dp_drv->dpcd.max_lane_count);
- reinit_completion(&dp_drv->idle_comp);
+ ret = mdss_dp_enable_mainlink_clocks(dp_drv);
+ if (ret)
+ goto exit;
- mdss_dp_configure_source_params(dp_drv, &ln_map);
+ mdss_dp_mainlink_reset(&dp_drv->ctrl_io);
- mdss_dp_train_main_link(dp_drv);
+ reinit_completion(&dp_drv->idle_comp);
+
+ mdss_dp_configure_source_params(dp_drv, &ln_map);
+
+ dp_drv->power_on = true;
+
+ ret = mdss_dp_train_main_link(dp_drv);
+
+ mutex_unlock(&dp_drv->train_mutex);
+ } while (ret == -EAGAIN);
- dp_drv->power_on = true;
pr_debug("end\n");
exit:
@@ -1273,12 +1278,19 @@ int mdss_dp_on_hpd(struct mdss_dp_drv_pdata *dp_drv)
mdss_dp_configure_source_params(dp_drv, &ln_map);
link_training:
- mdss_dp_train_main_link(dp_drv);
+ dp_drv->power_on = true;
+
+ if (-EAGAIN == mdss_dp_train_main_link(dp_drv)) {
+ mutex_unlock(&dp_drv->train_mutex);
+
+ mdss_dp_link_retraining(dp_drv);
+ return 0;
+ }
dp_drv->cont_splash = 0;
dp_drv->power_on = true;
- mdss_dp_set_audio_switch_node(dp_drv, true);
+ mdss_dp_ack_state(dp_drv, true);
pr_debug("End-\n");
exit:
@@ -1311,6 +1323,12 @@ static inline bool mdss_dp_is_link_status_updated(struct mdss_dp_drv_pdata *dp)
return dp->link_status.link_status_updated;
}
+static inline bool mdss_dp_is_downstream_port_status_changed(
+ struct mdss_dp_drv_pdata *dp)
+{
+ return dp->link_status.downstream_port_status_changed;
+}
+
static inline bool mdss_dp_is_link_training_requested(
struct mdss_dp_drv_pdata *dp)
{
@@ -1390,6 +1408,7 @@ static int mdss_dp_off_hpd(struct mdss_dp_drv_pdata *dp_drv)
dp_drv->dp_initialized = false;
dp_drv->power_on = false;
+ mdss_dp_ack_state(dp_drv, false);
mutex_unlock(&dp_drv->train_mutex);
pr_debug("DP off done\n");
@@ -1413,52 +1432,30 @@ int mdss_dp_off(struct mdss_panel_data *pdata)
return mdss_dp_off_hpd(dp);
}
-static void mdss_dp_send_cable_notification(
+static int mdss_dp_send_cable_notification(
struct mdss_dp_drv_pdata *dp, int val)
{
+ int ret = 0;
if (!dp) {
DEV_ERR("%s: invalid input\n", __func__);
- return;
+ ret = -EINVAL;
+ goto end;
}
if (dp && dp->ext_audio_data.intf_ops.hpd)
- dp->ext_audio_data.intf_ops.hpd(dp->ext_pdev,
+ ret = dp->ext_audio_data.intf_ops.hpd(dp->ext_pdev,
dp->ext_audio_data.type, val);
-}
-static void mdss_dp_audio_codec_wait(struct mdss_dp_drv_pdata *dp)
-{
- const int audio_completion_timeout_ms = HZ * 3;
- int ret = 0;
-
- if (!dp->wait_for_audio_comp)
- return;
-
- reinit_completion(&dp->audio_comp);
- ret = wait_for_completion_timeout(&dp->audio_comp,
- audio_completion_timeout_ms);
- if (ret <= 0)
- pr_warn("audio codec teardown timed out\n");
-
- dp->wait_for_audio_comp = false;
+end:
+ return ret;
}
-static void mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp, bool enable)
+static int mdss_dp_notify_clients(struct mdss_dp_drv_pdata *dp, bool enable)
{
- if (enable) {
- mdss_dp_send_cable_notification(dp, enable);
- } else {
- mdss_dp_set_audio_switch_node(dp, enable);
- mdss_dp_audio_codec_wait(dp);
- mdss_dp_send_cable_notification(dp, enable);
- }
-
- pr_debug("notify state %s done\n",
- enable ? "ENABLE" : "DISABLE");
+ return mdss_dp_send_cable_notification(dp, enable);
}
-
static int mdss_dp_edid_init(struct mdss_panel_data *pdata)
{
struct mdss_dp_drv_pdata *dp_drv = NULL;
@@ -1614,22 +1611,18 @@ end:
return rc;
}
-static void mdss_dp_hdcp_cb(void *ptr, enum hdcp_states status)
+static void mdss_dp_hdcp_cb_work(struct work_struct *work)
{
- struct mdss_dp_drv_pdata *dp = ptr;
+ struct mdss_dp_drv_pdata *dp;
+ struct delayed_work *dw = to_delayed_work(work);
struct hdcp_ops *ops;
int rc = 0;
- if (!dp) {
- pr_debug("invalid input\n");
- return;
- }
+ dp = container_of(dw, struct mdss_dp_drv_pdata, hdcp_cb_work);
ops = dp->hdcp.ops;
- mutex_lock(&dp->train_mutex);
-
- switch (status) {
+ switch (dp->hdcp_status) {
case HDCP_STATE_AUTHENTICATED:
pr_debug("hdcp authenticated\n");
dp->hdcp.auth_state = true;
@@ -1652,8 +1645,20 @@ static void mdss_dp_hdcp_cb(void *ptr, enum hdcp_states status)
default:
break;
}
+}
- mutex_unlock(&dp->train_mutex);
+static void mdss_dp_hdcp_cb(void *ptr, enum hdcp_states status)
+{
+ struct mdss_dp_drv_pdata *dp = ptr;
+
+ if (!dp) {
+ pr_err("invalid input\n");
+ return;
+ }
+
+ dp->hdcp_status = status;
+
+ queue_delayed_work(dp->workq, &dp->hdcp_cb_work, HZ/4);
}
static int mdss_dp_hdcp_init(struct mdss_panel_data *pdata)
@@ -1691,19 +1696,19 @@ static int mdss_dp_hdcp_init(struct mdss_panel_data *pdata)
hdcp_init_data.sec_access = true;
hdcp_init_data.client_id = HDCP_CLIENT_DP;
- dp_drv->hdcp.data = hdcp_1x_init(&hdcp_init_data);
- if (IS_ERR_OR_NULL(dp_drv->hdcp.data)) {
+ dp_drv->hdcp.hdcp1 = hdcp_1x_init(&hdcp_init_data);
+ if (IS_ERR_OR_NULL(dp_drv->hdcp.hdcp1)) {
pr_err("Error hdcp init\n");
rc = -EINVAL;
goto error;
}
- dp_drv->panel_data.panel_info.hdcp_1x_data = dp_drv->hdcp.data;
+ dp_drv->panel_data.panel_info.hdcp_1x_data = dp_drv->hdcp.hdcp1;
pr_debug("HDCP 1.3 initialized\n");
dp_drv->hdcp.hdcp2 = dp_hdcp2p2_init(&hdcp_init_data);
- if (!IS_ERR_OR_NULL(dp_drv->hdcp.data))
+ if (!IS_ERR_OR_NULL(dp_drv->hdcp.hdcp2))
pr_debug("HDCP 2.2 initialized\n");
dp_drv->hdcp.feature_enabled = true;
@@ -1882,6 +1887,13 @@ static void mdss_dp_update_hdcp_info(struct mdss_dp_drv_pdata *dp)
dp->hdcp.ops = ops;
}
+static inline bool dp_is_hdcp_enabled(struct mdss_dp_drv_pdata *dp_drv)
+{
+ return dp_drv->hdcp.feature_enabled &&
+ (dp_drv->hdcp.hdcp1_present || dp_drv->hdcp.hdcp2_present) &&
+ dp_drv->hdcp.ops;
+}
+
static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
int event, void *arg)
{
@@ -1913,8 +1925,10 @@ static int mdss_dp_event_handler(struct mdss_panel_data *pdata,
rc = mdss_dp_off(pdata);
break;
case MDSS_EVENT_BLANK:
- if (dp->hdcp.ops && dp->hdcp.ops->off)
+ if (dp_is_hdcp_enabled(dp) && dp->hdcp.ops->off) {
+ flush_delayed_work(&dp->hdcp_cb_work);
dp->hdcp.ops->off(dp->hdcp.data);
+ }
mdss_dp_mainlink_push_idle(pdata);
break;
@@ -2191,6 +2205,11 @@ irqreturn_t dp_isr(int irq, void *ptr)
dp_aux_native_handler(dp, isr1);
}
+ if (dp->hdcp.ops && dp->hdcp.ops->isr) {
+ if (dp->hdcp.ops->isr(dp->hdcp.data))
+ pr_err("dp_hdcp_isr failed\n");
+ }
+
return IRQ_HANDLED;
}
@@ -2205,6 +2224,7 @@ static int mdss_dp_event_setup(struct mdss_dp_drv_pdata *dp)
}
INIT_WORK(&dp->work, mdss_dp_event_work);
+ INIT_DELAYED_WORK(&dp->hdcp_cb_work, mdss_dp_hdcp_cb_work);
return 0;
}
@@ -2307,14 +2327,20 @@ static int mdss_dp_hpd_irq_notify_clients(struct mdss_dp_drv_pdata *dp)
int ret = 0;
if (dp->hpd_irq_toggled) {
- mdss_dp_notify_clients(dp, false);
-
- reinit_completion(&dp->irq_comp);
- ret = wait_for_completion_timeout(&dp->irq_comp,
- irq_comp_timeout);
- if (ret <= 0) {
- pr_warn("irq_comp timed out\n");
- return -EINVAL;
+ dp->hpd_irq_clients_notified = true;
+
+ ret = mdss_dp_notify_clients(dp, false);
+
+ if (!IS_ERR_VALUE(ret) && ret) {
+ reinit_completion(&dp->irq_comp);
+ ret = wait_for_completion_timeout(&dp->irq_comp,
+ irq_comp_timeout);
+ if (ret <= 0) {
+ pr_warn("irq_comp timed out\n");
+ ret = -EINVAL;
+ } else {
+ ret = 0;
+ }
}
}
@@ -2344,19 +2370,24 @@ static inline void mdss_dp_link_retraining(struct mdss_dp_drv_pdata *dp)
* This function will check for changes in the link status, e.g. clock
* recovery done on all lanes, and trigger link training if there is a
* failure/error on the link.
+ *
+ * The function will return 0 if the a link status update has been processed,
+ * otherwise it will return -EINVAL.
*/
-static void mdss_dp_process_link_status_update(struct mdss_dp_drv_pdata *dp)
+static int mdss_dp_process_link_status_update(struct mdss_dp_drv_pdata *dp)
{
if (!mdss_dp_is_link_status_updated(dp) ||
(mdss_dp_aux_channel_eq_done(dp) &&
mdss_dp_aux_clock_recovery_done(dp)))
- return;
+ return -EINVAL;
pr_info("channel_eq_done = %d, clock_recovery_done = %d\n",
mdss_dp_aux_channel_eq_done(dp),
mdss_dp_aux_clock_recovery_done(dp));
mdss_dp_link_retraining(dp);
+
+ return 0;
}
/**
@@ -2366,11 +2397,14 @@ static void mdss_dp_process_link_status_update(struct mdss_dp_drv_pdata *dp)
* This function will handle new link training requests that are initiated by
* the sink. In particular, it will update the requested lane count and link
* link rate, and then trigger the link retraining procedure.
+ *
+ * The function will return 0 if a link training request has been processed,
+ * otherwise it will return -EINVAL.
*/
-static void mdss_dp_process_link_training_request(struct mdss_dp_drv_pdata *dp)
+static int mdss_dp_process_link_training_request(struct mdss_dp_drv_pdata *dp)
{
if (!mdss_dp_is_link_training_requested(dp))
- return;
+ return -EINVAL;
mdss_dp_send_test_response(dp);
@@ -2383,6 +2417,28 @@ static void mdss_dp_process_link_training_request(struct mdss_dp_drv_pdata *dp)
dp->link_rate = dp->test_data.test_link_rate;
mdss_dp_link_retraining(dp);
+
+ return 0;
+}
+
+/**
+ * mdss_dp_process_downstream_port_status_change() - process port status changes
+ * @dp: Display Port Driver data
+ *
+ * This function will handle downstream port updates that are initiated by
+ * the sink. If the downstream port status has changed, the EDID is read via
+ * AUX.
+ *
+ * The function will return 0 if a downstream port update has been
+ * processed, otherwise it will return -EINVAL.
+ */
+static int mdss_dp_process_downstream_port_status_change(
+ struct mdss_dp_drv_pdata *dp)
+{
+ if (!mdss_dp_is_downstream_port_status_changed(dp))
+ return -EINVAL;
+
+ return mdss_dp_edid_read(dp);
}
/**
@@ -2393,21 +2449,31 @@ static void mdss_dp_process_link_training_request(struct mdss_dp_drv_pdata *dp)
* (including cases when there are back to back HPD IRQ HIGH) indicating
* the start of a new link training request or sink status update.
*/
-static void mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp)
+static int mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp)
{
- pr_debug("enter: HPD IRQ High\n");
+ int ret = 0;
dp->hpd_irq_on = true;
mdss_dp_aux_parse_sink_status_field(dp);
- mdss_dp_process_link_training_request(dp);
+ ret = mdss_dp_process_link_training_request(dp);
+ if (!ret)
+ goto exit;
- mdss_dp_process_link_status_update(dp);
+ ret = mdss_dp_process_link_status_update(dp);
+ if (!ret)
+ goto exit;
- mdss_dp_reset_test_data(dp);
+ ret = mdss_dp_process_downstream_port_status_change(dp);
+ if (!ret)
+ goto exit;
pr_debug("done\n");
+exit:
+ mdss_dp_reset_test_data(dp);
+
+ return ret;
}
/**
@@ -2417,11 +2483,15 @@ static void mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp)
* This function will handle the HPD IRQ state transitions from HIGH to LOW,
* indicating the end of a test request.
*/
-static void mdss_dp_process_hpd_irq_low(struct mdss_dp_drv_pdata *dp)
+static int mdss_dp_process_hpd_irq_low(struct mdss_dp_drv_pdata *dp)
{
+ if (!dp->hpd_irq_clients_notified)
+ return -EINVAL;
+
pr_debug("enter: HPD IRQ low\n");
dp->hpd_irq_on = false;
+ dp->hpd_irq_clients_notified = false;
mdss_dp_update_cable_status(dp, false);
mdss_dp_mainlink_push_idle(&dp->panel_data);
@@ -2430,6 +2500,7 @@ static void mdss_dp_process_hpd_irq_low(struct mdss_dp_drv_pdata *dp)
mdss_dp_reset_test_data(dp);
pr_debug("done\n");
+ return 0;
}
static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
@@ -2471,14 +2542,17 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
dp_drv->alt_mode.dp_status.hpd_irq;
if (dp_drv->alt_mode.dp_status.hpd_irq) {
- mdss_dp_process_hpd_irq_high(dp_drv);
- break;
- }
+ pr_debug("Attention: hpd_irq high\n");
- if (dp_drv->hpd_irq_toggled
- && !dp_drv->alt_mode.dp_status.hpd_irq) {
- mdss_dp_process_hpd_irq_low(dp_drv);
- break;
+ if (dp_drv->power_on && dp_drv->hdcp.ops &&
+ dp_drv->hdcp.ops->cp_irq)
+ dp_drv->hdcp.ops->cp_irq(dp_drv->hdcp.data);
+
+ if (!mdss_dp_process_hpd_irq_high(dp_drv))
+ break;
+ } else if (dp_drv->hpd_irq_toggled) {
+ if (!mdss_dp_process_hpd_irq_low(dp_drv))
+ break;
}
if (!dp_drv->alt_mode.dp_status.hpd_high) {
@@ -2500,9 +2574,6 @@ static void usbpd_response_callback(struct usbpd_svid_handler *hdlr, u8 cmd,
else
dp_send_events(dp_drv, EV_USBPD_DP_CONFIGURE);
- if (dp_drv->alt_mode.dp_status.hpd_irq && dp_drv->power_on &&
- dp_drv->hdcp.ops && dp_drv->hdcp.ops->isr)
- dp_drv->hdcp.ops->isr(dp_drv->hdcp.data);
break;
case DP_VDM_STATUS:
dp_drv->alt_mode.dp_status.response = *vdos;
@@ -2677,10 +2748,8 @@ static int mdss_dp_probe(struct platform_device *pdev)
mdss_dp_device_register(dp_drv);
dp_drv->inited = true;
- dp_drv->wait_for_audio_comp = false;
dp_drv->hpd_irq_on = false;
mdss_dp_reset_test_data(dp_drv);
- init_completion(&dp_drv->audio_comp);
init_completion(&dp_drv->irq_comp);
pr_debug("done\n");
@@ -2718,13 +2787,6 @@ void *mdss_dp_get_hdcp_data(struct device *dev)
return dp_drv->hdcp.data;
}
-static inline bool dp_is_hdcp_enabled(struct mdss_dp_drv_pdata *dp_drv)
-{
- return dp_drv->hdcp.feature_enabled &&
- (dp_drv->hdcp.hdcp1_present || dp_drv->hdcp.hdcp2_present) &&
- dp_drv->hdcp.ops;
-}
-
static inline bool dp_is_stream_shareable(struct mdss_dp_drv_pdata *dp_drv)
{
bool ret = 0;
diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h
index 4ba2d20d4261..e801eceeef1b 100644
--- a/drivers/video/fbdev/msm/mdss_dp.h
+++ b/drivers/video/fbdev/msm/mdss_dp.h
@@ -228,6 +228,18 @@ struct dp_alt_mode {
#define DP_LINK_RATE_MULTIPLIER 27000000
#define DP_MAX_PIXEL_CLK_KHZ 675000
+struct downstream_port_config {
+ /* Byte 02205h */
+ bool dfp_present;
+ u32 dfp_type;
+ bool format_conversion;
+ bool detailed_cap_info_available;
+ /* Byte 02207h */
+ u32 dfp_count;
+ bool msa_timing_par_ignored;
+ bool oui_support;
+};
+
struct dpcd_cap {
char major;
char minor;
@@ -240,6 +252,7 @@ struct dpcd_cap {
u32 flags;
u32 rx_port0_buf_size;
u32 training_read_interval;/* us */
+ struct downstream_port_config downstream_port;
};
struct dpcd_link_status {
@@ -437,7 +450,6 @@ struct mdss_dp_drv_pdata {
struct completion train_comp;
struct completion idle_comp;
struct completion video_comp;
- struct completion audio_comp;
struct completion irq_comp;
struct mutex aux_mutex;
struct mutex train_mutex;
@@ -463,13 +475,14 @@ struct mdss_dp_drv_pdata {
char delay_start;
u32 bpp;
struct dp_statistic dp_stat;
- bool wait_for_audio_comp;
bool hpd_irq_on;
bool hpd_irq_toggled;
+ bool hpd_irq_clients_notified;
/* event */
struct workqueue_struct *workq;
struct work_struct work;
+ struct delayed_work hdcp_cb_work;
u32 current_event;
spinlock_t event_lock;
spinlock_t lock;
@@ -480,6 +493,7 @@ struct mdss_dp_drv_pdata {
u32 vic;
u32 new_vic;
int fb_node;
+ int hdcp_status;
struct dpcd_test_request test_data;
struct dpcd_sink_count sink_count;
diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c
index 91066662e793..f9dba99a653d 100644
--- a/drivers/video/fbdev/msm/mdss_dp_aux.c
+++ b/drivers/video/fbdev/msm/mdss_dp_aux.c
@@ -527,8 +527,8 @@ char mdss_dp_gen_link_clk(struct mdss_panel_info *pinfo, char lane_cnt)
* Any changes in the section of code should
* consider this limitation.
*/
- min_link_rate = pinfo->clk_rate
- / (lane_cnt * encoding_factx10);
+ min_link_rate = (u32)div_u64(pinfo->clk_rate,
+ (lane_cnt * encoding_factx10));
min_link_rate /= ln_to_link_ratio;
min_link_rate = (min_link_rate * pinfo->bpp);
min_link_rate = (u32)div_u64(min_link_rate * 10,
@@ -801,6 +801,8 @@ static void dp_sink_capability_read(struct mdss_dp_drv_pdata *ep,
cap = &ep->dpcd;
bp = rp->data;
+ memset(cap, 0, sizeof(*cap));
+
data = *bp++; /* byte 0 */
cap->major = (data >> 4) & 0x0f;
cap->minor = data & 0x0f;
@@ -819,8 +821,13 @@ static void dp_sink_capability_read(struct mdss_dp_drv_pdata *ep,
if (data & BIT(7))
cap->enhanced_frame++;
- if (data & 0x40)
+ if (data & 0x40) {
cap->flags |= DPCD_TPS3;
+ pr_debug("pattern 3 supported\n");
+ } else {
+ pr_debug("pattern 3 not supported\n");
+ }
+
data &= 0x0f;
cap->max_lane_count = data;
if (--rlen <= 0)
@@ -846,11 +853,36 @@ static void dp_sink_capability_read(struct mdss_dp_drv_pdata *ep,
if (--rlen <= 0)
return;
- bp += 3; /* skip 5, 6 and 7 */
- rlen -= 3;
+ data = *bp++; /* Byte 5: DOWN_STREAM_PORT_PRESENT */
+ cap->downstream_port.dfp_present = data & BIT(0);
+ cap->downstream_port.dfp_type = data & 0x6;
+ cap->downstream_port.format_conversion = data & BIT(3);
+ cap->downstream_port.detailed_cap_info_available = data & BIT(4);
+ pr_debug("dfp_present = %d, dfp_type = %d\n",
+ cap->downstream_port.dfp_present,
+ cap->downstream_port.dfp_type);
+ pr_debug("format_conversion = %d, detailed_cap_info_available = %d\n",
+ cap->downstream_port.format_conversion,
+ cap->downstream_port.detailed_cap_info_available);
+ if (--rlen <= 0)
+ return;
+
+ bp += 1; /* Skip Byte 6 */
+ rlen -= 1;
if (rlen <= 0)
return;
+ data = *bp++; /* Byte 7: DOWN_STREAM_PORT_COUNT */
+ cap->downstream_port.dfp_count = data & 0x7;
+ cap->downstream_port.msa_timing_par_ignored = data & BIT(6);
+ cap->downstream_port.oui_support = data & BIT(7);
+ pr_debug("dfp_count = %d, msa_timing_par_ignored = %d\n",
+ cap->downstream_port.dfp_count,
+ cap->downstream_port.msa_timing_par_ignored);
+ pr_debug("oui_support = %d\n", cap->downstream_port.oui_support);
+ if (--rlen <= 0)
+ return;
+
data = *bp++; /* byte 8 */
if (data & BIT(1)) {
cap->flags |= DPCD_PORT_0_EDID_PRESENTED;
@@ -861,7 +893,7 @@ static void dp_sink_capability_read(struct mdss_dp_drv_pdata *ep,
data = *bp++; /* byte 9 */
cap->rx_port0_buf_size = (data + 1) * 32;
- pr_debug("lane_buf_size=%d", cap->rx_port0_buf_size);
+ pr_debug("lane_buf_size=%d\n", cap->rx_port0_buf_size);
if (--rlen <= 0)
return;
@@ -1431,6 +1463,7 @@ static int dp_start_link_train_1(struct mdss_dp_drv_pdata *ep)
int tries, old_v_level;
int ret = 0;
int usleep_time;
+ int const maximum_retries = 5;
pr_debug("Entered++");
@@ -1458,7 +1491,7 @@ static int dp_start_link_train_1(struct mdss_dp_drv_pdata *ep)
if (old_v_level == ep->v_level) {
tries++;
- if (tries >= 5) {
+ if (tries >= maximum_retries) {
ret = -1;
break; /* quit */
}
@@ -1480,6 +1513,7 @@ static int dp_start_link_train_2(struct mdss_dp_drv_pdata *ep)
int ret = 0;
int usleep_time;
char pattern;
+ int const maximum_retries = 5;
pr_debug("Entered++");
@@ -1505,7 +1539,7 @@ static int dp_start_link_train_2(struct mdss_dp_drv_pdata *ep)
}
tries++;
- if (tries > 4) {
+ if (tries > maximum_retries) {
ret = -1;
break;
}
@@ -1518,47 +1552,27 @@ static int dp_start_link_train_2(struct mdss_dp_drv_pdata *ep)
static int dp_link_rate_down_shift(struct mdss_dp_drv_pdata *ep)
{
- u32 prate, lrate;
- int rate, lane, max_lane;
- int changed = 0;
-
- rate = ep->link_rate;
- lane = ep->lane_cnt;
- max_lane = ep->dpcd.max_lane_count;
-
- prate = ep->pixel_rate;
- prate /= 1000; /* avoid using 64 biits */
- prate *= ep->bpp;
- prate /= 8; /* byte */
-
- if (rate > DP_LINK_RATE_162 && rate <= DP_LINK_RATE_MAX) {
- rate -= 4; /* reduce rate */
- changed++;
- }
+ int ret = 0;
- if (changed) {
- if (lane >= 1 && lane < max_lane)
- lane <<= 1; /* increase lane */
+ if (!ep)
+ return -EINVAL;
- lrate = 270000000; /* 270M */
- lrate /= 1000; /* avoid using 64 bits */
- lrate *= rate;
- lrate /= 10; /* byte, 10 bits --> 8 bits */
- lrate *= lane;
+ switch (ep->link_rate) {
+ case DP_LINK_RATE_540:
+ ep->link_rate = DP_LINK_RATE_270;
+ break;
+ case DP_LINK_RATE_270:
+ ep->link_rate = DP_LINK_RATE_162;
+ break;
+ case DP_LINK_RATE_162:
+ default:
+ ret = -EINVAL;
+ break;
+ };
- pr_debug("new lrate=%u prate=%u rate=%d lane=%d p=%d b=%d\n",
- lrate, prate, rate, lane, ep->pixel_rate, ep->bpp);
+ pr_debug("new rate=%d\n", ep->link_rate);
- if (lrate > prate) {
- ep->link_rate = rate;
- ep->lane_cnt = lane;
- pr_debug("new rate=%d %d\n", rate, lane);
- return 0;
- }
- }
-
- /* add calculation later */
- return -EINVAL;
+ return ret;
}
int mdss_dp_aux_set_sink_power_state(struct mdss_dp_drv_pdata *ep, char state)
@@ -1595,7 +1609,6 @@ int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp)
mdss_dp_aux_set_sink_power_state(dp, SINK_POWER_ON);
-train_start:
dp->v_level = 0; /* start from default level */
dp->p_level = 0;
mdss_dp_config_ctrl(dp);
@@ -1605,11 +1618,12 @@ train_start:
ret = dp_start_link_train_1(dp);
if (ret < 0) {
- if (dp_link_rate_down_shift(dp) == 0) {
- goto train_start;
+ if (!dp_link_rate_down_shift(dp)) {
+ pr_debug("retry with lower rate\n");
+ return -EAGAIN;
} else {
pr_err("Training 1 failed\n");
- ret = -1;
+ ret = -EINVAL;
goto clear;
}
}
@@ -1618,21 +1632,21 @@ train_start:
ret = dp_start_link_train_2(dp);
if (ret < 0) {
- if (dp_link_rate_down_shift(dp) == 0) {
- goto train_start;
+ if (!dp_link_rate_down_shift(dp)) {
+ pr_debug("retry with lower rate\n");
+ return -EAGAIN;
} else {
pr_err("Training 2 failed\n");
- ret = -1;
+ ret = -EINVAL;
goto clear;
}
}
pr_debug("Training 2 completed successfully\n");
-
clear:
dp_clear_training_pattern(dp);
- if (ret != -1) {
+ if (ret != -EINVAL) {
mdss_dp_setup_tr_unit(&dp->ctrl_io, dp->link_rate,
dp->lane_cnt, dp->vic);
mdss_dp_state_ctrl(&dp->ctrl_io, ST_SEND_VIDEO);
diff --git a/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c b/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c
index 3891806b09bb..79cd94cfbe88 100644
--- a/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c
+++ b/drivers/video/fbdev/msm/mdss_dp_hdcp2p2.c
@@ -53,7 +53,6 @@ struct dp_hdcp2p2_ctrl {
struct kthread_work send_msg;
struct kthread_work recv_msg;
struct kthread_work link;
- struct kthread_work poll;
char *msg_buf;
uint32_t send_msg_len; /* length of all parameters in msg */
uint32_t timeout;
@@ -67,26 +66,6 @@ struct dp_hdcp2p2_ctrl {
bool polling;
};
-static inline char *dp_hdcp_cmd_to_str(uint32_t cmd)
-{
- switch (cmd) {
- case HDMI_HDCP_WKUP_CMD_SEND_MESSAGE:
- return "HDMI_HDCP_WKUP_CMD_SEND_MESSAGE";
- case HDMI_HDCP_WKUP_CMD_RECV_MESSAGE:
- return "HDMI_HDCP_WKUP_CMD_RECV_MESSAGE";
- case HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS:
- return "HDMI_HDCP_WKUP_CMD_STATUS_SUCCESS";
- case HDMI_HDCP_WKUP_CMD_STATUS_FAILED:
- return "DP_HDCP_WKUP_CMD_STATUS_FAIL";
- case HDMI_HDCP_WKUP_CMD_LINK_POLL:
- return "HDMI_HDCP_WKUP_CMD_LINK_POLL";
- case HDMI_HDCP_WKUP_CMD_AUTHENTICATE:
- return "HDMI_HDCP_WKUP_CMD_AUTHENTICATE";
- default:
- return "???";
- }
-}
-
static inline bool dp_hdcp2p2_is_valid_state(struct dp_hdcp2p2_ctrl *ctrl)
{
if (ctrl->wakeup_cmd == HDMI_HDCP_WKUP_CMD_AUTHENTICATE)
@@ -193,7 +172,7 @@ static int dp_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data)
queue_kthread_work(&ctrl->worker, &ctrl->status);
break;
case HDMI_HDCP_WKUP_CMD_LINK_POLL:
- queue_kthread_work(&ctrl->worker, &ctrl->poll);
+ ctrl->polling = true;
break;
case HDMI_HDCP_WKUP_CMD_AUTHENTICATE:
queue_kthread_work(&ctrl->worker, &ctrl->auth);
@@ -203,10 +182,11 @@ static int dp_hdcp2p2_wakeup(struct hdmi_hdcp_wakeup_data *data)
}
exit:
mutex_unlock(&ctrl->wakeup_mutex);
+
return 0;
}
-static inline int dp_hdcp2p2_wakeup_lib(struct dp_hdcp2p2_ctrl *ctrl,
+static inline void dp_hdcp2p2_wakeup_lib(struct dp_hdcp2p2_ctrl *ctrl,
struct hdcp_lib_wakeup_data *data)
{
int rc = 0;
@@ -218,8 +198,6 @@ static inline int dp_hdcp2p2_wakeup_lib(struct dp_hdcp2p2_ctrl *ctrl,
pr_err("error sending %s to lib\n",
hdcp_lib_cmd_to_str(data->cmd));
}
-
- return rc;
}
static void dp_hdcp2p2_reset(struct dp_hdcp2p2_ctrl *ctrl)
@@ -339,8 +317,6 @@ static void dp_hdcp2p2_auth_failed(struct dp_hdcp2p2_ctrl *ctrl)
return;
}
- atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL);
-
/* notify DP about HDCP failure */
ctrl->init_data.notify_status(ctrl->init_data.cb_data,
HDCP_STATE_AUTH_FAIL);
@@ -349,8 +325,7 @@ static void dp_hdcp2p2_auth_failed(struct dp_hdcp2p2_ctrl *ctrl)
static int dp_hdcp2p2_aux_read_message(struct dp_hdcp2p2_ctrl *ctrl,
u8 *buf, int size, int offset, u32 timeout)
{
- int rc, max_size = 16, read_size, len = size;
- u8 *buf_start = buf;
+ int rc, max_size = 16, read_size;
if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
pr_err("hdcp is off\n");
@@ -378,8 +353,6 @@ static int dp_hdcp2p2_aux_read_message(struct dp_hdcp2p2_ctrl *ctrl,
size -= read_size;
} while (size > 0);
- print_hex_dump(KERN_DEBUG, "hdcp2p2: ", DUMP_PREFIX_NONE,
- 16, 1, buf_start, len, false);
return rc;
}
@@ -452,12 +425,9 @@ end:
static void dp_hdcp2p2_send_msg_work(struct kthread_work *work)
{
int rc = 0;
- int i;
- int sent_bytes = 0;
struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
struct dp_hdcp2p2_ctrl, send_msg);
struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
- char *buf = NULL;
if (!ctrl) {
pr_err("invalid input\n");
@@ -474,20 +444,13 @@ static void dp_hdcp2p2_send_msg_work(struct kthread_work *work)
mutex_lock(&ctrl->msg_lock);
- /* Loop through number of parameters in the messages. */
- for (i = 0; i < ctrl->num_messages; i++) {
- buf = ctrl->msg_buf + sent_bytes;
-
- /* Forward the message to the sink */
- rc = dp_hdcp2p2_aux_write_message(ctrl, buf,
- (size_t)ctrl->msg_part[i].length,
- ctrl->msg_part[i].offset, ctrl->timeout);
- if (rc) {
- pr_err("Error sending msg to sink %d\n", rc);
- mutex_unlock(&ctrl->msg_lock);
- goto exit;
- }
- sent_bytes += ctrl->msg_part[i].length;
+ rc = dp_hdcp2p2_aux_write_message(ctrl, ctrl->msg_buf,
+ ctrl->send_msg_len, ctrl->msg_part->offset,
+ ctrl->timeout);
+ if (rc) {
+ pr_err("Error sending msg to sink %d\n", rc);
+ mutex_unlock(&ctrl->msg_lock);
+ goto exit;
}
cdata.cmd = HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS;
@@ -505,10 +468,9 @@ exit:
static int dp_hdcp2p2_get_msg_from_sink(struct dp_hdcp2p2_ctrl *ctrl)
{
- int i, rc = 0;
+ int rc = 0;
char *recvd_msg_buf = NULL;
struct hdcp_lib_wakeup_data cdata = { HDCP_LIB_WKUP_CMD_INVALID };
- int bytes_read = 0;
cdata.context = ctrl->lib_ctx;
@@ -518,17 +480,12 @@ static int dp_hdcp2p2_get_msg_from_sink(struct dp_hdcp2p2_ctrl *ctrl)
goto exit;
}
- for (i = 0; i < ctrl->num_messages; i++) {
- rc = dp_hdcp2p2_aux_read_message(
- ctrl, recvd_msg_buf + bytes_read,
- ctrl->msg_part[i].length,
- ctrl->msg_part[i].offset,
- ctrl->timeout);
- if (rc) {
- pr_err("error reading message %d\n", rc);
- goto exit;
- }
- bytes_read += ctrl->msg_part[i].length;
+ rc = dp_hdcp2p2_aux_read_message(ctrl, recvd_msg_buf,
+ ctrl->send_msg_len, ctrl->msg_part->offset,
+ ctrl->timeout);
+ if (rc) {
+ pr_err("error reading message %d\n", rc);
+ goto exit;
}
cdata.recvd_msg_buf = recvd_msg_buf;
@@ -550,7 +507,6 @@ exit:
static void dp_hdcp2p2_recv_msg_work(struct kthread_work *work)
{
- int rc = 0;
struct hdcp_lib_wakeup_data cdata = { HDCP_LIB_WKUP_CMD_INVALID };
struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
struct dp_hdcp2p2_ctrl, recv_msg);
@@ -559,44 +515,24 @@ static void dp_hdcp2p2_recv_msg_work(struct kthread_work *work)
if (atomic_read(&ctrl->auth_state) == HDCP_STATE_INACTIVE) {
pr_err("hdcp is off\n");
- goto exit;
+ return;
}
- if (ctrl->sink_rx_status & ctrl->abort_mask) {
- pr_err("reauth or Link fail triggered by sink\n");
-
- ctrl->sink_rx_status = 0;
- rc = -ENOLINK;
- cdata.cmd = HDCP_LIB_WKUP_CMD_STOP;
-
- goto exit;
- }
+ if (ctrl->rx_status) {
+ if (!ctrl->cp_irq_done) {
+ pr_debug("waiting for CP_IRQ\n");
+ ctrl->polling = true;
+ return;
+ }
- if (ctrl->rx_status && !ctrl->sink_rx_status) {
- pr_debug("Recv msg for RxStatus, but no CP_IRQ yet\n");
- ctrl->polling = true;
- goto exit;
+ if (ctrl->rx_status & ctrl->sink_rx_status) {
+ ctrl->cp_irq_done = false;
+ ctrl->sink_rx_status = 0;
+ ctrl->rx_status = 0;
+ }
}
dp_hdcp2p2_get_msg_from_sink(ctrl);
-
- return;
-exit:
- if (rc)
- dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
-}
-
-static void dp_hdcp2p2_poll_work(struct kthread_work *work)
-{
- struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
- struct dp_hdcp2p2_ctrl, poll);
-
- if (ctrl->cp_irq_done) {
- ctrl->cp_irq_done = false;
- dp_hdcp2p2_get_msg_from_sink(ctrl);
- } else {
- ctrl->polling = true;
- }
}
static void dp_hdcp2p2_auth_status_work(struct kthread_work *work)
@@ -645,44 +581,45 @@ static void dp_hdcp2p2_link_work(struct kthread_work *work)
if (rc) {
pr_err("failed to read rx status\n");
- cdata.cmd = HDCP_LIB_WKUP_CMD_STOP;
+ cdata.cmd = HDCP_LIB_WKUP_CMD_LINK_FAILED;
+ atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL);
goto exit;
}
if (ctrl->sink_rx_status & ctrl->abort_mask) {
- pr_err("reauth or Link fail triggered by sink\n");
+ if (ctrl->sink_rx_status & BIT(3))
+ pr_err("reauth_req set by sink\n");
+
+ if (ctrl->sink_rx_status & BIT(4))
+ pr_err("link failure reported by sink\n");
ctrl->sink_rx_status = 0;
ctrl->rx_status = 0;
rc = -ENOLINK;
- cdata.cmd = HDCP_LIB_WKUP_CMD_STOP;
+
+ cdata.cmd = HDCP_LIB_WKUP_CMD_LINK_FAILED;
+ atomic_set(&ctrl->auth_state, HDCP_STATE_AUTH_FAIL);
goto exit;
}
- /* if polling, get message from sink else let polling start */
if (ctrl->polling && (ctrl->sink_rx_status & ctrl->rx_status)) {
ctrl->sink_rx_status = 0;
ctrl->rx_status = 0;
- rc = dp_hdcp2p2_get_msg_from_sink(ctrl);
+ dp_hdcp2p2_get_msg_from_sink(ctrl);
ctrl->polling = false;
} else {
ctrl->cp_irq_done = true;
}
exit:
- dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
-
- if (rc) {
- dp_hdcp2p2_auth_failed(ctrl);
- return;
- }
+ if (rc)
+ dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
}
static void dp_hdcp2p2_auth_work(struct kthread_work *work)
{
- int rc = 0;
struct hdcp_lib_wakeup_data cdata = {HDCP_LIB_WKUP_CMD_INVALID};
struct dp_hdcp2p2_ctrl *ctrl = container_of(work,
struct dp_hdcp2p2_ctrl, auth);
@@ -694,12 +631,10 @@ static void dp_hdcp2p2_auth_work(struct kthread_work *work)
else
cdata.cmd = HDCP_LIB_WKUP_CMD_STOP;
- rc = dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
- if (rc)
- dp_hdcp2p2_auth_failed(ctrl);
+ dp_hdcp2p2_wakeup_lib(ctrl, &cdata);
}
-static int dp_hdcp2p2_isr(void *input)
+static int dp_hdcp2p2_cp_irq(void *input)
{
struct dp_hdcp2p2_ctrl *ctrl = input;
@@ -748,7 +683,7 @@ void *dp_hdcp2p2_init(struct hdcp_init_data *init_data)
.authenticate = dp_hdcp2p2_authenticate,
.feature_supported = dp_hdcp2p2_feature_supported,
.off = dp_hdcp2p2_off,
- .isr = dp_hdcp2p2_isr
+ .cp_irq = dp_hdcp2p2_cp_irq,
};
static struct hdcp_client_ops client_ops = {
@@ -806,7 +741,6 @@ void *dp_hdcp2p2_init(struct hdcp_init_data *init_data)
init_kthread_work(&ctrl->recv_msg, dp_hdcp2p2_recv_msg_work);
init_kthread_work(&ctrl->status, dp_hdcp2p2_auth_status_work);
init_kthread_work(&ctrl->link, dp_hdcp2p2_link_work);
- init_kthread_work(&ctrl->poll, dp_hdcp2p2_poll_work);
ctrl->thread = kthread_run(kthread_worker_fn,
&ctrl->worker, "dp_hdcp2p2");
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h
index 7091dc2f38b9..3536cb2d294d 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.h
+++ b/drivers/video/fbdev/msm/mdss_dsi.h
@@ -468,6 +468,7 @@ struct mdss_dsi_ctrl_pdata {
bool cmd_sync_wait_trigger;
struct mdss_rect roi;
+ struct mdss_dsi_dual_pu_roi dual_roi;
struct pwm_device *pwm_bl;
u32 pclk_rate;
u32 byte_clk_rate;
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index bd0c2ad32c05..7c36bb627043 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -447,28 +447,82 @@ static int mdss_dsi_roi_merge(struct mdss_dsi_ctrl_pdata *ctrl,
static char caset[] = {0x2a, 0x00, 0x00, 0x03, 0x00}; /* DTYPE_DCS_LWRITE */
static char paset[] = {0x2b, 0x00, 0x00, 0x05, 0x00}; /* DTYPE_DCS_LWRITE */
+/*
+ * Some panels can support multiple ROIs as part of the below commands
+ */
+static char caset_dual[] = {0x2a, 0x00, 0x00, 0x03, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00};/* DTYPE_DCS_LWRITE */
+static char paset_dual[] = {0x2b, 0x00, 0x00, 0x05, 0x00, 0x03,
+ 0x00, 0x00, 0x00, 0x00};/* DTYPE_DCS_LWRITE */
+
/* pack into one frame before sent */
static struct dsi_cmd_desc set_col_page_addr_cmd[] = {
{{DTYPE_DCS_LWRITE, 0, 0, 0, 1, sizeof(caset)}, caset}, /* packed */
{{DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(paset)}, paset},
};
+/* pack into one frame before sent */
+static struct dsi_cmd_desc set_dual_col_page_addr_cmd[] = { /*packed*/
+ {{DTYPE_DCS_LWRITE, 0, 0, 0, 1, sizeof(caset_dual)}, caset_dual},
+ {{DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(paset_dual)}, paset_dual},
+};
+
+
+static void __mdss_dsi_send_col_page_addr(struct mdss_dsi_ctrl_pdata *ctrl,
+ struct mdss_rect *roi, bool dual_roi)
+{
+ if (dual_roi) {
+ struct mdss_rect *first, *second;
+
+ first = &ctrl->panel_data.panel_info.dual_roi.first_roi;
+ second = &ctrl->panel_data.panel_info.dual_roi.second_roi;
+
+ caset_dual[1] = (((first->x) & 0xFF00) >> 8);
+ caset_dual[2] = (((first->x) & 0xFF));
+ caset_dual[3] = (((first->x - 1 + first->w) & 0xFF00) >> 8);
+ caset_dual[4] = (((first->x - 1 + first->w) & 0xFF));
+ /* skip the MPU setting byte*/
+ caset_dual[6] = (((second->x) & 0xFF00) >> 8);
+ caset_dual[7] = (((second->x) & 0xFF));
+ caset_dual[8] = (((second->x - 1 + second->w) & 0xFF00) >> 8);
+ caset_dual[9] = (((second->x - 1 + second->w) & 0xFF));
+ set_dual_col_page_addr_cmd[0].payload = caset_dual;
+
+ paset_dual[1] = (((first->y) & 0xFF00) >> 8);
+ paset_dual[2] = (((first->y) & 0xFF));
+ paset_dual[3] = (((first->y - 1 + first->h) & 0xFF00) >> 8);
+ paset_dual[4] = (((first->y - 1 + first->h) & 0xFF));
+ /* skip the MPU setting byte */
+ paset_dual[6] = (((second->y) & 0xFF00) >> 8);
+ paset_dual[7] = (((second->y) & 0xFF));
+ paset_dual[8] = (((second->y - 1 + second->h) & 0xFF00) >> 8);
+ paset_dual[9] = (((second->y - 1 + second->h) & 0xFF));
+ set_dual_col_page_addr_cmd[1].payload = paset_dual;
+ } else {
+ caset[1] = (((roi->x) & 0xFF00) >> 8);
+ caset[2] = (((roi->x) & 0xFF));
+ caset[3] = (((roi->x - 1 + roi->w) & 0xFF00) >> 8);
+ caset[4] = (((roi->x - 1 + roi->w) & 0xFF));
+ set_col_page_addr_cmd[0].payload = caset;
+
+ paset[1] = (((roi->y) & 0xFF00) >> 8);
+ paset[2] = (((roi->y) & 0xFF));
+ paset[3] = (((roi->y - 1 + roi->h) & 0xFF00) >> 8);
+ paset[4] = (((roi->y - 1 + roi->h) & 0xFF));
+ set_col_page_addr_cmd[1].payload = paset;
+ }
+ pr_debug("%s Sending 2A 2B cmnd with dual_roi=%d\n", __func__,
+ dual_roi);
+
+}
static void mdss_dsi_send_col_page_addr(struct mdss_dsi_ctrl_pdata *ctrl,
struct mdss_rect *roi, int unicast)
{
struct dcs_cmd_req cmdreq;
+ struct mdss_panel_info *pinfo = &ctrl->panel_data.panel_info;
+ bool dual_roi = pinfo->dual_roi.enabled;
- caset[1] = (((roi->x) & 0xFF00) >> 8);
- caset[2] = (((roi->x) & 0xFF));
- caset[3] = (((roi->x - 1 + roi->w) & 0xFF00) >> 8);
- caset[4] = (((roi->x - 1 + roi->w) & 0xFF));
- set_col_page_addr_cmd[0].payload = caset;
-
- paset[1] = (((roi->y) & 0xFF00) >> 8);
- paset[2] = (((roi->y) & 0xFF));
- paset[3] = (((roi->y - 1 + roi->h) & 0xFF00) >> 8);
- paset[4] = (((roi->y - 1 + roi->h) & 0xFF));
- set_col_page_addr_cmd[1].payload = paset;
+ __mdss_dsi_send_col_page_addr(ctrl, roi, dual_roi);
memset(&cmdreq, 0, sizeof(cmdreq));
cmdreq.cmds_cnt = 2;
@@ -478,7 +532,9 @@ static void mdss_dsi_send_col_page_addr(struct mdss_dsi_ctrl_pdata *ctrl,
cmdreq.rlen = 0;
cmdreq.cb = NULL;
- cmdreq.cmds = set_col_page_addr_cmd;
+ /* Send default or dual roi 2A/2B cmd */
+ cmdreq.cmds = dual_roi ? set_dual_col_page_addr_cmd :
+ set_col_page_addr_cmd;
mdss_dsi_cmdlist_put(ctrl, &cmdreq);
}
@@ -1837,20 +1893,28 @@ error:
pinfo->esd_check_enabled = false;
}
-static int mdss_dsi_parse_panel_features(struct device_node *np,
- struct mdss_dsi_ctrl_pdata *ctrl)
+static void mdss_dsi_parse_partial_update_caps(struct device_node *np,
+ struct mdss_dsi_ctrl_pdata *ctrl)
{
struct mdss_panel_info *pinfo;
-
- if (!np || !ctrl) {
- pr_err("%s: Invalid arguments\n", __func__);
- return -ENODEV;
- }
+ const char *data;
pinfo = &ctrl->panel_data.panel_info;
- pinfo->partial_update_supported = of_property_read_bool(np,
- "qcom,partial-update-enabled");
+ data = of_get_property(np, "qcom,partial-update-enabled", NULL);
+ if (data && !strcmp(data, "single_roi"))
+ pinfo->partial_update_supported =
+ PU_SINGLE_ROI;
+ else if (data && !strcmp(data, "dual_roi"))
+ pinfo->partial_update_supported =
+ PU_DUAL_ROI;
+ else if (data && !strcmp(data, "none"))
+ pinfo->partial_update_supported =
+ PU_NOT_SUPPORTED;
+ else
+ pinfo->partial_update_supported =
+ PU_NOT_SUPPORTED;
+
if (pinfo->mipi.mode == DSI_CMD_MODE) {
pinfo->partial_update_enabled = pinfo->partial_update_supported;
pr_info("%s: partial_update_enabled=%d\n", __func__,
@@ -1862,6 +1926,21 @@ static int mdss_dsi_parse_panel_features(struct device_node *np,
"qcom,partial-update-roi-merge");
}
}
+}
+
+static int mdss_dsi_parse_panel_features(struct device_node *np,
+ struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ struct mdss_panel_info *pinfo;
+
+ if (!np || !ctrl) {
+ pr_err("%s: Invalid arguments\n", __func__);
+ return -ENODEV;
+ }
+
+ pinfo = &ctrl->panel_data.panel_info;
+
+ mdss_dsi_parse_partial_update_caps(np, ctrl);
pinfo->dcs_cmd_by_left = of_property_read_bool(np,
"qcom,dcs-cmd-by-left");
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index bcd23d3c19f2..08e06c75522a 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -564,7 +564,7 @@ static ssize_t mdss_fb_get_panel_info(struct device *dev,
"min_fps=%d\nmax_fps=%d\npanel_name=%s\n"
"primary_panel=%d\nis_pluggable=%d\ndisplay_id=%s\n"
"is_cec_supported=%d\nis_pingpong_split=%d\n"
- "dfps_porch_mode=%d\n",
+ "dfps_porch_mode=%d\npu_roi_cnt=%d\ndual_dsi=%d",
pinfo->partial_update_enabled,
pinfo->roi_alignment.xstart_pix_align,
pinfo->roi_alignment.width_pix_align,
@@ -577,7 +577,8 @@ static ssize_t mdss_fb_get_panel_info(struct device *dev,
pinfo->panel_name, pinfo->is_prim_panel,
pinfo->is_pluggable, pinfo->display_id,
pinfo->is_cec_supported, is_pingpong_split(mfd),
- dfps_porch_mode);
+ dfps_porch_mode, pinfo->partial_update_enabled,
+ is_panel_split(mfd));
return ret;
}
@@ -3282,6 +3283,7 @@ int mdss_fb_atomic_commit(struct fb_info *info,
mfd->msm_fb_backup.atomic_commit = true;
mfd->msm_fb_backup.disp_commit.l_roi = commit_v1->left_roi;
mfd->msm_fb_backup.disp_commit.r_roi = commit_v1->right_roi;
+ mfd->msm_fb_backup.disp_commit.flags = commit_v1->flags;
mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt);
diff --git a/drivers/video/fbdev/msm/mdss_hdcp.h b/drivers/video/fbdev/msm/mdss_hdcp.h
index d373d22384e8..6e347a867366 100644
--- a/drivers/video/fbdev/msm/mdss_hdcp.h
+++ b/drivers/video/fbdev/msm/mdss_hdcp.h
@@ -55,6 +55,7 @@ struct hdcp_init_data {
struct hdcp_ops {
int (*isr)(void *ptr);
+ int (*cp_irq)(void *ptr);
int (*reauthenticate)(void *input);
int (*authenticate)(void *hdcp_ctrl);
bool (*feature_supported)(void *input);
diff --git a/drivers/video/fbdev/msm/mdss_hdcp_1x.c b/drivers/video/fbdev/msm/mdss_hdcp_1x.c
index 1e502cf750a6..a8182c2f0e76 100644
--- a/drivers/video/fbdev/msm/mdss_hdcp_1x.c
+++ b/drivers/video/fbdev/msm/mdss_hdcp_1x.c
@@ -153,6 +153,7 @@ struct hdcp_reg_set {
u32 sec_data12;
u32 reset;
+ u32 reset_bit;
};
#define HDCP_REG_SET_CLIENT_HDMI \
@@ -175,7 +176,7 @@ struct hdcp_reg_set {
HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA10, \
HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA11, \
HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA12, \
- HDMI_HDCP_RESET}
+ HDMI_HDCP_RESET, BIT(0)}
#define HDCP_REG_SET_CLIENT_DP \
{DP_HDCP_STATUS, 16, 14, 13, DP_HDCP_CTRL, \
@@ -193,7 +194,8 @@ struct hdcp_reg_set {
HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA9, \
HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA10, \
HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11, \
- HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12, 0}
+ HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12, \
+ DP_SW_RESET, BIT(1)}
#define HDCP_HDMI_SINK_ADDR_MAP \
{{"bcaps", 0x40, 1}, {"bksv", 0x00, 5}, {"r0'", 0x08, 2}, \
@@ -1295,6 +1297,9 @@ static void hdcp_1x_int_work(struct work_struct *work)
return;
}
+ if (hdcp_ctrl->hdcp_state == HDCP_STATE_AUTHENTICATED)
+ hdcp1_set_enc(false);
+
mutex_lock(hdcp_ctrl->init_data.mutex);
hdcp_ctrl->hdcp_state = HDCP_STATE_AUTH_FAIL;
mutex_unlock(hdcp_ctrl->init_data.mutex);
@@ -1383,6 +1388,8 @@ error:
hdcp_ctrl->init_data.cb_data,
hdcp_ctrl->hdcp_state);
}
+
+ hdcp1_set_enc(true);
} else {
DEV_DBG("%s: %s: HDCP state changed during authentication\n",
__func__, HDCP_STATE_NAME);
@@ -1431,7 +1438,7 @@ int hdcp_1x_reauthenticate(void *input)
struct hdcp_reg_set *reg_set;
struct hdcp_int_set *isr;
u32 hdmi_hw_version;
- u32 ret = 0;
+ u32 ret = 0, reg;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -1462,15 +1469,17 @@ int hdcp_1x_reauthenticate(void *input)
/* Disable HDCP interrupts */
DSS_REG_W(io, isr->int_reg, DSS_REG_R(io, isr->int_reg) & ~HDCP_INT_EN);
- if (reg_set->reset)
- DSS_REG_W(io, reg_set->reset, BIT(0));
+ reg = DSS_REG_R(io, reg_set->reset);
+ DSS_REG_W(io, reg_set->reset, reg | reg_set->reset_bit);
/* Disable encryption and disable the HDCP block */
DSS_REG_W(io, reg_set->ctrl, 0);
+ DSS_REG_W(io, reg_set->reset, reg & ~reg_set->reset_bit);
+
if (!hdcp_1x_load_keys(input))
queue_delayed_work(hdcp_ctrl->init_data.workq,
- &hdcp_ctrl->hdcp_auth_work, HZ/2);
+ &hdcp_ctrl->hdcp_auth_work, HZ);
else
queue_work(hdcp_ctrl->init_data.workq,
&hdcp_ctrl->hdcp_int_work);
@@ -1485,6 +1494,7 @@ void hdcp_1x_off(void *input)
struct hdcp_reg_set *reg_set;
struct hdcp_int_set *isr;
int rc = 0;
+ u32 reg;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -1501,6 +1511,9 @@ void hdcp_1x_off(void *input)
return;
}
+ if (hdcp_ctrl->hdcp_state == HDCP_STATE_AUTHENTICATED)
+ hdcp1_set_enc(false);
+
/*
* Disable HDCP interrupts.
* Also, need to set the state to inactive here so that any ongoing
@@ -1527,12 +1540,15 @@ void hdcp_1x_off(void *input)
DEV_DBG("%s: %s: Deleted hdcp int work\n", __func__,
HDCP_STATE_NAME);
- if (reg_set->reset)
- DSS_REG_W(io, reg_set->reset, BIT(0));
+
+ reg = DSS_REG_R(io, reg_set->reset);
+ DSS_REG_W(io, reg_set->reset, reg | reg_set->reset_bit);
/* Disable encryption and disable the HDCP block */
DSS_REG_W(io, reg_set->ctrl, 0);
+ DSS_REG_W(io, reg_set->reset, reg & ~reg_set->reset_bit);
+
DEV_DBG("%s: %s: HDCP: Off\n", __func__, HDCP_STATE_NAME);
} /* hdcp_1x_off */
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c
index 04e8fa4ba576..1dae41391795 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -47,6 +47,8 @@
#include <linux/msm-bus-board.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/rpm-smd.h>
+#include "soc/qcom/secure_buffer.h"
+#include <asm/cacheflush.h>
#include "mdss.h"
#include "mdss_fb.h"
@@ -64,6 +66,8 @@
#define RES_1080p (1088*1920)
#define RES_UHD (3840*2160)
+#define MDP_DEVICE_ID 0x1A
+
struct mdss_data_type *mdss_res;
static u32 mem_protect_sd_ctrl_id;
@@ -87,6 +91,7 @@ struct msm_mdp_interface mdp5 = {
#define MEM_PROTECT_SD_CTRL 0xF
#define MEM_PROTECT_SD_CTRL_FLAT 0x14
+#define MEM_PROTECT_SD_CTRL_SWITCH 0x18
static DEFINE_SPINLOCK(mdp_lock);
static DEFINE_SPINLOCK(mdss_mdp_intr_lock);
@@ -1329,7 +1334,9 @@ int mdss_iommu_ctrl(int enable)
if (mdata->iommu_ref_cnt == 0) {
rc = mdss_smmu_detach(mdata);
if (mdss_has_quirk(mdata,
- MDSS_QUIRK_MIN_BUS_VOTE))
+ MDSS_QUIRK_MIN_BUS_VOTE) &&
+ (!mdata->sec_disp_en ||
+ !mdata->sec_cam_en))
mdss_bus_scale_set_quota(MDSS_HW_RT,
0, 0);
}
@@ -1985,6 +1992,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
mdata->pixel_ram_size = 50 * 1024;
mdata->rects_per_sspp[MDSS_MDP_PIPE_TYPE_DMA] = 2;
+ mem_protect_sd_ctrl_id = MEM_PROTECT_SD_CTRL_SWITCH;
set_bit(MDSS_QOS_PER_PIPE_IB, mdata->mdss_qos_map);
set_bit(MDSS_QOS_REMAPPER, mdata->mdss_qos_map);
set_bit(MDSS_QOS_TS_PREFILL, mdata->mdss_qos_map);
@@ -2015,6 +2023,7 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
mdata->has_wb_ubwc = true;
set_bit(MDSS_CAPS_10_BIT_SUPPORTED, mdata->mdss_caps_map);
set_bit(MDSS_CAPS_AVR_SUPPORTED, mdata->mdss_caps_map);
+ set_bit(MDSS_CAPS_SEC_DETACH_SMMU, mdata->mdss_caps_map);
break;
default:
mdata->max_target_zorder = 4; /* excluding base layer */
@@ -4939,29 +4948,115 @@ static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
}
}
-int mdss_mdp_secure_display_ctrl(unsigned int enable)
+int mdss_mdp_secure_session_ctrl(unsigned int enable, u64 flags)
{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
struct sd_ctrl_req {
unsigned int enable;
} __attribute__ ((__packed__)) request;
unsigned int resp = -1;
int ret = 0;
+ uint32_t sid_info;
struct scm_desc desc;
- desc.args[0] = request.enable = enable;
- desc.arginfo = SCM_ARGS(1);
+ if (test_bit(MDSS_CAPS_SEC_DETACH_SMMU, mdata->mdss_caps_map)) {
+ /*
+ * Prepare syscall to hypervisor to switch the secure_vmid
+ * between secure and non-secure contexts
+ */
+ /* MDP secure SID */
+ sid_info = 0x1;
+ desc.arginfo = SCM_ARGS(4, SCM_VAL, SCM_RW, SCM_VAL, SCM_VAL);
+ desc.args[0] = MDP_DEVICE_ID;
+ desc.args[1] = SCM_BUFFER_PHYS(&sid_info);
+ desc.args[2] = sizeof(uint32_t);
+
- if (!is_scm_armv8()) {
- ret = scm_call(SCM_SVC_MP, MEM_PROTECT_SD_CTRL,
- &request, sizeof(request), &resp, sizeof(resp));
- } else {
- ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP,
+ pr_debug("Enable/Disable: %d, Flags %llx\n", enable, flags);
+ if (enable) {
+ if (flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) {
+ desc.args[3] = VMID_CP_SEC_DISPLAY;
+ mdata->sec_disp_en = 1;
+ } else if (flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) {
+ desc.args[3] = VMID_CP_CAMERA_PREVIEW;
+ mdata->sec_cam_en = 1;
+ } else {
+ return 0;
+ }
+
+ /* detach smmu contexts */
+ ret = mdss_smmu_detach(mdata);
+ if (ret) {
+ pr_err("Error while detaching smmu contexts ret = %d\n",
+ ret);
+ return -EINVAL;
+ }
+
+ /* let the driver think smmu is still attached */
+ mdata->iommu_attached = true;
+
+ dmac_flush_range(&sid_info, &sid_info + 1);
+ ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP,
mem_protect_sd_ctrl_id), &desc);
- resp = desc.ret[0];
- }
+ if (ret) {
+ pr_err("Error scm_call MEM_PROTECT_SD_CTRL(%u) ret=%dm resp=%x\n",
+ enable, ret, resp);
+ return -EINVAL;
+ }
+ resp = desc.ret[0];
- pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x",
+ pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x\n",
+ enable, ret, resp);
+ } else {
+ desc.args[3] = VMID_CP_PIXEL;
+ if (flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION)
+ mdata->sec_disp_en = 0;
+ else if (flags & MDP_SECURE_CAMERA_OVERLAY_SESSION)
+ mdata->sec_cam_en = 0;
+
+ dmac_flush_range(&sid_info, &sid_info + 1);
+ ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP,
+ mem_protect_sd_ctrl_id), &desc);
+ if (ret)
+ MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl",
+ "dsi0_phy", "dsi1_ctrl",
+ "dsi1_phy", "vbif", "vbif_nrt",
+ "dbg_bus", "vbif_dbg_bus",
+ "panic");
+ resp = desc.ret[0];
+
+ pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x\n",
+ enable, ret, resp);
+
+ /* re-attach smmu contexts */
+ mdata->iommu_attached = false;
+ ret = mdss_smmu_attach(mdata);
+ if (ret) {
+ pr_err("Error while attaching smmu contexts ret = %d\n",
+ ret);
+ return -EINVAL;
+ }
+ }
+ MDSS_XLOG(enable);
+ } else {
+ desc.args[0] = request.enable = enable;
+ desc.arginfo = SCM_ARGS(1);
+
+ if (!is_scm_armv8()) {
+ ret = scm_call(SCM_SVC_MP, MEM_PROTECT_SD_CTRL,
+ &request,
+ sizeof(request),
+ &resp,
+ sizeof(resp));
+ } else {
+ ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP,
+ mem_protect_sd_ctrl_id), &desc);
+ resp = desc.ret[0];
+ }
+
+ pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x\n",
enable, ret, resp);
+ }
if (ret)
return ret;
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 93f5f9a51a63..e1c3841c82de 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -92,6 +92,8 @@
*/
#define ENABLE_PIXEL_EXT_ONLY 0x80000000
+/* Pipe flag to indicate this pipe contains secure camera buffer */
+#define MDP_SECURE_CAMERA_OVERLAY_SESSION 0x100000000
/**
* Destination Scaler control flags setting
*
@@ -562,6 +564,8 @@ struct mdss_mdp_mixer {
bool valid_roi;
bool roi_changed;
struct mdss_rect roi;
+ bool dsc_enabled;
+ bool dsc_merge_enabled;
u8 cursor_enabled;
u16 cursor_hotx;
@@ -627,7 +631,7 @@ struct mdss_mdp_img_data {
dma_addr_t addr;
unsigned long len;
u32 offset;
- u32 flags;
+ u64 flags;
u32 dir;
u32 domain;
bool mapped;
@@ -811,7 +815,7 @@ struct mdss_mdp_pipe {
struct file *file;
bool is_handed_off;
- u32 flags;
+ u64 flags;
u32 bwc_mode;
/* valid only when pipe's output is crossing both layer mixers */
@@ -827,6 +831,9 @@ struct mdss_mdp_pipe {
struct mdss_mdp_format_params *src_fmt;
struct mdss_mdp_plane_sizes src_planes;
+ /* flag to re-store roi in case of pu dual-roi validation error */
+ bool restore_roi;
+
/* compression ratio from the source format */
struct mult_factor comp_ratio;
@@ -916,6 +923,7 @@ struct mdss_overlay_private {
u32 splash_mem_addr;
u32 splash_mem_size;
u32 sd_enabled;
+ u32 sc_enabled;
struct sw_sync_timeline *vsync_timeline;
struct mdss_mdp_vsync_handler vsync_retire_handler;
@@ -1289,6 +1297,15 @@ static inline void mdss_update_sd_client(struct mdss_data_type *mdata,
atomic_add_unless(&mdss_res->sd_client_count, -1, 0);
}
+static inline void mdss_update_sc_client(struct mdss_data_type *mdata,
+ bool status)
+{
+ if (status)
+ atomic_inc(&mdata->sc_client_count);
+ else
+ atomic_add_unless(&mdss_res->sc_client_count, -1, 0);
+}
+
static inline int mdss_mdp_get_wb_ctl_support(struct mdss_data_type *mdata,
bool rotator_session)
{
@@ -1506,6 +1523,7 @@ static inline bool mdss_mdp_is_map_needed(struct mdss_data_type *mdata,
struct mdss_mdp_img_data *data)
{
u32 is_secure_ui = data->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION;
+ u64 is_secure_camera = data->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION;
/*
* For ULT Targets we need SMMU Map, to issue map call for secure Display.
@@ -1513,6 +1531,10 @@ static inline bool mdss_mdp_is_map_needed(struct mdss_data_type *mdata,
if (is_secure_ui && !mdss_has_quirk(mdata, MDSS_QUIRK_NEED_SECURE_MAP))
return false;
+ if (is_secure_camera && test_bit(MDSS_CAPS_SEC_DETACH_SMMU,
+ mdata->mdss_caps_map))
+ return false;
+
return true;
}
@@ -1569,7 +1591,7 @@ unsigned long mdss_mdp_get_clk_rate(u32 clk_idx, bool locked);
int mdss_mdp_vsync_clk_enable(int enable, bool locked);
void mdss_mdp_clk_ctrl(int enable);
struct mdss_data_type *mdss_mdp_get_mdata(void);
-int mdss_mdp_secure_display_ctrl(unsigned int enable);
+int mdss_mdp_secure_session_ctrl(unsigned int enable, u64 flags);
int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd);
int mdss_mdp_dfps_update_params(struct msm_fb_data_type *mfd,
@@ -1603,7 +1625,7 @@ int mdss_mdp_overlay_start(struct msm_fb_data_type *mfd);
void mdss_mdp_overlay_set_chroma_sample(
struct mdss_mdp_pipe *pipe);
int mdp_pipe_tune_perf(struct mdss_mdp_pipe *pipe,
- u32 flags);
+ u64 flags);
int mdss_mdp_overlay_setup_scaling(struct mdss_mdp_pipe *pipe);
struct mdss_mdp_pipe *mdss_mdp_pipe_assign(struct mdss_data_type *mdata,
struct mdss_mdp_mixer *mixer, u32 ndx,
@@ -1836,7 +1858,7 @@ struct mult_factor *mdss_mdp_get_comp_factor(u32 format,
int mdss_mdp_data_map(struct mdss_mdp_data *data, bool rotator, int dir);
void mdss_mdp_data_free(struct mdss_mdp_data *data, bool rotator, int dir);
int mdss_mdp_data_get_and_validate_size(struct mdss_mdp_data *data,
- struct msmfb_data *planes, int num_planes, u32 flags,
+ struct msmfb_data *planes, int num_planes, u64 flags,
struct device *dev, bool rotator, int dir,
struct mdp_layer_buffer *buffer);
u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd);
@@ -1847,7 +1869,7 @@ void mdss_mdp_intersect_rect(struct mdss_rect *res_rect,
const struct mdss_rect *sci_rect);
void mdss_mdp_crop_rect(struct mdss_rect *src_rect,
struct mdss_rect *dst_rect,
- const struct mdss_rect *sci_rect);
+ const struct mdss_rect *sci_rect, bool normalize);
void rect_copy_mdss_to_mdp(struct mdp_rect *user, struct mdss_rect *kernel);
void rect_copy_mdp_to_mdss(struct mdp_rect *user, struct mdss_rect *kernel);
bool mdss_rect_overlap_check(struct mdss_rect *rect1, struct mdss_rect *rect2);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 1d61653b76bb..9ed44937efe6 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -728,7 +728,7 @@ int mdss_mdp_get_pipe_overlap_bw(struct mdss_mdp_pipe *pipe,
/* crop rectangles */
if (roi && !mixer->ctl->is_video_mode && !pipe->src_split_req)
- mdss_mdp_crop_rect(&src, &dst, roi);
+ mdss_mdp_crop_rect(&src, &dst, roi, true);
/*
* when doing vertical decimation lines will be skipped, hence there is
@@ -1108,7 +1108,7 @@ int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
/* crop rectangles */
if (roi && !mixer->ctl->is_video_mode && !pipe->src_split_req)
- mdss_mdp_crop_rect(&src, &dst, roi);
+ mdss_mdp_crop_rect(&src, &dst, roi, true);
pr_debug("v_total=%d, xres=%d fps=%d\n", v_total, xres, fps);
pr_debug("src(w,h)(%d,%d) dst(w,h)(%d,%d) dst_y=%d bpp=%d yuv=%d\n",
@@ -2743,6 +2743,7 @@ static inline void __dsc_enable(struct mdss_mdp_mixer *mixer)
{
mdss_mdp_pingpong_write(mixer->pingpong_base,
MDSS_MDP_REG_PP_DSC_MODE, 1);
+ mixer->dsc_enabled = true;
}
static inline void __dsc_disable(struct mdss_mdp_mixer *mixer)
@@ -2762,6 +2763,13 @@ static inline void __dsc_disable(struct mdss_mdp_mixer *mixer)
return;
}
writel_relaxed(0, offset + MDSS_MDP_REG_DSC_COMMON_MODE);
+ mixer->dsc_enabled = false;
+ mixer->dsc_merge_enabled = false;
+}
+
+static bool __is_dsc_merge_enabled(u32 common_mode)
+{
+ return common_mode & BIT(1);
}
static void __dsc_config(struct mdss_mdp_mixer *mixer,
@@ -2774,6 +2782,7 @@ static void __dsc_config(struct mdss_mdp_mixer *mixer,
u32 initial_lines = dsc->initial_lines;
bool is_cmd_mode = !(mode & BIT(2));
+ mixer->dsc_merge_enabled = __is_dsc_merge_enabled(mode);
data = mdss_mdp_pingpong_read(mixer->pingpong_base,
MDSS_MDP_REG_PP_DCE_DATA_OUT_SWAP);
data |= BIT(18); /* endian flip */
@@ -2928,11 +2937,6 @@ static void __dsc_config_thresh(struct mdss_mdp_mixer *mixer,
}
}
-static bool __is_dsc_merge_enabled(u32 common_mode)
-{
- return common_mode & BIT(1);
-}
-
static bool __dsc_is_3d_mux_enabled(struct mdss_mdp_ctl *ctl,
struct mdss_panel_info *pinfo)
{
@@ -3291,8 +3295,19 @@ void mdss_mdp_ctl_dsc_setup(struct mdss_mdp_ctl *ctl,
struct mdss_mdp_ctl *sctl;
struct mdss_panel_info *spinfo;
- if (!is_dsc_compression(pinfo))
+ /*
+ * Check for dynamic resolution switch from DSC On to DSC Off
+ * and disable DSC
+ */
+ if ((ctl->pending_mode_switch == SWITCH_RESOLUTION) &&
+ ctl->is_master &&
+ (!is_dsc_compression(pinfo))) {
+ if (ctl->mixer_left && ctl->mixer_left->dsc_enabled)
+ __dsc_disable(ctl->mixer_left);
+ if (ctl->mixer_right && ctl->mixer_right->dsc_enabled)
+ __dsc_disable(ctl->mixer_right);
return;
+ }
if (!ctl->is_master) {
pr_debug("skip slave ctl because master will program for both\n");
@@ -3703,6 +3718,30 @@ skip_intf_reconfig:
ctl->mixer_right->width = ctl->width / 2;
ctl->mixer_right->height = ctl->height;
}
+
+ /*
+ * If we are transitioning from DSC On + DSC Merge to DSC Off
+ * the 3D mux needs to be enabled
+ */
+ if (!is_dsc_compression(&pdata->panel_info) &&
+ ctl->mixer_left &&
+ ctl->mixer_left->dsc_enabled &&
+ ctl->mixer_left->dsc_merge_enabled) {
+ ctl->opmode |= MDSS_MDP_CTL_OP_PACK_3D_ENABLE |
+ MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT;
+ }
+
+ /*
+ * If we are transitioning from DSC Off to DSC On + DSC Merge
+ * the 3D mux needs to be disabled
+ */
+ if (is_dsc_compression(&pdata->panel_info) &&
+ ctl->mixer_left &&
+ !ctl->mixer_left->dsc_enabled &&
+ pdata->panel_info.dsc_enc_total != 1) {
+ ctl->opmode &= ~(MDSS_MDP_CTL_OP_PACK_3D_ENABLE |
+ MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT);
+ }
} else {
/*
* Handles MDP_SPLIT_MODE_NONE, MDP_DUAL_LM_DUAL_DISPLAY and
@@ -3717,7 +3756,6 @@ skip_intf_reconfig:
ctl->border_x_off = pdata->panel_info.lcdc.border_left;
ctl->border_y_off = pdata->panel_info.lcdc.border_top;
-
return ret;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_debug.c b/drivers/video/fbdev/msm/mdss_mdp_debug.c
index 4c4fa9ea98d0..711d2d222c7d 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_debug.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_debug.c
@@ -1868,7 +1868,7 @@ static void __dump_pipe(struct seq_file *s, struct mdss_mdp_pipe *pipe)
int smps[4];
int i;
- seq_printf(s, "\nSSPP #%d type=%s ndx=%x flags=0x%08x play_cnt=%u xin_id=%d\n",
+ seq_printf(s, "\nSSPP #%d type=%s ndx=%x flags=0x%16llx play_cnt=%u xin_id=%d\n",
pipe->num, mdss_mdp_pipetype2str(pipe->type),
pipe->ndx, pipe->flags, pipe->play_cnt, pipe->xin_id);
seq_printf(s, "\tstage=%d alpha=0x%x transp=0x%x blend_op=%d\n",
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index 4eb121f01aca..f08af5d6edd3 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -2029,8 +2029,22 @@ static void mdss_mdp_cmd_dsc_reconfig(struct mdss_mdp_ctl *ctl)
return;
pinfo = &ctl->panel_data->panel_info;
- if (pinfo->compression_mode != COMPRESSION_DSC)
- return;
+ if (pinfo->compression_mode != COMPRESSION_DSC) {
+ /*
+ * Check for a dynamic resolution switch from DSC On to
+ * DSC Off and call mdss_mdp_ctl_dsc_setup to disable DSC
+ */
+ if (ctl->pending_mode_switch == SWITCH_RESOLUTION) {
+ if (ctl->mixer_left && ctl->mixer_left->dsc_enabled)
+ changed = true;
+ if (is_split_lm(ctl->mfd) &&
+ ctl->mixer_right &&
+ ctl->mixer_right->dsc_enabled)
+ changed = true;
+ } else {
+ return;
+ }
+ }
changed = ctl->mixer_left->roi_changed;
if (is_split_lm(ctl->mfd))
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index 353d07ad64ac..20fcc26bb4bf 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -522,6 +522,56 @@ static void __update_avr_info(struct mdss_mdp_ctl *ctl,
}
/*
+ * __validate_dual_partial_update() - validation function for
+ * dual partial update ROIs
+ *
+ * - This function uses the commit structs "left_roi" and "right_roi"
+ * to pass the first and second ROI information for the multiple
+ * partial update feature.
+ * - Supports only SINGLE DSI with a max of 2 PU ROIs.
+ * - Not supported along with destination scalar.
+ * - Not supported when source-split is disabled.
+ * - Not supported with ping-pong split enabled.
+ */
+static int __validate_dual_partial_update(
+ struct mdss_mdp_ctl *ctl, struct mdp_layer_commit_v1 *commit)
+{
+ struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info;
+ struct mdss_data_type *mdata = ctl->mdata;
+ struct mdss_rect first_roi, second_roi;
+ int ret = 0;
+ struct mdp_destination_scaler_data *ds_data = commit->dest_scaler;
+
+ if (!mdata->has_src_split
+ || (is_panel_split(ctl->mfd))
+ || (is_pingpong_split(ctl->mfd))
+ || (ds_data && commit->dest_scaler_cnt &&
+ ds_data->flags & MDP_DESTSCALER_ENABLE)) {
+ pr_err("Invalid mode multi pu src_split:%d, split_mode:%d, ds_cnt:%d\n",
+ mdata->has_src_split, ctl->mfd->split_mode,
+ commit->dest_scaler_cnt);
+ ret = -EINVAL;
+ goto end;
+ }
+
+ rect_copy_mdp_to_mdss(&commit->left_roi, &first_roi);
+ rect_copy_mdp_to_mdss(&commit->right_roi, &second_roi);
+
+ if (!is_valid_pu_dual_roi(pinfo, &first_roi, &second_roi))
+ ret = -EINVAL;
+
+ MDSS_XLOG(ctl->num, first_roi.x, first_roi.y, first_roi.w, first_roi.h,
+ second_roi.x, second_roi.y, second_roi.w, second_roi.h,
+ ret);
+ pr_debug("Multiple PU ROIs - roi0:{%d,%d,%d,%d}, roi1{%d,%d,%d,%d}, ret:%d\n",
+ first_roi.x, first_roi.y, first_roi.w, first_roi.h,
+ second_roi.x, second_roi.y, second_roi.w,
+ second_roi.h, ret);
+end:
+ return ret;
+}
+
+/*
* __layer_needs_src_split() - check needs source split configuration
* @layer: input layer
*
@@ -936,7 +986,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
{
int ret = 0;
u32 left_lm_w = left_lm_w_from_mfd(mfd);
- u32 flags;
+ u64 flags;
struct mdss_mdp_mixer *mixer = NULL;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
@@ -978,6 +1028,8 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
pipe->flags |= MDP_BWC_EN;
if (layer->flags & MDP_LAYER_PP)
pipe->flags |= MDP_OVERLAY_PP_CFG_EN;
+ if (layer->flags & MDP_LAYER_SECURE_CAMERA_SESSION)
+ pipe->flags |= MDP_SECURE_CAMERA_OVERLAY_SESSION;
pipe->scaler.enable = (layer->flags & SCALER_ENABLED);
pipe->is_fg = layer->flags & MDP_LAYER_FORGROUND;
@@ -1000,6 +1052,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
pipe->is_handed_off = false;
pipe->async_update = (layer->flags & MDP_LAYER_ASYNC) ? true : false;
pipe->csc_coeff_set = layer->color_space;
+ pipe->restore_roi = false;
if (mixer->ctl) {
pipe->dst.x += mixer->ctl->border_x_off;
@@ -1007,7 +1060,7 @@ static int __configure_pipe_params(struct msm_fb_data_type *mfd,
pr_debug("border{%d,%d}\n", mixer->ctl->border_x_off,
mixer->ctl->border_y_off);
}
- pr_debug("src{%d,%d,%d,%d}, dst{%d,%d,%d,%d}\n",
+ pr_debug("pipe:%d src{%d,%d,%d,%d}, dst{%d,%d,%d,%d}\n", pipe->num,
pipe->src.x, pipe->src.y, pipe->src.w, pipe->src.h,
pipe->dst.x, pipe->dst.y, pipe->dst.w, pipe->dst.h);
@@ -1348,7 +1401,7 @@ static struct mdss_mdp_data *__map_layer_buffer(struct msm_fb_data_type *mfd,
struct mdp_layer_buffer *buffer;
struct msmfb_data image;
int i, ret;
- u32 flags;
+ u64 flags;
struct mdss_mdp_validate_info_t *vitem;
for (i = 0; i < layer_count; i++) {
@@ -1374,7 +1427,8 @@ static struct mdss_mdp_data *__map_layer_buffer(struct msm_fb_data_type *mfd,
}
flags = (pipe->flags & (MDP_SECURE_OVERLAY_SESSION |
- MDP_SECURE_DISPLAY_OVERLAY_SESSION));
+ MDP_SECURE_DISPLAY_OVERLAY_SESSION |
+ MDP_SECURE_CAMERA_OVERLAY_SESSION));
if (buffer->planes[0].fd < 0) {
pr_err("invalid file descriptor for layer buffer\n");
@@ -1585,34 +1639,48 @@ end:
}
/*
- * __validate_secure_display() - validate secure display
+ * __validate_secure_session() - validate various secure sessions
*
* This function travers through used pipe list and checks if any pipe
- * is with secure display enabled flag. It fails if client tries to stage
- * unsecure content with secure display session.
+ * is with secure display, secure video and secure camera enabled flag.
+ * It fails if client tries to stage unsecure content with
+ * secure display session and secure camera with secure video sessions.
*
*/
-static int __validate_secure_display(struct mdss_overlay_private *mdp5_data)
+static int __validate_secure_session(struct mdss_overlay_private *mdp5_data)
{
struct mdss_mdp_pipe *pipe, *tmp;
uint32_t sd_pipes = 0, nonsd_pipes = 0;
+ uint32_t secure_vid_pipes = 0, secure_cam_pipes = 0;
mutex_lock(&mdp5_data->list_lock);
list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_used, list) {
if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION)
sd_pipes++;
+ else if (pipe->flags & MDP_SECURE_OVERLAY_SESSION)
+ secure_vid_pipes++;
+ else if (pipe->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION)
+ secure_cam_pipes++;
else
nonsd_pipes++;
}
mutex_unlock(&mdp5_data->list_lock);
- pr_debug("pipe count:: secure display:%d non-secure:%d\n",
- sd_pipes, nonsd_pipes);
+ pr_debug("pipe count:: secure display:%d non-secure:%d secure-vid:%d,secure-cam:%d\n",
+ sd_pipes, nonsd_pipes, secure_vid_pipes, secure_cam_pipes);
- if ((sd_pipes || mdss_get_sd_client_cnt()) && nonsd_pipes) {
+ if ((sd_pipes || mdss_get_sd_client_cnt()) &&
+ (nonsd_pipes || secure_vid_pipes ||
+ secure_cam_pipes)) {
pr_err("non-secure layer validation request during secure display session\n");
- pr_err(" secure client cnt:%d secure pipe cnt:%d non-secure pipe cnt:%d\n",
- mdss_get_sd_client_cnt(), sd_pipes, nonsd_pipes);
+ pr_err(" secure client cnt:%d secure pipe:%d non-secure pipe:%d, secure-vid:%d, secure-cam:%d\n",
+ mdss_get_sd_client_cnt(), sd_pipes, nonsd_pipes,
+ secure_vid_pipes, secure_cam_pipes);
+ return -EINVAL;
+ } else if (secure_cam_pipes && (secure_vid_pipes || sd_pipes)) {
+ pr_err(" incompatible layers during secure camera session\n");
+ pr_err("secure-camera cnt:%d secure video:%d secure display:%d\n",
+ secure_cam_pipes, secure_vid_pipes, sd_pipes);
return -EINVAL;
} else {
return 0;
@@ -2388,7 +2456,7 @@ static int __validate_layers(struct msm_fb_data_type *mfd,
validate_skip:
__handle_free_list(mdp5_data, validate_info_list, layer_count);
- ret = __validate_secure_display(mdp5_data);
+ ret = __validate_secure_session(mdp5_data);
validate_exit:
pr_debug("err=%d total_layer:%d left:%d right:%d rec0_rel_ndx=0x%x rec1_rel_ndx=0x%x rec0_destroy_ndx=0x%x rec1_destroy_ndx=0x%x processed=%d\n",
@@ -2625,6 +2693,7 @@ int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd,
{
struct mdss_overlay_private *mdp5_data;
struct mdp_destination_scaler_data *ds_data;
+ struct mdss_panel_info *pinfo;
int rc = 0;
if (!mfd || !commit) {
@@ -2658,6 +2727,23 @@ int mdss_mdp_layer_atomic_validate(struct msm_fb_data_type *mfd,
}
}
+ pinfo = mfd->panel_info;
+ if (pinfo->partial_update_enabled == PU_DUAL_ROI) {
+ if (commit->flags & MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI) {
+ rc = __validate_dual_partial_update(mdp5_data->ctl,
+ commit);
+ if (IS_ERR_VALUE(rc)) {
+ pr_err("Multiple pu pre-validate fail\n");
+ return rc;
+ }
+ }
+ } else {
+ if (commit->flags & MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI) {
+ pr_err("Multiple partial update not supported!\n");
+ return -EINVAL;
+ }
+ }
+
ds_data = commit->dest_scaler;
if (ds_data && commit->dest_scaler_cnt &&
(ds_data->flags & MDP_DESTSCALER_ENABLE)) {
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 9bdc66232dd5..664850a1a617 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -396,7 +396,7 @@ int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
}
int mdp_pipe_tune_perf(struct mdss_mdp_pipe *pipe,
- u32 flags)
+ u64 flags)
{
struct mdss_data_type *mdata = pipe->mixer_left->ctl->mdata;
struct mdss_mdp_perf_params perf;
@@ -1188,11 +1188,10 @@ static void __overlay_pipe_cleanup(struct msm_fb_data_type *mfd,
list_move(&buf->buf_list, &mdp5_data->bufs_freelist);
/*
- * in case of secure UI, the buffer needs to be released as
- * soon as session is closed.
+ * free the buffers on the same cycle instead of waiting for
+ * next kickoff
*/
- if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION)
- mdss_mdp_overlay_buf_free(mfd, buf);
+ mdss_mdp_overlay_buf_free(mfd, buf);
}
mdss_mdp_pipe_destroy(pipe);
@@ -1477,7 +1476,7 @@ static int __overlay_queue_pipes(struct msm_fb_data_type *mfd)
*/
if (mdss_get_sd_client_cnt() &&
!(pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION)) {
- pr_warn("Non secure pipe during secure display: %u: %08X, skip\n",
+ pr_warn("Non secure pipe during secure display: %u: %16llx, skip\n",
pipe->num, pipe->flags);
continue;
}
@@ -1861,12 +1860,109 @@ int mdss_mode_switch_post(struct msm_fb_data_type *mfd, u32 mode)
return rc;
}
+static void __restore_pipe(struct mdss_mdp_pipe *pipe)
+{
+
+ if (!pipe->restore_roi)
+ return;
+
+ pr_debug("restoring pipe:%d dst from:{%d,%d,%d,%d} to:{%d,%d,%d,%d}\n",
+ pipe->num, pipe->dst.x, pipe->dst.y,
+ pipe->dst.w, pipe->dst.h, pipe->layer.dst_rect.x,
+ pipe->layer.dst_rect.y, pipe->layer.dst_rect.w,
+ pipe->layer.dst_rect.h);
+ pr_debug("restoring pipe:%d src from:{%d,%d,%d,%d} to:{%d,%d,%d,%d}\n",
+ pipe->num, pipe->src.x, pipe->src.y,
+ pipe->src.w, pipe->src.h, pipe->layer.src_rect.x,
+ pipe->layer.src_rect.y, pipe->layer.src_rect.w,
+ pipe->layer.src_rect.h);
+
+ pipe->src.x = pipe->layer.src_rect.x;
+ pipe->src.y = pipe->layer.src_rect.y;
+ pipe->src.w = pipe->layer.src_rect.w;
+ pipe->src.h = pipe->layer.src_rect.h;
+
+ pipe->dst.x = pipe->layer.dst_rect.x;
+ pipe->dst.y = pipe->layer.dst_rect.y;
+ pipe->dst.w = pipe->layer.dst_rect.w;
+ pipe->dst.h = pipe->layer.dst_rect.h;
+}
+
+ /**
+ * __crop_adjust_pipe_rect() - Adjust pipe roi for dual partial
+ * update feature.
+ * @pipe: pipe to check against.
+ * @dual_roi: roi's for the dual partial roi.
+ *
+ * For dual PU ROI case, the layer mixer is configured
+ * by merging the two width aligned ROIs (first_roi and
+ * second_roi) vertically. So, the y-offset of all the
+ * pipes belonging to the second_roi needs to adjusted
+ * accordingly. Also the cropping of the pipe's src/dst
+ * rect has to be done with respect to the ROI the pipe
+ * is intersecting with, before the adjustment.
+ */
+static int __crop_adjust_pipe_rect(struct mdss_mdp_pipe *pipe,
+ struct mdss_dsi_dual_pu_roi *dual_roi)
+{
+ u32 adjust_h;
+ u32 roi_y_pos;
+ int ret = 0;
+
+ pipe->restore_roi = false;
+ if (mdss_rect_overlap_check(&pipe->dst, &dual_roi->first_roi)) {
+ mdss_mdp_crop_rect(&pipe->src, &pipe->dst,
+ &dual_roi->first_roi, false);
+ pipe->restore_roi = true;
+
+ } else if (mdss_rect_overlap_check(&pipe->dst, &dual_roi->second_roi)) {
+ mdss_mdp_crop_rect(&pipe->src, &pipe->dst,
+ &dual_roi->second_roi, false);
+ adjust_h = dual_roi->second_roi.y;
+ roi_y_pos = dual_roi->first_roi.y + dual_roi->first_roi.h;
+
+ if (adjust_h > roi_y_pos) {
+ adjust_h = adjust_h - roi_y_pos;
+ pipe->dst.y -= adjust_h;
+ } else {
+ pr_err("wrong y-pos adjust_y:%d roi_y_pos:%d\n",
+ adjust_h, roi_y_pos);
+ ret = -EINVAL;
+ }
+ pipe->restore_roi = true;
+
+ } else {
+ ret = -EINVAL;
+ }
+
+ pr_debug("crop/adjusted p:%d src:{%d,%d,%d,%d} dst:{%d,%d,%d,%d} r:%d\n",
+ pipe->num, pipe->src.x, pipe->src.y,
+ pipe->src.w, pipe->src.h, pipe->dst.x,
+ pipe->dst.y, pipe->dst.w, pipe->dst.h,
+ pipe->restore_roi);
+
+ if (ret) {
+ pr_err("dual roi error p%d dst{%d,%d,%d,%d}",
+ pipe->num, pipe->dst.x, pipe->dst.y, pipe->dst.w,
+ pipe->dst.h);
+ pr_err(" roi1{%d,%d,%d,%d} roi2{%d,%d,%d,%d}\n",
+ dual_roi->first_roi.x, dual_roi->first_roi.y,
+ dual_roi->first_roi.w, dual_roi->first_roi.h,
+ dual_roi->second_roi.x, dual_roi->second_roi.y,
+ dual_roi->second_roi.w, dual_roi->second_roi.h);
+ }
+
+ return ret;
+}
+
static void __validate_and_set_roi(struct msm_fb_data_type *mfd,
struct mdp_display_commit *commit)
{
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info;
+ struct mdss_dsi_dual_pu_roi *dual_roi = &pinfo->dual_roi;
struct mdss_rect l_roi = {0}, r_roi = {0};
struct mdp_rect tmp_roi = {0};
bool skip_partial_update = true;
@@ -1881,6 +1977,39 @@ static void __validate_and_set_roi(struct msm_fb_data_type *mfd,
rect_copy_mdp_to_mdss(&commit->l_roi, &l_roi);
rect_copy_mdp_to_mdss(&commit->r_roi, &r_roi);
+ /*
+ * In case of dual partial update ROI, update the two ROIs to dual_roi
+ * struct and combine both the ROIs and assign it as a merged ROI in
+ * l_roi, as MDP would need only the merged ROI information for all
+ * LM settings.
+ */
+ if (pinfo->partial_update_enabled == PU_DUAL_ROI) {
+ if (commit->flags & MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI) {
+
+ if (!is_valid_pu_dual_roi(pinfo, &l_roi, &r_roi)) {
+ pr_err("Invalid dual roi - fall back to full screen update\n");
+ goto set_roi;
+ }
+
+ dual_roi->first_roi = (struct mdss_rect)
+ {l_roi.x, l_roi.y, l_roi.w, l_roi.h};
+ dual_roi->second_roi = (struct mdss_rect)
+ {r_roi.x, r_roi.y, r_roi.w, r_roi.h};
+ dual_roi->enabled = true;
+
+ l_roi.h += r_roi.h;
+ memset(&r_roi, 0, sizeof(struct mdss_rect));
+
+ pr_debug("Dual ROI - first_roi:{%d,%d,%d,%d}, second_roi:{%d,%d,%d,%d}\n",
+ dual_roi->first_roi.x, dual_roi->first_roi.y,
+ dual_roi->first_roi.w, dual_roi->first_roi.h,
+ dual_roi->second_roi.x, dual_roi->second_roi.y,
+ dual_roi->second_roi.w, dual_roi->second_roi.h);
+ } else {
+ dual_roi->enabled = false;
+ }
+ }
+
pr_debug("input: l_roi:-> %d %d %d %d r_roi:-> %d %d %d %d\n",
l_roi.x, l_roi.y, l_roi.w, l_roi.h,
r_roi.x, r_roi.y, r_roi.w, r_roi.h);
@@ -1926,12 +2055,24 @@ static void __validate_and_set_roi(struct msm_fb_data_type *mfd,
}
list_for_each_entry(pipe, &mdp5_data->pipes_used, list) {
+ pr_debug("pipe:%d src:{%d,%d,%d,%d} dst:{%d,%d,%d,%d}\n",
+ pipe->num, pipe->src.x, pipe->src.y,
+ pipe->src.w, pipe->src.h, pipe->dst.x,
+ pipe->dst.y, pipe->dst.w, pipe->dst.h);
+
+ if (dual_roi->enabled) {
+ if (__crop_adjust_pipe_rect(pipe, dual_roi)) {
+ skip_partial_update = true;
+ break;
+ }
+ }
+
if (!__is_roi_valid(pipe, &l_roi, &r_roi)) {
skip_partial_update = true;
- pr_err("error. invalid pu config for pipe%d: %d,%d,%d,%d\n",
- pipe->num,
- pipe->dst.x, pipe->dst.y,
- pipe->dst.w, pipe->dst.h);
+ pr_err("error. invalid pu config for pipe%d: %d,%d,%d,%d, dual_pu_roi:%d\n",
+ pipe->num, pipe->dst.x, pipe->dst.y,
+ pipe->dst.w, pipe->dst.h,
+ dual_roi->enabled);
break;
}
}
@@ -1946,17 +2087,114 @@ set_roi:
ctl->mixer_right->width,
ctl->mixer_right->height};
}
+
+ if (pinfo->partial_update_enabled == PU_DUAL_ROI) {
+ if (dual_roi->enabled) {
+ /* we failed pu validation, restore pipes */
+ list_for_each_entry(pipe,
+ &mdp5_data->pipes_used, list)
+ __restore_pipe(pipe);
+ }
+ dual_roi->enabled = false;
+ }
}
- pr_debug("after processing: %s l_roi:-> %d %d %d %d r_roi:-> %d %d %d %d\n",
+ pr_debug("after processing: %s l_roi:-> %d %d %d %d r_roi:-> %d %d %d %d, dual_pu_roi:%d\n",
(l_roi.w && l_roi.h && r_roi.w && r_roi.h) ? "left+right" :
((l_roi.w && l_roi.h) ? "left-only" : "right-only"),
l_roi.x, l_roi.y, l_roi.w, l_roi.h,
- r_roi.x, r_roi.y, r_roi.w, r_roi.h);
+ r_roi.x, r_roi.y, r_roi.w, r_roi.h,
+ dual_roi->enabled);
mdss_mdp_set_roi(ctl, &l_roi, &r_roi);
}
+/*
+ * Enables/disable secure (display or camera) sessions
+ */
+static int __overlay_secure_ctrl(struct msm_fb_data_type *mfd)
+{
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
+ struct mdss_mdp_pipe *pipe;
+ int ret = 0;
+ int sd_in_pipe = 0;
+ int sc_in_pipe = 0;
+
+ list_for_each_entry(pipe, &mdp5_data->pipes_used, list) {
+ if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) {
+ sd_in_pipe = 1;
+ pr_debug("Secure pipe: %u : %16llx\n",
+ pipe->num, pipe->flags);
+ } else if (pipe->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION) {
+ sc_in_pipe = 1;
+ pr_debug("Secure camera: %u: %16llx\n",
+ pipe->num, pipe->flags);
+ }
+ }
+
+ if ((!sd_in_pipe && !mdp5_data->sd_enabled) ||
+ (sd_in_pipe && mdp5_data->sd_enabled) ||
+ (!sc_in_pipe && !mdp5_data->sc_enabled) ||
+ (sc_in_pipe && mdp5_data->sc_enabled))
+ return ret;
+
+ /* Secure Display */
+ if (!mdp5_data->sd_enabled && sd_in_pipe) {
+ if (!mdss_get_sd_client_cnt()) {
+ /*wait for ping pong done */
+ if (ctl->ops.wait_pingpong)
+ mdss_mdp_display_wait4pingpong(ctl, true);
+ ret = mdss_mdp_secure_session_ctrl(1,
+ MDP_SECURE_DISPLAY_OVERLAY_SESSION);
+ if (ret)
+ return ret;
+ }
+ mdp5_data->sd_enabled = 1;
+ mdss_update_sd_client(mdp5_data->mdata, true);
+ } else if (mdp5_data->sd_enabled && !sd_in_pipe) {
+ /* disable the secure display on last client */
+ if (mdss_get_sd_client_cnt() == 1) {
+ if (ctl->ops.wait_pingpong)
+ mdss_mdp_display_wait4pingpong(ctl, true);
+ ret = mdss_mdp_secure_session_ctrl(0,
+ MDP_SECURE_DISPLAY_OVERLAY_SESSION);
+ if (ret)
+ return ret;
+ }
+ mdss_update_sd_client(mdp5_data->mdata, false);
+ mdp5_data->sd_enabled = 0;
+ }
+
+ /* Secure Camera */
+ if (!mdp5_data->sc_enabled && sc_in_pipe) {
+ if (!mdss_get_sc_client_cnt()) {
+ if (ctl->ops.wait_pingpong)
+ mdss_mdp_display_wait4pingpong(ctl, true);
+ ret = mdss_mdp_secure_session_ctrl(1,
+ MDP_SECURE_CAMERA_OVERLAY_SESSION);
+ if (ret)
+ return ret;
+ }
+ mdp5_data->sc_enabled = 1;
+ mdss_update_sc_client(mdp5_data->mdata, true);
+ } else if (mdp5_data->sc_enabled && !sc_in_pipe) {
+ /* disable the secure camera on last client */
+ if (mdss_get_sc_client_cnt() == 1) {
+ if (ctl->ops.wait_pingpong)
+ mdss_mdp_display_wait4pingpong(ctl, true);
+ ret = mdss_mdp_secure_session_ctrl(0,
+ MDP_SECURE_CAMERA_OVERLAY_SESSION);
+ if (ret)
+ return ret;
+ }
+ mdss_update_sc_client(mdp5_data->mdata, false);
+ mdp5_data->sc_enabled = 0;
+ }
+
+ return ret;
+}
+
int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
struct mdp_display_commit *data)
{
@@ -1964,7 +2202,6 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
struct mdss_mdp_pipe *pipe, *tmp;
struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
int ret = 0;
- int sd_in_pipe = 0;
struct mdss_mdp_commit_cb commit_cb;
if (!ctl)
@@ -1995,30 +2232,12 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
mutex_unlock(ctl->shared_lock);
return ret;
}
- mutex_lock(&mdp5_data->list_lock);
-
- /*
- * check if there is a secure display session
- */
- list_for_each_entry(pipe, &mdp5_data->pipes_used, list) {
- if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) {
- sd_in_pipe = 1;
- pr_debug("Secure pipe: %u : %08X\n",
- pipe->num, pipe->flags);
- }
- }
- /*
- * start secure display session if there is secure display session and
- * sd_enabled is not true.
- */
- if (!mdp5_data->sd_enabled && sd_in_pipe) {
- if (!mdss_get_sd_client_cnt())
- ret = mdss_mdp_secure_display_ctrl(1);
- if (!ret) {
- mdp5_data->sd_enabled = 1;
- mdss_update_sd_client(mdp5_data->mdata, true);
- }
+ mutex_lock(&mdp5_data->list_lock);
+ ret = __overlay_secure_ctrl(mfd);
+ if (IS_ERR_VALUE(ret)) {
+ pr_err("secure operation failed %d\n", ret);
+ goto commit_fail;
}
if (!ctl->shared_lock)
@@ -2108,19 +2327,6 @@ int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
}
mutex_lock(&mdp5_data->ov_lock);
- /*
- * If there is no secure display session and sd_enabled, disable the
- * secure display session
- */
- if (mdp5_data->sd_enabled && !sd_in_pipe && !ret) {
- /* disable the secure display on last client */
- if (mdss_get_sd_client_cnt() == 1)
- ret = mdss_mdp_secure_display_ctrl(0);
- if (!ret) {
- mdss_update_sd_client(mdp5_data->mdata, false);
- mdp5_data->sd_enabled = 0;
- }
- }
mdss_fb_update_notify_update(mfd);
commit_fail:
@@ -2272,7 +2478,7 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
struct mdss_mdp_data *src_data;
struct mdp_layer_buffer buffer;
int ret;
- u32 flags;
+ u64 flags;
pipe = __overlay_find_pipe(mfd, req->id);
if (!pipe) {
@@ -2298,7 +2504,8 @@ static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
pr_warn("Unexpected buffer queue to a solid fill pipe\n");
flags = (pipe->flags & (MDP_SECURE_OVERLAY_SESSION |
- MDP_SECURE_DISPLAY_OVERLAY_SESSION));
+ MDP_SECURE_DISPLAY_OVERLAY_SESSION |
+ MDP_SECURE_CAMERA_OVERLAY_SESSION));
mutex_lock(&mdp5_data->list_lock);
src_data = mdss_mdp_overlay_buf_alloc(mfd, pipe);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
index 8f211a977aa4..e370a80ad998 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
@@ -1878,7 +1878,8 @@ static void mdss_mdp_pipe_stride_update(struct mdss_mdp_pipe *pipe)
if (pipe->multirect.mode == MDSS_MDP_PIPE_MULTIRECT_NONE) {
memcpy(&ystride, &pipe->src_planes.ystride,
sizeof(u32) * MAX_PLANES);
- if (pipe->flags & MDP_SECURE_OVERLAY_SESSION)
+ if (pipe->flags & (MDP_SECURE_OVERLAY_SESSION |
+ MDP_SECURE_CAMERA_OVERLAY_SESSION))
secure = 0xF;
} else {
if (pipe->multirect.num == MDSS_MDP_PIPE_RECT0) {
@@ -1891,12 +1892,14 @@ static void mdss_mdp_pipe_stride_update(struct mdss_mdp_pipe *pipe)
ystride[0] = rec0_pipe->src_planes.ystride[0];
ystride[2] = rec0_pipe->src_planes.ystride[2];
- if (rec0_pipe->flags & MDP_SECURE_OVERLAY_SESSION)
+ if (rec0_pipe->flags & (MDP_SECURE_OVERLAY_SESSION |
+ MDP_SECURE_CAMERA_OVERLAY_SESSION))
secure |= 0x5;
ystride[1] = rec1_pipe->src_planes.ystride[0];
ystride[3] = rec1_pipe->src_planes.ystride[2];
- if (rec1_pipe->flags & MDP_SECURE_OVERLAY_SESSION)
+ if (rec1_pipe->flags & (MDP_SECURE_OVERLAY_SESSION |
+ MDP_SECURE_CAMERA_OVERLAY_SESSION))
secure |= 0xA;
}
@@ -1998,7 +2001,7 @@ static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe,
dst.x -= left_lm_w_from_mfd(pipe->mfd);
}
- mdss_mdp_crop_rect(&src, &dst, &roi);
+ mdss_mdp_crop_rect(&src, &dst, &roi, true);
if (mdata->has_src_split && is_right_mixer) {
/*
@@ -2320,11 +2323,13 @@ static int mdss_mdp_pipe_solidfill_setup(struct mdss_mdp_pipe *pipe)
}
format = MDSS_MDP_FMT_SOLID_FILL;
- secure = (pipe->flags & MDP_SECURE_OVERLAY_SESSION ? 0xF : 0x0);
+ secure = (pipe->flags & (MDP_SECURE_OVERLAY_SESSION |
+ MDP_SECURE_CAMERA_OVERLAY_SESSION)
+ ? 0xF : 0x0);
/* support ARGB color format only */
unpack = (C3_ALPHA << 24) | (C2_R_Cr << 16) |
- (C1_B_Cb << 8) | (C0_G_Y << 0);
+ (C0_G_Y << 8) | (C1_B_Cb << 0);
if (pipe->scaler.enable)
opmode |= (1 << 31);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_util.c b/drivers/video/fbdev/msm/mdss_mdp_util.c
index 8b0ebc3fdf05..199c2b66d90e 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_util.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_util.c
@@ -241,7 +241,7 @@ void mdss_mdp_intersect_rect(struct mdss_rect *res_rect,
void mdss_mdp_crop_rect(struct mdss_rect *src_rect,
struct mdss_rect *dst_rect,
- const struct mdss_rect *sci_rect)
+ const struct mdss_rect *sci_rect, bool normalize)
{
struct mdss_rect res;
mdss_mdp_intersect_rect(&res, dst_rect, sci_rect);
@@ -253,9 +253,17 @@ void mdss_mdp_crop_rect(struct mdss_rect *src_rect,
src_rect->w = res.w;
src_rect->h = res.h;
}
- *dst_rect = (struct mdss_rect)
- {(res.x - sci_rect->x), (res.y - sci_rect->y),
- res.w, res.h};
+
+ /* adjust dest rect based on the sci_rect starting */
+ if (normalize) {
+ *dst_rect = (struct mdss_rect) {(res.x - sci_rect->x),
+ (res.y - sci_rect->y), res.w, res.h};
+
+ /* return the actual cropped intersecting rect */
+ } else {
+ *dst_rect = (struct mdss_rect) {res.x, res.y,
+ res.w, res.h};
+ }
}
}
@@ -963,16 +971,17 @@ static int mdss_mdp_put_img(struct mdss_mdp_img_data *data, bool rotator,
data->srcp_dma_buf = NULL;
}
}
- } else if (data->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) {
+ } else if ((data->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) ||
+ (data->flags & MDP_SECURE_CAMERA_OVERLAY_SESSION)) {
/*
- * skip memory unmapping - secure display uses physical
- * address which does not require buffer unmapping
+ * skip memory unmapping - secure display and camera uses
+ * physical address which does not require buffer unmapping
*
* For LT targets in secure display usecase, srcp_dma_buf will
* be filled due to map call which will be unmapped above.
*
*/
- pr_debug("skip memory unmapping for secure display content\n");
+ pr_debug("skip memory unmapping for secure display/camera content\n");
} else {
return -ENOMEM;
}
@@ -1188,7 +1197,7 @@ err_unmap:
}
static int mdss_mdp_data_get(struct mdss_mdp_data *data,
- struct msmfb_data *planes, int num_planes, u32 flags,
+ struct msmfb_data *planes, int num_planes, u64 flags,
struct device *dev, bool rotator, int dir)
{
int i, rc = 0;
@@ -1201,7 +1210,7 @@ static int mdss_mdp_data_get(struct mdss_mdp_data *data,
rc = mdss_mdp_get_img(&planes[i], &data->p[i], dev, rotator,
dir);
if (rc) {
- pr_err("failed to get buf p=%d flags=%x\n", i, flags);
+ pr_err("failed to get buf p=%d flags=%llx\n", i, flags);
while (i > 0) {
i--;
mdss_mdp_put_img(&data->p[i], rotator, dir);
@@ -1251,7 +1260,7 @@ void mdss_mdp_data_free(struct mdss_mdp_data *data, bool rotator, int dir)
}
int mdss_mdp_data_get_and_validate_size(struct mdss_mdp_data *data,
- struct msmfb_data *planes, int num_planes, u32 flags,
+ struct msmfb_data *planes, int num_planes, u64 flags,
struct device *dev, bool rotator, int dir,
struct mdp_layer_buffer *buffer)
{
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index 18a93f9d3c3e..0483e3d42873 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -137,6 +137,25 @@ enum {
SIM_HW_TE_MODE,
};
+
+/*
+ * enum partial_update_mode - Different modes for partial update feature
+ *
+ * @PU_NOT_SUPPORTED: Feature is not supported on target.
+ * @PU_SINGLE_ROI: Default mode, only one ROI is triggered to the
+ * panel(one on each DSI in case of split dsi)
+ * @PU_DUAL_ROI: Support for sending two roi's that are clubbed
+ * together as one big single ROI. This is only
+ * supported on certain panels that have this
+ * capability in their DDIC.
+ *
+ */
+enum {
+ PU_NOT_SUPPORTED = 0,
+ PU_SINGLE_ROI,
+ PU_DUAL_ROI,
+};
+
struct mdss_rect {
u16 x;
u16 y;
@@ -664,6 +683,50 @@ struct mdss_panel_roi_alignment {
u32 min_height;
};
+
+/*
+ * Nomeclature used to represent partial ROI in case of
+ * dual roi when the panel supports it. Region marked (XXX) is
+ * the extended roi to align with the second roi since LM output
+ * has to be rectangle.
+ *
+ * For single ROI, only the first ROI will be used in the struct.
+ * DSI driver will merge it based on the partial_update_roi_merge
+ * property.
+ *
+ * -------------------------------
+ * | DSI0 | DSI1 |
+ * -------------------------------
+ * | | |
+ * | | |
+ * | =========|=======----+ |
+ * | | | |XXXX| |
+ * | | First| Roi |XXXX| |
+ * | | | |XXXX| |
+ * | =========|=======----+ |
+ * | | |
+ * | | |
+ * | | |
+ * | +----================= |
+ * | |XXXX| | | |
+ * | |XXXX| Second Roi | |
+ * | |XXXX| | | |
+ * | +----====|============ |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * | | |
+ * ------------------------------
+ *
+ */
+
+struct mdss_dsi_dual_pu_roi {
+ struct mdss_rect first_roi;
+ struct mdss_rect second_roi;
+ bool enabled;
+};
+
struct mdss_panel_info {
u32 xres;
u32 yres;
@@ -689,6 +752,7 @@ struct mdss_panel_info {
u32 vic; /* video identification code */
u32 deep_color;
struct mdss_rect roi;
+ struct mdss_dsi_dual_pu_roi dual_roi;
int pwm_pmic_gpio;
int pwm_lpg_chan;
int pwm_period;
@@ -723,8 +787,8 @@ struct mdss_panel_info {
u32 cont_splash_enabled;
bool esd_rdy;
- bool partial_update_supported; /* value from dts if pu is supported */
- bool partial_update_enabled; /* is pu currently allowed */
+ u32 partial_update_supported; /* value from dts if pu is supported */
+ u32 partial_update_enabled; /* is pu currently allowed */
u32 dcs_cmd_by_left;
u32 partial_update_roi_merge;
struct ion_handle *splash_ihdl;
@@ -1000,6 +1064,27 @@ static inline bool is_lm_configs_dsc_compatible(struct mdss_panel_info *pinfo,
return true;
}
+static inline bool is_valid_pu_dual_roi(struct mdss_panel_info *pinfo,
+ struct mdss_rect *first_roi, struct mdss_rect *second_roi)
+{
+ if ((first_roi->x != second_roi->x) || (first_roi->w != second_roi->w)
+ || (first_roi->y > second_roi->y)
+ || ((first_roi->y + first_roi->h) > second_roi->y)
+ || (is_dsc_compression(pinfo) &&
+ !is_lm_configs_dsc_compatible(pinfo,
+ first_roi->w, first_roi->h) &&
+ !is_lm_configs_dsc_compatible(pinfo,
+ second_roi->w, second_roi->h))) {
+ pr_err("Invalid multiple PU ROIs, roi0:{%d,%d,%d,%d}, roi1{%d,%d,%d,%d}\n",
+ first_roi->x, first_roi->y, first_roi->w,
+ first_roi->h, second_roi->x, second_roi->y,
+ second_roi->w, second_roi->h);
+ return false;
+ }
+
+ return true;
+}
+
int mdss_register_panel(struct platform_device *pdev,
struct mdss_panel_data *pdata);
diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c
index eab7bcaaa156..2239791fdad0 100644
--- a/drivers/video/fbdev/msm/mdss_smmu.c
+++ b/drivers/video/fbdev/msm/mdss_smmu.c
@@ -162,12 +162,15 @@ end:
}
/*
- * mdss_smmu_v2_attach()
+ * mdss_smmu_attach_v2()
*
* Associates each configured VA range with the corresponding smmu context
* bank device. Enables the clks as smmu_v2 requires voting it before the usage.
* And iommu attach is done only once during the initial attach and it is never
* detached as smmu v2 uses a feature called 'retention'.
+ * Only detach the secure and non-secure contexts in case of secure display
+ * case and secure contexts for secure camera use cases for the platforms
+ * which have caps MDSS_CAPS_SEC_DETACH_SMMU enabled
*/
static int mdss_smmu_attach_v2(struct mdss_data_type *mdata)
{
@@ -191,7 +194,9 @@ static int mdss_smmu_attach_v2(struct mdss_data_type *mdata)
}
mdss_smmu->handoff_pending = false;
- if (!mdss_smmu->domain_attached) {
+ if (!mdss_smmu->domain_attached &&
+ mdss_smmu_is_valid_domain_condition(mdata,
+ i, true)) {
rc = arm_iommu_attach_device(mdss_smmu->dev,
mdss_smmu->mmu_mapping);
if (rc) {
@@ -229,10 +234,11 @@ err:
}
/*
- * mdss_smmu_v2_detach()
+ * mdss_smmu_detach_v2()
*
- * Only disables the clks as it is not required to detach the iommu mapped
- * VA range from the device in smmu_v2 as explained in the mdss_smmu_v2_attach
+ * Disables the clks only when it is not required to detach the iommu mapped
+ * VA range (as long as not in secure display use case)
+ * from the device in smmu_v2 as explained in the mdss_smmu_v2_attach
*/
static int mdss_smmu_detach_v2(struct mdss_data_type *mdata)
{
@@ -245,8 +251,24 @@ static int mdss_smmu_detach_v2(struct mdss_data_type *mdata)
continue;
mdss_smmu = mdss_smmu_get_cb(i);
- if (mdss_smmu && mdss_smmu->dev && !mdss_smmu->handoff_pending)
- mdss_smmu_enable_power(mdss_smmu, false);
+ if (mdss_smmu && mdss_smmu->dev) {
+ if (!mdss_smmu->handoff_pending &&
+ mdss_smmu->domain_attached &&
+ mdss_smmu_is_valid_domain_condition(mdata,
+ i, false)) {
+ /*
+ * if entering in secure display or
+ * secure camera use case(for secured contexts
+ * leave the smmu clocks on and only detach the
+ * smmu contexts
+ */
+ arm_iommu_detach_device(mdss_smmu->dev);
+ mdss_smmu->domain_attached = false;
+ pr_debug("iommu v2 domain[%i] detached\n", i);
+ } else {
+ mdss_smmu_enable_power(mdss_smmu, false);
+ }
+ }
}
mutex_unlock(&mdp_iommu_lock);
@@ -609,6 +631,7 @@ int mdss_smmu_probe(struct platform_device *pdev)
}
mdss_smmu = &mdata->mdss_smmu[smmu_domain.domain];
+ mdss_smmu->domain = smmu_domain.domain;
mp = &mdss_smmu->mp;
memset(mp, 0, sizeof(struct dss_module_power));
diff --git a/drivers/video/fbdev/msm/mdss_smmu.h b/drivers/video/fbdev/msm/mdss_smmu.h
index a987066cc773..f7e6e275c16a 100644
--- a/drivers/video/fbdev/msm/mdss_smmu.h
+++ b/drivers/video/fbdev/msm/mdss_smmu.h
@@ -73,6 +73,38 @@ static inline bool mdss_smmu_is_valid_domain_type(struct mdss_data_type *mdata,
return true;
}
+static inline bool mdss_smmu_is_valid_domain_condition(
+ struct mdss_data_type *mdata,
+ int domain_type,
+ bool is_attach)
+{
+ if (is_attach) {
+ if (test_bit(MDSS_CAPS_SEC_DETACH_SMMU,
+ mdata->mdss_caps_map) &&
+ (mdata->sec_disp_en ||
+ (mdata->sec_cam_en &&
+ domain_type == MDSS_IOMMU_DOMAIN_SECURE))) {
+ pr_debug("SMMU attach not attempted, sd:%d, sc:%d\n",
+ mdata->sec_disp_en, mdata->sec_cam_en);
+ return false;
+ } else {
+ return true;
+ }
+ } else {
+ if (test_bit(MDSS_CAPS_SEC_DETACH_SMMU,
+ mdata->mdss_caps_map) &&
+ (mdata->sec_disp_en ||
+ (mdata->sec_cam_en &&
+ domain_type == MDSS_IOMMU_DOMAIN_SECURE))) {
+ pr_debug("SMMU detach attempted, sd:%d, sc:%d\n",
+ mdata->sec_disp_en, mdata->sec_cam_en);
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
static inline struct mdss_smmu_client *mdss_smmu_get_cb(u32 domain)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
@@ -96,7 +128,7 @@ static inline int is_mdss_iommu_attached(void)
return mdata ? mdata->iommu_attached : false;
}
-static inline int mdss_smmu_get_domain_type(u32 flags, bool rotator)
+static inline int mdss_smmu_get_domain_type(u64 flags, bool rotator)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
int type;
diff --git a/drivers/video/fbdev/msm/msm_ext_display.c b/drivers/video/fbdev/msm/msm_ext_display.c
index f6c6548bdaa5..ca01ee6345d2 100644
--- a/drivers/video/fbdev/msm/msm_ext_display.c
+++ b/drivers/video/fbdev/msm/msm_ext_display.c
@@ -38,15 +38,18 @@ struct msm_ext_disp {
struct switch_dev hdmi_sdev;
struct switch_dev audio_sdev;
bool ack_enabled;
- atomic_t ack_pending;
+ bool audio_session_on;
struct list_head display_list;
struct mutex lock;
+ struct completion hpd_comp;
};
static int msm_ext_disp_get_intf_data(struct msm_ext_disp *ext_disp,
enum msm_ext_disp_type type,
struct msm_ext_disp_init_data **data);
static int msm_ext_disp_audio_ack(struct platform_device *pdev, u32 ack);
+static int msm_ext_disp_update_audio_ops(struct msm_ext_disp *ext_disp,
+ enum msm_ext_disp_cable_state state);
static int msm_ext_disp_switch_dev_register(struct msm_ext_disp *ext_disp)
{
@@ -313,14 +316,14 @@ static void msm_ext_disp_remove_intf_data(struct msm_ext_disp *ext_disp,
}
}
-static void msm_ext_disp_send_cable_notification(struct msm_ext_disp *ext_disp,
+static int msm_ext_disp_send_cable_notification(struct msm_ext_disp *ext_disp,
enum msm_ext_disp_cable_state new_state)
{
int state = EXT_DISPLAY_CABLE_STATE_MAX;
if (!ext_disp) {
pr_err("Invalid params\n");
- return;
+ return -EINVAL;
}
state = ext_disp->hdmi_sdev.state;
@@ -330,6 +333,77 @@ static void msm_ext_disp_send_cable_notification(struct msm_ext_disp *ext_disp,
ext_disp->hdmi_sdev.state == state ?
"is same" : "switched to",
ext_disp->hdmi_sdev.state);
+
+ return ext_disp->hdmi_sdev.state == state ? 0 : 1;
+}
+
+static int msm_ext_disp_send_audio_notification(struct msm_ext_disp *ext_disp,
+ enum msm_ext_disp_cable_state new_state)
+{
+ int state = EXT_DISPLAY_CABLE_STATE_MAX;
+
+ if (!ext_disp) {
+ pr_err("Invalid params\n");
+ return -EINVAL;
+ }
+
+ state = ext_disp->audio_sdev.state;
+ switch_set_state(&ext_disp->audio_sdev, !!new_state);
+
+ pr_debug("Audio state %s %d\n",
+ ext_disp->audio_sdev.state == state ?
+ "is same" : "switched to",
+ ext_disp->audio_sdev.state);
+
+ return ext_disp->audio_sdev.state == state ? 0 : 1;
+}
+
+static int msm_ext_disp_process_display(struct msm_ext_disp *ext_disp,
+ enum msm_ext_disp_cable_state state)
+{
+ int ret = msm_ext_disp_send_cable_notification(ext_disp, state);
+
+ /* positive ret value means audio node was switched */
+ if (IS_ERR_VALUE(ret) || !ret) {
+ pr_debug("not waiting for display\n");
+ goto end;
+ }
+
+ reinit_completion(&ext_disp->hpd_comp);
+ ret = wait_for_completion_timeout(&ext_disp->hpd_comp, HZ * 2);
+ if (!ret) {
+ pr_err("display timeout\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ ret = 0;
+end:
+ return ret;
+}
+
+static int msm_ext_disp_process_audio(struct msm_ext_disp *ext_disp,
+ enum msm_ext_disp_cable_state state)
+{
+ int ret = msm_ext_disp_send_audio_notification(ext_disp, state);
+
+ /* positive ret value means audio node was switched */
+ if (IS_ERR_VALUE(ret) || !ret || !ext_disp->ack_enabled) {
+ pr_debug("not waiting for audio\n");
+ goto end;
+ }
+
+ reinit_completion(&ext_disp->hpd_comp);
+ ret = wait_for_completion_timeout(&ext_disp->hpd_comp, HZ * 2);
+ if (!ret) {
+ pr_err("audio timeout\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ ret = 0;
+end:
+ return ret;
}
static int msm_ext_disp_hpd(struct platform_device *pdev,
@@ -337,7 +411,6 @@ static int msm_ext_disp_hpd(struct platform_device *pdev,
enum msm_ext_disp_cable_state state)
{
int ret = 0;
- struct msm_ext_disp_init_data *data = NULL;
struct msm_ext_disp *ext_disp = NULL;
if (!pdev) {
@@ -379,27 +452,28 @@ static int msm_ext_disp_hpd(struct platform_device *pdev,
goto end;
}
- ret = msm_ext_disp_get_intf_data(ext_disp, type, &data);
- if (ret)
- goto end;
-
if (state == EXT_DISPLAY_CABLE_CONNECT) {
- ext_disp->current_disp = data->type;
- } else if ((state == EXT_DISPLAY_CABLE_DISCONNECT) &&
- !ext_disp->ack_enabled) {
- if (ext_disp->ops) {
- ext_disp->ops->audio_info_setup = NULL;
- ext_disp->ops->get_audio_edid_blk = NULL;
- ext_disp->ops->cable_status = NULL;
- ext_disp->ops->get_intf_id = NULL;
- ext_disp->ops->teardown_done = NULL;
- }
+ ext_disp->current_disp = type;
+
+ ret = msm_ext_disp_process_display(ext_disp, state);
+ if (ret)
+ goto end;
+
+ msm_ext_disp_update_audio_ops(ext_disp, state);
+ if (ret)
+ goto end;
+
+ ret = msm_ext_disp_process_audio(ext_disp, state);
+ if (ret)
+ goto end;
+ } else {
+ msm_ext_disp_process_audio(ext_disp, state);
+ msm_ext_disp_update_audio_ops(ext_disp, state);
+ msm_ext_disp_process_display(ext_disp, state);
ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
}
- msm_ext_disp_send_cable_notification(ext_disp, state);
-
pr_debug("Hpd (%d) for display (%s)\n", state,
msm_ext_disp_name(type));
@@ -427,23 +501,18 @@ static int msm_ext_disp_get_intf_data_helper(struct platform_device *pdev,
goto end;
}
- mutex_lock(&ext_disp->lock);
-
if (ext_disp->current_disp == EXT_DISPLAY_TYPE_MAX) {
ret = -EINVAL;
pr_err("No display connected\n");
- goto error;
+ goto end;
}
ret = msm_ext_disp_get_intf_data(ext_disp, ext_disp->current_disp,
data);
- if (ret)
- goto error;
-error:
- mutex_unlock(&ext_disp->lock);
end:
return ret;
}
+
static int msm_ext_disp_cable_status(struct platform_device *pdev, u32 vote)
{
int ret = 0;
@@ -480,11 +549,21 @@ static int msm_ext_disp_audio_info_setup(struct platform_device *pdev,
{
int ret = 0;
struct msm_ext_disp_init_data *data = NULL;
+ struct msm_ext_disp *ext_disp = NULL;
ret = msm_ext_disp_get_intf_data_helper(pdev, &data);
if (ret || !data)
goto end;
+ ext_disp = platform_get_drvdata(pdev);
+ if (!ext_disp) {
+ pr_err("No drvdata found\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ ext_disp->audio_session_on = true;
+
ret = data->codec_ops.audio_info_setup(data->pdev, params);
end:
@@ -495,6 +574,7 @@ static void msm_ext_disp_teardown_done(struct platform_device *pdev)
{
int ret = 0;
struct msm_ext_disp_init_data *data = NULL;
+ struct msm_ext_disp *ext_disp = NULL;
ret = msm_ext_disp_get_intf_data_helper(pdev, &data);
if (ret || !data) {
@@ -502,7 +582,21 @@ static void msm_ext_disp_teardown_done(struct platform_device *pdev)
return;
}
- data->codec_ops.teardown_done(data->pdev);
+ ext_disp = platform_get_drvdata(pdev);
+ if (!ext_disp) {
+ pr_err("No drvdata found\n");
+ return;
+ }
+
+ if (data->codec_ops.teardown_done)
+ data->codec_ops.teardown_done(data->pdev);
+
+ ext_disp->audio_session_on = false;
+
+ pr_debug("%s tearing down audio\n",
+ msm_ext_disp_name(ext_disp->current_disp));
+
+ complete_all(&ext_disp->hpd_comp);
}
static int msm_ext_disp_get_intf_id(struct platform_device *pdev)
@@ -523,93 +617,78 @@ static int msm_ext_disp_get_intf_id(struct platform_device *pdev)
goto end;
}
- mutex_lock(&ext_disp->lock);
ret = ext_disp->current_disp;
- mutex_unlock(&ext_disp->lock);
end:
return ret;
}
+static int msm_ext_disp_update_audio_ops(struct msm_ext_disp *ext_disp,
+ enum msm_ext_disp_cable_state state)
+{
+ int ret = 0;
+ struct msm_ext_disp_audio_codec_ops *ops = ext_disp->ops;
+
+ if (!ops) {
+ pr_err("Invalid audio ops\n");
+ ret = -EINVAL;
+ goto end;
+ }
+
+ if (state == EXT_DISPLAY_CABLE_CONNECT) {
+ ops->audio_info_setup = msm_ext_disp_audio_info_setup;
+ ops->get_audio_edid_blk = msm_ext_disp_get_audio_edid_blk;
+ ops->cable_status = msm_ext_disp_cable_status;
+ ops->get_intf_id = msm_ext_disp_get_intf_id;
+ ops->teardown_done = msm_ext_disp_teardown_done;
+ } else {
+ ops->audio_info_setup = NULL;
+ ops->get_audio_edid_blk = NULL;
+ ops->cable_status = NULL;
+ ops->get_intf_id = NULL;
+ ops->teardown_done = NULL;
+ }
+end:
+ return ret;
+}
+
static int msm_ext_disp_notify(struct platform_device *pdev,
- enum msm_ext_disp_cable_state new_state)
+ enum msm_ext_disp_cable_state state)
{
int ret = 0;
- int state = 0;
- bool switched;
- struct msm_ext_disp_init_data *data = NULL;
struct msm_ext_disp *ext_disp = NULL;
if (!pdev) {
pr_err("Invalid platform device\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto end;
}
ext_disp = platform_get_drvdata(pdev);
if (!ext_disp) {
pr_err("Invalid drvdata\n");
- return -EINVAL;
- }
-
- mutex_lock(&ext_disp->lock);
-
- if (state < EXT_DISPLAY_CABLE_DISCONNECT ||
- state >= EXT_DISPLAY_CABLE_STATE_MAX) {
- pr_err("Invalid state (%d)\n", state);
ret = -EINVAL;
goto end;
}
- state = ext_disp->audio_sdev.state;
- if (state == new_state)
- goto end;
-
- if (ext_disp->ack_enabled &&
- atomic_read(&ext_disp->ack_pending)) {
+ if (state < EXT_DISPLAY_CABLE_DISCONNECT ||
+ state >= EXT_DISPLAY_CABLE_STATE_MAX) {
+ pr_err("Invalid state (%d)\n", state);
ret = -EINVAL;
- pr_err("%s ack pending, not notifying %s\n",
- state ? "connect" : "disconnect",
- new_state ? "connect" : "disconnect");
goto end;
}
- ret = msm_ext_disp_get_intf_data(ext_disp, ext_disp->current_disp,
- &data);
- if (ret)
- goto end;
-
- if (new_state == EXT_DISPLAY_CABLE_CONNECT && ext_disp->ops) {
- ext_disp->ops->audio_info_setup =
- msm_ext_disp_audio_info_setup;
- ext_disp->ops->get_audio_edid_blk =
- msm_ext_disp_get_audio_edid_blk;
- ext_disp->ops->cable_status =
- msm_ext_disp_cable_status;
- ext_disp->ops->get_intf_id =
- msm_ext_disp_get_intf_id;
- ext_disp->ops->teardown_done =
- msm_ext_disp_teardown_done;
- }
-
- switch_set_state(&ext_disp->audio_sdev, (int)new_state);
- switched = ext_disp->audio_sdev.state != state;
-
- if (ext_disp->ack_enabled && switched)
- atomic_set(&ext_disp->ack_pending, 1);
-
- pr_debug("audio %s %s\n", switched ? "switched to" : "same as",
- ext_disp->audio_sdev.state ? "HDMI" : "SPKR");
+ pr_debug("%s notifying hpd (%d)\n",
+ msm_ext_disp_name(ext_disp->current_disp), state);
+ complete_all(&ext_disp->hpd_comp);
end:
- mutex_unlock(&ext_disp->lock);
-
return ret;
}
static int msm_ext_disp_audio_ack(struct platform_device *pdev, u32 ack)
{
u32 ack_hpd;
- u32 hpd;
int ret = 0;
struct msm_ext_disp *ext_disp = NULL;
@@ -624,10 +703,6 @@ static int msm_ext_disp_audio_ack(struct platform_device *pdev, u32 ack)
return -EINVAL;
}
- mutex_lock(&ext_disp->lock);
-
- hpd = ext_disp->current_disp != EXT_DISPLAY_TYPE_MAX;
-
if (ack & AUDIO_ACK_SET_ENABLE) {
ext_disp->ack_enabled = ack & AUDIO_ACK_ENABLE ?
true : false;
@@ -640,44 +715,14 @@ static int msm_ext_disp_audio_ack(struct platform_device *pdev, u32 ack)
if (!ext_disp->ack_enabled)
goto end;
- atomic_set(&ext_disp->ack_pending, 0);
-
ack_hpd = ack & AUDIO_ACK_CONNECT;
- pr_debug("acknowledging %s\n",
- ack_hpd ? "connect" : "disconnect");
-
- /**
- * If the ack feature is enabled and we receive an ack for
- * disconnect then we reset the current display state to
- * empty.
- */
- if (!ack_hpd) {
- if (ext_disp->ops) {
- ext_disp->ops->audio_info_setup = NULL;
- ext_disp->ops->get_audio_edid_blk = NULL;
- ext_disp->ops->cable_status = NULL;
- ext_disp->ops->get_intf_id = NULL;
- ext_disp->ops->teardown_done = NULL;
- }
-
- ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
- }
-
- if (ack_hpd != hpd) {
- pr_err("unbalanced audio state, ack %d, hpd %d\n",
- ack_hpd, hpd);
-
- mutex_unlock(&ext_disp->lock);
-
- ret = msm_ext_disp_notify(pdev, hpd);
-
- return ret;
- }
+ pr_debug("%s acknowledging audio (%d)\n",
+ msm_ext_disp_name(ext_disp->current_disp), ack_hpd);
+ if (!ext_disp->audio_session_on)
+ complete_all(&ext_disp->hpd_comp);
end:
- mutex_unlock(&ext_disp->lock);
-
return ret;
}
@@ -850,6 +895,7 @@ static int msm_ext_disp_probe(struct platform_device *pdev)
mutex_init(&ext_disp->lock);
INIT_LIST_HEAD(&ext_disp->display_list);
+ init_completion(&ext_disp->hpd_comp);
ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
return ret;
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 7d3e5d0e9aa4..8ab6238c9299 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -73,7 +73,7 @@ struct virtio_balloon {
/* The array of pfns we tell the Host about. */
unsigned int num_pfns;
- u32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX];
+ __virtio32 pfns[VIRTIO_BALLOON_ARRAY_PFNS_MAX];
/* Memory statistics */
int need_stats_update;
@@ -125,14 +125,16 @@ static void tell_host(struct virtio_balloon *vb, struct virtqueue *vq)
wait_event(vb->acked, virtqueue_get_buf(vq, &len));
}
-static void set_page_pfns(u32 pfns[], struct page *page)
+static void set_page_pfns(struct virtio_balloon *vb,
+ __virtio32 pfns[], struct page *page)
{
unsigned int i;
/* Set balloon pfns pointing at this page.
* Note that the first pfn points at start of the page. */
for (i = 0; i < VIRTIO_BALLOON_PAGES_PER_PAGE; i++)
- pfns[i] = page_to_balloon_pfn(page) + i;
+ pfns[i] = cpu_to_virtio32(vb->vdev,
+ page_to_balloon_pfn(page) + i);
}
static void fill_balloon(struct virtio_balloon *vb, size_t num)
@@ -155,7 +157,7 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num)
msleep(200);
break;
}
- set_page_pfns(vb->pfns + vb->num_pfns, page);
+ set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
if (!virtio_has_feature(vb->vdev,
VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
@@ -171,10 +173,12 @@ static void fill_balloon(struct virtio_balloon *vb, size_t num)
static void release_pages_balloon(struct virtio_balloon *vb)
{
unsigned int i;
+ struct page *page;
/* Find pfns pointing at start of each page, get pages and free them. */
for (i = 0; i < vb->num_pfns; i += VIRTIO_BALLOON_PAGES_PER_PAGE) {
- struct page *page = balloon_pfn_to_page(vb->pfns[i]);
+ page = balloon_pfn_to_page(virtio32_to_cpu(vb->vdev,
+ vb->pfns[i]));
if (!virtio_has_feature(vb->vdev,
VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
adjust_managed_page_count(page, 1);
@@ -197,7 +201,7 @@ static unsigned leak_balloon(struct virtio_balloon *vb, size_t num)
page = balloon_page_dequeue(vb_dev_info);
if (!page)
break;
- set_page_pfns(vb->pfns + vb->num_pfns, page);
+ set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
vb->num_pages -= VIRTIO_BALLOON_PAGES_PER_PAGE;
}
@@ -465,13 +469,13 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info,
__count_vm_event(BALLOON_MIGRATE);
spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags);
vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
- set_page_pfns(vb->pfns, newpage);
+ set_page_pfns(vb, vb->pfns, newpage);
tell_host(vb, vb->inflate_vq);
/* balloon's page migration 2nd step -- deflate "page" */
balloon_page_delete(page);
vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE;
- set_page_pfns(vb->pfns, page);
+ set_page_pfns(vb, vb->pfns, page);
tell_host(vb, vb->deflate_vq);
mutex_unlock(&vb->balloon_lock);
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index 364bc44610c1..cfab1d24e4bc 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -152,8 +152,6 @@ static DECLARE_WAIT_QUEUE_HEAD(balloon_wq);
static void balloon_process(struct work_struct *work);
static DECLARE_DELAYED_WORK(balloon_worker, balloon_process);
-static void release_memory_resource(struct resource *resource);
-
/* When ballooning out (allocating memory to return to Xen) we don't really
want the kernel to try too hard since that can trigger the oom killer. */
#define GFP_BALLOON \
@@ -249,6 +247,19 @@ static enum bp_state update_schedule(enum bp_state state)
}
#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
+static void release_memory_resource(struct resource *resource)
+{
+ if (!resource)
+ return;
+
+ /*
+ * No need to reset region to identity mapped since we now
+ * know that no I/O can be in this region
+ */
+ release_resource(resource);
+ kfree(resource);
+}
+
static struct resource *additional_memory_resource(phys_addr_t size)
{
struct resource *res;
@@ -287,19 +298,6 @@ static struct resource *additional_memory_resource(phys_addr_t size)
return res;
}
-static void release_memory_resource(struct resource *resource)
-{
- if (!resource)
- return;
-
- /*
- * No need to reset region to identity mapped since we now
- * know that no I/O can be in this region
- */
- release_resource(resource);
- kfree(resource);
-}
-
static enum bp_state reserve_additional_memory(void)
{
long credit;
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index 44367783f07a..83ec7b89d308 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -487,7 +487,8 @@ static void eoi_pirq(struct irq_data *data)
if (!VALID_EVTCHN(evtchn))
return;
- if (unlikely(irqd_is_setaffinity_pending(data))) {
+ if (unlikely(irqd_is_setaffinity_pending(data)) &&
+ likely(!irqd_irq_disabled(data))) {
int masked = test_and_set_mask(evtchn);
clear_evtchn(evtchn);
@@ -1370,7 +1371,8 @@ static void ack_dynirq(struct irq_data *data)
if (!VALID_EVTCHN(evtchn))
return;
- if (unlikely(irqd_is_setaffinity_pending(data))) {
+ if (unlikely(irqd_is_setaffinity_pending(data)) &&
+ likely(!irqd_irq_disabled(data))) {
int masked = test_and_set_mask(evtchn);
clear_evtchn(evtchn);
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index 70fa438000af..611f9c11da85 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -423,36 +423,7 @@ upload:
return 0;
}
-static int __init check_prereq(void)
-{
- struct cpuinfo_x86 *c = &cpu_data(0);
-
- if (!xen_initial_domain())
- return -ENODEV;
-
- if (!acpi_gbl_FADT.smi_command)
- return -ENODEV;
-
- if (c->x86_vendor == X86_VENDOR_INTEL) {
- if (!cpu_has(c, X86_FEATURE_EST))
- return -ENODEV;
- return 0;
- }
- if (c->x86_vendor == X86_VENDOR_AMD) {
- /* Copied from powernow-k8.h, can't include ../cpufreq/powernow
- * as we get compile warnings for the static functions.
- */
-#define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007
-#define USE_HW_PSTATE 0x00000080
- u32 eax, ebx, ecx, edx;
- cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
- if ((edx & USE_HW_PSTATE) != USE_HW_PSTATE)
- return -ENODEV;
- return 0;
- }
- return -ENODEV;
-}
/* acpi_perf_data is a pointer to percpu data. */
static struct acpi_processor_performance __percpu *acpi_perf_data;
@@ -509,10 +480,10 @@ struct notifier_block xen_acpi_processor_resume_nb = {
static int __init xen_acpi_processor_init(void)
{
unsigned int i;
- int rc = check_prereq();
+ int rc;
- if (rc)
- return rc;
+ if (!xen_initial_domain())
+ return -ENODEV;
nr_acpi_bits = get_max_acpi_id() + 1;
acpi_ids_done = kcalloc(BITS_TO_LONGS(nr_acpi_bits), sizeof(unsigned long), GFP_KERNEL);
diff --git a/fs/affs/super.c b/fs/affs/super.c
index 5b50c4ca43a7..f90c535703ce 100644
--- a/fs/affs/super.c
+++ b/fs/affs/super.c
@@ -528,7 +528,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
char *prefix = NULL;
new_opts = kstrdup(data, GFP_KERNEL);
- if (!new_opts)
+ if (data && !new_opts)
return -ENOMEM;
pr_debug("%s(flags=0x%x,opts=\"%s\")\n", __func__, *flags, data);
@@ -546,7 +546,8 @@ affs_remount(struct super_block *sb, int *flags, char *data)
}
flush_delayed_work(&sbi->sb_work);
- replace_mount_options(sb, new_opts);
+ if (new_opts)
+ replace_mount_options(sb, new_opts);
sbi->s_flags = mount_flags;
sbi->s_mode = mode;
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 5b8e235c4b6d..0f2b7c622ce3 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -1551,6 +1551,7 @@ noinline int btrfs_cow_block(struct btrfs_trans_handle *trans,
trans->transid, root->fs_info->generation);
if (!should_cow_block(trans, root, buf)) {
+ trans->dirty = true;
*cow_ret = buf;
return 0;
}
@@ -2773,8 +2774,10 @@ again:
* then we don't want to set the path blocking,
* so we test it here
*/
- if (!should_cow_block(trans, root, b))
+ if (!should_cow_block(trans, root, b)) {
+ trans->dirty = true;
goto cow_done;
+ }
/*
* must have write locks on this node and the
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 2368cac1115a..47cdc6f3390b 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -7856,7 +7856,7 @@ btrfs_init_new_buffer(struct btrfs_trans_handle *trans, struct btrfs_root *root,
set_extent_dirty(&trans->transaction->dirty_pages, buf->start,
buf->start + buf->len - 1, GFP_NOFS);
}
- trans->blocks_used++;
+ trans->dirty = true;
/* this returns a buffer locked for blocking */
return buf;
}
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index f07d01bc4875..bfcd87ee8ff5 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1648,7 +1648,7 @@ static noinline int btrfs_ioctl_snap_create_transid(struct file *file,
src_inode = file_inode(src.file);
if (src_inode->i_sb != file_inode(file)->i_sb) {
- btrfs_info(BTRFS_I(src_inode)->root->fs_info,
+ btrfs_info(BTRFS_I(file_inode(file))->root->fs_info,
"Snapshot src from another FS");
ret = -EXDEV;
} else if (!inode_owner_or_capable(src_inode)) {
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index fe609b81dd1b..5d34a062ca4f 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -239,7 +239,7 @@ void __btrfs_abort_transaction(struct btrfs_trans_handle *trans,
trans->aborted = errno;
/* Nothing used. The other threads that have joined this
* transaction may be able to continue. */
- if (!trans->blocks_used && list_empty(&trans->new_bgs)) {
+ if (!trans->dirty && list_empty(&trans->new_bgs)) {
const char *errstr;
errstr = btrfs_decode_error(errno);
diff --git a/fs/btrfs/transaction.h b/fs/btrfs/transaction.h
index 64c8221b6165..1e872923ec2c 100644
--- a/fs/btrfs/transaction.h
+++ b/fs/btrfs/transaction.h
@@ -110,7 +110,6 @@ struct btrfs_trans_handle {
u64 chunk_bytes_reserved;
unsigned long use_count;
unsigned long blocks_reserved;
- unsigned long blocks_used;
unsigned long delayed_ref_updates;
struct btrfs_transaction *transaction;
struct btrfs_block_rsv *block_rsv;
@@ -121,6 +120,7 @@ struct btrfs_trans_handle {
bool can_flush_pending_bgs;
bool reloc_reserved;
bool sync;
+ bool dirty;
unsigned int type;
/*
* this root is only needed to validate that the root passed to
diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c
index 5a53ac6b1e02..02b071bf3732 100644
--- a/fs/cifs/cifs_unicode.c
+++ b/fs/cifs/cifs_unicode.c
@@ -101,6 +101,12 @@ convert_sfm_char(const __u16 src_char, char *target)
case SFM_SLASH:
*target = '\\';
break;
+ case SFM_SPACE:
+ *target = ' ';
+ break;
+ case SFM_PERIOD:
+ *target = '.';
+ break;
default:
return false;
}
@@ -404,7 +410,7 @@ static __le16 convert_to_sfu_char(char src_char)
return dest_char;
}
-static __le16 convert_to_sfm_char(char src_char)
+static __le16 convert_to_sfm_char(char src_char, bool end_of_string)
{
__le16 dest_char;
@@ -427,6 +433,18 @@ static __le16 convert_to_sfm_char(char src_char)
case '|':
dest_char = cpu_to_le16(SFM_PIPE);
break;
+ case '.':
+ if (end_of_string)
+ dest_char = cpu_to_le16(SFM_PERIOD);
+ else
+ dest_char = 0;
+ break;
+ case ' ':
+ if (end_of_string)
+ dest_char = cpu_to_le16(SFM_SPACE);
+ else
+ dest_char = 0;
+ break;
default:
dest_char = 0;
}
@@ -469,9 +487,16 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
/* see if we must remap this char */
if (map_chars == SFU_MAP_UNI_RSVD)
dst_char = convert_to_sfu_char(src_char);
- else if (map_chars == SFM_MAP_UNI_RSVD)
- dst_char = convert_to_sfm_char(src_char);
- else
+ else if (map_chars == SFM_MAP_UNI_RSVD) {
+ bool end_of_string;
+
+ if (i == srclen - 1)
+ end_of_string = true;
+ else
+ end_of_string = false;
+
+ dst_char = convert_to_sfm_char(src_char, end_of_string);
+ } else
dst_char = 0;
/*
* FIXME: We can not handle remapping backslash (UNI_SLASH)
diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h
index bdc52cb9a676..479bc0a941f3 100644
--- a/fs/cifs/cifs_unicode.h
+++ b/fs/cifs/cifs_unicode.h
@@ -64,6 +64,8 @@
#define SFM_LESSTHAN ((__u16) 0xF023)
#define SFM_PIPE ((__u16) 0xF027)
#define SFM_SLASH ((__u16) 0xF026)
+#define SFM_PERIOD ((__u16) 0xF028)
+#define SFM_SPACE ((__u16) 0xF029)
/*
* Mapping mechanism to use when one of the seven reserved characters is
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 3c194ff0d2f0..5481a6eb9a95 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -425,7 +425,9 @@ cifs_echo_request(struct work_struct *work)
* server->ops->need_neg() == true. Also, no need to ping if
* we got a response recently.
*/
- if (!server->ops->need_neg || server->ops->need_neg(server) ||
+
+ if (server->tcpStatus == CifsNeedReconnect ||
+ server->tcpStatus == CifsExiting || server->tcpStatus == CifsNew ||
(server->ops->can_echo && !server->ops->can_echo(server)) ||
time_before(jiffies, server->lstrp + SMB_ECHO_INTERVAL - HZ))
goto requeue_echo;
diff --git a/fs/cifs/ntlmssp.h b/fs/cifs/ntlmssp.h
index 848249fa120f..3079b38f0afb 100644
--- a/fs/cifs/ntlmssp.h
+++ b/fs/cifs/ntlmssp.h
@@ -133,6 +133,6 @@ typedef struct _AUTHENTICATE_MESSAGE {
int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses);
void build_ntlmssp_negotiate_blob(unsigned char *pbuffer, struct cifs_ses *ses);
-int build_ntlmssp_auth_blob(unsigned char *pbuffer, u16 *buflen,
+int build_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
struct cifs_ses *ses,
const struct nls_table *nls_cp);
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 59727e32ed0f..e88ffe1da045 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -364,19 +364,43 @@ void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
sec_blob->DomainName.MaximumLength = 0;
}
-/* We do not malloc the blob, it is passed in pbuffer, because its
- maximum possible size is fixed and small, making this approach cleaner.
- This function returns the length of the data in the blob */
-int build_ntlmssp_auth_blob(unsigned char *pbuffer,
+static int size_of_ntlmssp_blob(struct cifs_ses *ses)
+{
+ int sz = sizeof(AUTHENTICATE_MESSAGE) + ses->auth_key.len
+ - CIFS_SESS_KEY_SIZE + CIFS_CPHTXT_SIZE + 2;
+
+ if (ses->domainName)
+ sz += 2 * strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN);
+ else
+ sz += 2;
+
+ if (ses->user_name)
+ sz += 2 * strnlen(ses->user_name, CIFS_MAX_USERNAME_LEN);
+ else
+ sz += 2;
+
+ return sz;
+}
+
+int build_ntlmssp_auth_blob(unsigned char **pbuffer,
u16 *buflen,
struct cifs_ses *ses,
const struct nls_table *nls_cp)
{
int rc;
- AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
+ AUTHENTICATE_MESSAGE *sec_blob;
__u32 flags;
unsigned char *tmp;
+ rc = setup_ntlmv2_rsp(ses, nls_cp);
+ if (rc) {
+ cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
+ *buflen = 0;
+ goto setup_ntlmv2_ret;
+ }
+ *pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL);
+ sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer;
+
memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
sec_blob->MessageType = NtLmAuthenticate;
@@ -391,7 +415,7 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
flags |= NTLMSSP_NEGOTIATE_KEY_XCH;
}
- tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE);
+ tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
sec_blob->NegotiateFlags = cpu_to_le32(flags);
sec_blob->LmChallengeResponse.BufferOffset =
@@ -399,23 +423,27 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
sec_blob->LmChallengeResponse.Length = 0;
sec_blob->LmChallengeResponse.MaximumLength = 0;
- sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
- rc = setup_ntlmv2_rsp(ses, nls_cp);
- if (rc) {
- cifs_dbg(VFS, "Error %d during NTLMSSP authentication\n", rc);
- goto setup_ntlmv2_ret;
+ sec_blob->NtChallengeResponse.BufferOffset =
+ cpu_to_le32(tmp - *pbuffer);
+ if (ses->user_name != NULL) {
+ memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
+ ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+ tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
+
+ sec_blob->NtChallengeResponse.Length =
+ cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+ sec_blob->NtChallengeResponse.MaximumLength =
+ cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+ } else {
+ /*
+ * don't send an NT Response for anonymous access
+ */
+ sec_blob->NtChallengeResponse.Length = 0;
+ sec_blob->NtChallengeResponse.MaximumLength = 0;
}
- memcpy(tmp, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
- ses->auth_key.len - CIFS_SESS_KEY_SIZE);
- tmp += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
-
- sec_blob->NtChallengeResponse.Length =
- cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
- sec_blob->NtChallengeResponse.MaximumLength =
- cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
if (ses->domainName == NULL) {
- sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
sec_blob->DomainName.Length = 0;
sec_blob->DomainName.MaximumLength = 0;
tmp += 2;
@@ -424,14 +452,14 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName,
CIFS_MAX_USERNAME_LEN, nls_cp);
len *= 2; /* unicode is 2 bytes each */
- sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
sec_blob->DomainName.Length = cpu_to_le16(len);
sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
tmp += len;
}
if (ses->user_name == NULL) {
- sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
sec_blob->UserName.Length = 0;
sec_blob->UserName.MaximumLength = 0;
tmp += 2;
@@ -440,13 +468,13 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name,
CIFS_MAX_USERNAME_LEN, nls_cp);
len *= 2; /* unicode is 2 bytes each */
- sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
sec_blob->UserName.Length = cpu_to_le16(len);
sec_blob->UserName.MaximumLength = cpu_to_le16(len);
tmp += len;
}
- sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - *pbuffer);
sec_blob->WorkstationName.Length = 0;
sec_blob->WorkstationName.MaximumLength = 0;
tmp += 2;
@@ -455,19 +483,19 @@ int build_ntlmssp_auth_blob(unsigned char *pbuffer,
(ses->ntlmssp->server_flags & NTLMSSP_NEGOTIATE_EXTENDED_SEC))
&& !calc_seckey(ses)) {
memcpy(tmp, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE);
- sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
sec_blob->SessionKey.Length = cpu_to_le16(CIFS_CPHTXT_SIZE);
sec_blob->SessionKey.MaximumLength =
cpu_to_le16(CIFS_CPHTXT_SIZE);
tmp += CIFS_CPHTXT_SIZE;
} else {
- sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - *pbuffer);
sec_blob->SessionKey.Length = 0;
sec_blob->SessionKey.MaximumLength = 0;
}
+ *buflen = tmp - *pbuffer;
setup_ntlmv2_ret:
- *buflen = tmp - pbuffer;
return rc;
}
@@ -670,20 +698,24 @@ sess_auth_lanman(struct sess_data *sess_data)
pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE;
- /* no capabilities flags in old lanman negotiation */
- pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
-
- /* Calculate hash with password and copy into bcc_ptr.
- * Encryption Key (stored as in cryptkey) gets used if the
- * security mode bit in Negottiate Protocol response states
- * to use challenge/response method (i.e. Password bit is 1).
- */
- rc = calc_lanman_hash(ses->password, ses->server->cryptkey,
- ses->server->sec_mode & SECMODE_PW_ENCRYPT ?
- true : false, lnm_session_key);
-
- memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE);
- bcc_ptr += CIFS_AUTH_RESP_SIZE;
+ if (ses->user_name != NULL) {
+ /* no capabilities flags in old lanman negotiation */
+ pSMB->old_req.PasswordLength = cpu_to_le16(CIFS_AUTH_RESP_SIZE);
+
+ /* Calculate hash with password and copy into bcc_ptr.
+ * Encryption Key (stored as in cryptkey) gets used if the
+ * security mode bit in Negottiate Protocol response states
+ * to use challenge/response method (i.e. Password bit is 1).
+ */
+ rc = calc_lanman_hash(ses->password, ses->server->cryptkey,
+ ses->server->sec_mode & SECMODE_PW_ENCRYPT ?
+ true : false, lnm_session_key);
+
+ memcpy(bcc_ptr, (char *)lnm_session_key, CIFS_AUTH_RESP_SIZE);
+ bcc_ptr += CIFS_AUTH_RESP_SIZE;
+ } else {
+ pSMB->old_req.PasswordLength = 0;
+ }
/*
* can not sign if LANMAN negotiated so no need
@@ -769,27 +801,32 @@ sess_auth_ntlm(struct sess_data *sess_data)
capabilities = cifs_ssetup_hdr(ses, pSMB);
pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
- pSMB->req_no_secext.CaseInsensitivePasswordLength =
- cpu_to_le16(CIFS_AUTH_RESP_SIZE);
- pSMB->req_no_secext.CaseSensitivePasswordLength =
- cpu_to_le16(CIFS_AUTH_RESP_SIZE);
+ if (ses->user_name != NULL) {
+ pSMB->req_no_secext.CaseInsensitivePasswordLength =
+ cpu_to_le16(CIFS_AUTH_RESP_SIZE);
+ pSMB->req_no_secext.CaseSensitivePasswordLength =
+ cpu_to_le16(CIFS_AUTH_RESP_SIZE);
+
+ /* calculate ntlm response and session key */
+ rc = setup_ntlm_response(ses, sess_data->nls_cp);
+ if (rc) {
+ cifs_dbg(VFS, "Error %d during NTLM authentication\n",
+ rc);
+ goto out;
+ }
- /* calculate ntlm response and session key */
- rc = setup_ntlm_response(ses, sess_data->nls_cp);
- if (rc) {
- cifs_dbg(VFS, "Error %d during NTLM authentication\n",
- rc);
- goto out;
+ /* copy ntlm response */
+ memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
+ CIFS_AUTH_RESP_SIZE);
+ bcc_ptr += CIFS_AUTH_RESP_SIZE;
+ memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
+ CIFS_AUTH_RESP_SIZE);
+ bcc_ptr += CIFS_AUTH_RESP_SIZE;
+ } else {
+ pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
+ pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
}
- /* copy ntlm response */
- memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
- CIFS_AUTH_RESP_SIZE);
- bcc_ptr += CIFS_AUTH_RESP_SIZE;
- memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
- CIFS_AUTH_RESP_SIZE);
- bcc_ptr += CIFS_AUTH_RESP_SIZE;
-
if (ses->capabilities & CAP_UNICODE) {
/* unicode strings must be word aligned */
if (sess_data->iov[0].iov_len % 2) {
@@ -878,22 +915,26 @@ sess_auth_ntlmv2(struct sess_data *sess_data)
/* LM2 password would be here if we supported it */
pSMB->req_no_secext.CaseInsensitivePasswordLength = 0;
- /* calculate nlmv2 response and session key */
- rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp);
- if (rc) {
- cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc);
- goto out;
- }
+ if (ses->user_name != NULL) {
+ /* calculate nlmv2 response and session key */
+ rc = setup_ntlmv2_rsp(ses, sess_data->nls_cp);
+ if (rc) {
+ cifs_dbg(VFS, "Error %d during NTLMv2 authentication\n", rc);
+ goto out;
+ }
- memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
- ses->auth_key.len - CIFS_SESS_KEY_SIZE);
- bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
+ memcpy(bcc_ptr, ses->auth_key.response + CIFS_SESS_KEY_SIZE,
+ ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+ bcc_ptr += ses->auth_key.len - CIFS_SESS_KEY_SIZE;
- /* set case sensitive password length after tilen may get
- * assigned, tilen is 0 otherwise.
- */
- pSMB->req_no_secext.CaseSensitivePasswordLength =
- cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+ /* set case sensitive password length after tilen may get
+ * assigned, tilen is 0 otherwise.
+ */
+ pSMB->req_no_secext.CaseSensitivePasswordLength =
+ cpu_to_le16(ses->auth_key.len - CIFS_SESS_KEY_SIZE);
+ } else {
+ pSMB->req_no_secext.CaseSensitivePasswordLength = 0;
+ }
if (ses->capabilities & CAP_UNICODE) {
if (sess_data->iov[0].iov_len % 2) {
@@ -1245,7 +1286,7 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
struct cifs_ses *ses = sess_data->ses;
__u16 bytes_remaining;
char *bcc_ptr;
- char *ntlmsspblob = NULL;
+ unsigned char *ntlmsspblob = NULL;
u16 blob_len;
cifs_dbg(FYI, "rawntlmssp session setup authenticate phase\n");
@@ -1258,19 +1299,7 @@ sess_auth_rawntlmssp_authenticate(struct sess_data *sess_data)
/* Build security blob before we assemble the request */
pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
smb_buf = (struct smb_hdr *)pSMB;
- /*
- * 5 is an empirical value, large enough to hold
- * authenticate message plus max 10 of av paris,
- * domain, user, workstation names, flags, etc.
- */
- ntlmsspblob = kzalloc(5*sizeof(struct _AUTHENTICATE_MESSAGE),
- GFP_KERNEL);
- if (!ntlmsspblob) {
- rc = -ENOMEM;
- goto out;
- }
-
- rc = build_ntlmssp_auth_blob(ntlmsspblob,
+ rc = build_ntlmssp_auth_blob(&ntlmsspblob,
&blob_len, ses, sess_data->nls_cp);
if (rc)
goto out_free_ntlmsspblob;
diff --git a/fs/cifs/smb2glob.h b/fs/cifs/smb2glob.h
index bc0bb9c34f72..0ffa18094335 100644
--- a/fs/cifs/smb2glob.h
+++ b/fs/cifs/smb2glob.h
@@ -44,6 +44,7 @@
#define SMB2_OP_DELETE 7
#define SMB2_OP_HARDLINK 8
#define SMB2_OP_SET_EOF 9
+#define SMB2_OP_RMDIR 10
/* Used when constructing chained read requests. */
#define CHAINED_REQUEST 1
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index 899bbc86f73e..4f0231e685a9 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -80,6 +80,10 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
* SMB2_open() call.
*/
break;
+ case SMB2_OP_RMDIR:
+ tmprc = SMB2_rmdir(xid, tcon, fid.persistent_fid,
+ fid.volatile_fid);
+ break;
case SMB2_OP_RENAME:
tmprc = SMB2_rename(xid, tcon, fid.persistent_fid,
fid.volatile_fid, (__le16 *)data);
@@ -191,8 +195,8 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
struct cifs_sb_info *cifs_sb)
{
return smb2_open_op_close(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
- CREATE_NOT_FILE | CREATE_DELETE_ON_CLOSE,
- NULL, SMB2_OP_DELETE);
+ CREATE_NOT_FILE,
+ NULL, SMB2_OP_RMDIR);
}
int
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 373b5cd1c913..0b6dc1942bdc 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -591,7 +591,7 @@ SMB2_sess_setup(const unsigned int xid, struct cifs_ses *ses,
u16 blob_length = 0;
struct key *spnego_key = NULL;
char *security_blob = NULL;
- char *ntlmssp_blob = NULL;
+ unsigned char *ntlmssp_blob = NULL;
bool use_spnego = false; /* else use raw ntlmssp */
cifs_dbg(FYI, "Session Setup\n");
@@ -716,13 +716,7 @@ ssetup_ntlmssp_authenticate:
iov[1].iov_len = blob_length;
} else if (phase == NtLmAuthenticate) {
req->hdr.SessionId = ses->Suid;
- ntlmssp_blob = kzalloc(sizeof(struct _NEGOTIATE_MESSAGE) + 500,
- GFP_KERNEL);
- if (ntlmssp_blob == NULL) {
- rc = -ENOMEM;
- goto ssetup_exit;
- }
- rc = build_ntlmssp_auth_blob(ntlmssp_blob, &blob_length, ses,
+ rc = build_ntlmssp_auth_blob(&ntlmssp_blob, &blob_length, ses,
nls_cp);
if (rc) {
cifs_dbg(FYI, "build_ntlmssp_auth_blob failed %d\n",
@@ -1820,6 +1814,33 @@ SMB2_echo(struct TCP_Server_Info *server)
cifs_dbg(FYI, "In echo request\n");
+ if (server->tcpStatus == CifsNeedNegotiate) {
+ struct list_head *tmp, *tmp2;
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+
+ cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n");
+ spin_lock(&cifs_tcp_ses_lock);
+ list_for_each(tmp, &server->smb_ses_list) {
+ ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
+ list_for_each(tmp2, &ses->tcon_list) {
+ tcon = list_entry(tmp2, struct cifs_tcon,
+ tcon_list);
+ /* add check for persistent handle reconnect */
+ if (tcon && tcon->need_reconnect) {
+ spin_unlock(&cifs_tcp_ses_lock);
+ rc = smb2_reconnect(SMB2_ECHO, tcon);
+ spin_lock(&cifs_tcp_ses_lock);
+ }
+ }
+ }
+ spin_unlock(&cifs_tcp_ses_lock);
+ }
+
+ /* if no session, renegotiate failed above */
+ if (server->tcpStatus == CifsNeedNegotiate)
+ return -EIO;
+
rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req);
if (rc)
return rc;
@@ -2577,6 +2598,22 @@ SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
}
int
+SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid)
+{
+ __u8 delete_pending = 1;
+ void *data;
+ unsigned int size;
+
+ data = &delete_pending;
+ size = 1; /* sizeof __u8 */
+
+ return send_set_info(xid, tcon, persistent_fid, volatile_fid,
+ current->tgid, FILE_DISPOSITION_INFORMATION, 1, &data,
+ &size);
+}
+
+int
SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, __le16 *target_file)
{
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 79dc650c18b2..9bc59f9c12fb 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -140,6 +140,8 @@ extern int SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
extern int SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid,
__le16 *target_file);
+extern int SMB2_rmdir(const unsigned int xid, struct cifs_tcon *tcon,
+ u64 persistent_fid, u64 volatile_fid);
extern int SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid,
__le16 *target_file);
diff --git a/fs/dcache.c b/fs/dcache.c
index 240935d77844..d04920036269 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -1618,7 +1618,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
struct dentry *dentry = __d_alloc(parent->d_sb, name);
if (!dentry)
return NULL;
-
+ dentry->d_flags |= DCACHE_RCUACCESS;
spin_lock(&parent->d_lock);
/*
* don't need child lock because it is not subject
@@ -2413,7 +2413,6 @@ static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b)
{
BUG_ON(!d_unhashed(entry));
hlist_bl_lock(b);
- entry->d_flags |= DCACHE_RCUACCESS;
hlist_bl_add_head_rcu(&entry->d_hash, b);
hlist_bl_unlock(b);
}
@@ -2632,6 +2631,7 @@ static void __d_move(struct dentry *dentry, struct dentry *target,
/* ... and switch them in the tree */
if (IS_ROOT(dentry)) {
/* splicing a tree */
+ dentry->d_flags |= DCACHE_RCUACCESS;
dentry->d_parent = target->d_parent;
target->d_parent = target;
list_del_init(&target->d_child);
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 4c999ce7e73a..3ab9c68b8bce 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1588,7 +1588,7 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
{
int res = 0, eavail, timed_out = 0;
unsigned long flags;
- long slack = 0;
+ u64 slack = 0;
wait_queue_t wait;
ktime_t expires, *to = NULL;
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 53f2b98a69f3..5388207d2832 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1143,25 +1143,20 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
unsigned long max_ino = le32_to_cpu(EXT4_SB(sb)->s_es->s_inodes_count);
ext4_group_t block_group;
int bit;
- struct buffer_head *bitmap_bh;
+ struct buffer_head *bitmap_bh = NULL;
struct inode *inode = NULL;
- long err = -EIO;
+ int err = -EFSCORRUPTED;
- /* Error cases - e2fsck has already cleaned up for us */
- if (ino > max_ino) {
- ext4_warning(sb, "bad orphan ino %lu! e2fsck was run?", ino);
- err = -EFSCORRUPTED;
- goto error;
- }
+ if (ino < EXT4_FIRST_INO(sb) || ino > max_ino)
+ goto bad_orphan;
block_group = (ino - 1) / EXT4_INODES_PER_GROUP(sb);
bit = (ino - 1) % EXT4_INODES_PER_GROUP(sb);
bitmap_bh = ext4_read_inode_bitmap(sb, block_group);
if (IS_ERR(bitmap_bh)) {
- err = PTR_ERR(bitmap_bh);
- ext4_warning(sb, "inode bitmap error %ld for orphan %lu",
- ino, err);
- goto error;
+ ext4_error(sb, "inode bitmap error %ld for orphan %lu",
+ ino, PTR_ERR(bitmap_bh));
+ return (struct inode *) bitmap_bh;
}
/* Having the inode bit set should be a 100% indicator that this
@@ -1172,15 +1167,21 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
goto bad_orphan;
inode = ext4_iget(sb, ino);
- if (IS_ERR(inode))
- goto iget_failed;
+ if (IS_ERR(inode)) {
+ err = PTR_ERR(inode);
+ ext4_error(sb, "couldn't read orphan inode %lu (err %d)",
+ ino, err);
+ return inode;
+ }
/*
- * If the orphans has i_nlinks > 0 then it should be able to be
- * truncated, otherwise it won't be removed from the orphan list
- * during processing and an infinite loop will result.
+ * If the orphans has i_nlinks > 0 then it should be able to
+ * be truncated, otherwise it won't be removed from the orphan
+ * list during processing and an infinite loop will result.
+ * Similarly, it must not be a bad inode.
*/
- if (inode->i_nlink && !ext4_can_truncate(inode))
+ if ((inode->i_nlink && !ext4_can_truncate(inode)) ||
+ is_bad_inode(inode))
goto bad_orphan;
if (NEXT_ORPHAN(inode) > max_ino)
@@ -1188,29 +1189,25 @@ struct inode *ext4_orphan_get(struct super_block *sb, unsigned long ino)
brelse(bitmap_bh);
return inode;
-iget_failed:
- err = PTR_ERR(inode);
- inode = NULL;
bad_orphan:
- ext4_warning(sb, "bad orphan inode %lu! e2fsck was run?", ino);
- printk(KERN_WARNING "ext4_test_bit(bit=%d, block=%llu) = %d\n",
- bit, (unsigned long long)bitmap_bh->b_blocknr,
- ext4_test_bit(bit, bitmap_bh->b_data));
- printk(KERN_WARNING "inode=%p\n", inode);
+ ext4_error(sb, "bad orphan inode %lu", ino);
+ if (bitmap_bh)
+ printk(KERN_ERR "ext4_test_bit(bit=%d, block=%llu) = %d\n",
+ bit, (unsigned long long)bitmap_bh->b_blocknr,
+ ext4_test_bit(bit, bitmap_bh->b_data));
if (inode) {
- printk(KERN_WARNING "is_bad_inode(inode)=%d\n",
+ printk(KERN_ERR "is_bad_inode(inode)=%d\n",
is_bad_inode(inode));
- printk(KERN_WARNING "NEXT_ORPHAN(inode)=%u\n",
+ printk(KERN_ERR "NEXT_ORPHAN(inode)=%u\n",
NEXT_ORPHAN(inode));
- printk(KERN_WARNING "max_ino=%lu\n", max_ino);
- printk(KERN_WARNING "i_nlink=%u\n", inode->i_nlink);
+ printk(KERN_ERR "max_ino=%lu\n", max_ino);
+ printk(KERN_ERR "i_nlink=%u\n", inode->i_nlink);
/* Avoid freeing blocks if we got a bad deleted inode */
if (inode->i_nlink == 0)
inode->i_blocks = 0;
iput(inode);
}
brelse(bitmap_bh);
-error:
return ERR_PTR(err);
}
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index a235f3c20433..2f53c3822daa 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -1259,6 +1259,7 @@ static void ext4_mb_unload_buddy(struct ext4_buddy *e4b)
static int mb_find_order_for_block(struct ext4_buddy *e4b, int block)
{
int order = 1;
+ int bb_incr = 1 << (e4b->bd_blkbits - 1);
void *bb;
BUG_ON(e4b->bd_bitmap == e4b->bd_buddy);
@@ -1271,7 +1272,8 @@ static int mb_find_order_for_block(struct ext4_buddy *e4b, int block)
/* this block is part of buddy of order 'order' */
return order;
}
- bb += 1 << (e4b->bd_blkbits - order);
+ bb += bb_incr;
+ bb_incr >>= 1;
order++;
}
return 0;
@@ -2576,7 +2578,7 @@ int ext4_mb_init(struct super_block *sb)
{
struct ext4_sb_info *sbi = EXT4_SB(sb);
unsigned i, j;
- unsigned offset;
+ unsigned offset, offset_incr;
unsigned max;
int ret;
@@ -2605,11 +2607,13 @@ int ext4_mb_init(struct super_block *sb)
i = 1;
offset = 0;
+ offset_incr = 1 << (sb->s_blocksize_bits - 1);
max = sb->s_blocksize << 2;
do {
sbi->s_mb_offsets[i] = offset;
sbi->s_mb_maxs[i] = max;
- offset += 1 << (sb->s_blocksize_bits - i);
+ offset += offset_incr;
+ offset_incr = offset_incr >> 1;
max = max >> 1;
i++;
} while (i <= sb->s_blocksize_bits + 1);
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 9bdbf98240a0..796ff0eafd3c 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -390,6 +390,7 @@ data_copy:
*err = ext4_get_block(orig_inode, orig_blk_offset + i, bh, 0);
if (*err < 0)
break;
+ bh = bh->b_this_page;
}
if (!*err)
*err = block_commit_write(pagep[0], from, from + replaced_size);
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index c9aad3b8951f..d5a634ed6c93 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -2824,7 +2824,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode)
* list entries can cause panics at unmount time.
*/
mutex_lock(&sbi->s_orphan_lock);
- list_del(&EXT4_I(inode)->i_orphan);
+ list_del_init(&EXT4_I(inode)->i_orphan);
mutex_unlock(&sbi->s_orphan_lock);
}
}
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 1398674f0614..5f83efb824a3 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -14,6 +14,7 @@
#include <linux/poll.h>
#include <linux/uio.h>
#include <linux/miscdevice.h>
+#include <linux/namei.h>
#include <linux/pagemap.h>
#include <linux/file.h>
#include <linux/slab.h>
@@ -1941,6 +1942,10 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
cs->move_pages = 0;
err = copy_out_args(cs, &req->out, nbytes);
+ if (req->in.h.opcode == FUSE_CANONICAL_PATH) {
+ req->out.h.error = kern_path((char *)req->out.args[0].value, 0,
+ req->canonical_path);
+ }
fuse_copy_finish(cs);
fuse_setup_passthrough(fc, req);
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 640f66719314..48fb86bc153d 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -267,6 +267,50 @@ invalid:
goto out;
}
+/*
+ * Get the canonical path. Since we must translate to a path, this must be done
+ * in the context of the userspace daemon, however, the userspace daemon cannot
+ * look up paths on its own. Instead, we handle the lookup as a special case
+ * inside of the write request.
+ */
+static void fuse_dentry_canonical_path(const struct path *path, struct path *canonical_path) {
+ struct inode *inode = path->dentry->d_inode;
+ struct fuse_conn *fc = get_fuse_conn(inode);
+ struct fuse_req *req;
+ int err;
+ char *path_name;
+
+ req = fuse_get_req(fc, 1);
+ err = PTR_ERR(req);
+ if (IS_ERR(req))
+ goto default_path;
+
+ path_name = (char*)__get_free_page(GFP_KERNEL);
+ if (!path_name) {
+ fuse_put_request(fc, req);
+ goto default_path;
+ }
+
+ req->in.h.opcode = FUSE_CANONICAL_PATH;
+ req->in.h.nodeid = get_node_id(inode);
+ req->in.numargs = 0;
+ req->out.numargs = 1;
+ req->out.args[0].size = PATH_MAX;
+ req->out.args[0].value = path_name;
+ req->canonical_path = canonical_path;
+ req->out.argvar = 1;
+ fuse_request_send(fc, req);
+ err = req->out.h.error;
+ fuse_put_request(fc, req);
+ free_page((unsigned long)path_name);
+ if (!err)
+ return;
+default_path:
+ canonical_path->dentry = path->dentry;
+ canonical_path->mnt = path->mnt;
+ path_get(canonical_path);
+}
+
static int invalid_nodeid(u64 nodeid)
{
return !nodeid || nodeid == FUSE_ROOT_ID;
@@ -274,6 +318,7 @@ static int invalid_nodeid(u64 nodeid)
const struct dentry_operations fuse_dentry_operations = {
.d_revalidate = fuse_dentry_revalidate,
+ .d_canonical_path = fuse_dentry_canonical_path,
};
int fuse_valid_type(int m)
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 0cbeea6ee831..1cc0dce47a2f 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -377,6 +377,9 @@ struct fuse_req {
/** Inode used in the request or NULL */
struct inode *inode;
+ /** Path used for completing d_canonical_path */
+ struct path *canonical_path;
+
/** AIO control block */
struct fuse_io_priv *io;
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c
index a561591896bd..3713fd52b44b 100644
--- a/fs/hpfs/super.c
+++ b/fs/hpfs/super.c
@@ -15,6 +15,7 @@
#include <linux/sched.h>
#include <linux/bitmap.h>
#include <linux/slab.h>
+#include <linux/seq_file.h>
/* Mark the filesystem dirty, so that chkdsk checks it when os/2 booted */
@@ -453,10 +454,6 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
int lowercase, eas, chk, errs, chkdsk, timeshift;
int o;
struct hpfs_sb_info *sbi = hpfs_sb(s);
- char *new_opts = kstrdup(data, GFP_KERNEL);
-
- if (!new_opts)
- return -ENOMEM;
sync_filesystem(s);
@@ -493,17 +490,44 @@ static int hpfs_remount_fs(struct super_block *s, int *flags, char *data)
if (!(*flags & MS_RDONLY)) mark_dirty(s, 1);
- replace_mount_options(s, new_opts);
-
hpfs_unlock(s);
return 0;
out_err:
hpfs_unlock(s);
- kfree(new_opts);
return -EINVAL;
}
+static int hpfs_show_options(struct seq_file *seq, struct dentry *root)
+{
+ struct hpfs_sb_info *sbi = hpfs_sb(root->d_sb);
+
+ seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, sbi->sb_uid));
+ seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, sbi->sb_gid));
+ seq_printf(seq, ",umask=%03o", (~sbi->sb_mode & 0777));
+ if (sbi->sb_lowercase)
+ seq_printf(seq, ",case=lower");
+ if (!sbi->sb_chk)
+ seq_printf(seq, ",check=none");
+ if (sbi->sb_chk == 2)
+ seq_printf(seq, ",check=strict");
+ if (!sbi->sb_err)
+ seq_printf(seq, ",errors=continue");
+ if (sbi->sb_err == 2)
+ seq_printf(seq, ",errors=panic");
+ if (!sbi->sb_chkdsk)
+ seq_printf(seq, ",chkdsk=no");
+ if (sbi->sb_chkdsk == 2)
+ seq_printf(seq, ",chkdsk=always");
+ if (!sbi->sb_eas)
+ seq_printf(seq, ",eas=no");
+ if (sbi->sb_eas == 1)
+ seq_printf(seq, ",eas=ro");
+ if (sbi->sb_timeshift)
+ seq_printf(seq, ",timeshift=%d", sbi->sb_timeshift);
+ return 0;
+}
+
/* Super operations */
static const struct super_operations hpfs_sops =
@@ -514,7 +538,7 @@ static const struct super_operations hpfs_sops =
.put_super = hpfs_put_super,
.statfs = hpfs_statfs,
.remount_fs = hpfs_remount_fs,
- .show_options = generic_show_options,
+ .show_options = hpfs_show_options,
};
static int hpfs_fill_super(struct super_block *s, void *options, int silent)
@@ -537,8 +561,6 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
int o;
- save_mount_options(s, options);
-
sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
if (!sbi) {
return -ENOMEM;
diff --git a/fs/namespace.c b/fs/namespace.c
index 0570729c87fd..33064fcbfff9 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2401,8 +2401,10 @@ static int do_new_mount(struct path *path, const char *fstype, int flags,
mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV;
}
if (type->fs_flags & FS_USERNS_VISIBLE) {
- if (!fs_fully_visible(type, &mnt_flags))
+ if (!fs_fully_visible(type, &mnt_flags)) {
+ put_filesystem(type);
return -EPERM;
+ }
}
}
@@ -3236,6 +3238,10 @@ static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
if (mnt->mnt.mnt_sb->s_iflags & SB_I_NOEXEC)
mnt_flags &= ~(MNT_LOCK_NOSUID | MNT_LOCK_NOEXEC);
+ /* Don't miss readonly hidden in the superblock flags */
+ if (mnt->mnt.mnt_sb->s_flags & MS_RDONLY)
+ mnt_flags |= MNT_LOCK_READONLY;
+
/* Verify the mount flags are equal to or more permissive
* than the proposed new mount.
*/
@@ -3262,7 +3268,7 @@ static bool fs_fully_visible(struct file_system_type *type, int *new_mnt_flags)
list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
struct inode *inode = child->mnt_mountpoint->d_inode;
/* Only worry about locked mounts */
- if (!(mnt_flags & MNT_LOCKED))
+ if (!(child->mnt.mnt_flags & MNT_LOCKED))
continue;
/* Is the directory permanetly empty? */
if (!is_empty_dir_inode(inode))
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 5fc2162afb67..46cfed63d229 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1531,9 +1531,9 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
err = PTR_ERR(inode);
trace_nfs_atomic_open_exit(dir, ctx, open_flags, err);
put_nfs_open_context(ctx);
+ d_drop(dentry);
switch (err) {
case -ENOENT:
- d_drop(dentry);
d_add(dentry, NULL);
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
break;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 98a44157353a..fc215ab4dcd5 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2854,12 +2854,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
call_close |= is_wronly;
else if (is_wronly)
calldata->arg.fmode |= FMODE_WRITE;
+ if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE))
+ call_close |= is_rdwr;
} else if (is_rdwr)
calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;
- if (calldata->arg.fmode == 0)
- call_close |= is_rdwr;
-
if (!nfs4_valid_open_stateid(state))
call_close = 0;
spin_unlock(&state->owner->so_lock);
diff --git a/fs/nfsd/nfs2acl.c b/fs/nfsd/nfs2acl.c
index 1580ea6fd64d..d08cd88155c7 100644
--- a/fs/nfsd/nfs2acl.c
+++ b/fs/nfsd/nfs2acl.c
@@ -104,22 +104,21 @@ static __be32 nfsacld_proc_setacl(struct svc_rqst * rqstp,
goto out;
inode = d_inode(fh->fh_dentry);
- if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) {
- error = -EOPNOTSUPP;
- goto out_errno;
- }
error = fh_want_write(fh);
if (error)
goto out_errno;
- error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS);
+ fh_lock(fh);
+
+ error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access);
if (error)
- goto out_drop_write;
- error = inode->i_op->set_acl(inode, argp->acl_default,
- ACL_TYPE_DEFAULT);
+ goto out_drop_lock;
+ error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default);
if (error)
- goto out_drop_write;
+ goto out_drop_lock;
+
+ fh_unlock(fh);
fh_drop_write(fh);
@@ -131,7 +130,8 @@ out:
posix_acl_release(argp->acl_access);
posix_acl_release(argp->acl_default);
return nfserr;
-out_drop_write:
+out_drop_lock:
+ fh_unlock(fh);
fh_drop_write(fh);
out_errno:
nfserr = nfserrno(error);
diff --git a/fs/nfsd/nfs3acl.c b/fs/nfsd/nfs3acl.c
index 01df4cd7c753..0c890347cde3 100644
--- a/fs/nfsd/nfs3acl.c
+++ b/fs/nfsd/nfs3acl.c
@@ -95,22 +95,20 @@ static __be32 nfsd3_proc_setacl(struct svc_rqst * rqstp,
goto out;
inode = d_inode(fh->fh_dentry);
- if (!IS_POSIXACL(inode) || !inode->i_op->set_acl) {
- error = -EOPNOTSUPP;
- goto out_errno;
- }
error = fh_want_write(fh);
if (error)
goto out_errno;
- error = inode->i_op->set_acl(inode, argp->acl_access, ACL_TYPE_ACCESS);
+ fh_lock(fh);
+
+ error = set_posix_acl(inode, ACL_TYPE_ACCESS, argp->acl_access);
if (error)
- goto out_drop_write;
- error = inode->i_op->set_acl(inode, argp->acl_default,
- ACL_TYPE_DEFAULT);
+ goto out_drop_lock;
+ error = set_posix_acl(inode, ACL_TYPE_DEFAULT, argp->acl_default);
-out_drop_write:
+out_drop_lock:
+ fh_unlock(fh);
fh_drop_write(fh);
out_errno:
nfserr = nfserrno(error);
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 6adabd6049b7..71292a0d6f09 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -770,9 +770,6 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
dentry = fhp->fh_dentry;
inode = d_inode(dentry);
- if (!inode->i_op->set_acl || !IS_POSIXACL(inode))
- return nfserr_attrnotsupp;
-
if (S_ISDIR(inode->i_mode))
flags = NFS4_ACL_DIR;
@@ -782,16 +779,19 @@ nfsd4_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
if (host_error < 0)
goto out_nfserr;
- host_error = inode->i_op->set_acl(inode, pacl, ACL_TYPE_ACCESS);
+ fh_lock(fhp);
+
+ host_error = set_posix_acl(inode, ACL_TYPE_ACCESS, pacl);
if (host_error < 0)
- goto out_release;
+ goto out_drop_lock;
if (S_ISDIR(inode->i_mode)) {
- host_error = inode->i_op->set_acl(inode, dpacl,
- ACL_TYPE_DEFAULT);
+ host_error = set_posix_acl(inode, ACL_TYPE_DEFAULT, dpacl);
}
-out_release:
+out_drop_lock:
+ fh_unlock(fhp);
+
posix_acl_release(pacl);
posix_acl_release(dpacl);
out_nfserr:
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index e7f50c4081d6..15bdc2d48cfe 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -710,22 +710,6 @@ static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc
}
}
-static struct rpc_clnt *create_backchannel_client(struct rpc_create_args *args)
-{
- struct rpc_xprt *xprt;
-
- if (args->protocol != XPRT_TRANSPORT_BC_TCP)
- return rpc_create(args);
-
- xprt = args->bc_xprt->xpt_bc_xprt;
- if (xprt) {
- xprt_get(xprt);
- return rpc_create_xprt(args, xprt);
- }
-
- return rpc_create(args);
-}
-
static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
{
int maxtime = max_cb_time(clp->net);
@@ -768,7 +752,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
args.authflavor = ses->se_cb_sec.flavor;
}
/* Create RPC client */
- client = create_backchannel_client(&args);
+ client = rpc_create(&args);
if (IS_ERR(client)) {
dprintk("NFSD: couldn't create callback client: %ld\n",
PTR_ERR(client));
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 6b800b5b8fed..ed2f64ca49de 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3452,6 +3452,10 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
struct nfs4_openowner *oo = open->op_openowner;
struct nfs4_ol_stateid *retstp = NULL;
+ /* We are moving these outside of the spinlocks to avoid the warnings */
+ mutex_init(&stp->st_mutex);
+ mutex_lock(&stp->st_mutex);
+
spin_lock(&oo->oo_owner.so_client->cl_lock);
spin_lock(&fp->fi_lock);
@@ -3467,13 +3471,17 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
stp->st_access_bmap = 0;
stp->st_deny_bmap = 0;
stp->st_openstp = NULL;
- init_rwsem(&stp->st_rwsem);
list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids);
list_add(&stp->st_perfile, &fp->fi_stateids);
out_unlock:
spin_unlock(&fp->fi_lock);
spin_unlock(&oo->oo_owner.so_client->cl_lock);
+ if (retstp) {
+ mutex_lock(&retstp->st_mutex);
+ /* Not that we need to, just for neatness */
+ mutex_unlock(&stp->st_mutex);
+ }
return retstp;
}
@@ -4300,32 +4308,34 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
*/
if (stp) {
/* Stateid was found, this is an OPEN upgrade */
- down_read(&stp->st_rwsem);
+ mutex_lock(&stp->st_mutex);
status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open);
if (status) {
- up_read(&stp->st_rwsem);
+ mutex_unlock(&stp->st_mutex);
goto out;
}
} else {
stp = open->op_stp;
open->op_stp = NULL;
+ /*
+ * init_open_stateid() either returns a locked stateid
+ * it found, or initializes and locks the new one we passed in
+ */
swapstp = init_open_stateid(stp, fp, open);
if (swapstp) {
nfs4_put_stid(&stp->st_stid);
stp = swapstp;
- down_read(&stp->st_rwsem);
status = nfs4_upgrade_open(rqstp, fp, current_fh,
stp, open);
if (status) {
- up_read(&stp->st_rwsem);
+ mutex_unlock(&stp->st_mutex);
goto out;
}
goto upgrade_out;
}
- down_read(&stp->st_rwsem);
status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open);
if (status) {
- up_read(&stp->st_rwsem);
+ mutex_unlock(&stp->st_mutex);
release_open_stateid(stp);
goto out;
}
@@ -4337,7 +4347,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
}
upgrade_out:
nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid);
- up_read(&stp->st_rwsem);
+ mutex_unlock(&stp->st_mutex);
if (nfsd4_has_session(&resp->cstate)) {
if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) {
@@ -4950,12 +4960,12 @@ static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_
* revoked delegations are kept only for free_stateid.
*/
return nfserr_bad_stateid;
- down_write(&stp->st_rwsem);
+ mutex_lock(&stp->st_mutex);
status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate));
if (status == nfs_ok)
status = nfs4_check_fh(current_fh, &stp->st_stid);
if (status != nfs_ok)
- up_write(&stp->st_rwsem);
+ mutex_unlock(&stp->st_mutex);
return status;
}
@@ -5003,7 +5013,7 @@ static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cs
return status;
oo = openowner(stp->st_stateowner);
if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) {
- up_write(&stp->st_rwsem);
+ mutex_unlock(&stp->st_mutex);
nfs4_put_stid(&stp->st_stid);
return nfserr_bad_stateid;
}
@@ -5035,12 +5045,12 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
oo = openowner(stp->st_stateowner);
status = nfserr_bad_stateid;
if (oo->oo_flags & NFS4_OO_CONFIRMED) {
- up_write(&stp->st_rwsem);
+ mutex_unlock(&stp->st_mutex);
goto put_stateid;
}
oo->oo_flags |= NFS4_OO_CONFIRMED;
nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid);
- up_write(&stp->st_rwsem);
+ mutex_unlock(&stp->st_mutex);
dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
__func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid));
@@ -5116,7 +5126,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
nfs4_inc_and_copy_stateid(&od->od_stateid, &stp->st_stid);
status = nfs_ok;
put_stateid:
- up_write(&stp->st_rwsem);
+ mutex_unlock(&stp->st_mutex);
nfs4_put_stid(&stp->st_stid);
out:
nfsd4_bump_seqid(cstate, status);
@@ -5169,7 +5179,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (status)
goto out;
nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid);
- up_write(&stp->st_rwsem);
+ mutex_unlock(&stp->st_mutex);
nfsd4_close_open_stateid(stp);
@@ -5395,7 +5405,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
stp->st_access_bmap = 0;
stp->st_deny_bmap = open_stp->st_deny_bmap;
stp->st_openstp = open_stp;
- init_rwsem(&stp->st_rwsem);
+ mutex_init(&stp->st_mutex);
list_add(&stp->st_locks, &open_stp->st_locks);
list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids);
spin_lock(&fp->fi_lock);
@@ -5564,7 +5574,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
&open_stp, nn);
if (status)
goto out;
- up_write(&open_stp->st_rwsem);
+ mutex_unlock(&open_stp->st_mutex);
open_sop = openowner(open_stp->st_stateowner);
status = nfserr_bad_stateid;
if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid,
@@ -5573,7 +5583,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
status = lookup_or_create_lock_state(cstate, open_stp, lock,
&lock_stp, &new);
if (status == nfs_ok)
- down_write(&lock_stp->st_rwsem);
+ mutex_lock(&lock_stp->st_mutex);
} else {
status = nfs4_preprocess_seqid_op(cstate,
lock->lk_old_lock_seqid,
@@ -5677,7 +5687,7 @@ out:
seqid_mutating_err(ntohl(status)))
lock_sop->lo_owner.so_seqid++;
- up_write(&lock_stp->st_rwsem);
+ mutex_unlock(&lock_stp->st_mutex);
/*
* If this is a new, never-before-used stateid, and we are
@@ -5847,7 +5857,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
fput:
fput(filp);
put_stateid:
- up_write(&stp->st_rwsem);
+ mutex_unlock(&stp->st_mutex);
nfs4_put_stid(&stp->st_stid);
out:
nfsd4_bump_seqid(cstate, status);
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 77fdf4de91ba..77860b75da9d 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -535,7 +535,7 @@ struct nfs4_ol_stateid {
unsigned char st_access_bmap;
unsigned char st_deny_bmap;
struct nfs4_ol_stateid *st_openstp;
- struct rw_semaphore st_rwsem;
+ struct mutex st_mutex;
};
static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s)
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index f72f3b25b3f2..e2893f17dde2 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -746,7 +746,7 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
/* support stacked filesystems */
if(path.dentry && path.dentry->d_op) {
if (path.dentry->d_op->d_canonical_path) {
- path.dentry->d_op->d_canonical_path(path.dentry, &alteredpath);
+ path.dentry->d_op->d_canonical_path(&path, &alteredpath);
canonical_path = &alteredpath;
path_put(&path);
}
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index a2b1d7ce3e1a..ba5ef733951f 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -511,6 +511,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
struct dentry *upper;
struct dentry *opaquedir = NULL;
int err;
+ int flags = 0;
if (WARN_ON(!workdir))
return -EROFS;
@@ -540,46 +541,39 @@ static int ovl_remove_and_whiteout(struct dentry *dentry, bool is_dir)
if (err)
goto out_dput;
- whiteout = ovl_whiteout(workdir, dentry);
- err = PTR_ERR(whiteout);
- if (IS_ERR(whiteout))
+ upper = lookup_one_len(dentry->d_name.name, upperdir,
+ dentry->d_name.len);
+ err = PTR_ERR(upper);
+ if (IS_ERR(upper))
goto out_unlock;
- upper = ovl_dentry_upper(dentry);
- if (!upper) {
- upper = lookup_one_len(dentry->d_name.name, upperdir,
- dentry->d_name.len);
- err = PTR_ERR(upper);
- if (IS_ERR(upper))
- goto kill_whiteout;
-
- err = ovl_do_rename(wdir, whiteout, udir, upper, 0);
- dput(upper);
- if (err)
- goto kill_whiteout;
- } else {
- int flags = 0;
+ err = -ESTALE;
+ if ((opaquedir && upper != opaquedir) ||
+ (!opaquedir && ovl_dentry_upper(dentry) &&
+ upper != ovl_dentry_upper(dentry))) {
+ goto out_dput_upper;
+ }
- if (opaquedir)
- upper = opaquedir;
- err = -ESTALE;
- if (upper->d_parent != upperdir)
- goto kill_whiteout;
+ whiteout = ovl_whiteout(workdir, dentry);
+ err = PTR_ERR(whiteout);
+ if (IS_ERR(whiteout))
+ goto out_dput_upper;
- if (is_dir)
- flags |= RENAME_EXCHANGE;
+ if (d_is_dir(upper))
+ flags = RENAME_EXCHANGE;
- err = ovl_do_rename(wdir, whiteout, udir, upper, flags);
- if (err)
- goto kill_whiteout;
+ err = ovl_do_rename(wdir, whiteout, udir, upper, flags);
+ if (err)
+ goto kill_whiteout;
+ if (flags)
+ ovl_cleanup(wdir, upper);
- if (is_dir)
- ovl_cleanup(wdir, upper);
- }
ovl_dentry_version_inc(dentry->d_parent);
out_d_drop:
d_drop(dentry);
dput(whiteout);
+out_dput_upper:
+ dput(upper);
out_unlock:
unlock_rename(workdir, upperdir);
out_dput:
@@ -596,21 +590,25 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir)
{
struct dentry *upperdir = ovl_dentry_upper(dentry->d_parent);
struct inode *dir = upperdir->d_inode;
- struct dentry *upper = ovl_dentry_upper(dentry);
+ struct dentry *upper;
int err;
mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
+ upper = lookup_one_len(dentry->d_name.name, upperdir,
+ dentry->d_name.len);
+ err = PTR_ERR(upper);
+ if (IS_ERR(upper))
+ goto out_unlock;
+
err = -ESTALE;
- if (upper->d_parent == upperdir) {
- /* Don't let d_delete() think it can reset d_inode */
- dget(upper);
+ if (upper == ovl_dentry_upper(dentry)) {
if (is_dir)
err = vfs_rmdir(dir, upper);
else
err = vfs_unlink(dir, upper, NULL);
- dput(upper);
ovl_dentry_version_inc(dentry->d_parent);
}
+ dput(upper);
/*
* Keeping this dentry hashed would mean having to release
@@ -620,6 +618,7 @@ static int ovl_remove_upper(struct dentry *dentry, bool is_dir)
*/
if (!err)
d_drop(dentry);
+out_unlock:
mutex_unlock(&dir->i_mutex);
return err;
@@ -840,29 +839,39 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
trap = lock_rename(new_upperdir, old_upperdir);
- olddentry = ovl_dentry_upper(old);
- newdentry = ovl_dentry_upper(new);
- if (newdentry) {
+
+ olddentry = lookup_one_len(old->d_name.name, old_upperdir,
+ old->d_name.len);
+ err = PTR_ERR(olddentry);
+ if (IS_ERR(olddentry))
+ goto out_unlock;
+
+ err = -ESTALE;
+ if (olddentry != ovl_dentry_upper(old))
+ goto out_dput_old;
+
+ newdentry = lookup_one_len(new->d_name.name, new_upperdir,
+ new->d_name.len);
+ err = PTR_ERR(newdentry);
+ if (IS_ERR(newdentry))
+ goto out_dput_old;
+
+ err = -ESTALE;
+ if (ovl_dentry_upper(new)) {
if (opaquedir) {
- newdentry = opaquedir;
- opaquedir = NULL;
+ if (newdentry != opaquedir)
+ goto out_dput;
} else {
- dget(newdentry);
+ if (newdentry != ovl_dentry_upper(new))
+ goto out_dput;
}
} else {
new_create = true;
- newdentry = lookup_one_len(new->d_name.name, new_upperdir,
- new->d_name.len);
- err = PTR_ERR(newdentry);
- if (IS_ERR(newdentry))
- goto out_unlock;
+ if (!d_is_negative(newdentry) &&
+ (!new_opaque || !ovl_is_whiteout(newdentry)))
+ goto out_dput;
}
- err = -ESTALE;
- if (olddentry->d_parent != old_upperdir)
- goto out_dput;
- if (newdentry->d_parent != new_upperdir)
- goto out_dput;
if (olddentry == trap)
goto out_dput;
if (newdentry == trap)
@@ -925,6 +934,8 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
out_dput:
dput(newdentry);
+out_dput_old:
+ dput(olddentry);
out_unlock:
unlock_rename(new_upperdir, old_upperdir);
out_revert_creds:
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 05ac9a95e881..0597820f5d9d 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -412,12 +412,11 @@ struct inode *ovl_new_inode(struct super_block *sb, umode_t mode,
if (!inode)
return NULL;
- mode &= S_IFMT;
-
inode->i_ino = get_next_ino();
inode->i_mode = mode;
inode->i_flags |= S_NOATIME | S_NOCMTIME;
+ mode &= S_IFMT;
switch (mode) {
case S_IFDIR:
inode->i_private = oe;
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index e17154aeaae4..735e1d49b301 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -181,6 +181,7 @@ static inline void ovl_copyattr(struct inode *from, struct inode *to)
{
to->i_uid = from->i_uid;
to->i_gid = from->i_gid;
+ to->i_mode = from->i_mode;
}
/* dir.c */
diff --git a/fs/pipe.c b/fs/pipe.c
index 42cf8ddf0e55..ab8dad3ccb6a 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -38,6 +38,12 @@ unsigned int pipe_max_size = 1048576;
*/
unsigned int pipe_min_size = PAGE_SIZE;
+/* Maximum allocatable pages per user. Hard limit is unset by default, soft
+ * matches default values.
+ */
+unsigned long pipe_user_pages_hard;
+unsigned long pipe_user_pages_soft = PIPE_DEF_BUFFERS * INR_OPEN_CUR;
+
/*
* We use a start+len construction, which provides full use of the
* allocated memory.
@@ -583,20 +589,49 @@ pipe_fasync(int fd, struct file *filp, int on)
return retval;
}
+static void account_pipe_buffers(struct pipe_inode_info *pipe,
+ unsigned long old, unsigned long new)
+{
+ atomic_long_add(new - old, &pipe->user->pipe_bufs);
+}
+
+static bool too_many_pipe_buffers_soft(struct user_struct *user)
+{
+ return pipe_user_pages_soft &&
+ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_soft;
+}
+
+static bool too_many_pipe_buffers_hard(struct user_struct *user)
+{
+ return pipe_user_pages_hard &&
+ atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_hard;
+}
+
struct pipe_inode_info *alloc_pipe_info(void)
{
struct pipe_inode_info *pipe;
pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
if (pipe) {
- pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * PIPE_DEF_BUFFERS, GFP_KERNEL);
+ unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
+ struct user_struct *user = get_current_user();
+
+ if (!too_many_pipe_buffers_hard(user)) {
+ if (too_many_pipe_buffers_soft(user))
+ pipe_bufs = 1;
+ pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL);
+ }
+
if (pipe->bufs) {
init_waitqueue_head(&pipe->wait);
pipe->r_counter = pipe->w_counter = 1;
- pipe->buffers = PIPE_DEF_BUFFERS;
+ pipe->buffers = pipe_bufs;
+ pipe->user = user;
+ account_pipe_buffers(pipe, 0, pipe_bufs);
mutex_init(&pipe->mutex);
return pipe;
}
+ free_uid(user);
kfree(pipe);
}
@@ -607,6 +642,8 @@ void free_pipe_info(struct pipe_inode_info *pipe)
{
int i;
+ account_pipe_buffers(pipe, pipe->buffers, 0);
+ free_uid(pipe->user);
for (i = 0; i < pipe->buffers; i++) {
struct pipe_buffer *buf = pipe->bufs + i;
if (buf->ops)
@@ -998,6 +1035,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages)
memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer));
}
+ account_pipe_buffers(pipe, pipe->buffers, nr_pages);
pipe->curbuf = 0;
kfree(pipe->bufs);
pipe->bufs = bufs;
@@ -1069,6 +1107,11 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
ret = -EPERM;
goto out;
+ } else if ((too_many_pipe_buffers_hard(pipe->user) ||
+ too_many_pipe_buffers_soft(pipe->user)) &&
+ !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) {
+ ret = -EPERM;
+ goto out;
}
ret = pipe_set_size(pipe, nr_pages);
break;
diff --git a/fs/posix_acl.c b/fs/posix_acl.c
index 4adde1e2cbec..34bd1bd354e6 100644
--- a/fs/posix_acl.c
+++ b/fs/posix_acl.c
@@ -788,6 +788,28 @@ posix_acl_xattr_get(const struct xattr_handler *handler,
return error;
}
+int
+set_posix_acl(struct inode *inode, int type, struct posix_acl *acl)
+{
+ if (!IS_POSIXACL(inode))
+ return -EOPNOTSUPP;
+ if (!inode->i_op->set_acl)
+ return -EOPNOTSUPP;
+
+ if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
+ return acl ? -EACCES : 0;
+ if (!inode_owner_or_capable(inode))
+ return -EPERM;
+
+ if (acl) {
+ int ret = posix_acl_valid(acl);
+ if (ret)
+ return ret;
+ }
+ return inode->i_op->set_acl(inode, acl, type);
+}
+EXPORT_SYMBOL(set_posix_acl);
+
static int
posix_acl_xattr_set(const struct xattr_handler *handler,
struct dentry *dentry, const char *name,
@@ -799,30 +821,13 @@ posix_acl_xattr_set(const struct xattr_handler *handler,
if (strcmp(name, "") != 0)
return -EINVAL;
- if (!IS_POSIXACL(inode))
- return -EOPNOTSUPP;
- if (!inode->i_op->set_acl)
- return -EOPNOTSUPP;
-
- if (handler->flags == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode))
- return value ? -EACCES : 0;
- if (!inode_owner_or_capable(inode))
- return -EPERM;
if (value) {
acl = posix_acl_from_xattr(&init_user_ns, value, size);
if (IS_ERR(acl))
return PTR_ERR(acl);
-
- if (acl) {
- ret = posix_acl_valid(acl);
- if (ret)
- goto out;
- }
}
-
- ret = inode->i_op->set_acl(inode, acl, handler->flags);
-out:
+ ret = set_posix_acl(inode, handler->flags, acl);
posix_acl_release(acl);
return ret;
}
diff --git a/fs/proc/base.c b/fs/proc/base.c
index de2dcc1d1167..7d61792c053a 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -2443,6 +2443,72 @@ static const struct file_operations proc_timers_operations = {
.release = seq_release_private,
};
+static ssize_t timerslack_ns_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *offset)
+{
+ struct inode *inode = file_inode(file);
+ struct task_struct *p;
+ u64 slack_ns;
+ int err;
+
+ err = kstrtoull_from_user(buf, count, 10, &slack_ns);
+ if (err < 0)
+ return err;
+
+ p = get_proc_task(inode);
+ if (!p)
+ return -ESRCH;
+
+ if (ptrace_may_access(p, PTRACE_MODE_ATTACH_FSCREDS)) {
+ task_lock(p);
+ if (slack_ns == 0)
+ p->timer_slack_ns = p->default_timer_slack_ns;
+ else
+ p->timer_slack_ns = slack_ns;
+ task_unlock(p);
+ } else
+ count = -EPERM;
+
+ put_task_struct(p);
+
+ return count;
+}
+
+static int timerslack_ns_show(struct seq_file *m, void *v)
+{
+ struct inode *inode = m->private;
+ struct task_struct *p;
+ int err = 0;
+
+ p = get_proc_task(inode);
+ if (!p)
+ return -ESRCH;
+
+ if (ptrace_may_access(p, PTRACE_MODE_ATTACH_FSCREDS)) {
+ task_lock(p);
+ seq_printf(m, "%llu\n", p->timer_slack_ns);
+ task_unlock(p);
+ } else
+ err = -EPERM;
+
+ put_task_struct(p);
+
+ return err;
+}
+
+static int timerslack_ns_open(struct inode *inode, struct file *filp)
+{
+ return single_open(filp, timerslack_ns_show, inode);
+}
+
+static const struct file_operations proc_pid_set_timerslack_ns_operations = {
+ .open = timerslack_ns_open,
+ .read = seq_read,
+ .write = timerslack_ns_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int proc_pident_instantiate(struct inode *dir,
struct dentry *dentry, struct task_struct *task, const void *ptr)
{
@@ -3030,6 +3096,7 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_CHECKPOINT_RESTORE
REG("timers", S_IRUGO, proc_timers_operations),
#endif
+ REG("timerslack_ns", S_IRUGO|S_IWUGO, proc_pid_set_timerslack_ns_operations),
};
static int proc_tgid_base_readdir(struct file *file, struct dir_context *ctx)
@@ -3287,6 +3354,44 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
}
/*
+ * proc_tid_comm_permission is a special permission function exclusively
+ * used for the node /proc/<pid>/task/<tid>/comm.
+ * It bypasses generic permission checks in the case where a task of the same
+ * task group attempts to access the node.
+ * The rational behind this is that glibc and bionic access this node for
+ * cross thread naming (pthread_set/getname_np(!self)). However, if
+ * PR_SET_DUMPABLE gets set to 0 this node among others becomes uid=0 gid=0,
+ * which locks out the cross thread naming implementation.
+ * This function makes sure that the node is always accessible for members of
+ * same thread group.
+ */
+static int proc_tid_comm_permission(struct inode *inode, int mask)
+{
+ bool is_same_tgroup;
+ struct task_struct *task;
+
+ task = get_proc_task(inode);
+ if (!task)
+ return -ESRCH;
+ is_same_tgroup = same_thread_group(current, task);
+ put_task_struct(task);
+
+ if (likely(is_same_tgroup && !(mask & MAY_EXEC))) {
+ /* This file (/proc/<pid>/task/<tid>/comm) can always be
+ * read or written by the members of the corresponding
+ * thread group.
+ */
+ return 0;
+ }
+
+ return generic_permission(inode, mask);
+}
+
+static const struct inode_operations proc_tid_comm_inode_operations = {
+ .permission = proc_tid_comm_permission,
+};
+
+/*
* Tasks
*/
static const struct pid_entry tid_base_stuff[] = {
@@ -3304,7 +3409,9 @@ static const struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_SCHED_DEBUG
REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
- REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
+ NOD("comm", S_IFREG|S_IRUGO|S_IWUSR,
+ &proc_tid_comm_inode_operations,
+ &proc_pid_set_comm_operations, {}),
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
ONE("syscall", S_IRUSR, proc_pid_syscall),
#endif
diff --git a/fs/sdcardfs/dentry.c b/fs/sdcardfs/dentry.c
index ba165ef11e27..971928ab6c21 100644
--- a/fs/sdcardfs/dentry.c
+++ b/fs/sdcardfs/dentry.c
@@ -172,11 +172,15 @@ static int sdcardfs_cmp_ci(const struct dentry *parent,
return 1;
}
+static void sdcardfs_canonical_path(const struct path *path, struct path *actual_path) {
+ sdcardfs_get_real_lower(path->dentry, actual_path);
+}
+
const struct dentry_operations sdcardfs_ci_dops = {
.d_revalidate = sdcardfs_d_revalidate,
.d_release = sdcardfs_d_release,
.d_hash = sdcardfs_hash_ci,
.d_compare = sdcardfs_cmp_ci,
- .d_canonical_path = sdcardfs_get_real_lower,
+ .d_canonical_path = sdcardfs_canonical_path,
};
diff --git a/fs/sdcardfs/packagelist.c b/fs/sdcardfs/packagelist.c
index 10f0d6be718b..9c3340528eee 100644
--- a/fs/sdcardfs/packagelist.c
+++ b/fs/sdcardfs/packagelist.c
@@ -335,13 +335,20 @@ static ssize_t packages_attr_show(struct config_item *item,
struct hashtable_entry *hash_cur;
struct hlist_node *h_t;
int i;
- int count = 0;
+ int count = 0, written = 0;
+ char errormsg[] = "<truncated>\n";
+
mutex_lock(&pkgl_data_all->hashtable_lock);
- hash_for_each_safe(pkgl_data_all->package_to_appid, i, h_t, hash_cur, hlist)
- count += snprintf(page + count, PAGE_SIZE - count, "%s %d\n", (char *)hash_cur->key, hash_cur->value);
+ hash_for_each_safe(pkgl_data_all->package_to_appid, i, h_t, hash_cur, hlist) {
+ written = scnprintf(page + count, PAGE_SIZE - sizeof(errormsg) - count, "%s %d\n", (char *)hash_cur->key, hash_cur->value);
+ if (count + written == PAGE_SIZE - sizeof(errormsg)) {
+ count += scnprintf(page + count, PAGE_SIZE - count, errormsg);
+ break;
+ }
+ count += written;
+ }
mutex_unlock(&pkgl_data_all->hashtable_lock);
-
return count;
}
diff --git a/fs/select.c b/fs/select.c
index 015547330e88..09e71a00a9b8 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -70,9 +70,9 @@ static long __estimate_accuracy(struct timespec *tv)
return slack;
}
-long select_estimate_accuracy(struct timespec *tv)
+u64 select_estimate_accuracy(struct timespec *tv)
{
- unsigned long ret;
+ u64 ret;
struct timespec now;
/*
@@ -402,7 +402,7 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
struct poll_wqueues table;
poll_table *wait;
int retval, i, timed_out = 0;
- unsigned long slack = 0;
+ u64 slack = 0;
unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0;
unsigned long busy_end = 0;
@@ -784,7 +784,7 @@ static int do_poll(unsigned int nfds, struct poll_list *list,
poll_table* pt = &wait->pt;
ktime_t expire, *to = NULL;
int timed_out = 0, count = 0;
- unsigned long slack = 0;
+ u64 slack = 0;
unsigned int busy_flag = net_busy_loop_on() ? POLL_BUSY_LOOP : 0;
unsigned long busy_end = 0;
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 0edc12856147..b895af7d8d80 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -52,6 +52,7 @@
#include "ubifs.h"
#include <linux/mount.h>
#include <linux/slab.h>
+#include <linux/migrate.h>
static int read_block(struct inode *inode, void *addr, unsigned int block,
struct ubifs_data_node *dn)
@@ -1452,6 +1453,26 @@ static int ubifs_set_page_dirty(struct page *page)
return ret;
}
+#ifdef CONFIG_MIGRATION
+static int ubifs_migrate_page(struct address_space *mapping,
+ struct page *newpage, struct page *page, enum migrate_mode mode)
+{
+ int rc;
+
+ rc = migrate_page_move_mapping(mapping, newpage, page, NULL, mode, 0);
+ if (rc != MIGRATEPAGE_SUCCESS)
+ return rc;
+
+ if (PagePrivate(page)) {
+ ClearPagePrivate(page);
+ SetPagePrivate(newpage);
+ }
+
+ migrate_page_copy(newpage, page);
+ return MIGRATEPAGE_SUCCESS;
+}
+#endif
+
static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags)
{
/*
@@ -1591,6 +1612,9 @@ const struct address_space_operations ubifs_file_address_operations = {
.write_end = ubifs_write_end,
.invalidatepage = ubifs_invalidatepage,
.set_page_dirty = ubifs_set_page_dirty,
+#ifdef CONFIG_MIGRATION
+ .migratepage = ubifs_migrate_page,
+#endif
.releasepage = ubifs_releasepage,
};
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 3479294c1d58..e1e7fe3b5424 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -535,6 +535,7 @@ xfs_agfl_write_verify(
}
const struct xfs_buf_ops xfs_agfl_buf_ops = {
+ .name = "xfs_agfl",
.verify_read = xfs_agfl_read_verify,
.verify_write = xfs_agfl_write_verify,
};
@@ -2339,6 +2340,7 @@ xfs_agf_write_verify(
}
const struct xfs_buf_ops xfs_agf_buf_ops = {
+ .name = "xfs_agf",
.verify_read = xfs_agf_read_verify,
.verify_write = xfs_agf_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c
index 90de071dd4c2..eb8bbfe85484 100644
--- a/fs/xfs/libxfs/xfs_alloc_btree.c
+++ b/fs/xfs/libxfs/xfs_alloc_btree.c
@@ -379,6 +379,7 @@ xfs_allocbt_write_verify(
}
const struct xfs_buf_ops xfs_allocbt_buf_ops = {
+ .name = "xfs_allocbt",
.verify_read = xfs_allocbt_read_verify,
.verify_write = xfs_allocbt_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index aa187f7ba2dd..01a5ecfedfcf 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -328,6 +328,7 @@ xfs_attr3_leaf_read_verify(
}
const struct xfs_buf_ops xfs_attr3_leaf_buf_ops = {
+ .name = "xfs_attr3_leaf",
.verify_read = xfs_attr3_leaf_read_verify,
.verify_write = xfs_attr3_leaf_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c
index 5ab95ffa4ae9..f3ed9bf0b065 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.c
+++ b/fs/xfs/libxfs/xfs_attr_remote.c
@@ -201,6 +201,7 @@ xfs_attr3_rmt_write_verify(
}
const struct xfs_buf_ops xfs_attr3_rmt_buf_ops = {
+ .name = "xfs_attr3_rmt",
.verify_read = xfs_attr3_rmt_read_verify,
.verify_write = xfs_attr3_rmt_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index 6b0cf6546a82..1637c37bfbaa 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -720,6 +720,7 @@ xfs_bmbt_write_verify(
}
const struct xfs_buf_ops xfs_bmbt_buf_ops = {
+ .name = "xfs_bmbt",
.verify_read = xfs_bmbt_read_verify,
.verify_write = xfs_bmbt_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
index e89a0f8f827c..097bf7717d80 100644
--- a/fs/xfs/libxfs/xfs_da_btree.c
+++ b/fs/xfs/libxfs/xfs_da_btree.c
@@ -245,6 +245,7 @@ xfs_da3_node_read_verify(
}
const struct xfs_buf_ops xfs_da3_node_buf_ops = {
+ .name = "xfs_da3_node",
.verify_read = xfs_da3_node_read_verify,
.verify_write = xfs_da3_node_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_dir2_block.c b/fs/xfs/libxfs/xfs_dir2_block.c
index 9c10e2b8cfcb..aa17cb788946 100644
--- a/fs/xfs/libxfs/xfs_dir2_block.c
+++ b/fs/xfs/libxfs/xfs_dir2_block.c
@@ -123,6 +123,7 @@ xfs_dir3_block_write_verify(
}
const struct xfs_buf_ops xfs_dir3_block_buf_ops = {
+ .name = "xfs_dir3_block",
.verify_read = xfs_dir3_block_read_verify,
.verify_write = xfs_dir3_block_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_dir2_data.c b/fs/xfs/libxfs/xfs_dir2_data.c
index af71a84f343c..725fc7841fde 100644
--- a/fs/xfs/libxfs/xfs_dir2_data.c
+++ b/fs/xfs/libxfs/xfs_dir2_data.c
@@ -305,11 +305,13 @@ xfs_dir3_data_write_verify(
}
const struct xfs_buf_ops xfs_dir3_data_buf_ops = {
+ .name = "xfs_dir3_data",
.verify_read = xfs_dir3_data_read_verify,
.verify_write = xfs_dir3_data_write_verify,
};
static const struct xfs_buf_ops xfs_dir3_data_reada_buf_ops = {
+ .name = "xfs_dir3_data_reada",
.verify_read = xfs_dir3_data_reada_verify,
.verify_write = xfs_dir3_data_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_dir2_leaf.c b/fs/xfs/libxfs/xfs_dir2_leaf.c
index 3923e1f94697..b887fb2a2bcf 100644
--- a/fs/xfs/libxfs/xfs_dir2_leaf.c
+++ b/fs/xfs/libxfs/xfs_dir2_leaf.c
@@ -245,11 +245,13 @@ xfs_dir3_leafn_write_verify(
}
const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops = {
+ .name = "xfs_dir3_leaf1",
.verify_read = xfs_dir3_leaf1_read_verify,
.verify_write = xfs_dir3_leaf1_write_verify,
};
const struct xfs_buf_ops xfs_dir3_leafn_buf_ops = {
+ .name = "xfs_dir3_leafn",
.verify_read = xfs_dir3_leafn_read_verify,
.verify_write = xfs_dir3_leafn_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c
index 70b0cb2fd556..63ee03db796c 100644
--- a/fs/xfs/libxfs/xfs_dir2_node.c
+++ b/fs/xfs/libxfs/xfs_dir2_node.c
@@ -150,6 +150,7 @@ xfs_dir3_free_write_verify(
}
const struct xfs_buf_ops xfs_dir3_free_buf_ops = {
+ .name = "xfs_dir3_free",
.verify_read = xfs_dir3_free_read_verify,
.verify_write = xfs_dir3_free_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c
index 5331b7f0460c..3cc3cf767474 100644
--- a/fs/xfs/libxfs/xfs_dquot_buf.c
+++ b/fs/xfs/libxfs/xfs_dquot_buf.c
@@ -54,7 +54,7 @@ xfs_dqcheck(
xfs_dqid_t id,
uint type, /* used only when IO_dorepair is true */
uint flags,
- char *str)
+ const char *str)
{
xfs_dqblk_t *d = (xfs_dqblk_t *)ddq;
int errs = 0;
@@ -207,7 +207,8 @@ xfs_dquot_buf_verify_crc(
STATIC bool
xfs_dquot_buf_verify(
struct xfs_mount *mp,
- struct xfs_buf *bp)
+ struct xfs_buf *bp,
+ int warn)
{
struct xfs_dqblk *d = (struct xfs_dqblk *)bp->b_addr;
xfs_dqid_t id = 0;
@@ -240,8 +241,7 @@ xfs_dquot_buf_verify(
if (i == 0)
id = be32_to_cpu(ddq->d_id);
- error = xfs_dqcheck(mp, ddq, id + i, 0, XFS_QMOPT_DOWARN,
- "xfs_dquot_buf_verify");
+ error = xfs_dqcheck(mp, ddq, id + i, 0, warn, __func__);
if (error)
return false;
}
@@ -256,7 +256,7 @@ xfs_dquot_buf_read_verify(
if (!xfs_dquot_buf_verify_crc(mp, bp))
xfs_buf_ioerror(bp, -EFSBADCRC);
- else if (!xfs_dquot_buf_verify(mp, bp))
+ else if (!xfs_dquot_buf_verify(mp, bp, XFS_QMOPT_DOWARN))
xfs_buf_ioerror(bp, -EFSCORRUPTED);
if (bp->b_error)
@@ -264,6 +264,25 @@ xfs_dquot_buf_read_verify(
}
/*
+ * readahead errors are silent and simply leave the buffer as !done so a real
+ * read will then be run with the xfs_dquot_buf_ops verifier. See
+ * xfs_inode_buf_verify() for why we use EIO and ~XBF_DONE here rather than
+ * reporting the failure.
+ */
+static void
+xfs_dquot_buf_readahead_verify(
+ struct xfs_buf *bp)
+{
+ struct xfs_mount *mp = bp->b_target->bt_mount;
+
+ if (!xfs_dquot_buf_verify_crc(mp, bp) ||
+ !xfs_dquot_buf_verify(mp, bp, 0)) {
+ xfs_buf_ioerror(bp, -EIO);
+ bp->b_flags &= ~XBF_DONE;
+ }
+}
+
+/*
* we don't calculate the CRC here as that is done when the dquot is flushed to
* the buffer after the update is done. This ensures that the dquot in the
* buffer always has an up-to-date CRC value.
@@ -274,7 +293,7 @@ xfs_dquot_buf_write_verify(
{
struct xfs_mount *mp = bp->b_target->bt_mount;
- if (!xfs_dquot_buf_verify(mp, bp)) {
+ if (!xfs_dquot_buf_verify(mp, bp, XFS_QMOPT_DOWARN)) {
xfs_buf_ioerror(bp, -EFSCORRUPTED);
xfs_verifier_error(bp);
return;
@@ -282,7 +301,13 @@ xfs_dquot_buf_write_verify(
}
const struct xfs_buf_ops xfs_dquot_buf_ops = {
+ .name = "xfs_dquot",
.verify_read = xfs_dquot_buf_read_verify,
.verify_write = xfs_dquot_buf_write_verify,
};
+const struct xfs_buf_ops xfs_dquot_buf_ra_ops = {
+ .name = "xfs_dquot_ra",
+ .verify_read = xfs_dquot_buf_readahead_verify,
+ .verify_write = xfs_dquot_buf_write_verify,
+};
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 70c1db99f6a7..66d702e6b9ff 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -2572,6 +2572,7 @@ xfs_agi_write_verify(
}
const struct xfs_buf_ops xfs_agi_buf_ops = {
+ .name = "xfs_agi",
.verify_read = xfs_agi_read_verify,
.verify_write = xfs_agi_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
index f39b285beb19..6dd44f9ea727 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
@@ -304,6 +304,7 @@ xfs_inobt_write_verify(
}
const struct xfs_buf_ops xfs_inobt_buf_ops = {
+ .name = "xfs_inobt",
.verify_read = xfs_inobt_read_verify,
.verify_write = xfs_inobt_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index 65485cfc4ade..1aabfda669b0 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -68,6 +68,8 @@ xfs_inobp_check(
* recovery and we don't get unnecssary panics on debug kernels. We use EIO here
* because all we want to do is say readahead failed; there is no-one to report
* the error to, so this will distinguish it from a non-ra verifier failure.
+ * Changes to this readahead error behavour also need to be reflected in
+ * xfs_dquot_buf_readahead_verify().
*/
static void
xfs_inode_buf_verify(
@@ -134,11 +136,13 @@ xfs_inode_buf_write_verify(
}
const struct xfs_buf_ops xfs_inode_buf_ops = {
+ .name = "xfs_inode",
.verify_read = xfs_inode_buf_read_verify,
.verify_write = xfs_inode_buf_write_verify,
};
const struct xfs_buf_ops xfs_inode_buf_ra_ops = {
+ .name = "xxfs_inode_ra",
.verify_read = xfs_inode_buf_readahead_verify,
.verify_write = xfs_inode_buf_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_quota_defs.h b/fs/xfs/libxfs/xfs_quota_defs.h
index 1b0a08379759..f51078f1e92a 100644
--- a/fs/xfs/libxfs/xfs_quota_defs.h
+++ b/fs/xfs/libxfs/xfs_quota_defs.h
@@ -153,7 +153,7 @@ typedef __uint16_t xfs_qwarncnt_t;
#define XFS_QMOPT_RESBLK_MASK (XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_RES_RTBLKS)
extern int xfs_dqcheck(struct xfs_mount *mp, xfs_disk_dquot_t *ddq,
- xfs_dqid_t id, uint type, uint flags, char *str);
+ xfs_dqid_t id, uint type, uint flags, const char *str);
extern int xfs_calc_dquots_per_chunk(unsigned int nbblks);
#endif /* __XFS_QUOTA_H__ */
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index a0b071d881a0..8a53eaa349f4 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -679,11 +679,13 @@ xfs_sb_write_verify(
}
const struct xfs_buf_ops xfs_sb_buf_ops = {
+ .name = "xfs_sb",
.verify_read = xfs_sb_read_verify,
.verify_write = xfs_sb_write_verify,
};
const struct xfs_buf_ops xfs_sb_quiet_buf_ops = {
+ .name = "xfs_sb_quiet",
.verify_read = xfs_sb_quiet_read_verify,
.verify_write = xfs_sb_write_verify,
};
diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h
index 5be529707903..15c3ceb845b9 100644
--- a/fs/xfs/libxfs/xfs_shared.h
+++ b/fs/xfs/libxfs/xfs_shared.h
@@ -49,6 +49,7 @@ extern const struct xfs_buf_ops xfs_inobt_buf_ops;
extern const struct xfs_buf_ops xfs_inode_buf_ops;
extern const struct xfs_buf_ops xfs_inode_buf_ra_ops;
extern const struct xfs_buf_ops xfs_dquot_buf_ops;
+extern const struct xfs_buf_ops xfs_dquot_buf_ra_ops;
extern const struct xfs_buf_ops xfs_sb_buf_ops;
extern const struct xfs_buf_ops xfs_sb_quiet_buf_ops;
extern const struct xfs_buf_ops xfs_symlink_buf_ops;
diff --git a/fs/xfs/libxfs/xfs_symlink_remote.c b/fs/xfs/libxfs/xfs_symlink_remote.c
index cb6fd20a4d3d..2e2c6716b623 100644
--- a/fs/xfs/libxfs/xfs_symlink_remote.c
+++ b/fs/xfs/libxfs/xfs_symlink_remote.c
@@ -168,6 +168,7 @@ xfs_symlink_write_verify(
}
const struct xfs_buf_ops xfs_symlink_buf_ops = {
+ .name = "xfs_symlink",
.verify_read = xfs_symlink_read_verify,
.verify_write = xfs_symlink_write_verify,
};
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index c79b717d9b88..c75721acd867 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -132,6 +132,7 @@ struct xfs_buf_map {
struct xfs_buf_map (map) = { .bm_bn = (blkno), .bm_len = (numblk) };
struct xfs_buf_ops {
+ char *name;
void (*verify_read)(struct xfs_buf *);
void (*verify_write)(struct xfs_buf *);
};
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 74d0e5966ebc..88693a98fac5 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -164,9 +164,9 @@ xfs_verifier_error(
{
struct xfs_mount *mp = bp->b_target->bt_mount;
- xfs_alert(mp, "Metadata %s detected at %pF, block 0x%llx",
+ xfs_alert(mp, "Metadata %s detected at %pF, %s block 0x%llx",
bp->b_error == -EFSBADCRC ? "CRC error" : "corruption",
- __return_address, bp->b_bn);
+ __return_address, bp->b_ops->name, bp->b_bn);
xfs_alert(mp, "Unmount and run xfs_repair");
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index ee3aaa0a5317..ca0d3eb44925 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -243,8 +243,8 @@ xfs_growfs_data_private(
agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp));
agf->agf_levels[XFS_BTNUM_BNOi] = cpu_to_be32(1);
agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1);
- agf->agf_flfirst = 0;
- agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1);
+ agf->agf_flfirst = cpu_to_be32(1);
+ agf->agf_fllast = 0;
agf->agf_flcount = 0;
tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp);
agf->agf_freeblks = cpu_to_be32(tmpsize);
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 8ee393996b7d..f0ce28cd311d 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -3220,13 +3220,14 @@ xfs_iflush_cluster(
* We need to check under the i_flags_lock for a valid inode
* here. Skip it if it is not valid or the wrong inode.
*/
- spin_lock(&ip->i_flags_lock);
- if (!ip->i_ino ||
+ spin_lock(&iq->i_flags_lock);
+ if (!iq->i_ino ||
+ __xfs_iflags_test(iq, XFS_ISTALE) ||
(XFS_INO_TO_AGINO(mp, iq->i_ino) & mask) != first_index) {
- spin_unlock(&ip->i_flags_lock);
+ spin_unlock(&iq->i_flags_lock);
continue;
}
- spin_unlock(&ip->i_flags_lock);
+ spin_unlock(&iq->i_flags_lock);
/*
* Do an un-protected check to see if the inode is dirty and
@@ -3342,7 +3343,7 @@ xfs_iflush(
struct xfs_buf **bpp)
{
struct xfs_mount *mp = ip->i_mount;
- struct xfs_buf *bp;
+ struct xfs_buf *bp = NULL;
struct xfs_dinode *dip;
int error;
@@ -3384,14 +3385,22 @@ xfs_iflush(
}
/*
- * Get the buffer containing the on-disk inode.
+ * Get the buffer containing the on-disk inode. We are doing a try-lock
+ * operation here, so we may get an EAGAIN error. In that case, we
+ * simply want to return with the inode still dirty.
+ *
+ * If we get any other error, we effectively have a corruption situation
+ * and we cannot flush the inode, so we treat it the same as failing
+ * xfs_iflush_int().
*/
error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK,
0);
- if (error || !bp) {
+ if (error == -EAGAIN) {
xfs_ifunlock(ip);
return error;
}
+ if (error)
+ goto corrupt_out;
/*
* First flush out the inode that xfs_iflush was called with.
@@ -3419,7 +3428,8 @@ xfs_iflush(
return 0;
corrupt_out:
- xfs_buf_relse(bp);
+ if (bp)
+ xfs_buf_relse(bp);
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
cluster_corrupt_out:
error = -EFSCORRUPTED;
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index c5ecaacdd218..5991cdcb9040 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -3204,6 +3204,7 @@ xlog_recover_dquot_ra_pass2(
struct xfs_disk_dquot *recddq;
struct xfs_dq_logformat *dq_f;
uint type;
+ int len;
if (mp->m_qflags == 0)
@@ -3224,8 +3225,12 @@ xlog_recover_dquot_ra_pass2(
ASSERT(dq_f);
ASSERT(dq_f->qlf_len == 1);
- xfs_buf_readahead(mp->m_ddev_targp, dq_f->qlf_blkno,
- XFS_FSB_TO_BB(mp, dq_f->qlf_len), NULL);
+ len = XFS_FSB_TO_BB(mp, dq_f->qlf_len);
+ if (xlog_peek_buffer_cancelled(log, dq_f->qlf_blkno, len, 0))
+ return;
+
+ xfs_buf_readahead(mp->m_ddev_targp, dq_f->qlf_blkno, len,
+ &xfs_dquot_buf_ra_ops);
}
STATIC void
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 36bd8825bfb0..ef64a1e1a66a 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1233,6 +1233,16 @@ xfs_fs_remount(
return -EINVAL;
}
+ if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 &&
+ xfs_sb_has_ro_compat_feature(sbp,
+ XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
+ xfs_warn(mp,
+"ro->rw transition prohibited on unknown (0x%x) ro-compat filesystem",
+ (sbp->sb_features_ro_compat &
+ XFS_SB_FEAT_RO_COMPAT_UNKNOWN));
+ return -EINVAL;
+ }
+
mp->m_flags &= ~XFS_MOUNT_RDONLY;
/*
diff --git a/include/asm-generic/qspinlock.h b/include/asm-generic/qspinlock.h
index e2aadbc7151f..1885fc44b1bc 100644
--- a/include/asm-generic/qspinlock.h
+++ b/include/asm-generic/qspinlock.h
@@ -21,14 +21,33 @@
#include <asm-generic/qspinlock_types.h>
/**
+ * queued_spin_unlock_wait - wait until the _current_ lock holder releases the lock
+ * @lock : Pointer to queued spinlock structure
+ *
+ * There is a very slight possibility of live-lock if the lockers keep coming
+ * and the waiter is just unfortunate enough to not see any unlock state.
+ */
+#ifndef queued_spin_unlock_wait
+extern void queued_spin_unlock_wait(struct qspinlock *lock);
+#endif
+
+/**
* queued_spin_is_locked - is the spinlock locked?
* @lock: Pointer to queued spinlock structure
* Return: 1 if it is locked, 0 otherwise
*/
+#ifndef queued_spin_is_locked
static __always_inline int queued_spin_is_locked(struct qspinlock *lock)
{
+ /*
+ * See queued_spin_unlock_wait().
+ *
+ * Any !0 state indicates it is locked, even if _Q_LOCKED_VAL
+ * isn't immediately observable.
+ */
return atomic_read(&lock->val);
}
+#endif
/**
* queued_spin_value_unlocked - is the spinlock structure unlocked?
@@ -98,19 +117,6 @@ static __always_inline void queued_spin_unlock(struct qspinlock *lock)
}
#endif
-/**
- * queued_spin_unlock_wait - wait until current lock holder releases the lock
- * @lock : Pointer to queued spinlock structure
- *
- * There is a very slight possibility of live-lock if the lockers keep coming
- * and the waiter is just unfortunate enough to not see any unlock state.
- */
-static inline void queued_spin_unlock_wait(struct qspinlock *lock)
-{
- while (atomic_read(&lock->val) & _Q_LOCKED_MASK)
- cpu_relax();
-}
-
#ifndef virt_spin_lock
static __always_inline bool virt_spin_lock(struct qspinlock *lock)
{
diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
index 3d1a3af5cf59..a2508a8f9a9c 100644
--- a/include/asm-generic/siginfo.h
+++ b/include/asm-generic/siginfo.h
@@ -17,21 +17,6 @@
struct siginfo;
void do_schedule_next_timer(struct siginfo *info);
-#ifndef HAVE_ARCH_COPY_SIGINFO
-
-#include <linux/string.h>
-
-static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
-{
- if (from->si_code < 0)
- memcpy(to, from, sizeof(*to));
- else
- /* _sigchld is currently the largest know union member */
- memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
-}
-
-#endif
-
extern int copy_siginfo_to_user(struct siginfo __user *to, const struct siginfo *from);
#endif
diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h
index c768ddfbe53c..b7bfa513e6ed 100644
--- a/include/drm/ttm/ttm_bo_api.h
+++ b/include/drm/ttm/ttm_bo_api.h
@@ -316,6 +316,20 @@ ttm_bo_reference(struct ttm_buffer_object *bo)
*/
extern int ttm_bo_wait(struct ttm_buffer_object *bo, bool lazy,
bool interruptible, bool no_wait);
+
+/**
+ * ttm_bo_mem_compat - Check if proposed placement is compatible with a bo
+ *
+ * @placement: Return immediately if buffer is busy.
+ * @mem: The struct ttm_mem_reg indicating the region where the bo resides
+ * @new_flags: Describes compatible placement found
+ *
+ * Returns true if the placement is compatible
+ */
+extern bool ttm_bo_mem_compat(struct ttm_placement *placement,
+ struct ttm_mem_reg *mem,
+ uint32_t *new_flags);
+
/**
* ttm_bo_validate
*
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
index 9006c4e75cf7..3d8dcdd1aeae 100644
--- a/include/linux/amba/bus.h
+++ b/include/linux/amba/bus.h
@@ -163,4 +163,13 @@ struct amba_device name##_device = { \
#define module_amba_driver(__amba_drv) \
module_driver(__amba_drv, amba_driver_register, amba_driver_unregister)
+/*
+ * builtin_amba_driver() - Helper macro for drivers that don't do anything
+ * special in driver initcall. This eliminates a lot of boilerplate. Each
+ * driver may only use this macro once, and calling it replaces the instance
+ * device_initcall().
+ */
+#define builtin_amba_driver(__amba_drv) \
+ builtin_driver(__amba_drv, amba_driver_register)
+
#endif
diff --git a/include/linux/amba/mmci.h b/include/linux/amba/mmci.h
index 8bfd21c13d59..eff56cb0016a 100644
--- a/include/linux/amba/mmci.h
+++ b/include/linux/amba/mmci.h
@@ -40,10 +40,7 @@ struct mmci_platform_data {
int gpio_wp;
int gpio_cd;
bool cd_invert;
- unsigned int status_irq;
struct embedded_sdio_data *embedded_sdio;
- int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
-
};
#endif
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 67bc2da5d233..4f6d29c8e3d8 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -198,6 +198,10 @@ static inline struct bpf_prog *bpf_prog_get(u32 ufd)
static inline void bpf_prog_put(struct bpf_prog *prog)
{
}
+
+static inline void bpf_prog_put_rcu(struct bpf_prog *prog)
+{
+}
#endif /* CONFIG_BPF_SYSCALL */
/* verifier prototypes for helper functions called from eBPF programs */
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 735f9f8c4e43..5261751f6bd4 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -40,8 +40,11 @@ struct can_priv {
struct can_clock clock;
enum can_state state;
- u32 ctrlmode;
- u32 ctrlmode_supported;
+
+ /* CAN controller features - see include/uapi/linux/can/netlink.h */
+ u32 ctrlmode; /* current options setting */
+ u32 ctrlmode_supported; /* options that can be modified by netlink */
+ u32 ctrlmode_static; /* static enabled options for driver/hardware */
int restart_ms;
struct timer_list restart_timer;
@@ -108,6 +111,21 @@ static inline bool can_is_canfd_skb(const struct sk_buff *skb)
return skb->len == CANFD_MTU;
}
+/* helper to define static CAN controller features at device creation time */
+static inline void can_set_static_ctrlmode(struct net_device *dev,
+ u32 static_mode)
+{
+ struct can_priv *priv = netdev_priv(dev);
+
+ /* alloc_candev() succeeded => netdev_priv() is valid at this point */
+ priv->ctrlmode = static_mode;
+ priv->ctrlmode_static = static_mode;
+
+ /* override MTU which was set by default in can_setup()? */
+ if (static_mode & CAN_CTRLMODE_FD)
+ dev->mtu = CANFD_MTU;
+}
+
/* get data length from can_dlc with sanitized can_dlc */
u8 can_dlc2len(u8 can_dlc);
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index d184e283cf81..702b6c53c12f 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -161,7 +161,7 @@ struct dentry_operations {
struct vfsmount *(*d_automount)(struct path *);
int (*d_manage)(struct dentry *, bool);
struct inode *(*d_select_inode)(struct dentry *, unsigned);
- void (*d_canonical_path)(const struct dentry *, struct path *);
+ void (*d_canonical_path)(const struct path *, struct path *);
struct dentry *(*d_real)(struct dentry *, struct inode *);
} ____cacheline_aligned;
@@ -604,5 +604,17 @@ static inline struct inode *vfs_select_inode(struct dentry *dentry,
return inode;
}
+/**
+ * d_real_inode - Return the real inode
+ * @dentry: The dentry to query
+ *
+ * If dentry is on an union/overlay, then return the underlying, real inode.
+ * Otherwise return d_inode().
+ */
+static inline struct inode *d_real_inode(struct dentry *dentry)
+{
+ return d_backing_inode(d_real(dentry));
+}
+
#endif /* __LINUX_DCACHE_H */
diff --git a/include/linux/freezer.h b/include/linux/freezer.h
index 6b7fd9cf5ea2..dd03e837ebb7 100644
--- a/include/linux/freezer.h
+++ b/include/linux/freezer.h
@@ -231,7 +231,7 @@ static inline long freezable_schedule_timeout_killable_unsafe(long timeout)
* call this with locks held.
*/
static inline int freezable_schedule_hrtimeout_range(ktime_t *expires,
- unsigned long delta, const enum hrtimer_mode mode)
+ u64 delta, const enum hrtimer_mode mode)
{
int __retval;
freezer_do_not_count();
diff --git a/include/linux/hdcp_qseecom.h b/include/linux/hdcp_qseecom.h
index f66264bc935a..68f2dd993170 100644
--- a/include/linux/hdcp_qseecom.h
+++ b/include/linux/hdcp_qseecom.h
@@ -26,6 +26,7 @@ enum hdcp_lib_wakeup_cmd {
HDCP_LIB_WKUP_CMD_MSG_RECV_FAILED,
HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT,
HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE,
+ HDCP_LIB_WKUP_CMD_LINK_FAILED,
};
enum hdmi_hdcp_wakeup_cmd {
@@ -47,6 +48,7 @@ struct hdcp_lib_wakeup_data {
};
struct hdcp_msg_part {
+ char *name;
uint32_t offset;
uint32_t length;
};
@@ -106,6 +108,8 @@ static inline char *hdcp_lib_cmd_to_str(uint32_t cmd)
return "HDCP_LIB_WKUP_CMD_MSG_RECV_TIMEOUT";
case HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE:
return "HDCP_LIB_WKUP_CMD_QUERY_STREAM_TYPE";
+ case HDCP_LIB_WKUP_CMD_LINK_FAILED:
+ return "HDCP_LIB_WKUP_CMD_LINK_FAILED";
default:
return "???";
}
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 952adcacc4cf..74921a39edee 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -223,7 +223,7 @@ static inline void hrtimer_set_expires_range(struct hrtimer *timer, ktime_t time
timer->node.expires = ktime_add_safe(time, delta);
}
-static inline void hrtimer_set_expires_range_ns(struct hrtimer *timer, ktime_t time, unsigned long delta)
+static inline void hrtimer_set_expires_range_ns(struct hrtimer *timer, ktime_t time, u64 delta)
{
timer->_softexpires = time;
timer->node.expires = ktime_add_safe(time, ns_to_ktime(delta));
@@ -384,7 +384,7 @@ static inline void destroy_hrtimer_on_stack(struct hrtimer *timer) { }
/* Basic timer operations: */
extern void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
- unsigned long range_ns, const enum hrtimer_mode mode);
+ u64 range_ns, const enum hrtimer_mode mode);
/**
* hrtimer_start - (re)start an hrtimer on the current CPU
@@ -405,7 +405,7 @@ extern int hrtimer_try_to_cancel(struct hrtimer *timer);
static inline void hrtimer_start_expires(struct hrtimer *timer,
enum hrtimer_mode mode)
{
- unsigned long delta;
+ u64 delta;
ktime_t soft, hard;
soft = hrtimer_get_softexpires(timer);
hard = hrtimer_get_expires(timer);
@@ -483,10 +483,12 @@ extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
extern void hrtimer_init_sleeper(struct hrtimer_sleeper *sl,
struct task_struct *tsk);
-extern int schedule_hrtimeout_range(ktime_t *expires, unsigned long delta,
+extern int schedule_hrtimeout_range(ktime_t *expires, u64 delta,
const enum hrtimer_mode mode);
extern int schedule_hrtimeout_range_clock(ktime_t *expires,
- unsigned long delta, const enum hrtimer_mode mode, int clock);
+ u64 delta,
+ const enum hrtimer_mode mode,
+ int clock);
extern int schedule_hrtimeout(ktime_t *expires, const enum hrtimer_mode mode);
/* Soft interrupt function to run the hrtimer queues: */
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index d5d798b35c1f..e98425058f20 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -301,7 +301,7 @@
#define ICC_SGI1R_AFFINITY_1_SHIFT 16
#define ICC_SGI1R_AFFINITY_1_MASK (0xff << ICC_SGI1R_AFFINITY_1_SHIFT)
#define ICC_SGI1R_SGI_ID_SHIFT 24
-#define ICC_SGI1R_SGI_ID_MASK (0xff << ICC_SGI1R_SGI_ID_SHIFT)
+#define ICC_SGI1R_SGI_ID_MASK (0xfULL << ICC_SGI1R_SGI_ID_SHIFT)
#define ICC_SGI1R_AFFINITY_2_SHIFT 32
#define ICC_SGI1R_AFFINITY_2_MASK (0xffULL << ICC_SGI1R_AFFINITY_1_SHIFT)
#define ICC_SGI1R_IRQ_ROUTING_MODE_BIT 40
diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index 0536524bb9eb..68904469fba1 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -117,13 +117,18 @@ struct module;
#include <linux/atomic.h>
+#ifdef HAVE_JUMP_LABEL
+
static inline int static_key_count(struct static_key *key)
{
- return atomic_read(&key->enabled);
+ /*
+ * -1 means the first static_key_slow_inc() is in progress.
+ * static_key_enabled() must return true, so return 1 here.
+ */
+ int n = atomic_read(&key->enabled);
+ return n >= 0 ? n : 1;
}
-#ifdef HAVE_JUMP_LABEL
-
#define JUMP_TYPE_FALSE 0UL
#define JUMP_TYPE_TRUE 1UL
#define JUMP_TYPE_MASK 1UL
@@ -162,6 +167,11 @@ extern void jump_label_apply_nops(struct module *mod);
#else /* !HAVE_JUMP_LABEL */
+static inline int static_key_count(struct static_key *key)
+{
+ return atomic_read(&key->enabled);
+}
+
static __always_inline void jump_label_init(void)
{
static_key_initialized = true;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 57a44fa9ab89..6c1ea7f327c4 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1709,7 +1709,7 @@ extern void free_highmem_page(struct page *page);
extern void adjust_managed_page_count(struct page *page, long count);
extern void mem_init_print_info(const char *str);
-extern void reserve_bootmem_region(unsigned long start, unsigned long end);
+extern void reserve_bootmem_region(phys_addr_t start, phys_addr_t end);
/* Free the reserved page into the buddy system, so it gets managed. */
static inline void __free_reserved_page(struct page *page)
diff --git a/include/linux/net.h b/include/linux/net.h
index 25ef630f1bd6..c00b8d182226 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -251,7 +251,8 @@ do { \
DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT) && \
net_ratelimit()) \
- __dynamic_pr_debug(&descriptor, fmt, ##__VA_ARGS__); \
+ __dynamic_pr_debug(&descriptor, pr_fmt(fmt), \
+ ##__VA_ARGS__); \
} while (0)
#elif defined(DEBUG)
#define net_dbg_ratelimited(fmt, ...) \
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index c5577410c25d..04078e8a4803 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -239,11 +239,18 @@ void xt_unregister_match(struct xt_match *target);
int xt_register_matches(struct xt_match *match, unsigned int n);
void xt_unregister_matches(struct xt_match *match, unsigned int n);
+int xt_check_entry_offsets(const void *base, const char *elems,
+ unsigned int target_offset,
+ unsigned int next_offset);
+
int xt_check_match(struct xt_mtchk_param *, unsigned int size, u_int8_t proto,
bool inv_proto);
int xt_check_target(struct xt_tgchk_param *, unsigned int size, u_int8_t proto,
bool inv_proto);
+void *xt_copy_counters_from_user(const void __user *user, unsigned int len,
+ struct xt_counters_info *info, bool compat);
+
struct xt_table *xt_register_table(struct net *net,
const struct xt_table *table,
struct xt_table_info *bootstrap,
@@ -478,7 +485,7 @@ void xt_compat_init_offsets(u_int8_t af, unsigned int number);
int xt_compat_calc_jump(u_int8_t af, unsigned int offset);
int xt_compat_match_offset(const struct xt_match *match);
-int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
+void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
unsigned int *size);
int xt_compat_match_to_user(const struct xt_entry_match *m,
void __user **dstptr, unsigned int *size);
@@ -488,6 +495,9 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
unsigned int *size);
int xt_compat_target_to_user(const struct xt_entry_target *t,
void __user **dstptr, unsigned int *size);
+int xt_compat_check_entry_offsets(const void *base, const char *elems,
+ unsigned int target_offset,
+ unsigned int next_offset);
#endif /* CONFIG_COMPAT */
#endif /* _X_TABLES_H */
diff --git a/include/linux/nfcinfo.h b/include/linux/nfcinfo.h
new file mode 100644
index 000000000000..595544f92a37
--- /dev/null
+++ b/include/linux/nfcinfo.h
@@ -0,0 +1,6 @@
+#ifndef _NFCINFO_H
+#define _NFCINFO_H
+
+#include <uapi/linux/nfc/nfcinfo.h>
+
+#endif
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 4f28b91f49c5..12d3415a3ef5 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -380,7 +380,7 @@ struct pmu {
/*
* Set up pmu-private data structures for an AUX area
*/
- void *(*setup_aux) (int cpu, void **pages,
+ void *(*setup_aux) (struct perf_event *event, void **pages,
int nr_pages, bool overwrite);
/* optional */
@@ -393,6 +393,14 @@ struct pmu {
* Filter events for PMU-specific reasons.
*/
int (*filter_match) (struct perf_event *event); /* optional */
+
+ /*
+ * Initial, PMU driver specific configuration.
+ */
+ int (*get_drv_configs) (struct perf_event *event,
+ void __user *arg); /* optional */
+ void (*free_drv_configs) (struct perf_event *event);
+ /* optional */
};
/**
@@ -560,6 +568,7 @@ struct perf_event {
struct irq_work pending;
atomic_t event_limit;
+ struct list_head drv_configs;
void (*destroy)(struct perf_event *);
struct rcu_head rcu_head;
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index eb8b8ac6df3c..24f5470d3944 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -42,6 +42,7 @@ struct pipe_buffer {
* @fasync_readers: reader side fasync
* @fasync_writers: writer side fasync
* @bufs: the circular array of pipe buffers
+ * @user: the user who created this pipe
**/
struct pipe_inode_info {
struct mutex mutex;
@@ -57,6 +58,7 @@ struct pipe_inode_info {
struct fasync_struct *fasync_readers;
struct fasync_struct *fasync_writers;
struct pipe_buffer *bufs;
+ struct user_struct *user;
};
/*
@@ -123,6 +125,8 @@ void pipe_unlock(struct pipe_inode_info *);
void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
extern unsigned int pipe_max_size, pipe_min_size;
+extern unsigned long pipe_user_pages_hard;
+extern unsigned long pipe_user_pages_soft;
int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 528be6787796..6a5d654f4447 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -573,6 +573,7 @@ struct dev_pm_info {
struct wakeup_source *wakeup;
bool wakeup_path:1;
bool syscore:1;
+ bool no_pm_callbacks:1; /* Owned by the PM core */
#else
unsigned int should_wakeup:1;
#endif
diff --git a/include/linux/poll.h b/include/linux/poll.h
index c08386fb3e08..9fb4f40d9a26 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -96,7 +96,7 @@ extern void poll_initwait(struct poll_wqueues *pwq);
extern void poll_freewait(struct poll_wqueues *pwq);
extern int poll_schedule_timeout(struct poll_wqueues *pwq, int state,
ktime_t *expires, unsigned long slack);
-extern long select_estimate_accuracy(struct timespec *tv);
+extern u64 select_estimate_accuracy(struct timespec *tv);
static inline int poll_schedule(struct poll_wqueues *pwq, int state)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 06acefeffd4c..4f6711f31939 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -446,6 +446,7 @@ extern unsigned int hardlockup_panic;
void lockup_detector_init(void);
extern void watchdog_enable(unsigned int cpu);
extern void watchdog_disable(unsigned int cpu);
+extern bool watchdog_configured(unsigned int cpu);
#else
static inline void touch_softlockup_watchdog_sched(void)
{
@@ -468,6 +469,14 @@ static inline void watchdog_enable(unsigned int cpu)
static inline void watchdog_disable(unsigned int cpu)
{
}
+static inline bool watchdog_configured(unsigned int cpu)
+{
+ /*
+ * Predend the watchdog is always configured.
+ * We will be waiting for the watchdog to be enabled in core isolation
+ */
+ return true;
+}
#endif
#ifdef CONFIG_DETECT_HUNG_TASK
@@ -900,6 +909,7 @@ struct user_struct {
#endif
unsigned long locked_shm; /* How many pages of mlocked shm ? */
unsigned long unix_inflight; /* How many files in flight in unix sockets */
+ atomic_long_t pipe_bufs; /* how many pages are allocated in pipe buffers */
#ifdef CONFIG_KEYS
struct key *uid_keyring; /* UID specific keyring */
@@ -1900,8 +1910,8 @@ struct task_struct {
* time slack values; these are used to round up poll() and
* select() etc timeout values. These are in nanoseconds.
*/
- unsigned long timer_slack_ns;
- unsigned long default_timer_slack_ns;
+ u64 timer_slack_ns;
+ u64 default_timer_slack_ns;
#ifdef CONFIG_KASAN
unsigned int kasan_depth;
@@ -2392,6 +2402,7 @@ struct cpu_cycle_counter_cb {
};
#ifdef CONFIG_SCHED_HMP
+extern void free_task_load_ptrs(struct task_struct *p);
extern int sched_set_window(u64 window_start, unsigned int window_size);
extern unsigned long sched_get_busy(int cpu);
extern void sched_get_cpus_busy(struct sched_load *busy,
@@ -2417,6 +2428,8 @@ extern int sched_set_group_id(struct task_struct *p, unsigned int group_id);
extern unsigned int sched_get_group_id(struct task_struct *p);
#else /* CONFIG_SCHED_HMP */
+static inline void free_task_load_ptrs(struct task_struct *p) { }
+
static inline u64 sched_ktime_clock(void)
{
return 0;
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 92557bbce7e7..d80259afb9e5 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -28,6 +28,21 @@ struct sigpending {
sigset_t signal;
};
+#ifndef HAVE_ARCH_COPY_SIGINFO
+
+#include <linux/string.h>
+
+static inline void copy_siginfo(struct siginfo *to, struct siginfo *from)
+{
+ if (from->si_code < 0)
+ memcpy(to, from, sizeof(*to));
+ else
+ /* _sigchld is currently the largest know union member */
+ memcpy(to, from, __ARCH_SI_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
+}
+
+#endif
+
/*
* Define some primitives to manipulate sigset_t.
*/
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 4fde61804191..d443d9ab0236 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -982,6 +982,7 @@ __skb_set_sw_hash(struct sk_buff *skb, __u32 hash, bool is_l4)
}
void __skb_get_hash(struct sk_buff *skb);
+u32 __skb_get_hash_symmetric(struct sk_buff *skb);
u32 skb_get_poff(const struct sk_buff *skb);
u32 __skb_get_poff(const struct sk_buff *skb, void *data,
const struct flow_keys *keys, int hlen);
@@ -2564,6 +2565,13 @@ static inline int skb_clone_writable(const struct sk_buff *skb, unsigned int len
skb_headroom(skb) + len <= skb->hdr_len;
}
+static inline int skb_try_make_writable(struct sk_buff *skb,
+ unsigned int write_len)
+{
+ return skb_cloned(skb) && !skb_clone_writable(skb, write_len) &&
+ pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+}
+
static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom,
int cloned)
{
@@ -2766,6 +2774,25 @@ static inline void skb_postpush_rcsum(struct sk_buff *skb,
}
/**
+ * skb_push_rcsum - push skb and update receive checksum
+ * @skb: buffer to update
+ * @len: length of data pulled
+ *
+ * This function performs an skb_push on the packet and updates
+ * the CHECKSUM_COMPLETE checksum. It should be used on
+ * receive path processing instead of skb_push unless you know
+ * that the checksum difference is zero (e.g., a valid IP header)
+ * or you are setting ip_summed to CHECKSUM_NONE.
+ */
+static inline unsigned char *skb_push_rcsum(struct sk_buff *skb,
+ unsigned int len)
+{
+ skb_push(skb, len);
+ skb_postpush_rcsum(skb, skb->data, len);
+ return skb->data;
+}
+
+/**
* pskb_trim_rcsum - trim received skb and update checksum
* @skb: buffer to trim
* @len: new length
diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h
index 4018b48f2b3b..a0596ca0e80a 100644
--- a/include/linux/sock_diag.h
+++ b/include/linux/sock_diag.h
@@ -36,6 +36,9 @@ enum sknetlink_groups sock_diag_destroy_group(const struct sock *sk)
{
switch (sk->sk_family) {
case AF_INET:
+ if (sk->sk_type == SOCK_RAW)
+ return SKNLGRP_NONE;
+
switch (sk->sk_protocol) {
case IPPROTO_TCP:
return SKNLGRP_INET_TCP_DESTROY;
@@ -45,6 +48,9 @@ enum sknetlink_groups sock_diag_destroy_group(const struct sock *sk)
return SKNLGRP_NONE;
}
case AF_INET6:
+ if (sk->sk_type == SOCK_RAW)
+ return SKNLGRP_NONE;
+
switch (sk->sk_protocol) {
case IPPROTO_TCP:
return SKNLGRP_INET6_TCP_DESTROY;
diff --git a/include/linux/spmi.h b/include/linux/spmi.h
index 1396a255d2a2..319c52a298ef 100644
--- a/include/linux/spmi.h
+++ b/include/linux/spmi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -171,6 +171,19 @@ static inline void spmi_driver_unregister(struct spmi_driver *sdrv)
module_driver(__spmi_driver, spmi_driver_register, \
spmi_driver_unregister)
+#ifdef CONFIG_QCOM_SHOW_RESUME_IRQ
+extern int msm_show_resume_irq_mask;
+static inline bool spmi_show_resume_irq(void)
+{
+ return msm_show_resume_irq_mask;
+}
+#else
+static inline bool spmi_show_resume_irq(void)
+{
+ return false;
+}
+#endif
+
int spmi_register_read(struct spmi_device *sdev, u8 addr, u8 *buf);
int spmi_ext_register_read(struct spmi_device *sdev, u8 addr, u8 *buf,
size_t len);
diff --git a/include/linux/stm.h b/include/linux/stm.h
index 9d0083d364e6..8369d8a8cabd 100644
--- a/include/linux/stm.h
+++ b/include/linux/stm.h
@@ -50,6 +50,8 @@ struct stm_device;
* @sw_end: last STP master available to software
* @sw_nchannels: number of STP channels per master
* @sw_mmiosz: size of one channel's IO space, for mmap, optional
+ * @hw_override: masters in the STP stream will not match the ones
+ * assigned by software, but are up to the STM hardware
* @packet: callback that sends an STP packet
* @mmio_addr: mmap callback, optional
* @link: called when a new stm_source gets linked to us, optional
@@ -67,6 +69,16 @@ struct stm_device;
* description. That is, the lowest master that can be allocated to software
* writers is @sw_start and data from this writer will appear is @sw_start
* master in the STP stream.
+ *
+ * The @packet callback should adhere to the following rules:
+ * 1) it must return the number of bytes it consumed from the payload;
+ * 2) therefore, if it sent a packet that does not have payload (like FLAG),
+ * it must return zero;
+ * 3) if it does not support the requested packet type/flag combination,
+ * it must return -ENOTSUPP.
+ *
+ * The @unlink callback is called when there are no more active writers so
+ * that the master/channel can be quiesced.
*/
struct stm_data {
const char *name;
@@ -75,6 +87,7 @@ struct stm_data {
unsigned int sw_end;
unsigned int sw_nchannels;
unsigned int sw_mmiosz;
+ unsigned int hw_override;
ssize_t (*packet)(struct stm_data *, unsigned int,
unsigned int, unsigned int,
unsigned int, unsigned int,
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 131032f15cc1..9b6027c51736 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -135,8 +135,6 @@ struct rpc_create_args {
#define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT (1UL << 9)
struct rpc_clnt *rpc_create(struct rpc_create_args *args);
-struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
- struct rpc_xprt *xprt);
struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *,
const struct rpc_program *, u32);
void rpc_task_reset_client(struct rpc_task *task, struct rpc_clnt *clnt);
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 3bf03b6b52e9..83b264c52898 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -338,7 +338,6 @@ struct tty_file_private {
#define TTY_EXCLUSIVE 3 /* Exclusive open mode */
#define TTY_DEBUG 4 /* Debugging */
#define TTY_DO_WRITE_WAKEUP 5 /* Call write_wakeup after queuing new */
-#define TTY_OTHER_DONE 6 /* Closed pty has completed input processing */
#define TTY_LDISC_OPEN 11 /* Line discipline is open */
#define TTY_PTY_LOCK 16 /* pty private */
#define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */
@@ -469,6 +468,7 @@ extern void tty_buffer_init(struct tty_port *port);
extern void tty_buffer_set_lock_subclass(struct tty_port *port);
extern bool tty_buffer_restart_work(struct tty_port *port);
extern bool tty_buffer_cancel_work(struct tty_port *port);
+extern void tty_buffer_flush_work(struct tty_port *port);
extern speed_t tty_termios_baud_rate(struct ktermios *termios);
extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
extern void tty_termios_encode_baud_rate(struct ktermios *termios,
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 55240f9a3b94..440248ba4123 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1079,7 +1079,7 @@ struct usbdrv_wrap {
* for interfaces bound to this driver.
* @soft_unbind: if set to 1, the USB core will not kill URBs and disable
* endpoints before calling the driver's disconnect method.
- * @disable_hub_initiated_lpm: if set to 0, the USB core will not allow hubs
+ * @disable_hub_initiated_lpm: if set to 1, the USB core will not allow hubs
* to initiate lower power link state transitions when an idle timeout
* occurs. Device-initiated USB 3.0 link PM will still be allowed.
*
diff --git a/include/linux/usb/class-dual-role.h b/include/linux/usb/class-dual-role.h
index af42ed34944a..c6df2238012e 100644
--- a/include/linux/usb/class-dual-role.h
+++ b/include/linux/usb/class-dual-role.h
@@ -109,18 +109,19 @@ extern int dual_role_property_is_writeable(struct dual_role_phy_instance
enum dual_role_property prop);
extern void *dual_role_get_drvdata(struct dual_role_phy_instance *dual_role);
#else /* CONFIG_DUAL_ROLE_USB_INTF */
-static void dual_role_instance_changed(struct dual_role_phy_instance
+static inline void dual_role_instance_changed(struct dual_role_phy_instance
*dual_role){}
-static struct dual_role_phy_instance *__must_check
+static inline struct dual_role_phy_instance *__must_check
devm_dual_role_instance_register(struct device *parent,
const struct dual_role_phy_desc *desc)
{
return ERR_PTR(-ENOSYS);
}
-static void devm_dual_role_instance_unregister(struct device *dev,
+static inline void devm_dual_role_instance_unregister(struct device *dev,
struct dual_role_phy_instance
*dual_role){}
-static void *dual_role_get_drvdata(struct dual_role_phy_instance *dual_role)
+static inline void *dual_role_get_drvdata(struct dual_role_phy_instance
+ *dual_role)
{
return ERR_PTR(-ENOSYS);
}
diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h
index 966889a20ea3..e479033bd782 100644
--- a/include/linux/usb/ehci_def.h
+++ b/include/linux/usb/ehci_def.h
@@ -180,11 +180,11 @@ struct ehci_regs {
* PORTSCx
*/
/* HOSTPC: offset 0x84 */
- u32 hostpc[1]; /* HOSTPC extension */
+ u32 hostpc[0]; /* HOSTPC extension */
#define HOSTPC_PHCD (1<<22) /* Phy clock disable */
#define HOSTPC_PSPD (3<<25) /* Port speed detection */
- u32 reserved5[16];
+ u32 reserved5[17];
/* USBMODE_EX: offset 0xc8 */
u32 usbmode_ex; /* USB Device mode extension */
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 62a750a6a8f8..af40bc586a1b 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -230,6 +230,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd);
int ip_tunnel_encap(struct sk_buff *skb, struct ip_tunnel *t,
u8 *protocol, struct flowi4 *fl4);
+int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict);
int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu);
struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev,
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 1d22ce9f352e..31d0e5143848 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -88,7 +88,7 @@ struct switchdev_obj_ipv4_fib {
struct switchdev_obj obj;
u32 dst;
int dst_len;
- struct fib_info fi;
+ struct fib_info *fi;
u8 tos;
u8 type;
u32 nlflags;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 15ee95fcd561..5ed36a59b08e 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1695,8 +1695,6 @@ static inline bool tcp_stream_memory_free(const struct sock *sk)
return notsent_bytes < tcp_notsent_lowat(tp);
}
-extern int tcp_nuke_addr(struct net *net, struct sockaddr *addr);
-
#ifdef CONFIG_PROC_FS
int tcp4_proc_init(void);
void tcp4_proc_exit(void);
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index f9f445be1a50..c37b22101473 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -243,6 +243,7 @@ scmd_printk(const char *, const struct scsi_cmnd *, const char *, ...);
enum scsi_target_state {
STARGET_CREATED = 1,
STARGET_RUNNING,
+ STARGET_REMOVE,
STARGET_DEL,
};
diff --git a/include/soc/qcom/qseecomi.h b/include/soc/qcom/qseecomi.h
index b0a8d67f50fa..e33fd9fc1841 100644
--- a/include/soc/qcom/qseecomi.h
+++ b/include/soc/qcom/qseecomi.h
@@ -68,6 +68,7 @@ enum qseecom_qceos_cmd_id {
QSEOS_CLIENT_SEND_DATA_COMMAND_WHITELIST = 0x1C,
QSEOS_TEE_OPEN_SESSION_WHITELIST = 0x1D,
QSEOS_TEE_INVOKE_COMMAND_WHITELIST = 0x1E,
+ QSEOS_LISTENER_DATA_RSP_COMMAND_WHITELIST = 0x1F,
QSEOS_FSM_LTEOTA_REQ_CMD = 0x109,
QSEOS_FSM_LTEOTA_REQ_RSP_CMD = 0x110,
QSEOS_FSM_IKE_REQ_CMD = 0x203,
@@ -217,6 +218,16 @@ __packed struct qseecom_client_listener_data_irsp {
uint32_t qsee_cmd_id;
uint32_t listener_id;
uint32_t status;
+ uint32_t sglistinfo_ptr;
+ uint32_t sglistinfo_len;
+};
+
+__packed struct qseecom_client_listener_data_64bit_irsp {
+ uint32_t qsee_cmd_id;
+ uint32_t listener_id;
+ uint32_t status;
+ uint64_t sglistinfo_ptr;
+ uint32_t sglistinfo_len;
};
/*
@@ -703,4 +714,12 @@ __packed struct qseecom_continue_blocked_request_ireq {
TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_BUF_RW, \
TZ_SYSCALL_PARAM_TYPE_VAL)
+#define TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_ID \
+ TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x05)
+
+#define TZ_OS_LISTENER_RESPONSE_HANDLER_WITH_WHITELIST_PARAM_ID \
+ TZ_SYSCALL_CREATE_PARAM_ID_4( \
+ TZ_SYSCALL_PARAM_TYPE_VAL, TZ_SYSCALL_PARAM_TYPE_VAL, \
+ TZ_SYSCALL_PARAM_TYPE_BUF_RW, TZ_SYSCALL_PARAM_TYPE_VAL)
+
#endif /* __QSEECOMI_H_ */
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 06b72b262395..e713641cc3ec 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -914,6 +914,34 @@ struct adm_cmd_connect_afe_port_v5 {
#define AFE_PORT_ID_SENARY_MI2S_RX 0x1018
/* ID of the senary MI2S Tx port. */
#define AFE_PORT_ID_SENARY_MI2S_TX 0x1019
+/* ID of the Internal 0 MI2S Rx port */
+#define AFE_PORT_ID_INT0_MI2S_RX 0x102E
+/* ID of the Internal 0 MI2S Tx port */
+#define AFE_PORT_ID_INT0_MI2S_TX 0x102F
+/* ID of the Internal 1 MI2S Rx port */
+#define AFE_PORT_ID_INT1_MI2S_RX 0x1030
+/* ID of the Internal 1 MI2S Tx port */
+#define AFE_PORT_ID_INT1_MI2S_TX 0x1031
+/* ID of the Internal 2 MI2S Rx port */
+#define AFE_PORT_ID_INT2_MI2S_RX 0x1032
+/* ID of the Internal 2 MI2S Tx port */
+#define AFE_PORT_ID_INT2_MI2S_TX 0x1033
+/* ID of the Internal 3 MI2S Rx port */
+#define AFE_PORT_ID_INT3_MI2S_RX 0x1034
+/* ID of the Internal 3 MI2S Tx port */
+#define AFE_PORT_ID_INT3_MI2S_TX 0x1035
+/* ID of the Internal 4 MI2S Rx port */
+#define AFE_PORT_ID_INT4_MI2S_RX 0x1036
+/* ID of the Internal 4 MI2S Tx port */
+#define AFE_PORT_ID_INT4_MI2S_TX 0x1037
+/* ID of the Internal 5 MI2S Rx port */
+#define AFE_PORT_ID_INT5_MI2S_RX 0x1038
+/* ID of the Internal 5 MI2S Tx port */
+#define AFE_PORT_ID_INT5_MI2S_TX 0x1039
+/* ID of the Internal 6 MI2S Rx port */
+#define AFE_PORT_ID_INT6_MI2S_RX 0x103A
+/* ID of the Internal 6 MI2S Tx port */
+#define AFE_PORT_ID_INT6_MI2S_TX 0x103B
#define AFE_PORT_ID_SPDIF_RX 0x5000
#define AFE_PORT_ID_RT_PROXY_PORT_001_RX 0x2000
#define AFE_PORT_ID_RT_PROXY_PORT_001_TX 0x2001
@@ -8858,6 +8886,20 @@ enum afe_lpass_clk_mode {
#define Q6AFE_LPASS_CLK_ID_SEN_MI2S_IBIT 0x10D
/* Clock ID for SENARY I2S EBIT */
#define Q6AFE_LPASS_CLK_ID_SEN_MI2S_EBIT 0x10E
+/* Clock ID for INT0 I2S IBIT */
+#define Q6AFE_LPASS_CLK_ID_INT0_MI2S_IBIT 0x10F
+/* Clock ID for INT1 I2S IBIT */
+#define Q6AFE_LPASS_CLK_ID_INT1_MI2S_IBIT 0x110
+/* Clock ID for INT2 I2S IBIT */
+#define Q6AFE_LPASS_CLK_ID_INT2_MI2S_IBIT 0x111
+/* Clock ID for INT3 I2S IBIT */
+#define Q6AFE_LPASS_CLK_ID_INT3_MI2S_IBIT 0x112
+/* Clock ID for INT4 I2S IBIT */
+#define Q6AFE_LPASS_CLK_ID_INT4_MI2S_IBIT 0x113
+/* Clock ID for INT5 I2S IBIT */
+#define Q6AFE_LPASS_CLK_ID_INT5_MI2S_IBIT 0x114
+/* Clock ID for INT6 I2S IBIT */
+#define Q6AFE_LPASS_CLK_ID_INT6_MI2S_IBIT 0x115
/* Clock ID for Primary PCM IBIT */
#define Q6AFE_LPASS_CLK_ID_PRI_PCM_IBIT 0x200
@@ -8899,8 +8941,19 @@ enum afe_lpass_clk_mode {
#define Q6AFE_LPASS_CLK_ID_MCLK_2 0x301
/* Clock ID for MCLK3 */
#define Q6AFE_LPASS_CLK_ID_MCLK_3 0x302
+/* Clock ID for MCLK4 */
+#define Q6AFE_LPASS_CLK_ID_MCLK_4 0x304
/* Clock ID for Internal Digital Codec Core */
#define Q6AFE_LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE 0x303
+/* Clock ID for INT MCLK0 */
+#define Q6AFE_LPASS_CLK_ID_INT_MCLK_0 0x305
+/* Clock ID for INT MCLK1 */
+#define Q6AFE_LPASS_CLK_ID_INT_MCLK_1 0x306
+/*
+ * Clock ID for soundwire NPL.
+ * This is the clock to be used to enable NPL clock for internal Soundwire.
+ */
+#define AFE_CLOCK_SET_CLOCK_ID_SWR_NPL_CLK 0x307
/* Clock ID for AHB HDMI input */
#define Q6AFE_LPASS_CLK_ID_AHB_HDMI_INPUT 0x400
diff --git a/include/sound/msm-dai-q6-v2.h b/include/sound/msm-dai-q6-v2.h
index c3c65a02a817..b1d76bf73f51 100644
--- a/include/sound/msm-dai-q6-v2.h
+++ b/include/sound/msm-dai-q6-v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -28,8 +28,15 @@
#define MSM_SEC_MI2S_SD1 4
#define MSM_QUIN_MI2S 5
#define MSM_SENARY_MI2S 6
+#define MSM_INT0_MI2S 7
+#define MSM_INT1_MI2S 8
+#define MSM_INT2_MI2S 9
+#define MSM_INT3_MI2S 10
+#define MSM_INT4_MI2S 11
+#define MSM_INT5_MI2S 12
+#define MSM_INT6_MI2S 13
#define MSM_MI2S_MIN MSM_PRIM_MI2S
-#define MSM_MI2S_MAX MSM_SENARY_MI2S
+#define MSM_MI2S_MAX MSM_INT6_MI2S
struct msm_dai_auxpcm_config {
u16 mode;
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 31f7c02b54b3..e0da428fa52f 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -183,10 +183,26 @@ enum {
IDX_AFE_PORT_ID_USB_TX,
/* IDX 124 */
IDX_DISPLAY_PORT_RX,
+ /* IDX 125-> 128 */
IDX_AFE_PORT_ID_TERTIARY_PCM_RX,
IDX_AFE_PORT_ID_TERTIARY_PCM_TX,
IDX_AFE_PORT_ID_QUATERNARY_PCM_RX,
IDX_AFE_PORT_ID_QUATERNARY_PCM_TX,
+ /* IDX 129-> 142 */
+ IDX_AFE_PORT_ID_INT0_MI2S_RX,
+ IDX_AFE_PORT_ID_INT0_MI2S_TX,
+ IDX_AFE_PORT_ID_INT1_MI2S_RX,
+ IDX_AFE_PORT_ID_INT1_MI2S_TX,
+ IDX_AFE_PORT_ID_INT2_MI2S_RX,
+ IDX_AFE_PORT_ID_INT2_MI2S_TX,
+ IDX_AFE_PORT_ID_INT3_MI2S_RX,
+ IDX_AFE_PORT_ID_INT3_MI2S_TX,
+ IDX_AFE_PORT_ID_INT4_MI2S_RX,
+ IDX_AFE_PORT_ID_INT4_MI2S_TX,
+ IDX_AFE_PORT_ID_INT5_MI2S_RX,
+ IDX_AFE_PORT_ID_INT5_MI2S_TX,
+ IDX_AFE_PORT_ID_INT6_MI2S_RX,
+ IDX_AFE_PORT_ID_INT6_MI2S_TX,
AFE_MAX_PORTS
};
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
index 80bfd1e8f813..4cbe6a37d121 100644
--- a/include/sound/soc-dai.h
+++ b/include/sound/soc-dai.h
@@ -269,7 +269,7 @@ struct snd_soc_dai {
struct snd_soc_dai_driver *driver;
/* DAI runtime info */
- unsigned int capture_active:1; /* stream is in use */
+ unsigned int capture_active; /* stream is in use */
unsigned int playback_active; /* stream is in use */
unsigned int symmetric_rates:1;
unsigned int symmetric_channels:1;
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index d6ff882ad6a7..14bd1e806ad7 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -23,6 +23,7 @@ header-y += netfilter_ipv6/
header-y += usb/
header-y += wimax/
header-y += mfd/
+header-y += nfc/
genhdr-y += version.h
diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h
index a08933a58079..8a702e7b3f71 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -359,6 +359,7 @@ enum fuse_opcode {
FUSE_FALLOCATE = 43,
FUSE_READDIRPLUS = 44,
FUSE_RENAME2 = 45,
+ FUSE_CANONICAL_PATH= 2016,
/* CUSE specific operations */
CUSE_INIT = 4096,
diff --git a/include/uapi/linux/libc-compat.h b/include/uapi/linux/libc-compat.h
index d5e38c73377c..e4f048ee7043 100644
--- a/include/uapi/linux/libc-compat.h
+++ b/include/uapi/linux/libc-compat.h
@@ -52,7 +52,7 @@
#if defined(__GLIBC__)
/* Coordinate with glibc net/if.h header. */
-#if defined(_NET_IF_H)
+#if defined(_NET_IF_H) && defined(__USE_MISC)
/* GLIBC headers included first so don't define anything
* that would already be defined. */
diff --git a/include/uapi/linux/msm_mdp_ext.h b/include/uapi/linux/msm_mdp_ext.h
index 811d8b4e1994..1a71e860ba48 100644
--- a/include/uapi/linux/msm_mdp_ext.h
+++ b/include/uapi/linux/msm_mdp_ext.h
@@ -96,6 +96,10 @@ LAYER FLAG CONFIGURATION
*/
#define MDP_LAYER_MULTIRECT_PARALLEL_MODE 0x2000
+
+/* Flag indicates that layer is associated with secure camera session */
+#define MDP_LAYER_SECURE_CAMERA_SESSION 0x4000
+
/**********************************************************************
DESTINATION SCALER FLAG CONFIGURATION
**********************************************************************/
@@ -147,6 +151,9 @@ VALIDATE/COMMIT FLAG CONFIGURATION
*/
#define MDP_COMMIT_AVR_ONE_SHOT_MODE 0x10
+/* Flag to indicate dual partial ROI update */
+#define MDP_COMMIT_PARTIAL_UPDATE_DUAL_ROI 0x20
+
/* Flag to enable concurrent writeback for the frame */
#define MDP_COMMIT_CWB_EN 0x800
diff --git a/include/uapi/linux/nfc/Kbuild b/include/uapi/linux/nfc/Kbuild
new file mode 100644
index 000000000000..90710153e462
--- /dev/null
+++ b/include/uapi/linux/nfc/Kbuild
@@ -0,0 +1,2 @@
+#UAPI export list
+header-y += nfcinfo.h
diff --git a/include/uapi/linux/nfc/nfcinfo.h b/include/uapi/linux/nfc/nfcinfo.h
new file mode 100644
index 000000000000..df178e2bbae6
--- /dev/null
+++ b/include/uapi/linux/nfc/nfcinfo.h
@@ -0,0 +1,21 @@
+#ifndef _UAPI_NFCINFO_H_
+#define _UAPI_NFCINFO_H_
+
+#include <linux/ioctl.h>
+
+#define NFCC_MAGIC 0xE9
+#define NFCC_GET_INFO _IOW(NFCC_MAGIC, 0x09, unsigned int)
+
+struct nqx_devinfo {
+ unsigned char chip_type;
+ unsigned char rom_version;
+ unsigned char fw_major;
+ unsigned char fw_minor;
+};
+
+union nqx_uinfo {
+ unsigned int i;
+ struct nqx_devinfo info;
+};
+
+#endif
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 7ac89001d223..686da166aeec 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -397,6 +397,7 @@ struct perf_event_attr {
#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *)
#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)
#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)
+#define PERF_EVENT_IOC_SET_DRV_CONFIGS _IOW('$', 10, char *)
enum perf_event_ioc_flags {
PERF_IOC_FLAG_GROUP = 1U << 0,
diff --git a/include/uapi/media/msm_sde_rotator.h b/include/uapi/media/msm_sde_rotator.h
index 4487edf0c854..12976e3f14d7 100644
--- a/include/uapi/media/msm_sde_rotator.h
+++ b/include/uapi/media/msm_sde_rotator.h
@@ -86,4 +86,10 @@ struct msm_sde_rotator_fence {
/* SDE Rotator private control ID's */
#define V4L2_CID_SDE_ROTATOR_SECURE (V4L2_CID_USER_BASE + 0x1000)
+/*
+ * This control Id indicates this context is associated with the
+ * secure camera
+ */
+#define V4L2_CID_SDE_ROTATOR_SECURE_CAMERA (V4L2_CID_USER_BASE + 0x2000)
+
#endif /* __UAPI_MSM_SDE_ROTATOR_H__ */
diff --git a/include/uapi/media/msmb_ispif.h b/include/uapi/media/msmb_ispif.h
index 7f4deaf12683..3720056aa28d 100644
--- a/include/uapi/media/msmb_ispif.h
+++ b/include/uapi/media/msmb_ispif.h
@@ -28,6 +28,7 @@ enum msm_ispif_intftype {
};
#define MAX_PARAM_ENTRIES (INTF_MAX * 2)
#define MAX_CID_CH 8
+#define MAX_CID_CH_PARAM_ENTRY 3
#define PIX0_MASK (1 << PIX0)
#define PIX1_MASK (1 << PIX1)
@@ -94,7 +95,7 @@ struct msm_ispif_params_entry {
enum msm_ispif_vfe_intf vfe_intf;
enum msm_ispif_intftype intftype;
int num_cids;
- enum msm_ispif_cid cids[3];
+ enum msm_ispif_cid cids[MAX_CID_CH_PARAM_ENTRY];
enum msm_ispif_csid csid;
int crop_enable;
uint16_t crop_start_pixel;
diff --git a/include/video/imx-ipu-v3.h b/include/video/imx-ipu-v3.h
index eeba75395f7d..c8529ce28a3f 100644
--- a/include/video/imx-ipu-v3.h
+++ b/include/video/imx-ipu-v3.h
@@ -16,6 +16,7 @@
#include <linux/videodev2.h>
#include <linux/bitmap.h>
#include <linux/fb.h>
+#include <linux/of.h>
#include <media/v4l2-mediabus.h>
#include <video/videomode.h>
@@ -344,6 +345,7 @@ struct ipu_client_platformdata {
int dc;
int dp;
int dma[2];
+ struct device_node *of_node;
};
#endif /* __DRM_IPU_H__ */
diff --git a/kernel/Documentation/firmware_updater/request_firmware.txt b/kernel/Documentation/firmware_updater/request_firmware.txt
deleted file mode 100644
index 317f04ac5684..000000000000
--- a/kernel/Documentation/firmware_updater/request_firmware.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-Firmware Update Function
-========================
-
-Call export function "synaptics_fw_updater" in rmi_fw_update.c to start
-firmware updating process in the driver.
-
-The RMI4 driver uses the kernel's request_firmware() feature to obtain
-firmware for the touch sensor. The firmware is expected to live in
-the file firmware/<firmware_name>.img.ihex.
-
-To prepare Synaptics provided .img file for reflashing, convert it to .ihex
-format using the following command:
-
- objcopy -I binary -O ihex <firmware_name>.img firmware/<firmware_name>.img.ihex
-
-Then make sure to add the image file name to the
-CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_FW_UPDATE entry in firmware/Makefile.
-If you don't do this, the image file won't be included, and
-the firmware loader class will delay for 60 seconds waiting for a non-existent
-userspace response to the firmware load request.
-
-Firmware updates for multichip solutions (aka LTS) are not supported.
diff --git a/kernel/Documentation/firmware_updater/synaptics_fw_updater b/kernel/Documentation/firmware_updater/synaptics_fw_updater
deleted file mode 100644
index b0c1b4d9e770..000000000000
--- a/kernel/Documentation/firmware_updater/synaptics_fw_updater
+++ /dev/null
Binary files differ
diff --git a/kernel/Documentation/firmware_updater/synaptics_fw_updater.c b/kernel/Documentation/firmware_updater/synaptics_fw_updater.c
deleted file mode 100644
index 7409dd424109..000000000000
--- a/kernel/Documentation/firmware_updater/synaptics_fw_updater.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- *
- * Copyright © 2011, 2012 Synaptics Incorporated. All rights reserved.
- *
- * The information in this file is confidential under the terms
- * of a non-disclosure agreement with Synaptics and is provided
- * AS IS without warranties or guarantees of any kind.
- *
- * The information in this file shall remain the exclusive property
- * of Synaptics and may be the subject of Synaptics patents, in
- * whole or part. Synaptics intellectual property rights in the
- * information in this file are not expressly or implicitly licensed
- * or otherwise transferred to you as a result of such information
- * being made available to you.
- *
- * File: synaptics_fw_updater.c
- *
- * Description: command line reflash implimentation using command
- * line args. This file should not be OS dependant and should build and
- * run under any Linux based OS that utilizes the Synaptice rmi driver
- * built into the kernel (kernel/drivers/input/rmi4).
- *
- * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- */
-#include <errno.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <sys/time.h>
-
-#define DEFAULT_SENSOR "/sys/class/input/input1"
-
-#define MAX_STRING_LEN 256
-#define MAX_INT_LEN 33
-
-#define DATA_FILENAME "data"
-#define IMAGESIZE_FILENAME "imagesize"
-#define DOREFLASH_FILENAME "doreflash"
-#define CONFIGAREA_FILENAME "configarea"
-#define READCONFIG_FILENAME "readconfig"
-#define WRITECONFIG_FILENAME "writeconfig"
-#define BLOCKSIZE_FILENAME "blocksize"
-#define IMAGEBLOCKCOUNT_FILENAME "fwblockcount"
-#define CONFIGBLOCKCOUNT_FILENAME "configblockcount"
-#define PMCONFIGBLOCKCOUNT_FILENAME "permconfigblockcount"
-#define BUILDID_FILENAME "buildid"
-#define FLASHPROG_FILENAME "flashprog"
-
-#define UI_CONFIG_AREA 0
-#define PERM_CONFIG_AREA 1
-#define BL_CONFIG_AREA 2
-#define DISP_CONFIG_AREA 3
-
-#define IMAGE_FILE_CHECKSUM_SIZE 4
-
-unsigned char *firmware = NULL;
-int fileSize;
-int firmwareBlockSize;
-int firmwareBlockCount;
-int firmwareImgSize;
-int configBlockSize;
-int configBlockCount;
-int configImgSize;
-int totalBlockCount;
-int readConfig = 0;
-int writeConfig = 0;
-int uiConfig = 0;
-int pmConfig = 0;
-int blConfig = 0;
-int dpConfig = 0;
-int force = 0;
-int verbose = 0;
-
-char mySensor[MAX_STRING_LEN];
-char imageFileName[MAX_STRING_LEN];
-
-static void usage(char *name)
-{
- printf("Usage: %s [-b {image_file}] [-d {sysfs_entry}] [-r] [-ui] [-pm] [-bl] [-dp] [-f] [-v]\n", name);
- printf("\t[-b {image_file}] - Name of image file\n");
- printf("\t[-d {sysfs_entry}] - Path to sysfs entry of sensor\n");
- printf("\t[-r] - Read config area\n");
- printf("\t[-ui] - UI config area\n");
- printf("\t[-pm] - Permanent config area\n");
- printf("\t[-bl] - BL config area\n");
- printf("\t[-dp] - Display config area\n");
- printf("\t[-f] - Force reflash\n");
- printf("\t[-v] - Verbose output\n");
-
- return;
-}
-
-static void TimeSubtract(struct timeval *result, struct timeval *x, struct timeval *y)
-{
- if (x->tv_usec < y->tv_usec) {
- result->tv_sec = x->tv_sec - y->tv_sec - 1;
- result->tv_usec = y->tv_usec - x->tv_usec;
- } else {
- result->tv_sec = x->tv_sec - y->tv_sec;
- result->tv_usec = x->tv_usec - y->tv_usec;
- }
-
- return;
-}
-
-static int CheckSysfsEntry(char *sensorName)
-{
- int retval;
- struct stat st;
-
- retval = stat(sensorName, &st);
- if (retval)
- printf("ERROR: sensor sysfs entry %s not found\n", sensorName);
-
- return retval;
-}
-
-static void WriteBinData(char *fname, unsigned char *buf, int len)
-{
- int numBytesWritten;
- FILE *fp;
-
- fp = fopen(fname, "wb");
- if (!fp) {
- printf("ERROR: failed to open %s for writing data\n", fname);
- exit(EIO);
- }
-
- numBytesWritten = fwrite(buf, 1, len, fp);
-
- if (numBytesWritten != len) {
- printf("ERROR: failed to write all data to bin file\n");
- fclose(fp);
- exit(EIO);
- }
-
- fclose(fp);
-
- return;
-}
-
-static void ReadBinData(char *fname, unsigned char *buf, int len)
-{
- int numBytesRead;
- FILE *fp;
-
- fp = fopen(fname, "rb");
- if (!fp) {
- printf("ERROR: failed to open %s for reading data\n", fname);
- exit(EIO);
- }
-
- numBytesRead = fread(buf, 1, len, fp);
-
- if (numBytesRead != len) {
- printf("ERROR: failed to read all data from bin file\n");
- fclose(fp);
- exit(EIO);
- }
-
- fclose(fp);
-
- return;
-}
-
-static void WriteValueToFp(FILE *fp, unsigned int value)
-{
- int numBytesWritten;
- char buf[MAX_INT_LEN];
-
- snprintf(buf, MAX_INT_LEN, "%u", value);
-
- fseek(fp, 0, 0);
-
- numBytesWritten = fwrite(buf, 1, strlen(buf) + 1, fp);
- if (numBytesWritten != ((int)(strlen(buf) + 1))) {
- printf("ERROR: failed to write value to file pointer\n");
- fclose(fp);
- exit(EIO);
- }
-
- return;
-}
-
-static void WriteValueToSysfsFile(char *fname, unsigned int value)
-{
- FILE *fp;
-
- fp = fopen(fname, "w");
- if (!fp) {
- printf("ERROR: failed to open %s for writing value\n", fname);
- exit(EIO);
- }
-
- WriteValueToFp(fp, value);
-
- fclose(fp);
-
- return;
-}
-
-static void ReadValueFromFp(FILE *fp, unsigned int *value)
-{
- int retVal;
- char buf[MAX_INT_LEN];
-
- fseek(fp, 0, 0);
-
- retVal = fread(buf, 1, sizeof(buf), fp);
- if (retVal == -1) {
- printf("ERROR: failed to read value from file pointer\n");
- exit(EIO);
- }
-
- *value = strtoul(buf, NULL, 0);
-
- return;
-}
-
-static void ReadValueFromSysfsFile(char *fname, unsigned int *value)
-{
- FILE *fp;
-
- fp = fopen(fname, "r");
- if (!fp) {
- printf("ERROR: failed to open %s for reading value\n", fname);
- exit(EIO);
- }
-
- ReadValueFromFp(fp, value);
-
- fclose(fp);
-
- return;
-}
-
-static void WriteBlockData(char *buf, int len)
-{
- char tmpfname[MAX_STRING_LEN];
-
- snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, DATA_FILENAME);
-
- WriteBinData(tmpfname, (unsigned char *)buf, len);
-
- return;
-}
-
-static void ReadBlockData(char *buf, int len)
-{
- char tmpfname[MAX_STRING_LEN];
-
- snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, DATA_FILENAME);
-
- ReadBinData(tmpfname, (unsigned char *)buf, len);
-
- return;
-}
-
-static void SetImageSize(int value)
-{
- char tmpfname[MAX_STRING_LEN];
-
- snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, IMAGESIZE_FILENAME);
-
- WriteValueToSysfsFile(tmpfname, value);
-
- return;
-}
-
-static void StartReflash(int value)
-{
- char tmpfname[MAX_STRING_LEN];
-
- snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, DOREFLASH_FILENAME);
-
- WriteValueToSysfsFile(tmpfname, value);
-
- return;
-}
-
-static void SetConfigArea(int value)
-{
- char tmpfname[MAX_STRING_LEN];
-
- snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, CONFIGAREA_FILENAME);
-
- WriteValueToSysfsFile(tmpfname, value);
-
- return;
-}
-
-static void StartWriteConfig(int value)
-{
- char tmpfname[MAX_STRING_LEN];
-
- snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, WRITECONFIG_FILENAME);
-
- WriteValueToSysfsFile(tmpfname, value);
-
- return;
-}
-
-static void StartReadConfig(int value)
-{
- char tmpfname[MAX_STRING_LEN];
-
- snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, READCONFIG_FILENAME);
-
- WriteValueToSysfsFile(tmpfname, value);
-
- return;
-}
-
-static int ReadBlockSize(void)
-{
- unsigned int blockSize;
- char tmpfname[MAX_STRING_LEN];
-
- snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, BLOCKSIZE_FILENAME);
-
- ReadValueFromSysfsFile(tmpfname, &blockSize);
-
- return blockSize;
-}
-
-static int ReadFirmwareBlockCount(void)
-{
- unsigned int imageBlockCount;
- char tmpfname[MAX_STRING_LEN];
-
- snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, IMAGEBLOCKCOUNT_FILENAME);
-
- ReadValueFromSysfsFile(tmpfname, &imageBlockCount);
-
- return imageBlockCount;
-}
-
-static int ReadConfigBlockCount(void)
-{
- unsigned int configBlockCount;
- char tmpfname[MAX_STRING_LEN];
-
- snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, CONFIGBLOCKCOUNT_FILENAME);
-
- ReadValueFromSysfsFile(tmpfname, &configBlockCount);
-
- return configBlockCount;
-}
-
-static int ReadPmConfigBlockCount(void)
-{
- unsigned int configBlockCount;
- char tmpfname[MAX_STRING_LEN];
-
- snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, PMCONFIGBLOCKCOUNT_FILENAME);
-
- ReadValueFromSysfsFile(tmpfname, &configBlockCount);
-
- return configBlockCount;
-}
-
-static int ReadBuildID(void)
-{
- unsigned int buildID;
- char tmpfname[MAX_STRING_LEN];
-
- snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, BUILDID_FILENAME);
-
- ReadValueFromSysfsFile(tmpfname, &buildID);
-
- return buildID;
-}
-
-static int ReadFlashProg(void)
-{
- unsigned int flashProg;
- char tmpfname[MAX_STRING_LEN];
-
- snprintf(tmpfname, MAX_STRING_LEN, "%s/%s", mySensor, FLASHPROG_FILENAME);
-
- ReadValueFromSysfsFile(tmpfname, &flashProg);
-
- return flashProg;
-}
-
-static void ReadFirmwareInfo(void)
-{
- firmwareBlockSize = ReadBlockSize();
- firmwareBlockCount = ReadFirmwareBlockCount();
- firmwareImgSize = firmwareBlockCount * firmwareBlockSize;
-
- return;
-}
-
-static void ReadConfigInfo(void)
-{
- configBlockSize = ReadBlockSize();
- configBlockCount = ReadConfigBlockCount();
- configImgSize = configBlockSize * configBlockCount;
-
- return;
-}
-
-static void CalculateChecksum(unsigned short *data, unsigned short len, unsigned long *result)
-{
- unsigned long temp;
- unsigned long sum1 = 0xffff;
- unsigned long sum2 = 0xffff;
-
- *result = 0xffffffff;
-
- while (len--) {
- temp = *data;
- sum1 += temp;
- sum2 += sum1;
- sum1 = (sum1 & 0xffff) + (sum1 >> 16);
- sum2 = (sum2 & 0xffff) + (sum2 >> 16);
- data++;
- }
-
- *result = sum2 << 16 | sum1;
-
- return;
-}
-
-static int CompareChecksum(void)
-{
- unsigned long headerChecksum;
- unsigned long computedChecksum;
-
- headerChecksum = (unsigned long)firmware[0] +
- (unsigned long)firmware[1] * 0x100 +
- (unsigned long)firmware[2] * 0x10000 +
- (unsigned long)firmware[3] * 0x1000000;
-
- CalculateChecksum((unsigned short *)&firmware[IMAGE_FILE_CHECKSUM_SIZE],
- ((fileSize - IMAGE_FILE_CHECKSUM_SIZE) / 2), &computedChecksum);
-
- if (verbose) {
- printf("Checksum in image file header = 0x%08x\n", (unsigned int)headerChecksum);
- printf("Checksum computed from image file = 0x%08x\n", (unsigned int)computedChecksum);
- }
-
- if (headerChecksum == computedChecksum)
- return 1;
- else
- return 0;
-}
-
-static int ProceedWithReflash(void)
-{
- int index = 0;
- int deviceBuildID;
- int imageBuildID;
- char imagePR[MAX_STRING_LEN];
- char *strptr;
-
- if (force) {
- printf("Force reflash...\n");
- return 1;
- }
-
- if (ReadFlashProg()) {
- printf("Force reflash (device in flash prog mode)...\n");
- return 1;
- }
-
- strptr = strstr(imageFileName, "PR");
- if (!strptr) {
- printf("No valid PR number (PRxxxxxxx) found in image file name...\n");
- return 0;
- }
-
- strptr += 2;
- while (strptr[index] >= '0' && strptr[index] <= '9') {
- imagePR[index] = strptr[index];
- index++;
- }
- imagePR[index] = 0;
-
- imageBuildID = strtoul(imagePR, NULL, 0);
- deviceBuildID = ReadBuildID();
- printf("Image file PR = %d\n", imageBuildID);
- printf("Device PR = %d\n", deviceBuildID);
-
- if (imageBuildID > deviceBuildID) {
- printf("Proceed with reflash...\n");
- return 1;
- } else {
- printf("No need to do reflash...\n");
- return 0;
- }
-}
-
-static void DoReadConfig(void)
-{
- int ii;
- int jj;
- int index = 0;
- int configSize;
- int blockCount;
- unsigned char *buffer;
-
- if (uiConfig) {
- SetConfigArea(UI_CONFIG_AREA);
- StartReadConfig(1);
- blockCount = configBlockCount;
- configSize = configImgSize;
- buffer = malloc(configSize);
- if (!buffer)
- exit(ENOMEM);
- ReadBlockData((char *)&buffer[0], configSize);
- } else if (pmConfig) {
- SetConfigArea(PERM_CONFIG_AREA);
- StartReadConfig(1);
- blockCount = ReadPmConfigBlockCount();
- configSize = configBlockSize * blockCount;
- buffer = malloc(configSize);
- if (!buffer)
- exit(ENOMEM);
- ReadBlockData((char *)&buffer[0], configSize);
- } else {
- return;
- }
-
- for (ii = 0; ii < blockCount; ii++) {
- for (jj = 0; jj < configBlockSize; jj++) {
- printf("0x%02x ", buffer[index]);
- index++;
- }
- printf("\n");
- }
-
- free(buffer);
-
- return;
-}
-
-static void DoWriteConfig(void)
-{
- printf("Starting config programming...\n");
-
- if (uiConfig)
- SetConfigArea(UI_CONFIG_AREA);
- else if (pmConfig)
- SetConfigArea(PERM_CONFIG_AREA);
- else if (blConfig)
- SetConfigArea(BL_CONFIG_AREA);
- else if (dpConfig)
- SetConfigArea(DISP_CONFIG_AREA);
- else
- return;
-
- SetImageSize(fileSize);
- WriteBlockData((char *)&firmware[0], fileSize);
- StartWriteConfig(1);
-
- printf("Config programming completed...\n");
-
- return;
-}
-
-static void DoReflash(void)
-{
- if (verbose)
- printf("Blocks: %d (firmware: %d, config: %d)\n", totalBlockCount, firmwareBlockCount, configBlockCount);
-
- if (!ProceedWithReflash())
- return;
-
- printf("Starting reflash...\n");
-
- SetImageSize(fileSize);
- WriteBlockData((char *)&firmware[0], fileSize);
- StartReflash(1);
-
- printf("Reflash completed...\n");
-
- return;
-}
-
-static int InitFirmwareImage(void)
-{
- int numBytesRead;
- FILE *fp;
-
- if (!readConfig) {
- fp = fopen(imageFileName, "rb");
-
- if (!fp) {
- printf("ERROR: image file %s not found\n", imageFileName);
- exit(ENODEV);
- }
-
- fseek(fp, 0L, SEEK_END);
- fileSize = ftell(fp);
- if (fileSize == -1) {
- printf("ERROR: failed to determine size of %s\n", imageFileName);
- exit(EIO);
- }
-
- fseek(fp, 0L, SEEK_SET);
-
- firmware = malloc(fileSize + 1);
- if (!firmware) {
- exit(ENOMEM);
- } else {
- numBytesRead = fread(firmware, 1, fileSize, fp);
- if (numBytesRead != fileSize) {
- printf("ERROR: failed to read entire content of image file\n");
- exit(EIO);
- }
- }
-
- fclose(fp);
-
- if (!(pmConfig || blConfig || dpConfig)) {
- if (!CompareChecksum()) {
- printf("ERROR: failed to validate checksum of image file\n");
- exit(EINVAL);
- }
- }
- }
-
- return 0;
-}
-
-int main(int argc, char* argv[])
-{
- int retVal;
- int this_arg = 1;
- struct stat st;
- struct timeval start_time;
- struct timeval end_time;
- struct timeval elapsed_time;
-
- if (argc == 1) {
- usage(argv[0]);
- exit(EINVAL);
- }
-
- while (this_arg < argc) {
- if (!strcmp((const char *)argv[this_arg], "-b")) {
- /* Image file */
- FILE *file;
-
- this_arg++;
- if (this_arg >= argc) {
- printf("ERROR: image file missing\n");
- exit(EINVAL);
- }
-
- /* check for presence of image file */
- file = fopen(argv[this_arg], "rb");
- if (file == 0) {
- printf("ERROR: image file %s not found\n", argv[this_arg]);
- exit(EINVAL);
- }
- fclose(file);
-
- strncpy(imageFileName, argv[this_arg], MAX_STRING_LEN);
- } else if (!strcmp((const char *)argv[this_arg], "-d")) {
- /* path to sensor sysfs entry */
- this_arg++;
-
- if (stat(argv[this_arg], &st) == 0) {
- strncpy(mySensor, argv[this_arg], MAX_STRING_LEN);
- } else {
- printf("ERROR: sensor sysfs entry %s not found\n", argv[this_arg]);
- exit(EINVAL);
- }
- } else if (!strcmp((const char *)argv[this_arg], "-r")) {
- readConfig = 1;
- } else if (!strcmp((const char *)argv[this_arg], "-ui")) {
- uiConfig = 1;
- } else if (!strcmp((const char *)argv[this_arg], "-pm")) {
- pmConfig = 1;
- } else if (!strcmp((const char *)argv[this_arg], "-bl")) {
- blConfig = 1;
- } else if (!strcmp((const char *)argv[this_arg], "-dp")) {
- dpConfig = 1;
- } else if (!strcmp((const char *)argv[this_arg], "-f")) {
- force = 1;
- } else if (!strcmp((const char *)argv[this_arg], "-v")) {
- verbose = 1;
- } else {
- usage(argv[0]);
- printf("ERROR: invalid parameter %s supplied\n", argv[this_arg]);
- exit(EINVAL);
- }
- this_arg++;
- }
-
- if ((uiConfig + pmConfig + blConfig + dpConfig) > 1) {
- printf("ERROR: too many parameters\n");
- exit(EINVAL);
- }
-
- if (uiConfig || pmConfig || blConfig || dpConfig)
- writeConfig = 1;
-
- if (!readConfig && !strlen(imageFileName)) {
- printf("ERROR: no image file specified\n");
- exit(EINVAL);
- }
-
- if (!strlen(mySensor))
- strncpy(mySensor, DEFAULT_SENSOR, MAX_STRING_LEN);
-
- if (CheckSysfsEntry(mySensor))
- exit(ENODEV);
-
- InitFirmwareImage();
-
- ReadFirmwareInfo();
- ReadConfigInfo();
- totalBlockCount = configBlockCount + firmwareBlockCount;
-
- retVal = gettimeofday(&start_time, NULL);
- if (retVal)
- printf("WARNING: failed to get start time\n");
-
- if (verbose) {
- if (!readConfig)
- printf("Image file: %s\n", imageFileName);
- printf("Sensor sysfs entry: %s\n", mySensor);
- }
-
- if (readConfig)
- DoReadConfig();
- else if (writeConfig)
- DoWriteConfig();
- else
- DoReflash();
-
- retVal = gettimeofday(&end_time, NULL);
- if (retVal)
- printf("WARNING: failed to get end time\n");
-
- TimeSubtract(&elapsed_time, &end_time, &start_time);
-
- if (verbose) {
- printf("Elapsed time = %ld.%06ld seconds\n",
- (long)elapsed_time.tv_sec,
- (long)elapsed_time.tv_usec);
- }
-
- return 0;
-}
diff --git a/kernel/Documentation/firmware_updater/synaptics_fw_updater_readme.txt b/kernel/Documentation/firmware_updater/synaptics_fw_updater_readme.txt
deleted file mode 100644
index 66f71922995a..000000000000
--- a/kernel/Documentation/firmware_updater/synaptics_fw_updater_readme.txt
+++ /dev/null
@@ -1,41 +0,0 @@
-Use ADB (Android Debug Bridge) to do command-line reflash
-- Power on device.
-- Connect device to host via USB.
-- Open command prompt on host and go to directory where adb, synaptics_fw_updater, and FW image (e.g. PR1234567.img) reside.
-- Run "adb devices" to ensure connection with device.
-- Run "adb root" to have root privileges.
-- Run "adb push synaptics_fw_updater /data" to copy synaptics_fw_updater to /data directory on device.
-- Run "adb push firmware.img /data" to copy firmware.img to /data directory on device.
-- Run "adb shell chmod 777 /data/synaptics_fw_updater" to make synaptics_fw_updater executable.
-- Run "adb shell /data/synaptics_fw_updater -b /data/PR1234567.img -f -v" to start reflash process.
-
-Parameters
-[-b {image_file}] - Name of image file
-[-d {sysfs_entry}] - Path to sysfs entry of sensor
-[-r] - Read config area
-[-ui] - UI config area
-[-pm] - Permanent config area
-[-bl] - BL config area
-[-dp] - Display config area
-[-f] - Force reflash
-[-v] - Verbose output
-
-Procedures for checking whether to proceed with reflash
-- If [-f] flag is set, proceed with reflash
-- If device is in flash prog (bootloader) mode, proceed with reflash
-- If PR number contained in name of new FW image is greater than PR number of FW on device, proceed with reflash.
-- Otherwise, no reflash is performed
-
-Usage examples
-- Perform reflash using PR1234567.img regardless of PR number of FW on device
- synaptics_fw_updater -b PR1234567.img -f
-- Perform reflash using PR1234567.img only if 1234567 is greater than PR number of FW on device.
- synaptics_fw_updater -b PR1234567.img
-- Write UI config area from PR1234567.img (parsing UI config area from firmware image file)
- synaptics_fw_updater -b PR1234567.img -ui
-- Write permanent config area from pmconfig.img (binary file containing permanent config data)
- synaptics_fw_updater -b pmconfig.img -pm
-- Read UI config area
- synaptics_fw_updater -r -ui
-- Read permanent config area
- synaptics_fw_updater -r -pm \ No newline at end of file
diff --git a/kernel/arch/arm/configs/omap3_beagle_android_defconfig b/kernel/arch/arm/configs/omap3_beagle_android_defconfig
deleted file mode 100644
index 4fc62c4fa440..000000000000
--- a/kernel/arch/arm/configs/omap3_beagle_android_defconfig
+++ /dev/null
@@ -1,2419 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux/arm 2.6.37 Kernel Configuration
-# Mon Apr 16 13:58:06 2012
-#
-CONFIG_ARM=y
-CONFIG_SYS_SUPPORTS_APM_EMULATION=y
-CONFIG_GENERIC_GPIO=y
-# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
-CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_HAVE_PROC_CPU=y
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_HAVE_LATENCYTOP_SUPPORT=y
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-CONFIG_HARDIRQS_SW_RESEND=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_ARCH_HAS_CPUFREQ=y
-CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_NEED_DMA_MAP_STATE=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_ARM_L1_CACHE_SHIFT_6=y
-CONFIG_VECTORS_BASE=0xffff0000
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-CONFIG_CONSTRUCTORS=y
-CONFIG_HAVE_IRQ_WORK=y
-CONFIG_IRQ_WORK=y
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-CONFIG_CROSS_COMPILE=""
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_HAVE_KERNEL_GZIP=y
-CONFIG_HAVE_KERNEL_LZMA=y
-CONFIG_HAVE_KERNEL_LZO=y
-CONFIG_KERNEL_GZIP=y
-# CONFIG_KERNEL_LZMA is not set
-# CONFIG_KERNEL_LZO is not set
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_POSIX_MQUEUE_SYSCTL=y
-CONFIG_BSD_PROCESS_ACCT=y
-# CONFIG_BSD_PROCESS_ACCT_V3 is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_AUDIT is not set
-# CONFIG_HAVE_GENERIC_HARDIRQS is not set
-# CONFIG_SPARSE_IRQ is not set
-
-#
-# RCU Subsystem
-#
-CONFIG_TINY_RCU=y
-# CONFIG_PREEMPT_RCU is not set
-# CONFIG_TREE_RCU_TRACE is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-# CONFIG_CGROUPS is not set
-# CONFIG_NAMESPACES is not set
-# CONFIG_SYSFS_DEPRECATED is not set
-# CONFIG_RELAY is not set
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-CONFIG_RD_GZIP=y
-# CONFIG_RD_BZIP2 is not set
-# CONFIG_RD_LZMA is not set
-# CONFIG_RD_LZO is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SYSCTL=y
-CONFIG_ANON_INODES=y
-CONFIG_PANIC_TIMEOUT=0
-CONFIG_EMBEDDED=y
-CONFIG_UID16=y
-# CONFIG_SYSCTL_SYSCALL is not set
-CONFIG_KALLSYMS=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_ASHMEM=y
-CONFIG_AIO=y
-CONFIG_HAVE_PERF_EVENTS=y
-CONFIG_PERF_USE_VMALLOC=y
-
-#
-# Kernel Performance Events And Counters
-#
-CONFIG_PERF_EVENTS=y
-# CONFIG_PERF_COUNTERS is not set
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_COMPAT_BRK=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
-# CONFIG_SLOB is not set
-CONFIG_PROFILING=y
-CONFIG_TRACEPOINTS=y
-CONFIG_OPROFILE=y
-CONFIG_HAVE_OPROFILE=y
-CONFIG_KPROBES=y
-CONFIG_KRETPROBES=y
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
-CONFIG_HAVE_CLK=y
-CONFIG_HAVE_HW_BREAKPOINT=y
-
-#
-# GCOV-based kernel profiling
-#
-# CONFIG_GCOV_KERNEL is not set
-CONFIG_HAVE_GENERIC_DMA_COHERENT=y
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_MODULE_FORCE_UNLOAD is not set
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_BLOCK=y
-CONFIG_LBDAF=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_BLK_DEV_INTEGRITY is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-# CONFIG_INLINE_SPIN_TRYLOCK is not set
-# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
-# CONFIG_INLINE_SPIN_LOCK is not set
-# CONFIG_INLINE_SPIN_LOCK_BH is not set
-# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
-# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
-CONFIG_INLINE_SPIN_UNLOCK=y
-# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
-CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
-# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
-# CONFIG_INLINE_READ_TRYLOCK is not set
-# CONFIG_INLINE_READ_LOCK is not set
-# CONFIG_INLINE_READ_LOCK_BH is not set
-# CONFIG_INLINE_READ_LOCK_IRQ is not set
-# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
-CONFIG_INLINE_READ_UNLOCK=y
-# CONFIG_INLINE_READ_UNLOCK_BH is not set
-CONFIG_INLINE_READ_UNLOCK_IRQ=y
-# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
-# CONFIG_INLINE_WRITE_TRYLOCK is not set
-# CONFIG_INLINE_WRITE_LOCK is not set
-# CONFIG_INLINE_WRITE_LOCK_BH is not set
-# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
-# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
-CONFIG_INLINE_WRITE_UNLOCK=y
-# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
-CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
-# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
-# CONFIG_MUTEX_SPIN_ON_OWNER is not set
-CONFIG_FREEZER=y
-
-#
-# System Type
-#
-CONFIG_MMU=y
-# CONFIG_ARCH_AAEC2000 is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_REALVIEW is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_VEXPRESS is not set
-# CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_BCMRING is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CNS3XXX is not set
-# CONFIG_ARCH_GEMINI is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_EP93XX is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_MXC is not set
-# CONFIG_ARCH_STMP3XXX is not set
-# CONFIG_ARCH_NETX is not set
-# CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_IOP13XX is not set
-# CONFIG_ARCH_IOP32X is not set
-# CONFIG_ARCH_IOP33X is not set
-# CONFIG_ARCH_IXP23XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_DOVE is not set
-# CONFIG_ARCH_KIRKWOOD is not set
-# CONFIG_ARCH_LOKI is not set
-# CONFIG_ARCH_LPC32XX is not set
-# CONFIG_ARCH_MV78XX0 is not set
-# CONFIG_ARCH_ORION5X is not set
-# CONFIG_ARCH_MMP is not set
-# CONFIG_ARCH_KS8695 is not set
-# CONFIG_ARCH_NS9XXX is not set
-# CONFIG_ARCH_W90X900 is not set
-# CONFIG_ARCH_NUC93X is not set
-# CONFIG_ARCH_TEGRA is not set
-# CONFIG_ARCH_PNX4008 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_MSM is not set
-# CONFIG_ARCH_SHMOBILE is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_S3C64XX is not set
-# CONFIG_ARCH_S5P64X0 is not set
-# CONFIG_ARCH_S5P6442 is not set
-# CONFIG_ARCH_S5PC100 is not set
-# CONFIG_ARCH_S5PV210 is not set
-# CONFIG_ARCH_S5PV310 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_TCC_926 is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_U300 is not set
-# CONFIG_ARCH_U8500 is not set
-# CONFIG_ARCH_NOMADIK is not set
-# CONFIG_ARCH_DAVINCI is not set
-CONFIG_ARCH_OMAP=y
-# CONFIG_PLAT_SPEAR is not set
-
-#
-# TI OMAP Common Features
-#
-CONFIG_ARCH_OMAP_OTG=y
-# CONFIG_ARCH_OMAP1 is not set
-CONFIG_ARCH_OMAP2PLUS=y
-
-#
-# OMAP Feature Selections
-#
-CONFIG_OMAP_SMARTREFLEX=y
-CONFIG_OMAP_SMARTREFLEX_CLASS3=y
-CONFIG_OMAP_RESET_CLOCKS=y
-CONFIG_OMAP_MUX=y
-CONFIG_OMAP_MUX_DEBUG=y
-CONFIG_OMAP_MUX_WARNINGS=y
-CONFIG_OMAP_MCBSP=y
-# CONFIG_OMAP_MBOX_FWK is not set
-CONFIG_OMAP_IOMMU=y
-# CONFIG_OMAP_IOMMU_DEBUG is not set
-# CONFIG_OMAP_MPU_TIMER is not set
-CONFIG_OMAP_32K_TIMER=y
-# CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE is not set
-CONFIG_OMAP_32K_TIMER_HZ=128
-CONFIG_OMAP_DM_TIMER=y
-# CONFIG_OMAP_PM_NONE is not set
-CONFIG_OMAP_PM_NOOP=y
-
-#
-# TI OMAP2/3/4 Specific Features
-#
-CONFIG_ARCH_OMAP2PLUS_TYPICAL=y
-# CONFIG_ARCH_OMAP2 is not set
-CONFIG_ARCH_OMAP3=y
-# CONFIG_ARCH_OMAP4 is not set
-# CONFIG_ARCH_TI81XX is not set
-CONFIG_ARCH_OMAP3430=y
-CONFIG_OMAP_PACKAGE_CBB=y
-
-#
-# OMAP Board Type
-#
-CONFIG_MACH_OMAP3_BEAGLE=y
-# CONFIG_MACH_DEVKIT8000 is not set
-# CONFIG_MACH_OMAP_LDP is not set
-# CONFIG_MACH_OMAP3530_LV_SOM is not set
-# CONFIG_MACH_OMAP3_TORPEDO is not set
-# CONFIG_MACH_OVERO is not set
-# CONFIG_MACH_OMAP3EVM is not set
-# CONFIG_MACH_FLASHBOARD is not set
-# CONFIG_MACH_OMAP3517EVM is not set
-# CONFIG_MACH_CRANEBOARD is not set
-# CONFIG_MACH_OMAP3_PANDORA is not set
-# CONFIG_MACH_OMAP3_TOUCHBOOK is not set
-# CONFIG_MACH_OMAP_3430SDP is not set
-# CONFIG_MACH_NOKIA_RM680 is not set
-# CONFIG_MACH_NOKIA_RX51 is not set
-# CONFIG_MACH_OMAP_ZOOM2 is not set
-# CONFIG_MACH_OMAP_ZOOM3 is not set
-# CONFIG_MACH_CM_T35 is not set
-# CONFIG_MACH_CM_T3517 is not set
-# CONFIG_MACH_IGEP0020 is not set
-# CONFIG_MACH_IGEP0030 is not set
-# CONFIG_MACH_SBC3530 is not set
-# CONFIG_MACH_OMAP_3630SDP is not set
-# CONFIG_OMAP3_EMU is not set
-CONFIG_OMAP3_PM_DISABLE_VT_SWITCH=y
-# CONFIG_OMAP3_SDRC_AC_TIMING is not set
-
-#
-# Processor Type
-#
-CONFIG_CPU_32v6K=y
-CONFIG_CPU_V7=y
-CONFIG_CPU_32v7=y
-CONFIG_CPU_ABRT_EV7=y
-CONFIG_CPU_PABRT_V7=y
-CONFIG_CPU_CACHE_V7=y
-CONFIG_CPU_CACHE_VIPT=y
-CONFIG_CPU_COPY_V6=y
-CONFIG_CPU_TLB_V7=y
-CONFIG_CPU_HAS_ASID=y
-CONFIG_CPU_CP15=y
-CONFIG_CPU_CP15_MMU=y
-
-#
-# Processor Features
-#
-CONFIG_ARM_THUMB=y
-CONFIG_ARM_THUMBEE=y
-# CONFIG_CPU_ICACHE_DISABLE is not set
-# CONFIG_CPU_DCACHE_DISABLE is not set
-# CONFIG_CPU_BPREDICT_DISABLE is not set
-CONFIG_ARM_L1_CACHE_SHIFT=6
-CONFIG_ARM_DMA_MEM_BUFFERABLE=y
-# CONFIG_ARM_ERRATA_430973 is not set
-# CONFIG_ARM_ERRATA_458693 is not set
-# CONFIG_ARM_ERRATA_460075 is not set
-# CONFIG_ARM_ERRATA_743622 is not set
-CONFIG_COMMON_CLKDEV=y
-# CONFIG_FIQ_DEBUGGER is not set
-
-#
-# Bus support
-#
-# CONFIG_PCI_SYSCALL is not set
-# CONFIG_ARCH_SUPPORTS_MSI is not set
-# CONFIG_PCCARD is not set
-
-#
-# Kernel Features
-#
-CONFIG_TICK_ONESHOT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-CONFIG_VMSPLIT_3G=y
-# CONFIG_VMSPLIT_2G is not set
-# CONFIG_VMSPLIT_1G is not set
-CONFIG_PAGE_OFFSET=0xC0000000
-CONFIG_PREEMPT_NONE=y
-# CONFIG_PREEMPT_VOLUNTARY is not set
-# CONFIG_PREEMPT is not set
-CONFIG_HZ=128
-# CONFIG_THUMB2_KERNEL is not set
-CONFIG_AEABI=y
-CONFIG_OABI_COMPAT=y
-CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y
-# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
-# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
-# CONFIG_HIGHMEM is not set
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-CONFIG_HAVE_MEMBLOCK=y
-CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_PHYS_ADDR_T_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=0
-CONFIG_VIRT_TO_BUS=y
-# CONFIG_KSM is not set
-CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
-CONFIG_NEED_PER_CPU_KM=y
-CONFIG_FORCE_MAX_ZONEORDER=11
-# CONFIG_LEDS is not set
-CONFIG_ALIGNMENT_TRAP=y
-# CONFIG_UACCESS_WITH_MEMCPY is not set
-# CONFIG_SECCOMP is not set
-# CONFIG_CC_STACKPROTECTOR is not set
-# CONFIG_DEPRECATED_PARAM_STRUCT is not set
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200"
-# CONFIG_CMDLINE_FORCE is not set
-# CONFIG_XIP_KERNEL is not set
-CONFIG_KEXEC=y
-CONFIG_ATAGS_PROC=y
-# CONFIG_AUTO_ZRELADDR is not set
-
-#
-# CPU Power Management
-#
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_TABLE=y
-# CONFIG_CPU_FREQ_DEBUG is not set
-CONFIG_CPU_FREQ_STAT=y
-CONFIG_CPU_FREQ_STAT_DETAILS=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-# CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set
-# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
-CONFIG_CPU_IDLE=y
-CONFIG_CPU_IDLE_GOV_LADDER=y
-CONFIG_CPU_IDLE_GOV_MENU=y
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_FPE_NWFPE=y
-# CONFIG_FPE_NWFPE_XP is not set
-# CONFIG_FPE_FASTFPE is not set
-CONFIG_VFP=y
-CONFIG_VFPv3=y
-CONFIG_NEON=y
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
-CONFIG_HAVE_AOUT=y
-# CONFIG_BINFMT_AOUT is not set
-CONFIG_BINFMT_MISC=y
-
-#
-# Power management options
-#
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-# CONFIG_PM_ADVANCED_DEBUG is not set
-# CONFIG_PM_VERBOSE is not set
-CONFIG_CAN_PM_TRACE=y
-CONFIG_PM_SLEEP=y
-CONFIG_SUSPEND_NVS=y
-CONFIG_SUSPEND=y
-# CONFIG_PM_TEST_SUSPEND is not set
-CONFIG_SUSPEND_FREEZER=y
-CONFIG_HAS_WAKELOCK=y
-CONFIG_HAS_EARLYSUSPEND=y
-CONFIG_WAKELOCK=y
-CONFIG_WAKELOCK_STAT=y
-CONFIG_USER_WAKELOCK=y
-CONFIG_EARLYSUSPEND=y
-# CONFIG_NO_USER_SPACE_SCREEN_ACCESS_CONTROL is not set
-# CONFIG_CONSOLE_EARLYSUSPEND is not set
-CONFIG_FB_EARLYSUSPEND=y
-# CONFIG_APM_EMULATION is not set
-CONFIG_PM_RUNTIME=y
-CONFIG_PM_OPS=y
-CONFIG_ARCH_HAS_OPP=y
-CONFIG_PM_OPP=y
-CONFIG_ARCH_SUSPEND_POSSIBLE=y
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=y
-# CONFIG_XFRM_SUB_POLICY is not set
-CONFIG_XFRM_MIGRATE=y
-# CONFIG_XFRM_STATISTICS is not set
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE_DEMUX is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-CONFIG_INET_TUNNEL=y
-CONFIG_INET_XFRM_MODE_TRANSPORT=y
-CONFIG_INET_XFRM_MODE_TUNNEL=y
-CONFIG_INET_XFRM_MODE_BEET=y
-# CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
-CONFIG_INET_TCP_DIAG=y
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-# CONFIG_TCP_MD5SIG is not set
-CONFIG_IPV6=y
-# CONFIG_IPV6_PRIVACY is not set
-# CONFIG_IPV6_ROUTER_PREF is not set
-# CONFIG_IPV6_OPTIMISTIC_DAD is not set
-# CONFIG_INET6_AH is not set
-# CONFIG_INET6_ESP is not set
-# CONFIG_INET6_IPCOMP is not set
-# CONFIG_IPV6_MIP6 is not set
-# CONFIG_INET6_XFRM_TUNNEL is not set
-# CONFIG_INET6_TUNNEL is not set
-CONFIG_INET6_XFRM_MODE_TRANSPORT=y
-CONFIG_INET6_XFRM_MODE_TUNNEL=y
-CONFIG_INET6_XFRM_MODE_BEET=y
-# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
-CONFIG_IPV6_SIT=y
-# CONFIG_IPV6_SIT_6RD is not set
-CONFIG_IPV6_NDISC_NODETYPE=y
-# CONFIG_IPV6_TUNNEL is not set
-# CONFIG_IPV6_MULTIPLE_TABLES is not set
-# CONFIG_IPV6_MROUTE is not set
-# CONFIG_NETLABEL is not set
-CONFIG_ANDROID_PARANOID_NETWORK=y
-CONFIG_NET_ACTIVITY_STATS=y
-# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_IP_DCCP is not set
-# CONFIG_IP_SCTP is not set
-# CONFIG_RDS is not set
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_L2TP is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_NET_DSA is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_PHONET is not set
-# CONFIG_IEEE802154 is not set
-# CONFIG_NET_SCHED is not set
-# CONFIG_DCB is not set
-CONFIG_DNS_RESOLVER=y
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NET_TCPPROBE is not set
-# CONFIG_NET_DROP_MONITOR is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_CAN is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_AF_RXRPC is not set
-CONFIG_WIRELESS=y
-CONFIG_WIRELESS_EXT=y
-CONFIG_WEXT_CORE=y
-CONFIG_WEXT_PROC=y
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT_SYSFS=y
-# CONFIG_LIB80211 is not set
-
-#
-# CFG80211 needs to be enabled for MAC80211
-#
-
-#
-# Some wireless drivers require a rate control algorithm
-#
-# CONFIG_WIMAX is not set
-# CONFIG_RFKILL is not set
-# CONFIG_NET_9P is not set
-# CONFIG_CAIF is not set
-# CONFIG_CEPH_LIB is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_DEVTMPFS is not set
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=y
-CONFIG_FIRMWARE_IN_KERNEL=y
-CONFIG_EXTRA_FIRMWARE=""
-# CONFIG_SYS_HYPERVISOR is not set
-# CONFIG_CONNECTOR is not set
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_TESTS is not set
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-# CONFIG_MTD_REDBOOT_PARTS is not set
-CONFIG_MTD_CMDLINE_PARTS=y
-# CONFIG_MTD_AFS_PARTS is not set
-# CONFIG_MTD_AR7_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-# CONFIG_SM_FTL is not set
-CONFIG_MTD_OOPS=y
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-# CONFIG_MTD_CFI_ADV_OPTIONS is not set
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-# CONFIG_MTD_CFI_AMDSTD is not set
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-# CONFIG_MTD_PHYSMAP is not set
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_DATAFLASH is not set
-# CONFIG_MTD_M25P80 is not set
-# CONFIG_MTD_SST25L is not set
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-CONFIG_MTD_NAND_IDS=y
-CONFIG_MTD_NAND_ECC=y
-# CONFIG_MTD_NAND_ECC_SMC is not set
-CONFIG_MTD_NAND=y
-# CONFIG_MTD_NAND_VERIFY_WRITE is not set
-# CONFIG_MTD_SM_COMMON is not set
-# CONFIG_MTD_NAND_MUSEUM_IDS is not set
-# CONFIG_MTD_NAND_GPIO is not set
-CONFIG_MTD_NAND_OMAP2=y
-# CONFIG_MTD_NAND_DISKONCHIP is not set
-# CONFIG_MTD_NAND_NANDSIM is not set
-# CONFIG_MTD_NAND_PLATFORM is not set
-# CONFIG_MTD_ALAUDA is not set
-CONFIG_MTD_ONENAND=y
-CONFIG_MTD_ONENAND_VERIFY_WRITE=y
-# CONFIG_MTD_ONENAND_GENERIC is not set
-CONFIG_MTD_ONENAND_OMAP2=y
-# CONFIG_MTD_ONENAND_OTP is not set
-# CONFIG_MTD_ONENAND_2X_PROGRAM is not set
-# CONFIG_MTD_ONENAND_SIM is not set
-
-#
-# LPDDR flash memory drivers
-#
-# CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_UBI is not set
-# CONFIG_PARPORT is not set
-CONFIG_BLK_DEV=y
-# CONFIG_BLK_DEV_COW_COMMON is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-
-#
-# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
-#
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_UB is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=16384
-# CONFIG_BLK_DEV_XIP is not set
-# CONFIG_CDROM_PKTCDVD is not set
-# CONFIG_ATA_OVER_ETH is not set
-# CONFIG_MG_DISK is not set
-# CONFIG_BLK_DEV_RBD is not set
-# CONFIG_MISC_DEVICES is not set
-CONFIG_HAVE_IDE=y
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI_MOD=y
-# CONFIG_RAID_ATTRS is not set
-CONFIG_SCSI=y
-CONFIG_SCSI_DMA=y
-# CONFIG_SCSI_TGT is not set
-# CONFIG_SCSI_NETLINK is not set
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
-# CONFIG_CHR_DEV_OSST is not set
-# CONFIG_BLK_DEV_SR is not set
-# CONFIG_CHR_DEV_SG is not set
-# CONFIG_CHR_DEV_SCH is not set
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_SCSI_WAIT_SCAN=m
-
-#
-# SCSI Transports
-#
-# CONFIG_SCSI_SPI_ATTRS is not set
-# CONFIG_SCSI_FC_ATTRS is not set
-# CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
-# CONFIG_SCSI_SAS_LIBSAS is not set
-# CONFIG_SCSI_SRP_ATTRS is not set
-CONFIG_SCSI_LOWLEVEL=y
-# CONFIG_ISCSI_TCP is not set
-# CONFIG_ISCSI_BOOT_SYSFS is not set
-# CONFIG_LIBFC is not set
-# CONFIG_LIBFCOE is not set
-# CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_DH is not set
-# CONFIG_SCSI_OSD_INITIATOR is not set
-# CONFIG_ATA is not set
-CONFIG_MD=y
-# CONFIG_BLK_DEV_MD is not set
-CONFIG_BLK_DEV_DM=y
-# CONFIG_DM_DEBUG is not set
-CONFIG_DM_CRYPT=y
-# CONFIG_DM_SNAPSHOT is not set
-# CONFIG_DM_MIRROR is not set
-# CONFIG_DM_ZERO is not set
-# CONFIG_DM_MULTIPATH is not set
-# CONFIG_DM_DELAY is not set
-CONFIG_DM_UEVENT=y
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_MACVLAN is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_VETH is not set
-CONFIG_MII=y
-CONFIG_PHYLIB=y
-
-#
-# MII PHY device drivers
-#
-# CONFIG_MARVELL_PHY is not set
-# CONFIG_DAVICOM_PHY is not set
-# CONFIG_QSEMI_PHY is not set
-# CONFIG_LXT_PHY is not set
-# CONFIG_CICADA_PHY is not set
-# CONFIG_VITESSE_PHY is not set
-CONFIG_SMSC_PHY=y
-# CONFIG_BROADCOM_PHY is not set
-# CONFIG_BCM63XX_PHY is not set
-# CONFIG_ICPLUS_PHY is not set
-# CONFIG_REALTEK_PHY is not set
-# CONFIG_NATIONAL_PHY is not set
-# CONFIG_STE10XP is not set
-# CONFIG_LSI_ET1011C_PHY is not set
-# CONFIG_MICREL_PHY is not set
-# CONFIG_FIXED_PHY is not set
-# CONFIG_MDIO_BITBANG is not set
-CONFIG_NET_ETHERNET=y
-# CONFIG_AX88796 is not set
-# CONFIG_SMC91X is not set
-# CONFIG_DM9000 is not set
-# CONFIG_ENC28J60 is not set
-# CONFIG_ETHOC is not set
-CONFIG_SMC911X=y
-CONFIG_SMSC911X=y
-# CONFIG_SMSC911X_ARCH_HOOKS is not set
-# CONFIG_DNET is not set
-# CONFIG_IBM_NEW_EMAC_ZMII is not set
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
-# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
-# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
-# CONFIG_B44 is not set
-# CONFIG_KS8851 is not set
-# CONFIG_KS8851_MLL is not set
-CONFIG_NETDEV_1000=y
-CONFIG_TI_DAVINCI_EMAC=y
-CONFIG_TI_DAVINCI_MDIO=y
-CONFIG_TI_DAVINCI_CPDMA=y
-# CONFIG_STMMAC_ETH is not set
-CONFIG_NETDEV_10000=y
-CONFIG_WLAN=y
-# CONFIG_USB_ZD1201 is not set
-# CONFIG_BCM4329 is not set
-# CONFIG_HOSTAP is not set
-CONFIG_WL12XX_PLATFORM_DATA=y
-
-#
-# Enable WiMAX (Networking options) to see the WiMAX drivers
-#
-
-#
-# USB Network Adapters
-#
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
-CONFIG_USB_USBNET=y
-CONFIG_USB_NET_AX8817X=y
-CONFIG_USB_NET_CDCETHER=y
-# CONFIG_USB_NET_CDC_EEM is not set
-# CONFIG_USB_NET_DM9601 is not set
-# CONFIG_USB_NET_SMSC75XX is not set
-CONFIG_USB_NET_SMSC95XX=y
-# CONFIG_USB_NET_GL620A is not set
-CONFIG_USB_NET_NET1080=y
-# CONFIG_USB_NET_PLUSB is not set
-# CONFIG_USB_NET_MCS7830 is not set
-# CONFIG_USB_NET_RNDIS_HOST is not set
-CONFIG_USB_NET_CDC_SUBSET=y
-CONFIG_USB_ALI_M5632=y
-CONFIG_USB_AN2720=y
-CONFIG_USB_BELKIN=y
-CONFIG_USB_ARMLINUX=y
-CONFIG_USB_EPSON2888=y
-CONFIG_USB_KC2190=y
-CONFIG_USB_NET_ZAURUS=y
-# CONFIG_USB_NET_CX82310_ETH is not set
-# CONFIG_USB_NET_INT51X1 is not set
-# CONFIG_USB_IPHETH is not set
-# CONFIG_USB_SIERRA_NET is not set
-# CONFIG_WAN is not set
-
-#
-# CAIF transport drivers
-#
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_ISDN is not set
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-# CONFIG_INPUT_FF_MEMLESS is not set
-# CONFIG_INPUT_POLLDEV is not set
-# CONFIG_INPUT_SPARSEKMAP is not set
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-CONFIG_INPUT_JOYDEV=y
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_EVBUG is not set
-# CONFIG_INPUT_KEYRESET is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-# CONFIG_KEYBOARD_ADP5588 is not set
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_QT2160 is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_KEYBOARD_GPIO_POLLED is not set
-# CONFIG_KEYBOARD_TCA6416 is not set
-# CONFIG_KEYBOARD_MATRIX is not set
-# CONFIG_KEYBOARD_MAX7359 is not set
-# CONFIG_KEYBOARD_MCS is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-# CONFIG_KEYBOARD_OPENCORES is not set
-# CONFIG_KEYBOARD_STOWAWAY is not set
-# CONFIG_KEYBOARD_SUNKBD is not set
-CONFIG_KEYBOARD_TWL4030=y
-# CONFIG_KEYBOARD_XTKBD is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-CONFIG_MOUSE_PS2_ALPS=y
-CONFIG_MOUSE_PS2_LOGIPS2PP=y
-CONFIG_MOUSE_PS2_SYNAPTICS=y
-CONFIG_MOUSE_PS2_TRACKPOINT=y
-# CONFIG_MOUSE_PS2_ELANTECH is not set
-# CONFIG_MOUSE_PS2_SENTELIC is not set
-# CONFIG_MOUSE_PS2_TOUCHKIT is not set
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_APPLETOUCH is not set
-# CONFIG_MOUSE_BCM5974 is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_MOUSE_GPIO is not set
-# CONFIG_MOUSE_SYNAPTICS_I2C is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TABLET is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_TOUCHSCREEN_ADS7846 is not set
-# CONFIG_TOUCHSCREEN_AD7877 is not set
-# CONFIG_TOUCHSCREEN_AD7879 is not set
-# CONFIG_TOUCHSCREEN_BU21013 is not set
-# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
-# CONFIG_TOUCHSCREEN_DYNAPRO is not set
-# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
-# CONFIG_TOUCHSCREEN_EETI is not set
-# CONFIG_TOUCHSCREEN_FUJITSU is not set
-# CONFIG_TOUCHSCREEN_GUNZE is not set
-# CONFIG_TOUCHSCREEN_ELO is not set
-# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
-# CONFIG_TOUCHSCREEN_MCS5000 is not set
-# CONFIG_TOUCHSCREEN_MTOUCH is not set
-# CONFIG_TOUCHSCREEN_INEXIO is not set
-# CONFIG_TOUCHSCREEN_MK712 is not set
-# CONFIG_TOUCHSCREEN_PENMOUNT is not set
-# CONFIG_TOUCHSCREEN_QT602240 is not set
-CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
-CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
-CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
-# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
-# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
-# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
-# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
-# CONFIG_TOUCHSCREEN_TSC2007 is not set
-# CONFIG_TOUCHSCREEN_TSC2004 is not set
-# CONFIG_TOUCHSCREEN_W90X900 is not set
-# CONFIG_TOUCHSCREEN_TPS6507X is not set
-CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_AD714X is not set
-# CONFIG_INPUT_ATI_REMOTE is not set
-# CONFIG_INPUT_ATI_REMOTE2 is not set
-# CONFIG_INPUT_KEYCHORD is not set
-# CONFIG_INPUT_KEYSPAN_REMOTE is not set
-# CONFIG_INPUT_POWERMATE is not set
-# CONFIG_INPUT_YEALINK is not set
-# CONFIG_INPUT_CM109 is not set
-CONFIG_INPUT_TWL4030_PWRBUTTON=y
-# CONFIG_INPUT_TWL4030_VIBRA is not set
-# CONFIG_INPUT_UINPUT is not set
-# CONFIG_INPUT_GPIO is not set
-# CONFIG_INPUT_PCF8574 is not set
-# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
-# CONFIG_INPUT_ADXL34X is not set
-
-#
-# Hardware I/O ports
-#
-CONFIG_SERIO=y
-CONFIG_SERIO_SERPORT=y
-CONFIG_SERIO_LIBPS2=y
-# CONFIG_SERIO_RAW is not set
-# CONFIG_SERIO_ALTERA_PS2 is not set
-# CONFIG_SERIO_PS2MULT is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_CONSOLE_TRANSLATIONS=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-CONFIG_DEVMEM=y
-CONFIG_DEVKMEM=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_N_GSM is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=32
-CONFIG_SERIAL_8250_RUNTIME_UARTS=4
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_MAX3100 is not set
-# CONFIG_SERIAL_MAX3107 is not set
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_SERIAL_OMAP=y
-CONFIG_SERIAL_OMAP_CONSOLE=y
-# CONFIG_SERIAL_TIMBERDALE is not set
-# CONFIG_SERIAL_ALTERA_JTAGUART is not set
-# CONFIG_SERIAL_ALTERA_UART is not set
-CONFIG_UNIX98_PTYS=y
-# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_TTY_PRINTK is not set
-# CONFIG_IPMI_HANDLER is not set
-CONFIG_HW_RANDOM=y
-# CONFIG_HW_RANDOM_TIMERIOMEM is not set
-# CONFIG_R3964 is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_TCG_TPM is not set
-# CONFIG_TI81XX_HDMI is not set
-# CONFIG_DCC_TTY is not set
-# CONFIG_RAMOOPS is not set
-CONFIG_I2C=y
-CONFIG_I2C_BOARDINFO=y
-CONFIG_I2C_COMPAT=y
-CONFIG_I2C_CHARDEV=y
-# CONFIG_I2C_MUX is not set
-CONFIG_I2C_HELPER_AUTO=y
-
-#
-# I2C Hardware Bus support
-#
-
-#
-# I2C system bus drivers (mostly embedded / system-on-chip)
-#
-# CONFIG_I2C_DESIGNWARE is not set
-# CONFIG_I2C_GPIO is not set
-# CONFIG_I2C_OCORES is not set
-CONFIG_I2C_OMAP=y
-# CONFIG_I2C_PCA_PLATFORM is not set
-# CONFIG_I2C_SIMTEC is not set
-# CONFIG_I2C_XILINX is not set
-
-#
-# External I2C/SMBus adapter drivers
-#
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_TINY_USB is not set
-
-#
-# Other I2C/SMBus bus drivers
-#
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_DEBUG_CORE is not set
-# CONFIG_I2C_DEBUG_ALGO is not set
-# CONFIG_I2C_DEBUG_BUS is not set
-CONFIG_SPI=y
-CONFIG_SPI_MASTER=y
-
-#
-# SPI Master Controller Drivers
-#
-# CONFIG_SPI_BITBANG is not set
-# CONFIG_SPI_GPIO is not set
-CONFIG_SPI_OMAP24XX=y
-# CONFIG_SPI_XILINX is not set
-# CONFIG_SPI_DESIGNWARE is not set
-
-#
-# SPI Protocol Masters
-#
-# CONFIG_SPI_SPIDEV is not set
-# CONFIG_SPI_TLE62X0 is not set
-
-#
-# PPS support
-#
-# CONFIG_PPS is not set
-CONFIG_ARCH_REQUIRE_GPIOLIB=y
-CONFIG_GPIOLIB=y
-CONFIG_GPIO_SYSFS=y
-
-#
-# Memory mapped GPIO expanders:
-#
-# CONFIG_GPIO_BASIC_MMIO is not set
-# CONFIG_GPIO_IT8761E is not set
-# CONFIG_GPIO_VX855 is not set
-
-#
-# I2C GPIO expanders:
-#
-# CONFIG_GPIO_MAX7300 is not set
-# CONFIG_GPIO_MAX732X is not set
-# CONFIG_GPIO_PCA953X is not set
-# CONFIG_GPIO_PCF857X is not set
-# CONFIG_GPIO_SX150X is not set
-CONFIG_GPIO_TWL4030=y
-# CONFIG_GPIO_ADP5588 is not set
-
-#
-# PCI GPIO expanders:
-#
-
-#
-# SPI GPIO expanders:
-#
-# CONFIG_GPIO_MAX7301 is not set
-# CONFIG_GPIO_MCP23S08 is not set
-# CONFIG_GPIO_MC33880 is not set
-# CONFIG_GPIO_74X164 is not set
-
-#
-# AC97 GPIO expanders:
-#
-
-#
-# MODULbus GPIO expanders:
-#
-# CONFIG_W1 is not set
-CONFIG_POWER_SUPPLY=y
-# CONFIG_POWER_SUPPLY_DEBUG is not set
-# CONFIG_PDA_POWER is not set
-# CONFIG_TEST_POWER is not set
-# CONFIG_BATTERY_DS2782 is not set
-# CONFIG_BATTERY_BQ20Z75 is not set
-# CONFIG_BATTERY_BQ27x00 is not set
-# CONFIG_BATTERY_MAX17040 is not set
-# CONFIG_CHARGER_ISP1704 is not set
-# CONFIG_CHARGER_TWL4030 is not set
-CONFIG_HWMON=y
-# CONFIG_HWMON_VID is not set
-# CONFIG_HWMON_DEBUG_CHIP is not set
-
-#
-# Native drivers
-#
-# CONFIG_SENSORS_AD7414 is not set
-# CONFIG_SENSORS_AD7418 is not set
-# CONFIG_SENSORS_ADCXX is not set
-# CONFIG_SENSORS_ADM1021 is not set
-# CONFIG_SENSORS_ADM1025 is not set
-# CONFIG_SENSORS_ADM1026 is not set
-# CONFIG_SENSORS_ADM1029 is not set
-# CONFIG_SENSORS_ADM1031 is not set
-# CONFIG_SENSORS_ADM9240 is not set
-# CONFIG_SENSORS_ADT7411 is not set
-# CONFIG_SENSORS_ADT7462 is not set
-# CONFIG_SENSORS_ADT7470 is not set
-# CONFIG_SENSORS_ADT7475 is not set
-# CONFIG_SENSORS_ASC7621 is not set
-# CONFIG_SENSORS_ATXP1 is not set
-# CONFIG_SENSORS_DS1621 is not set
-# CONFIG_SENSORS_F71805F is not set
-# CONFIG_SENSORS_F71882FG is not set
-# CONFIG_SENSORS_F75375S is not set
-# CONFIG_SENSORS_G760A is not set
-# CONFIG_SENSORS_GL518SM is not set
-# CONFIG_SENSORS_GL520SM is not set
-# CONFIG_SENSORS_GPIO_FAN is not set
-# CONFIG_SENSORS_IT87 is not set
-# CONFIG_SENSORS_JC42 is not set
-# CONFIG_SENSORS_LM63 is not set
-# CONFIG_SENSORS_LM70 is not set
-# CONFIG_SENSORS_LM73 is not set
-# CONFIG_SENSORS_LM75 is not set
-# CONFIG_SENSORS_LM77 is not set
-# CONFIG_SENSORS_LM78 is not set
-# CONFIG_SENSORS_LM80 is not set
-# CONFIG_SENSORS_LM83 is not set
-# CONFIG_SENSORS_LM85 is not set
-# CONFIG_SENSORS_LM87 is not set
-# CONFIG_SENSORS_LM90 is not set
-# CONFIG_SENSORS_LM92 is not set
-# CONFIG_SENSORS_LM93 is not set
-# CONFIG_SENSORS_LTC4215 is not set
-# CONFIG_SENSORS_LTC4245 is not set
-# CONFIG_SENSORS_LTC4261 is not set
-# CONFIG_SENSORS_LM95241 is not set
-# CONFIG_SENSORS_MAX1111 is not set
-# CONFIG_SENSORS_MAX1619 is not set
-# CONFIG_SENSORS_MAX6650 is not set
-# CONFIG_SENSORS_PC87360 is not set
-# CONFIG_SENSORS_PC87427 is not set
-# CONFIG_SENSORS_PCF8591 is not set
-# CONFIG_SENSORS_SHT15 is not set
-# CONFIG_SENSORS_SMM665 is not set
-# CONFIG_SENSORS_DME1737 is not set
-# CONFIG_SENSORS_EMC1403 is not set
-# CONFIG_SENSORS_EMC2103 is not set
-# CONFIG_SENSORS_SMSC47M1 is not set
-# CONFIG_SENSORS_SMSC47M192 is not set
-# CONFIG_SENSORS_SMSC47B397 is not set
-# CONFIG_SENSORS_ADS7828 is not set
-# CONFIG_SENSORS_ADS7871 is not set
-# CONFIG_SENSORS_AMC6821 is not set
-# CONFIG_SENSORS_THMC50 is not set
-# CONFIG_SENSORS_TMP102 is not set
-# CONFIG_SENSORS_TMP401 is not set
-# CONFIG_SENSORS_TMP421 is not set
-# CONFIG_SENSORS_VT1211 is not set
-# CONFIG_SENSORS_W83781D is not set
-# CONFIG_SENSORS_W83791D is not set
-# CONFIG_SENSORS_W83792D is not set
-# CONFIG_SENSORS_W83793 is not set
-# CONFIG_SENSORS_W83795 is not set
-# CONFIG_SENSORS_W83L785TS is not set
-# CONFIG_SENSORS_W83L786NG is not set
-# CONFIG_SENSORS_W83627HF is not set
-# CONFIG_SENSORS_W83627EHF is not set
-# CONFIG_SENSORS_LIS3_SPI is not set
-# CONFIG_SENSORS_LIS3_I2C is not set
-# CONFIG_THERMAL is not set
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_OMAP_WATCHDOG=y
-CONFIG_TWL4030_WATCHDOG=y
-# CONFIG_MAX63XX_WATCHDOG is not set
-
-#
-# USB-based Watchdog Cards
-#
-# CONFIG_USBPCWATCHDOG is not set
-CONFIG_SSB_POSSIBLE=y
-
-#
-# Sonics Silicon Backplane
-#
-# CONFIG_SSB is not set
-CONFIG_MFD_SUPPORT=y
-CONFIG_MFD_CORE=y
-# CONFIG_MFD_88PM860X is not set
-# CONFIG_MFD_SM501 is not set
-# CONFIG_MFD_ASIC3 is not set
-# CONFIG_HTC_EGPIO is not set
-# CONFIG_HTC_PASIC3 is not set
-# CONFIG_HTC_I2CPLD is not set
-# CONFIG_TPS65010 is not set
-# CONFIG_TPS6507X is not set
-CONFIG_TWL4030_CORE=y
-CONFIG_TWL4030_POWER=y
-CONFIG_TWL4030_SCRIPT=y
-CONFIG_TWL4030_CODEC=y
-# CONFIG_TWL6030_PWM is not set
-# CONFIG_MFD_STMPE is not set
-# CONFIG_MFD_TC35892 is not set
-# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_T7L66XB is not set
-# CONFIG_MFD_TC6387XB is not set
-# CONFIG_MFD_TC6393XB is not set
-# CONFIG_PMIC_DA903X is not set
-# CONFIG_PMIC_ADP5520 is not set
-# CONFIG_MFD_MAX8925 is not set
-# CONFIG_MFD_MAX8998 is not set
-# CONFIG_MFD_WM8400 is not set
-# CONFIG_MFD_WM831X_I2C is not set
-# CONFIG_MFD_WM831X_SPI is not set
-# CONFIG_MFD_WM8350_I2C is not set
-# CONFIG_MFD_WM8994 is not set
-# CONFIG_MFD_PCF50633 is not set
-# CONFIG_MFD_MC13XXX is not set
-# CONFIG_ABX500_CORE is not set
-# CONFIG_EZX_PCAP is not set
-# CONFIG_MFD_TPS6586X is not set
-CONFIG_REGULATOR=y
-# CONFIG_REGULATOR_DEBUG is not set
-CONFIG_REGULATOR_DUMMY=y
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
-# CONFIG_REGULATOR_MAX1586 is not set
-# CONFIG_REGULATOR_MAX8649 is not set
-# CONFIG_REGULATOR_MAX8660 is not set
-# CONFIG_REGULATOR_MAX8952 is not set
-CONFIG_REGULATOR_TWL4030=y
-# CONFIG_REGULATOR_LP3971 is not set
-# CONFIG_REGULATOR_LP3972 is not set
-# CONFIG_REGULATOR_TPS65023 is not set
-# CONFIG_REGULATOR_TPS6507X is not set
-# CONFIG_REGULATOR_ISL6271A is not set
-# CONFIG_REGULATOR_AD5398 is not set
-CONFIG_MEDIA_SUPPORT=y
-
-#
-# Multimedia core support
-#
-CONFIG_MEDIA_CONTROLLER=y
-CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_COMMON=y
-CONFIG_VIDEO_ALLOW_V4L1=y
-CONFIG_VIDEO_V4L1_COMPAT=y
-CONFIG_VIDEO_V4L2_SUBDEV_API=y
-# CONFIG_DVB_CORE is not set
-CONFIG_VIDEO_MEDIA=y
-
-#
-# Multimedia drivers
-#
-# CONFIG_IR_CORE is not set
-# CONFIG_MEDIA_ATTACH is not set
-CONFIG_MEDIA_TUNER=y
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
-CONFIG_MEDIA_TUNER_SIMPLE=y
-CONFIG_MEDIA_TUNER_TDA8290=y
-CONFIG_MEDIA_TUNER_TDA827X=y
-CONFIG_MEDIA_TUNER_TDA18271=y
-CONFIG_MEDIA_TUNER_TDA9887=y
-CONFIG_MEDIA_TUNER_TEA5761=y
-CONFIG_MEDIA_TUNER_TEA5767=y
-CONFIG_MEDIA_TUNER_MT20XX=y
-CONFIG_MEDIA_TUNER_XC2028=y
-CONFIG_MEDIA_TUNER_XC5000=y
-CONFIG_MEDIA_TUNER_MC44S803=y
-CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEO_V4L1=y
-CONFIG_VIDEOBUF_GEN=y
-CONFIG_VIDEOBUF_DMA_CONTIG=y
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
-# CONFIG_VIDEO_ADV_DEBUG is not set
-# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
-# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
-
-#
-# Encoders/decoders and other helper chips
-#
-
-#
-# Audio decoders
-#
-# CONFIG_VIDEO_TVAUDIO is not set
-# CONFIG_VIDEO_TDA7432 is not set
-# CONFIG_VIDEO_TDA9840 is not set
-# CONFIG_VIDEO_TDA9875 is not set
-# CONFIG_VIDEO_TEA6415C is not set
-# CONFIG_VIDEO_TEA6420 is not set
-# CONFIG_VIDEO_MSP3400 is not set
-# CONFIG_VIDEO_CS5345 is not set
-# CONFIG_VIDEO_CS53L32A is not set
-# CONFIG_VIDEO_M52790 is not set
-# CONFIG_VIDEO_TLV320AIC23B is not set
-# CONFIG_VIDEO_WM8775 is not set
-# CONFIG_VIDEO_WM8739 is not set
-# CONFIG_VIDEO_VP27SMPX is not set
-
-#
-# RDS decoders
-#
-# CONFIG_VIDEO_SAA6588 is not set
-
-#
-# Video decoders
-#
-# CONFIG_VIDEO_ADV7180 is not set
-# CONFIG_VIDEO_BT819 is not set
-# CONFIG_VIDEO_BT856 is not set
-# CONFIG_VIDEO_BT866 is not set
-# CONFIG_VIDEO_KS0127 is not set
-# CONFIG_VIDEO_OV7670 is not set
-# CONFIG_VIDEO_MT9T001 is not set
-CONFIG_VIDEO_MT9V011=y
-# CONFIG_VIDEO_MT9V032 is not set
-CONFIG_VIDEO_MT9V113=y
-# CONFIG_VIDEO_MT9T111 is not set
-# CONFIG_VIDEO_TCM825X is not set
-# CONFIG_VIDEO_SAA7110 is not set
-# CONFIG_VIDEO_SAA711X is not set
-# CONFIG_VIDEO_SAA717X is not set
-# CONFIG_VIDEO_SAA7191 is not set
-# CONFIG_VIDEO_TVP514X is not set
-# CONFIG_VIDEO_TVP5150 is not set
-# CONFIG_VIDEO_TVP7002 is not set
-# CONFIG_VIDEO_VPX3220 is not set
-
-#
-# Video and audio decoders
-#
-# CONFIG_VIDEO_CX25840 is not set
-
-#
-# MPEG video encoders
-#
-# CONFIG_VIDEO_CX2341X is not set
-
-#
-# Video encoders
-#
-# CONFIG_VIDEO_SAA7127 is not set
-# CONFIG_VIDEO_SAA7185 is not set
-# CONFIG_VIDEO_ADV7170 is not set
-# CONFIG_VIDEO_ADV7175 is not set
-# CONFIG_VIDEO_THS7303 is not set
-# CONFIG_VIDEO_ADV7343 is not set
-# CONFIG_VIDEO_AK881X is not set
-
-#
-# Video improvement chips
-#
-# CONFIG_VIDEO_UPD64031A is not set
-# CONFIG_VIDEO_UPD64083 is not set
-# CONFIG_VIDEO_VPSS_SYSTEM is not set
-# CONFIG_VIDEO_VPFE_CAPTURE is not set
-CONFIG_VIDEO_OMAP2_VOUT=y
-# CONFIG_VIDEO_CPIA2 is not set
-# CONFIG_VIDEO_SR030PC30 is not set
-CONFIG_VIDEO_OMAP3=y
-CONFIG_VIDEO_OMAP3_DEBUG=y
-# CONFIG_SOC_CAMERA is not set
-CONFIG_V4L_USB_DRIVERS=y
-CONFIG_USB_VIDEO_CLASS=y
-CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
-# CONFIG_USB_GSPCA is not set
-# CONFIG_VIDEO_PVRUSB2 is not set
-# CONFIG_VIDEO_HDPVR is not set
-# CONFIG_VIDEO_USBVISION is not set
-# CONFIG_USB_VICAM is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_KONICAWC is not set
-# CONFIG_USB_ET61X251 is not set
-# CONFIG_USB_SE401 is not set
-# CONFIG_USB_SN9C102 is not set
-# CONFIG_USB_PWC is not set
-# CONFIG_USB_ZR364XX is not set
-# CONFIG_USB_STKWEBCAM is not set
-# CONFIG_USB_S2255 is not set
-# CONFIG_V4L_MEM2MEM_DRIVERS is not set
-# CONFIG_RADIO_ADAPTERS is not set
-# CONFIG_DAB is not set
-
-#
-# Graphics support
-#
-# CONFIG_DRM is not set
-# CONFIG_VGASTATE is not set
-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
-CONFIG_FB=y
-CONFIG_FIRMWARE_EDID=y
-# CONFIG_FB_DDC is not set
-# CONFIG_FB_BOOT_VESA_SUPPORT is not set
-CONFIG_FB_CFB_FILLRECT=y
-CONFIG_FB_CFB_COPYAREA=y
-CONFIG_FB_CFB_IMAGEBLIT=y
-# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
-# CONFIG_FB_SYS_FILLRECT is not set
-# CONFIG_FB_SYS_COPYAREA is not set
-# CONFIG_FB_SYS_IMAGEBLIT is not set
-# CONFIG_FB_FOREIGN_ENDIAN is not set
-# CONFIG_FB_SYS_FOPS is not set
-# CONFIG_FB_SVGALIB is not set
-# CONFIG_FB_MACMODES is not set
-# CONFIG_FB_BACKLIGHT is not set
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-
-#
-# Frame buffer hardware drivers
-#
-# CONFIG_FB_S1D13XXX is not set
-# CONFIG_FB_TMIO is not set
-# CONFIG_FB_VIRTUAL is not set
-# CONFIG_FB_METRONOME is not set
-# CONFIG_FB_MB862XX is not set
-# CONFIG_FB_BROADSHEET is not set
-# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set
-CONFIG_OMAP2_VRAM=y
-CONFIG_OMAP2_VRFB=y
-CONFIG_OMAP2_DSS=y
-CONFIG_OMAP2_VRAM_SIZE=4
-CONFIG_OMAP2_DSS_DEBUG_SUPPORT=y
-# CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS is not set
-CONFIG_OMAP2_DSS_DPI=y
-# CONFIG_OMAP2_DSS_RFBI is not set
-CONFIG_OMAP2_DSS_VENC=y
-CONFIG_OMAP2_VENC_OUT_TYPE_SVIDEO=y
-# CONFIG_OMAP2_VENC_OUT_TYPE_COMPOSITE is not set
-# CONFIG_OMAP2_DSS_SDI is not set
-CONFIG_OMAP2_DSS_DSI=y
-CONFIG_OMAP2_DSS_USE_DSI_PLL=y
-# CONFIG_OMAP2_DSS_FAKE_VSYNC is not set
-CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK=1
-CONFIG_FB_OMAP2=y
-CONFIG_FB_OMAP2_DEBUG_SUPPORT=y
-CONFIG_FB_OMAP2_NUM_FBS=1
-
-#
-# OMAP2/3 Display Device Drivers
-#
-CONFIG_PANEL_GENERIC=y
-# CONFIG_PANEL_LGPHILIPS_LB035Q02 is not set
-# CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C is not set
-CONFIG_PANEL_SHARP_LS037V7DW01=y
-# CONFIG_PANEL_SHARP_LQ043T1DG01 is not set
-# CONFIG_PANEL_SAMSUNG_LMS700KF23 is not set
-# CONFIG_PANEL_TAAL is not set
-# CONFIG_PANEL_TOPPOLY_TDO35S is not set
-# CONFIG_PANEL_TPO_TD043MTEA1 is not set
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-# CONFIG_LCD_L4F00242T03 is not set
-# CONFIG_LCD_LMS283GF05 is not set
-# CONFIG_LCD_LTV350QV is not set
-# CONFIG_LCD_TDO24M is not set
-# CONFIG_LCD_VGG2432A4 is not set
-CONFIG_LCD_PLATFORM=y
-# CONFIG_LCD_S6E63M0 is not set
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_GENERIC=m
-# CONFIG_BACKLIGHT_ADP8860 is not set
-
-#
-# Display device support
-#
-CONFIG_DISPLAY_SUPPORT=y
-
-#
-# Display hardware drivers
-#
-
-#
-# Console display driver support
-#
-CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FRAMEBUFFER_CONSOLE is not set
-CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
-CONFIG_SOUND=y
-# CONFIG_SOUND_OSS_CORE is not set
-CONFIG_SND=y
-CONFIG_SND_TIMER=y
-CONFIG_SND_PCM=y
-CONFIG_SND_HWDEP=y
-CONFIG_SND_RAWMIDI=y
-CONFIG_SND_JACK=y
-# CONFIG_SND_SEQUENCER is not set
-# CONFIG_SND_MIXER_OSS is not set
-# CONFIG_SND_PCM_OSS is not set
-# CONFIG_SND_HRTIMER is not set
-# CONFIG_SND_DYNAMIC_MINORS is not set
-CONFIG_SND_SUPPORT_OLD_API=y
-CONFIG_SND_VERBOSE_PROCFS=y
-# CONFIG_SND_VERBOSE_PRINTK is not set
-# CONFIG_SND_DEBUG is not set
-# CONFIG_SND_RAWMIDI_SEQ is not set
-# CONFIG_SND_OPL3_LIB_SEQ is not set
-# CONFIG_SND_OPL4_LIB_SEQ is not set
-# CONFIG_SND_SBAWE_SEQ is not set
-# CONFIG_SND_EMU10K1_SEQ is not set
-CONFIG_SND_DRIVERS=y
-# CONFIG_SND_DUMMY is not set
-# CONFIG_SND_ALOOP is not set
-# CONFIG_SND_MTPAV is not set
-# CONFIG_SND_SERIAL_U16550 is not set
-# CONFIG_SND_MPU401 is not set
-CONFIG_SND_ARM=y
-CONFIG_SND_SPI=y
-CONFIG_SND_USB=y
-CONFIG_SND_USB_AUDIO=y
-# CONFIG_SND_USB_UA101 is not set
-# CONFIG_SND_USB_CAIAQ is not set
-CONFIG_SND_SOC=y
-CONFIG_SND_OMAP_SOC=y
-CONFIG_SND_OMAP_SOC_MCBSP=y
-CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE=y
-CONFIG_SND_SOC_I2C_AND_SPI=y
-# CONFIG_SND_SOC_ALL_CODECS is not set
-CONFIG_SND_SOC_TWL4030=y
-# CONFIG_SND_SOC_WL1271BT is not set
-# CONFIG_SOUND_PRIME is not set
-CONFIG_HID_SUPPORT=y
-CONFIG_HID=y
-# CONFIG_HIDRAW is not set
-
-#
-# USB Input Devices
-#
-CONFIG_USB_HID=y
-# CONFIG_HID_PID is not set
-# CONFIG_USB_HIDDEV is not set
-
-#
-# Special HID drivers
-#
-# CONFIG_HID_3M_PCT is not set
-# CONFIG_HID_A4TECH is not set
-# CONFIG_HID_ACRUX_FF is not set
-# CONFIG_HID_APPLE is not set
-# CONFIG_HID_BELKIN is not set
-# CONFIG_HID_CANDO is not set
-# CONFIG_HID_CHERRY is not set
-# CONFIG_HID_CHICONY is not set
-# CONFIG_HID_PRODIKEYS is not set
-# CONFIG_HID_CYPRESS is not set
-# CONFIG_HID_DRAGONRISE is not set
-# CONFIG_HID_EGALAX is not set
-# CONFIG_HID_EZKEY is not set
-# CONFIG_HID_KYE is not set
-# CONFIG_HID_UCLOGIC is not set
-# CONFIG_HID_WALTOP is not set
-# CONFIG_HID_GYRATION is not set
-# CONFIG_HID_TWINHAN is not set
-# CONFIG_HID_KENSINGTON is not set
-# CONFIG_HID_LOGITECH is not set
-# CONFIG_HID_MICROSOFT is not set
-# CONFIG_HID_MOSART is not set
-# CONFIG_HID_MONTEREY is not set
-# CONFIG_HID_NTRIG is not set
-# CONFIG_HID_ORTEK is not set
-# CONFIG_HID_PANTHERLORD is not set
-# CONFIG_HID_PETALYNX is not set
-# CONFIG_HID_PICOLCD is not set
-# CONFIG_HID_QUANTA is not set
-# CONFIG_HID_ROCCAT is not set
-# CONFIG_HID_ROCCAT_KONE is not set
-# CONFIG_HID_ROCCAT_PYRA is not set
-# CONFIG_HID_SAMSUNG is not set
-# CONFIG_HID_SONY is not set
-# CONFIG_HID_STANTUM is not set
-# CONFIG_HID_SUNPLUS is not set
-# CONFIG_HID_GREENASIA is not set
-# CONFIG_HID_SMARTJOYPLUS is not set
-# CONFIG_HID_TOPSEED is not set
-# CONFIG_HID_THRUSTMASTER is not set
-# CONFIG_HID_ZEROPLUS is not set
-# CONFIG_HID_ZYDACRON is not set
-CONFIG_USB_SUPPORT=y
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-CONFIG_USB_ARCH_HAS_EHCI=y
-CONFIG_USB=y
-# CONFIG_USB_DEBUG is not set
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-# CONFIG_USB_DEVICE_CLASS is not set
-# CONFIG_USB_DYNAMIC_MINORS is not set
-CONFIG_USB_SUSPEND=y
-CONFIG_USB_OTG=y
-# CONFIG_USB_OTG_WHITELIST is not set
-# CONFIG_USB_OTG_BLACKLIST_HUB is not set
-CONFIG_USB_MON=y
-# CONFIG_USB_WUSB is not set
-# CONFIG_USB_WUSB_CBAF is not set
-
-#
-# USB Host Controller Drivers
-#
-# CONFIG_USB_C67X00_HCD is not set
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_EHCI_ROOT_HUB_TT=y
-CONFIG_USB_EHCI_TT_NEWSCHED=y
-# CONFIG_USB_OXU210HP_HCD is not set
-# CONFIG_USB_ISP116X_HCD is not set
-# CONFIG_USB_ISP1760_HCD is not set
-# CONFIG_USB_ISP1362_HCD is not set
-# CONFIG_USB_OHCI_HCD is not set
-# CONFIG_USB_SL811_HCD is not set
-# CONFIG_USB_R8A66597_HCD is not set
-# CONFIG_USB_HWA_HCD is not set
-CONFIG_USB_MUSB_HDRC=y
-
-#
-# Platform Glue Layer
-#
-# CONFIG_USB_MUSB_TUSB6010_GLUE is not set
-CONFIG_USB_MUSB_OMAP2PLUS_GLUE=y
-# CONFIG_USB_MUSB_AM35X_GLUE is not set
-# CONFIG_USB_MUSB_DAVINCI is not set
-# CONFIG_USB_MUSB_DA8XX is not set
-# CONFIG_USB_MUSB_TUSB6010 is not set
-CONFIG_USB_MUSB_OMAP2PLUS=y
-# CONFIG_USB_MUSB_AM35X is not set
-# CONFIG_USB_MUSB_TI81XX is not set
-# CONFIG_USB_MUSB_BLACKFIN is not set
-# CONFIG_USB_MUSB_UX500 is not set
-# CONFIG_USB_MUSB_HOST is not set
-# CONFIG_USB_MUSB_PERIPHERAL is not set
-CONFIG_USB_MUSB_OTG=y
-CONFIG_USB_GADGET_MUSB_HDRC=y
-CONFIG_USB_MUSB_HDRC_HCD=y
-# CONFIG_MUSB_PIO_ONLY is not set
-CONFIG_USB_INVENTRA_DMA_HW=y
-# CONFIG_USB_TI_CPPI_DMA_HW is not set
-# CONFIG_USB_TI_CPPI41_DMA_HW is not set
-CONFIG_USB_INVENTRA_DMA=y
-CONFIG_MUSB_USE_SYSTEM_DMA_WORKAROUND=y
-# CONFIG_USB_TI_CPPI_DMA is not set
-# CONFIG_USB_TI_CPPI41_DMA is not set
-# CONFIG_USB_TUSB_OMAP_DMA is not set
-# CONFIG_USB_MUSB_DEBUG is not set
-
-#
-# USB Device Class drivers
-#
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_PRINTER is not set
-# CONFIG_USB_WDM is not set
-# CONFIG_USB_TMC is not set
-
-#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
-#
-
-#
-# also be needed; see USB_STORAGE Help for more info
-#
-CONFIG_USB_STORAGE=y
-# CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_DATAFAB is not set
-# CONFIG_USB_STORAGE_FREECOM is not set
-# CONFIG_USB_STORAGE_ISD200 is not set
-# CONFIG_USB_STORAGE_USBAT is not set
-# CONFIG_USB_STORAGE_SDDR09 is not set
-# CONFIG_USB_STORAGE_SDDR55 is not set
-# CONFIG_USB_STORAGE_JUMPSHOT is not set
-# CONFIG_USB_STORAGE_ALAUDA is not set
-# CONFIG_USB_STORAGE_ONETOUCH is not set
-# CONFIG_USB_STORAGE_KARMA is not set
-# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
-# CONFIG_USB_UAS is not set
-# CONFIG_USB_LIBUSUAL is not set
-
-#
-# USB Imaging devices
-#
-# CONFIG_USB_MDC800 is not set
-# CONFIG_USB_MICROTEK is not set
-
-#
-# USB port drivers
-#
-# CONFIG_USB_SERIAL is not set
-
-#
-# USB Miscellaneous drivers
-#
-# CONFIG_USB_EMI62 is not set
-# CONFIG_USB_EMI26 is not set
-# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_SEVSEG is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_LEGOTOWER is not set
-# CONFIG_USB_LCD is not set
-# CONFIG_USB_LED is not set
-# CONFIG_USB_CYPRESS_CY7C63 is not set
-# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_IDMOUSE is not set
-# CONFIG_USB_FTDI_ELAN is not set
-# CONFIG_USB_APPLEDISPLAY is not set
-# CONFIG_USB_SISUSBVGA is not set
-# CONFIG_USB_LD is not set
-# CONFIG_USB_TRANCEVIBRATOR is not set
-# CONFIG_USB_IOWARRIOR is not set
-# CONFIG_USB_TEST is not set
-# CONFIG_USB_ISIGHTFW is not set
-# CONFIG_USB_YUREX is not set
-CONFIG_USB_GADGET=y
-# CONFIG_USB_GADGET_DEBUG_FILES is not set
-# CONFIG_USB_GADGET_DEBUG_FS is not set
-CONFIG_USB_GADGET_VBUS_DRAW=2
-CONFIG_USB_GADGET_SELECTED=y
-# CONFIG_USB_GADGET_OMAP is not set
-# CONFIG_USB_GADGET_R8A66597 is not set
-# CONFIG_USB_GADGET_M66592 is not set
-# CONFIG_USB_GADGET_DUMMY_HCD is not set
-CONFIG_USB_GADGET_DUALSPEED=y
-# CONFIG_USB_ZERO is not set
-# CONFIG_USB_AUDIO is not set
-# CONFIG_USB_ETH is not set
-# CONFIG_USB_GADGETFS is not set
-# CONFIG_USB_FUNCTIONFS is not set
-# CONFIG_USB_FILE_STORAGE is not set
-# CONFIG_USB_MASS_STORAGE is not set
-# CONFIG_USB_G_SERIAL is not set
-# CONFIG_USB_MIDI_GADGET is not set
-# CONFIG_USB_G_PRINTER is not set
-CONFIG_USB_ANDROID=y
-# CONFIG_USB_ANDROID_ACM is not set
-CONFIG_USB_ANDROID_ADB=y
-CONFIG_USB_ANDROID_MASS_STORAGE=y
-# CONFIG_USB_ANDROID_MTP is not set
-# CONFIG_USB_ANDROID_RNDIS is not set
-# CONFIG_USB_CDC_COMPOSITE is not set
-# CONFIG_USB_G_MULTI is not set
-# CONFIG_USB_G_HID is not set
-# CONFIG_USB_G_DBGP is not set
-# CONFIG_USB_G_WEBCAM is not set
-
-#
-# OTG and related infrastructure
-#
-CONFIG_USB_OTG_UTILS=y
-# CONFIG_USB_GPIO_VBUS is not set
-# CONFIG_ISP1301_OMAP is not set
-# CONFIG_USB_ULPI is not set
-CONFIG_TWL4030_USB=y
-# CONFIG_NOP_USB_XCEIV is not set
-CONFIG_MMC=y
-# CONFIG_MMC_DEBUG is not set
-CONFIG_MMC_UNSAFE_RESUME=y
-# CONFIG_MMC_EMBEDDED_SDIO is not set
-# CONFIG_MMC_PARANOID_SD_INIT is not set
-
-#
-# MMC/SD/SDIO Card Drivers
-#
-CONFIG_MMC_BLOCK=y
-CONFIG_MMC_BLOCK_MINORS=8
-CONFIG_MMC_BLOCK_BOUNCE=y
-# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set
-CONFIG_SDIO_UART=y
-# CONFIG_MMC_TEST is not set
-
-#
-# MMC/SD/SDIO Host Controller Drivers
-#
-# CONFIG_MMC_SDHCI is not set
-CONFIG_MMC_OMAP=y
-CONFIG_MMC_OMAP_HS=y
-# CONFIG_MMC_SPI is not set
-# CONFIG_MMC_USHC is not set
-# CONFIG_MEMSTICK is not set
-# CONFIG_NEW_LEDS is not set
-CONFIG_SWITCH=y
-# CONFIG_SWITCH_GPIO is not set
-# CONFIG_ACCESSIBILITY is not set
-CONFIG_RTC_LIB=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_HCTOSYS=y
-CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
-# CONFIG_RTC_DEBUG is not set
-
-#
-# RTC interfaces
-#
-CONFIG_RTC_INTF_SYSFS=y
-CONFIG_RTC_INTF_PROC=y
-CONFIG_RTC_INTF_DEV=y
-# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
-CONFIG_RTC_INTF_ALARM=y
-CONFIG_RTC_INTF_ALARM_DEV=y
-# CONFIG_RTC_DRV_TEST is not set
-
-#
-# I2C RTC drivers
-#
-# CONFIG_RTC_DRV_DS1307 is not set
-# CONFIG_RTC_DRV_DS1374 is not set
-# CONFIG_RTC_DRV_DS1672 is not set
-# CONFIG_RTC_DRV_DS3232 is not set
-# CONFIG_RTC_DRV_MAX6900 is not set
-# CONFIG_RTC_DRV_RS5C372 is not set
-# CONFIG_RTC_DRV_ISL1208 is not set
-# CONFIG_RTC_DRV_ISL12022 is not set
-# CONFIG_RTC_DRV_X1205 is not set
-# CONFIG_RTC_DRV_PCF8563 is not set
-# CONFIG_RTC_DRV_PCF8583 is not set
-# CONFIG_RTC_DRV_M41T80 is not set
-# CONFIG_RTC_DRV_BQ32K is not set
-CONFIG_RTC_DRV_TWL4030=y
-# CONFIG_RTC_DRV_S35390A is not set
-# CONFIG_RTC_DRV_FM3130 is not set
-# CONFIG_RTC_DRV_RX8581 is not set
-# CONFIG_RTC_DRV_RX8025 is not set
-
-#
-# SPI RTC drivers
-#
-# CONFIG_RTC_DRV_M41T94 is not set
-# CONFIG_RTC_DRV_DS1305 is not set
-# CONFIG_RTC_DRV_DS1390 is not set
-# CONFIG_RTC_DRV_MAX6902 is not set
-# CONFIG_RTC_DRV_R9701 is not set
-# CONFIG_RTC_DRV_RS5C348 is not set
-# CONFIG_RTC_DRV_DS3234 is not set
-# CONFIG_RTC_DRV_PCF2123 is not set
-
-#
-# Platform RTC drivers
-#
-# CONFIG_RTC_DRV_CMOS is not set
-# CONFIG_RTC_DRV_DS1286 is not set
-# CONFIG_RTC_DRV_DS1511 is not set
-# CONFIG_RTC_DRV_DS1553 is not set
-# CONFIG_RTC_DRV_DS1742 is not set
-# CONFIG_RTC_DRV_STK17TA8 is not set
-# CONFIG_RTC_DRV_M48T86 is not set
-# CONFIG_RTC_DRV_M48T35 is not set
-# CONFIG_RTC_DRV_M48T59 is not set
-# CONFIG_RTC_DRV_MSM6242 is not set
-# CONFIG_RTC_DRV_BQ4802 is not set
-# CONFIG_RTC_DRV_RP5C01 is not set
-# CONFIG_RTC_DRV_V3020 is not set
-
-#
-# on-CPU RTC drivers
-#
-# CONFIG_DMADEVICES is not set
-# CONFIG_AUXDISPLAY is not set
-# CONFIG_UIO is not set
-CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
-# CONFIG_VIDEO_CPIA is not set
-# CONFIG_USB_IP_COMMON is not set
-# CONFIG_ECHO is not set
-# CONFIG_BRCM80211 is not set
-# CONFIG_RT2870 is not set
-# CONFIG_COMEDI is not set
-# CONFIG_ASUS_OLED is not set
-# CONFIG_R8712U is not set
-# CONFIG_TRANZPORT is not set
-
-#
-# Android
-#
-CONFIG_ANDROID=y
-CONFIG_ANDROID_BINDER_IPC=y
-CONFIG_ANDROID_LOGGER=y
-CONFIG_ANDROID_RAM_CONSOLE=y
-CONFIG_ANDROID_RAM_CONSOLE_ENABLE_VERBOSE=y
-CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
-CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_DATA_SIZE=128
-CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_ECC_SIZE=16
-CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_SYMBOL_SIZE=8
-CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL=0x11d
-# CONFIG_ANDROID_RAM_CONSOLE_EARLY_INIT is not set
-CONFIG_ANDROID_TIMED_OUTPUT=y
-CONFIG_ANDROID_TIMED_GPIO=y
-CONFIG_ANDROID_LOW_MEMORY_KILLER=y
-# CONFIG_POHMELFS is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_LINE6_USB is not set
-# CONFIG_VT6656 is not set
-# CONFIG_FB_UDL is not set
-# CONFIG_IIO is not set
-# CONFIG_ZRAM is not set
-# CONFIG_BATMAN_ADV is not set
-# CONFIG_FB_SM7XX is not set
-
-#
-# Texas Instruments shared transport line discipline
-#
-# CONFIG_ADIS16255 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_EASYCAP is not set
-# CONFIG_TIDSPBRIDGE is not set
-# CONFIG_WESTBRIDGE is not set
-CONFIG_WESTBRIDGE_HAL_SELECTED=y
-CONFIG_MACH_OMAP3_WESTBRIDGE_AST_PNAND_HAL=y
-# CONFIG_MACH_NO_WESTBRIDGE is not set
-# CONFIG_ATH6K_LEGACY is not set
-# CONFIG_USB_ENESTORAGE is not set
-# CONFIG_BCM_WIMAX is not set
-# CONFIG_FT1000 is not set
-
-#
-# Speakup console speech
-#
-# CONFIG_SPEAKUP is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT2_FS_XIP is not set
-CONFIG_EXT3_FS=y
-CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_EXT4_FS=y
-CONFIG_EXT4_FS_XATTR=y
-# CONFIG_EXT4_FS_POSIX_ACL is not set
-# CONFIG_EXT4_FS_SECURITY is not set
-# CONFIG_EXT4_DEBUG is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
-# CONFIG_GFS2_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_BTRFS_FS is not set
-# CONFIG_NILFS2_FS is not set
-CONFIG_FILE_LOCKING=y
-CONFIG_FSNOTIFY=y
-CONFIG_DNOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_FANOTIFY is not set
-CONFIG_QUOTA=y
-# CONFIG_QUOTA_NETLINK_INTERFACE is not set
-CONFIG_PRINT_QUOTA_WARNING=y
-# CONFIG_QUOTA_DEBUG is not set
-CONFIG_QUOTA_TREE=y
-# CONFIG_QFMT_V1 is not set
-CONFIG_QFMT_V2=y
-CONFIG_QUOTACTL=y
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
-
-#
-# Caches
-#
-# CONFIG_FSCACHE is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_PROC_PAGE_MONITOR=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLB_PAGE is not set
-# CONFIG_CONFIGFS_FS is not set
-CONFIG_MISC_FILESYSTEMS=y
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_ECRYPT_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_YAFFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_JFFS2_FS_WRITEBUFFER=y
-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_FS_XATTR=y
-CONFIG_JFFS2_FS_POSIX_ACL=y
-CONFIG_JFFS2_FS_SECURITY=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_ZLIB=y
-CONFIG_JFFS2_LZO=y
-CONFIG_JFFS2_RTIME=y
-CONFIG_JFFS2_RUBIN=y
-# CONFIG_JFFS2_CMODE_NONE is not set
-CONFIG_JFFS2_CMODE_PRIORITY=y
-# CONFIG_JFFS2_CMODE_SIZE is not set
-# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
-# CONFIG_LOGFS is not set
-CONFIG_CRAMFS=y
-# CONFIG_SQUASHFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_OMFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-# CONFIG_NFS_V4_1 is not set
-CONFIG_ROOT_NFS=y
-CONFIG_NFS_USE_LEGACY_DNS=y
-# CONFIG_NFS_USE_NEW_IDMAPPER is not set
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_NFS_ACL_SUPPORT=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-CONFIG_RPCSEC_GSS_KRB5=y
-# CONFIG_CEPH_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_ACORN_PARTITION is not set
-# CONFIG_OSF_PARTITION is not set
-# CONFIG_AMIGA_PARTITION is not set
-# CONFIG_ATARI_PARTITION is not set
-# CONFIG_MAC_PARTITION is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_BSD_DISKLABEL is not set
-# CONFIG_MINIX_SUBPARTITION is not set
-# CONFIG_SOLARIS_X86_PARTITION is not set
-# CONFIG_UNIXWARE_DISKLABEL is not set
-# CONFIG_LDM_PARTITION is not set
-# CONFIG_SGI_PARTITION is not set
-# CONFIG_ULTRIX_PARTITION is not set
-# CONFIG_SUN_PARTITION is not set
-# CONFIG_KARMA_PARTITION is not set
-# CONFIG_EFI_PARTITION is not set
-# CONFIG_SYSV68_PARTITION is not set
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=y
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
-# CONFIG_DLM is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-CONFIG_ENABLE_WARN_DEPRECATED=y
-CONFIG_ENABLE_MUST_CHECK=y
-CONFIG_FRAME_WARN=1024
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_STRIP_ASM_SYMS is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-CONFIG_DEBUG_FS=y
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_HARDLOCKUP_DETECTOR is not set
-CONFIG_BKL=y
-# CONFIG_SPARSE_RCU_POINTER is not set
-CONFIG_STACKTRACE=y
-CONFIG_DEBUG_BUGVERBOSE=y
-# CONFIG_DEBUG_MEMORY_INIT is not set
-CONFIG_FRAME_POINTER=y
-# CONFIG_LKDTM is not set
-# CONFIG_SYSCTL_SYSCALL_CHECK is not set
-CONFIG_NOP_TRACER=y
-CONFIG_HAVE_FUNCTION_TRACER=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
-CONFIG_RING_BUFFER=y
-CONFIG_EVENT_TRACING=y
-CONFIG_CONTEXT_SWITCH_TRACER=y
-CONFIG_RING_BUFFER_ALLOW_SWAP=y
-CONFIG_TRACING=y
-CONFIG_TRACING_SUPPORT=y
-CONFIG_FTRACE=y
-# CONFIG_FUNCTION_TRACER is not set
-# CONFIG_IRQSOFF_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_ENABLE_DEFAULT_TRACERS is not set
-CONFIG_BRANCH_PROFILE_NONE=y
-# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
-# CONFIG_PROFILE_ALL_BRANCHES is not set
-# CONFIG_STACK_TRACER is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-CONFIG_KPROBE_EVENT=y
-# CONFIG_RING_BUFFER_BENCHMARK is not set
-# CONFIG_DYNAMIC_DEBUG is not set
-# CONFIG_ATOMIC64_SELFTEST is not set
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_STRICT_DEVMEM is not set
-# CONFIG_ARM_UNWIND is not set
-# CONFIG_DEBUG_USER is not set
-# CONFIG_OC_ETM is not set
-
-#
-# Security options
-#
-CONFIG_KEYS=y
-# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
-# CONFIG_SECURITY_DMESG_RESTRICT is not set
-CONFIG_SECURITY=y
-# CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_NETWORK is not set
-# CONFIG_SECURITY_PATH is not set
-# CONFIG_SECURITY_TOMOYO is not set
-# CONFIG_SECURITY_APPARMOR is not set
-# CONFIG_IMA is not set
-CONFIG_DEFAULT_SECURITY_DAC=y
-CONFIG_DEFAULT_SECURITY=""
-CONFIG_CRYPTO=y
-
-#
-# Crypto core or helper
-#
-CONFIG_CRYPTO_ALGAPI=y
-CONFIG_CRYPTO_ALGAPI2=y
-CONFIG_CRYPTO_AEAD2=y
-CONFIG_CRYPTO_BLKCIPHER=y
-CONFIG_CRYPTO_BLKCIPHER2=y
-CONFIG_CRYPTO_HASH=y
-CONFIG_CRYPTO_HASH2=y
-CONFIG_CRYPTO_RNG2=y
-CONFIG_CRYPTO_PCOMP2=y
-CONFIG_CRYPTO_MANAGER=y
-CONFIG_CRYPTO_MANAGER2=y
-CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
-# CONFIG_CRYPTO_GF128MUL is not set
-# CONFIG_CRYPTO_NULL is not set
-CONFIG_CRYPTO_WORKQUEUE=y
-# CONFIG_CRYPTO_CRYPTD is not set
-# CONFIG_CRYPTO_AUTHENC is not set
-# CONFIG_CRYPTO_TEST is not set
-
-#
-# Authenticated Encryption with Associated Data
-#
-# CONFIG_CRYPTO_CCM is not set
-# CONFIG_CRYPTO_GCM is not set
-# CONFIG_CRYPTO_SEQIV is not set
-
-#
-# Block modes
-#
-CONFIG_CRYPTO_CBC=y
-# CONFIG_CRYPTO_CTR is not set
-# CONFIG_CRYPTO_CTS is not set
-# CONFIG_CRYPTO_ECB is not set
-# CONFIG_CRYPTO_LRW is not set
-# CONFIG_CRYPTO_PCBC is not set
-# CONFIG_CRYPTO_XTS is not set
-
-#
-# Hash modes
-#
-# CONFIG_CRYPTO_HMAC is not set
-# CONFIG_CRYPTO_XCBC is not set
-# CONFIG_CRYPTO_VMAC is not set
-
-#
-# Digest
-#
-CONFIG_CRYPTO_CRC32C=y
-# CONFIG_CRYPTO_GHASH is not set
-# CONFIG_CRYPTO_MD4 is not set
-CONFIG_CRYPTO_MD5=y
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-# CONFIG_CRYPTO_RMD128 is not set
-# CONFIG_CRYPTO_RMD160 is not set
-# CONFIG_CRYPTO_RMD256 is not set
-# CONFIG_CRYPTO_RMD320 is not set
-# CONFIG_CRYPTO_SHA1 is not set
-# CONFIG_CRYPTO_SHA256 is not set
-# CONFIG_CRYPTO_SHA512 is not set
-# CONFIG_CRYPTO_TGR192 is not set
-# CONFIG_CRYPTO_WP512 is not set
-
-#
-# Ciphers
-#
-# CONFIG_CRYPTO_AES is not set
-# CONFIG_CRYPTO_ANUBIS is not set
-# CONFIG_CRYPTO_ARC4 is not set
-# CONFIG_CRYPTO_BLOWFISH is not set
-# CONFIG_CRYPTO_CAMELLIA is not set
-# CONFIG_CRYPTO_CAST5 is not set
-# CONFIG_CRYPTO_CAST6 is not set
-CONFIG_CRYPTO_DES=y
-# CONFIG_CRYPTO_FCRYPT is not set
-# CONFIG_CRYPTO_KHAZAD is not set
-# CONFIG_CRYPTO_SALSA20 is not set
-# CONFIG_CRYPTO_SEED is not set
-# CONFIG_CRYPTO_SERPENT is not set
-# CONFIG_CRYPTO_TEA is not set
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRYPTO_TWOFISH_COMMON=y
-
-#
-# Compression
-#
-# CONFIG_CRYPTO_DEFLATE is not set
-# CONFIG_CRYPTO_ZLIB is not set
-# CONFIG_CRYPTO_LZO is not set
-
-#
-# Random Number Generation
-#
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_HW=y
-# CONFIG_CRYPTO_DEV_OMAP_SHAM is not set
-# CONFIG_CRYPTO_DEV_OMAP_AES is not set
-CONFIG_BINARY_PRINTF=y
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-CONFIG_GENERIC_FIND_LAST_BIT=y
-CONFIG_CRC_CCITT=y
-# CONFIG_CRC16 is not set
-# CONFIG_CRC_T10DIF is not set
-# CONFIG_CRC_ITU_T is not set
-CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
-CONFIG_LIBCRC32C=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_LZO_COMPRESS=y
-CONFIG_LZO_DECOMPRESS=y
-CONFIG_DECOMPRESS_GZIP=y
-CONFIG_REED_SOLOMON=y
-CONFIG_REED_SOLOMON_ENC8=y
-CONFIG_REED_SOLOMON_DEC8=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
-CONFIG_NLATTR=y
diff --git a/kernel/arch/arm/configs/panda_defconfig b/kernel/arch/arm/configs/panda_defconfig
deleted file mode 100644
index 4c5e56c56cf6..000000000000
--- a/kernel/arch/arm/configs/panda_defconfig
+++ /dev/null
@@ -1,331 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_CGROUPS=y
-CONFIG_CGROUP_DEBUG=y
-CONFIG_CGROUP_FREEZER=y
-CONFIG_CGROUP_CPUACCT=y
-CONFIG_RESOURCE_COUNTERS=y
-CONFIG_CGROUP_SCHED=y
-CONFIG_RT_GROUP_SCHED=y
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_KALLSYMS_ALL=y
-CONFIG_PANIC_TIMEOUT=5
-CONFIG_ASHMEM=y
-# CONFIG_AIO is not set
-CONFIG_EMBEDDED=y
-# CONFIG_SLUB_DEBUG is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_FORCE_LOAD=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_OMAP_RESET_CLOCKS=y
-# CONFIG_ARCH_OMAP2 is not set
-# CONFIG_ARCH_OMAP3 is not set
-# CONFIG_MACH_OMAP_4430SDP is not set
-CONFIG_ARM_THUMBEE=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_SMP=y
-# CONFIG_SMP_ON_UP is not set
-CONFIG_NR_CPUS=2
-CONFIG_PREEMPT=y
-CONFIG_CMDLINE="console=ttyO2,115200n8 mem=1G androidboot.console=ttyO2"
-CONFIG_CMDLINE_EXTEND=y
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE=y
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-CONFIG_CPU_FREQ_GOV_POWERSAVE=y
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
-CONFIG_CPU_IDLE=y
-CONFIG_OMAP_SMARTREFLEX=y
-CONFIG_OMAP_SMARTREFLEX_CLASS1P5=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_BINFMT_MISC=y
-CONFIG_WAKELOCK=y
-CONFIG_PM_DEBUG=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=y
-CONFIG_INET=y
-CONFIG_INET_ESP=y
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-CONFIG_IPV6=y
-CONFIG_IPV6_PRIVACY=y
-CONFIG_IPV6_ROUTER_PREF=y
-CONFIG_IPV6_OPTIMISTIC_DAD=y
-CONFIG_INET6_AH=y
-CONFIG_INET6_ESP=y
-CONFIG_INET6_IPCOMP=y
-CONFIG_IPV6_MIP6=y
-CONFIG_IPV6_TUNNEL=y
-CONFIG_IPV6_MULTIPLE_TABLES=y
-CONFIG_NETFILTER=y
-CONFIG_NETFILTER_NETLINK_LOG=y
-CONFIG_NETFILTER_TPROXY=y
-CONFIG_NF_CONNTRACK=y
-CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_DCCP=y
-CONFIG_NF_CT_PROTO_SCTP=y
-CONFIG_NF_CT_PROTO_UDPLITE=y
-CONFIG_NF_CONNTRACK_AMANDA=y
-CONFIG_NF_CONNTRACK_FTP=y
-CONFIG_NF_CONNTRACK_H323=y
-CONFIG_NF_CONNTRACK_IRC=y
-CONFIG_NF_CONNTRACK_NETBIOS_NS=y
-CONFIG_NF_CONNTRACK_PPTP=y
-CONFIG_NF_CONNTRACK_SANE=y
-CONFIG_NF_CONNTRACK_TFTP=y
-CONFIG_NF_CT_NETLINK=y
-CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
-CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
-CONFIG_NETFILTER_XT_TARGET_MARK=y
-CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
-CONFIG_NETFILTER_XT_MATCH_COMMENT=y
-CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
-CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
-CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
-CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
-CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
-CONFIG_NETFILTER_XT_MATCH_HELPER=y
-CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
-CONFIG_NETFILTER_XT_MATCH_LENGTH=y
-CONFIG_NETFILTER_XT_MATCH_LIMIT=y
-CONFIG_NETFILTER_XT_MATCH_MAC=y
-CONFIG_NETFILTER_XT_MATCH_MARK=y
-CONFIG_NETFILTER_XT_MATCH_POLICY=y
-CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
-CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
-CONFIG_NETFILTER_XT_MATCH_QUOTA=y
-CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
-CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
-CONFIG_NETFILTER_XT_MATCH_SOCKET=y
-CONFIG_NETFILTER_XT_MATCH_STATE=y
-CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
-CONFIG_NETFILTER_XT_MATCH_STRING=y
-CONFIG_NETFILTER_XT_MATCH_TIME=y
-CONFIG_NETFILTER_XT_MATCH_U32=y
-CONFIG_NF_CONNTRACK_IPV4=y
-CONFIG_NF_CONNTRACK_IPV6=y
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_MATCH_AH=y
-CONFIG_IP_NF_MATCH_ECN=y
-CONFIG_IP_NF_MATCH_TTL=y
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_IP_NF_TARGET_REJECT_SKERR=y
-CONFIG_IP_NF_TARGET_LOG=y
-CONFIG_NF_NAT=y
-CONFIG_IP_NF_MANGLE=y
-CONFIG_IP_NF_TARGET_MASQUERADE=y
-CONFIG_IP_NF_TARGET_NETMAP=y
-CONFIG_IP_NF_TARGET_REDIRECT=y
-CONFIG_IP_NF_RAW=y
-CONFIG_IP_NF_ARPTABLES=y
-CONFIG_IP_NF_ARPFILTER=y
-CONFIG_IP_NF_ARP_MANGLE=y
-CONFIG_IP6_NF_IPTABLES=y
-CONFIG_IP6_NF_TARGET_LOG=y
-CONFIG_IP6_NF_FILTER=y
-CONFIG_IP6_NF_TARGET_REJECT=y
-CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
-CONFIG_IP6_NF_MANGLE=y
-CONFIG_IP6_NF_RAW=y
-CONFIG_PHONET=y
-CONFIG_NET_SCHED=y
-CONFIG_NET_SCH_HTB=y
-CONFIG_NET_SCH_INGRESS=y
-CONFIG_NET_CLS_U32=y
-CONFIG_NET_EMATCH=y
-CONFIG_NET_EMATCH_U32=y
-CONFIG_NET_CLS_ACT=y
-CONFIG_NET_ACT_POLICE=y
-CONFIG_NET_ACT_GACT=y
-CONFIG_NET_ACT_MIRRED=y
-CONFIG_BT=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_L2CAP=y
-CONFIG_BT_SCO=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_HCIUART=y
-CONFIG_BT_HCIUART_H4=y
-CONFIG_BT_WILINK=y
-CONFIG_RFKILL=y
-CONFIG_RFKILL_INPUT=y
-CONFIG_MTD=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_NAND_IDS=y
-CONFIG_MTD_ONENAND=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_MISC_DEVICES=y
-# CONFIG_ANDROID_PMEM is not set
-CONFIG_KERNEL_DEBUGGER_CORE=y
-CONFIG_UID_STAT=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_SG=y
-CONFIG_MD=y
-CONFIG_BLK_DEV_DM=y
-CONFIG_DM_DEBUG=y
-CONFIG_DM_CRYPT=y
-CONFIG_DM_UEVENT=y
-CONFIG_NETDEVICES=y
-CONFIG_IFB=y
-CONFIG_USB_USBNET=y
-CONFIG_USB_NET_SMSC95XX=y
-CONFIG_PPP=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-CONFIG_PPP_MPPE=y
-CONFIG_PPPOLAC=y
-CONFIG_PPPOPNS=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_KEYRESET=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
-CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
-CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_KEYCHORD=y
-CONFIG_INPUT_UINPUT=y
-CONFIG_INPUT_GPIO=y
-# CONFIG_VT is not set
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_HW_RANDOM=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_SPI=y
-CONFIG_SPI_GPIO=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_TWL4030=y
-CONFIG_POWER_SUPPLY=y
-# CONFIG_HWMON is not set
-CONFIG_TWL6030_PWM=y
-CONFIG_REGULATOR_TWL4030=y
-CONFIG_MEDIA_SUPPORT=y
-CONFIG_PVR_SGX=y
-CONFIG_PVR_NEED_PVR_DPF=y
-CONFIG_PVR_NEED_PVR_ASSERT=y
-CONFIG_PVR_USSE_EDM_STATUS_DEBUG=y
-CONFIG_FB=y
-CONFIG_OMAP2_DSS=y
-# CONFIG_OMAP2_DSS_VENC is not set
-CONFIG_FB_OMAP2=y
-CONFIG_FB_OMAP2_NUM_FBS=2
-CONFIG_OMAP2_VRAM_SIZE=16
-CONFIG_PANEL_GENERIC_DPI=y
-CONFIG_DISPLAY_SUPPORT=y
-CONFIG_USB=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_SUSPEND=y
-CONFIG_USB_EHCI_HCD=y
-CONFIG_USB_MUSB_HDRC=y
-CONFIG_USB_MUSB_OMAP2PLUS=y
-CONFIG_USB_MUSB_PERIPHERAL=y
-CONFIG_USB_GADGET_MUSB_HDRC=y
-CONFIG_USB_ACM=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_SERIAL=y
-CONFIG_USB_SERIAL_KEYSPAN=y
-CONFIG_USB_SERIAL_KEYSPAN_MPR=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
-CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19=y
-CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
-CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
-CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_VBUS_DRAW=500
-CONFIG_USB_G_ANDROID=y
-CONFIG_MMC=y
-CONFIG_MMC_UNSAFE_RESUME=y
-CONFIG_MMC_EMBEDDED_SDIO=y
-CONFIG_MMC_PARANOID_SD_INIT=y
-CONFIG_MMC_OMAP=y
-CONFIG_MMC_OMAP_HS=y
-CONFIG_SWITCH=y
-CONFIG_SWITCH_GPIO=y
-CONFIG_RTC_CLASS=y
-CONFIG_STAGING=y
-CONFIG_ANDROID=y
-CONFIG_ANDROID_BINDER_IPC=y
-CONFIG_ANDROID_LOGGER=y
-CONFIG_ANDROID_RAM_CONSOLE=y
-CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION=y
-CONFIG_ANDROID_TIMED_GPIO=y
-CONFIG_ANDROID_LOW_MEMORY_KILLER=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT4_FS=y
-# CONFIG_EXT4_FS_XATTR is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_FUSE_FS=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_TMPFS_POSIX_ACL=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_EFI_PARTITION=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ASCII=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_PRINTK_TIME=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_DEBUG_PREEMPT is not set
-CONFIG_DEBUG_RT_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
-CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-# CONFIG_ARM_UNWIND is not set
-CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_TWOFISH=y
-CONFIG_CRC_CCITT=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_SOC=y
-CONFIG_SND_OMAP_SOC=y
-CONFIG_SND_OMAP_SOC_SDP4430=y
-CONFIG_SND_OMAP_SOC_OMAP4_HDMI=y
-CONFIG_OMAP_HSI=y
-CONFIG_OMAP_HSI_DEVICE=y
-CONFIG_CFG80211=y
-CONFIG_NL80211_TESTMODE=y
-CONFIG_LIB80211=y
-CONFIG_MAC80211=y
-CONFIG_MAC80211_LEDS=y
-CONFIG_MAC80211_DEBUGFS=y
-CONFIG_USB_ZD1201=y
-CONFIG_WL12XX_MENU=y
-CONFIG_WL12XX=y
-CONFIG_WL12XX_SDIO=y
-CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_MD4=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_OMAP_TEMP_SENSOR=y
-CONFIG_OMAP_DIE_TEMP_SENSOR=y
-CONFIG_TI_ST=y
-CONFIG_KEYBOARD_GPIO=y
diff --git a/kernel/arch/arm/mach-omap2/board-omap3beagle.c b/kernel/arch/arm/mach-omap2/board-omap3beagle.c
deleted file mode 100644
index b3d1b81b2a2e..000000000000
--- a/kernel/arch/arm/mach-omap2/board-omap3beagle.c
+++ /dev/null
@@ -1,1038 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/board-omap3beagle.c
- *
- * Copyright (C) 2008 Texas Instruments
- *
- * Modified from mach-omap2/board-3430sdp.c
- *
- * Initial code: Syed Mohammed Khasim
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/leds.h>
-#include <linux/gpio.h>
-#include <linux/input.h>
-#include <linux/gpio_keys.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/nand.h>
-#include <linux/mmc/host.h>
-
-#include <linux/usb/android_composite.h>
-
-#include <linux/regulator/machine.h>
-#include <linux/i2c/twl.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/flash.h>
-
-#include <plat/board.h>
-#include <plat/common.h>
-#include <plat/display.h>
-#include <plat/gpmc.h>
-#include <plat/nand.h>
-#include <plat/usb.h>
-
-#include "mux.h"
-#include "hsmmc.h"
-#include "timer-gp.h"
-#include "board-flash.h"
-
-#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4
-#include <linux/input/synaptics_dsx.h>
-
-#define TM_SAMPLE1 (1) // 2D only
-#define TM_SAMPLE2 (2) // 2D + 0D x 2
-#define TM_SAMPLE3 (3) // 2D + 0D x 4
-#define SYNAPTICS_MODULE TM_SAMPLE1
-#endif
-
-#define NAND_BLOCK_SIZE SZ_128K
-
-#ifdef CONFIG_USB_ANDROID
-#define GOOGLE_VENDOR_ID 0x18d1
-#define GOOGLE_PRODUCT_ID 0x9018
-#define GOOGLE_ADB_PRODUCT_ID 0x9015
-#endif
-
-/* Synaptics Thin Driver */
-#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4
-static int synaptics_gpio_setup(unsigned gpio, bool configure)
-{
- int retval=0;
- if (configure)
- {
- retval = gpio_request(gpio, "rmi4_attn");
- if (retval) {
- pr_err("%s: Failed to get attn gpio %d. Code: %d.",
- __func__, gpio, retval);
- return retval;
- }
- omap_mux_init_signal("sdmmc2_clk.gpio_130", OMAP_PIN_INPUT_PULLUP);
-
- retval = gpio_direction_input(gpio);
- if (retval) {
- pr_err("%s: Failed to setup attn gpio %d. Code: %d.",
- __func__, gpio, retval);
- gpio_free(gpio);
- }
- } else {
- pr_warn("%s: No way to deconfigure gpio %d.",
- __func__, gpio);
- }
-
- return retval;
-}
-
- #if (SYNAPTICS_MODULE == TM_SAMPLE1)
-#define TM_SAMPLE1_ADDR 0x20
-#define TM_SAMPLE1_ATTN 130
-
-static unsigned char TM_SAMPLE1_f1a_button_codes[] = {};
-
-static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE1_capacitance_button_map = {
- .nbuttons = ARRAY_SIZE(TM_SAMPLE1_f1a_button_codes),
- .map = TM_SAMPLE1_f1a_button_codes,
-};
-
-static struct synaptics_rmi4_platform_data rmi4_platformdata = {
- .irq_flags = IRQF_TRIGGER_FALLING,
- .irq_gpio = TM_SAMPLE1_ATTN,
- .gpio_config = synaptics_gpio_setup,
- .capacitance_button_map = &TM_SAMPLE1_capacitance_button_map,
-};
-
-static struct i2c_board_info bus2_i2c_devices[] = {
- {
- I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE1_ADDR),
- .platform_data = &rmi4_platformdata,
- },
-};
-
-#elif (SYNAPTICS_MODULE == TM_SAMPLE2)
-#define TM_SAMPLE2_ADDR 0x20
-#define TM_SAMPLE2_ATTN 130
-
-static unsigned char TM_SAMPLE2_f1a_button_codes[] = {KEY_MENU, KEY_BACK};
-
-static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE2_capacitance_button_map = {
- .nbuttons = ARRAY_SIZE(TM_SAMPLE2_f1a_button_codes),
- .map = TM_SAMPLE2_f1a_button_codes,
-};
-
-static struct synaptics_rmi4_platform_data rmi4_platformdata = {
- .irq_flags = IRQF_TRIGGER_FALLING,
- .irq_gpio = TM_SAMPLE2_ATTN,
- .gpio_config = synaptics_gpio_setup,
- .capacitance_button_map = &TM_SAMPLE2_capacitance_button_map,
-};
-
-static struct i2c_board_info bus2_i2c_devices[] = {
- {
- I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE2_ADDR),
- .platform_data = &rmi4_platformdata,
- },
-};
-
-#elif (SYNAPTICS_MODULE == TM_SAMPLE3)
-#define TM_SAMPLE3_ADDR 0x20
-#define TM_SAMPLE3_ATTN 130
-
-static unsigned char TM_SAMPLE3_f1a_button_codes[] = {KEY_MENU, KEY_HOME,KEY_BACK,KEY_SEARCH};
-
-static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE3_capacitance_button_map = {
- .nbuttons = ARRAY_SIZE(TM_SAMPLE3_f1a_button_codes),
- .map = TM_SAMPLE3_f1a_button_codes,
-};
-
-static struct synaptics_rmi4_platform_data rmi4_platformdata = {
- .irq_flags = IRQF_TRIGGER_FALLING,
- .irq_gpio = TM_SAMPLE3_ATTN,
- .gpio_config = synaptics_gpio_setup,
- .capacitance_button_map = &TM_SAMPLE3_capacitance_button_map,
-};
-
-static struct i2c_board_info bus2_i2c_devices[] = {
- {
- I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE3_ADDR),
- .platform_data = &rmi4_platformdata,
- },
-};
-#endif
-
-void __init i2c_device_setup(void)
-{
- pr_info(">>>>I2C device setup.");
- if (ARRAY_SIZE(bus2_i2c_devices)) {
- i2c_register_board_info(2, bus2_i2c_devices,
- ARRAY_SIZE(bus2_i2c_devices));
- }
-}
-
-/* End of Synaptics change for beagle board */
-
-static char *usb_functions_adb[] = {
- "adb",
-};
-
-static char *usb_functions_mass_storage[] = {
- "usb_mass_storage",
-};
-static char *usb_functions_ums_adb[] = {
- "usb_mass_storage",
- "adb",
-};
-
-static char *usb_functions_all[] = {
- "adb", "usb_mass_storage",
-};
-
-static struct android_usb_product usb_products[] = {
- {
- .product_id = GOOGLE_PRODUCT_ID,
- .num_functions = ARRAY_SIZE(usb_functions_adb),
- .functions = usb_functions_adb,
- },
- {
- .product_id = GOOGLE_PRODUCT_ID,
- .num_functions = ARRAY_SIZE(usb_functions_mass_storage),
- .functions = usb_functions_mass_storage,
- },
- {
- .product_id = GOOGLE_PRODUCT_ID,
- .num_functions = ARRAY_SIZE(usb_functions_ums_adb),
- .functions = usb_functions_ums_adb,
- },
-};
-
-static struct usb_mass_storage_platform_data mass_storage_pdata = {
- .nluns = 1,
- .vendor = "rowboat",
- .product = "rowboat gadget",
- .release = 0x100,
-};
-
-static struct platform_device usb_mass_storage_device = {
- .name = "usb_mass_storage",
- .id = -1,
- .dev = {
- .platform_data = &mass_storage_pdata,
- },
-};
-
-static struct android_usb_platform_data android_usb_pdata = {
- .vendor_id = GOOGLE_VENDOR_ID,
- .product_id = GOOGLE_PRODUCT_ID,
- .functions = usb_functions_all,
- .products = usb_products,
- .num_products = ARRAY_SIZE(usb_products),
- .version = 0x0100,
- .product_name = "rowboat gadget",
- .manufacturer_name = "rowboat",
- .serial_number = "20100720",
- .num_functions = ARRAY_SIZE(usb_functions_all),
-};
-
-static struct platform_device androidusb_device = {
- .name = "android_usb",
- .id = -1,
- .dev = {
- .platform_data = &android_usb_pdata,
- },
-};
-
-static void omap3beagle_android_gadget_init(void)
-{
- platform_device_register(&androidusb_device);
-}
-#endif
-/*
- * OMAP3 Beagle revision
- * Run time detection of Beagle revision is done by reading GPIO.
- * GPIO ID -
- * AXBX = GPIO173, GPIO172, GPIO171: 1 1 1
- * C1_3 = GPIO173, GPIO172, GPIO171: 1 1 0
- * C4 = GPIO173, GPIO172, GPIO171: 1 0 1
- * XM = GPIO173, GPIO172, GPIO171: 0 0 0
- */
-enum {
- OMAP3BEAGLE_BOARD_UNKN = 0,
- OMAP3BEAGLE_BOARD_AXBX,
- OMAP3BEAGLE_BOARD_C1_3,
- OMAP3BEAGLE_BOARD_C4,
- OMAP3BEAGLE_BOARD_XM,
- OMAP3BEAGLE_BOARD_XMC,
-};
-
-extern void omap_pm_sys_offmode_select(int);
-extern void omap_pm_sys_offmode_pol(int);
-extern void omap_pm_sys_clkreq_pol(int);
-extern void omap_pm_auto_off(int);
-extern void omap_pm_auto_ret(int);
-
-static u8 omap3_beagle_version;
-
-static u8 omap3_beagle_get_rev(void)
-{
- return omap3_beagle_version;
-}
-
-/**
- * Board specific initialization of PM components
- */
-static void __init omap3_beagle_pm_init(void)
-{
- /* Use sys_offmode signal */
- omap_pm_sys_offmode_select(1);
-
- /* sys_clkreq - active high */
- omap_pm_sys_clkreq_pol(1);
-
- /* sys_offmode - active low */
- omap_pm_sys_offmode_pol(0);
-
- /* Automatically send OFF command */
- omap_pm_auto_off(1);
-
- /* Automatically send RET command */
- omap_pm_auto_ret(1);
-}
-
-static void __init omap3_beagle_init_rev(void)
-{
- int ret;
- u16 beagle_rev = 0;
-
- omap_mux_init_gpio(171, OMAP_PIN_INPUT_PULLUP);
- omap_mux_init_gpio(172, OMAP_PIN_INPUT_PULLUP);
- omap_mux_init_gpio(173, OMAP_PIN_INPUT_PULLUP);
-
- ret = gpio_request(171, "rev_id_0");
- if (ret < 0)
- goto fail0;
-
- ret = gpio_request(172, "rev_id_1");
- if (ret < 0)
- goto fail1;
-
- ret = gpio_request(173, "rev_id_2");
- if (ret < 0)
- goto fail2;
-
- gpio_direction_input(171);
- gpio_direction_input(172);
- gpio_direction_input(173);
-
- beagle_rev = gpio_get_value(171) | (gpio_get_value(172) << 1)
- | (gpio_get_value(173) << 2);
-
- switch (beagle_rev) {
- case 7:
- printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n");
- omap3_beagle_version = OMAP3BEAGLE_BOARD_AXBX;
- break;
- case 6:
- printk(KERN_INFO "OMAP3 Beagle Rev: C1/C2/C3\n");
- omap3_beagle_version = OMAP3BEAGLE_BOARD_C1_3;
- break;
- case 5:
- printk(KERN_INFO "OMAP3 Beagle Rev: C4\n");
- omap3_beagle_version = OMAP3BEAGLE_BOARD_C4;
- break;
- case 2:
- printk(KERN_INFO "OMAP3 Beagle Rev: xM C\n");
- omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC;
- break;
- case 0:
- printk(KERN_INFO "OMAP3 Beagle Rev: xM\n");
- omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
- break;
- default:
- printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev);
- omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN;
- }
-
- return;
-
-fail2:
- gpio_free(172);
-fail1:
- gpio_free(171);
-fail0:
- printk(KERN_ERR "Unable to get revision detection GPIO pins\n");
- omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN;
-
- return;
-}
-
-static struct mtd_partition omap3beagle_nand_partitions[] = {
- /* All the partition sizes are listed in terms of NAND block size */
- {
- .name = "X-Loader",
- .offset = 0,
- .size = 4 * NAND_BLOCK_SIZE,
- .mask_flags = MTD_WRITEABLE, /* force read-only */
- },
- {
- .name = "U-Boot",
- .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
- .size = 15 * NAND_BLOCK_SIZE,
- .mask_flags = MTD_WRITEABLE, /* force read-only */
- },
- {
- .name = "U-Boot Env",
- .offset = MTDPART_OFS_APPEND, /* Offset = 0x260000 */
- .size = 1 * NAND_BLOCK_SIZE,
- },
- {
- .name = "Kernel",
- .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */
- .size = 32 * NAND_BLOCK_SIZE,
- },
- {
- .name = "File System",
- .offset = MTDPART_OFS_APPEND, /* Offset = 0x680000 */
- .size = MTDPART_SIZ_FULL,
- },
-};
-
-/* DSS */
-
-static int beagle_enable_dvi(struct omap_dss_device *dssdev)
-{
- if (gpio_is_valid(dssdev->reset_gpio))
- gpio_set_value(dssdev->reset_gpio, 1);
-
- return 0;
-}
-
-static void beagle_disable_dvi(struct omap_dss_device *dssdev)
-{
- if (gpio_is_valid(dssdev->reset_gpio))
- gpio_set_value(dssdev->reset_gpio, 0);
-}
-
-static struct omap_dss_device beagle_dvi_device = {
- .type = OMAP_DISPLAY_TYPE_DPI,
- .name = "dvi",
- .driver_name = "generic_panel",
- .phy.dpi.data_lines = 24,
- .reset_gpio = -EINVAL,
- .platform_enable = beagle_enable_dvi,
- .platform_disable = beagle_disable_dvi,
-};
-
-static struct omap_dss_device beagle_tv_device = {
- .name = "tv",
- .driver_name = "venc",
- .type = OMAP_DISPLAY_TYPE_VENC,
- .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
-};
-
-static struct omap_dss_device *beagle_dss_devices[] = {
- &beagle_dvi_device,
- &beagle_tv_device,
-};
-
-static struct omap_dss_board_info beagle_dss_data = {
- .num_devices = ARRAY_SIZE(beagle_dss_devices),
- .devices = beagle_dss_devices,
- .default_device = &beagle_dvi_device,
-};
-
-static struct platform_device beagle_dss_device = {
- .name = "omapdss",
- .id = -1,
- .dev = {
- .platform_data = &beagle_dss_data,
- },
-};
-
-static struct regulator_consumer_supply beagle_vdac_supply =
- REGULATOR_SUPPLY("vdda_dac", "omapdss");
-
-static struct regulator_consumer_supply beagle_vdvi_supply =
- REGULATOR_SUPPLY("vdds_dsi", "omapdss");
-
-static void __init beagle_display_init(void)
-{
- int r;
-
- r = gpio_request(beagle_dvi_device.reset_gpio, "DVI reset");
- if (r < 0) {
- printk(KERN_ERR "Unable to get DVI reset GPIO\n");
- return;
- }
-
- gpio_direction_output(beagle_dvi_device.reset_gpio, 0);
-}
-
-#include "sdram-micron-mt46h32m32lf-6.h"
-
-static struct omap2_hsmmc_info mmc[] = {
- {
- .mmc = 1,
- .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
- .gpio_wp = 29,
- },
- {} /* Terminator */
-};
-
-static struct regulator_consumer_supply beagle_vmmc1_supply = {
- .supply = "vmmc",
-};
-
-static struct regulator_consumer_supply beagle_vsim_supply = {
- .supply = "vmmc_aux",
-};
-
-static struct regulator_consumer_supply beagle_vaux3_supply = {
- .supply = "cam_1v8",
-};
-
-static struct regulator_consumer_supply beagle_vaux4_supply = {
- .supply = "cam_2v8",
-};
-
-static struct gpio_led gpio_leds[];
-
-static int beagle_twl_gpio_setup(struct device *dev,
- unsigned gpio, unsigned ngpio)
-{
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC) {
- mmc[0].gpio_wp = -EINVAL;
- } else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
- (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) {
- omap_mux_init_gpio(23, OMAP_PIN_INPUT);
- mmc[0].gpio_wp = 23;
- } else {
- omap_mux_init_gpio(29, OMAP_PIN_INPUT);
- }
- /* gpio + 0 is "mmc0_cd" (input/IRQ) */
- mmc[0].gpio_cd = gpio + 0;
- omap2_hsmmc_init(mmc);
-
- /* link regulators to MMC adapters */
- beagle_vmmc1_supply.dev = mmc[0].dev;
- beagle_vsim_supply.dev = mmc[0].dev;
-
- /* REVISIT: need ehci-omap hooks for external VBUS
- * power switch and overcurrent detect
- */
- if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC) {
- gpio_request(gpio + 1, "EHCI_nOC");
- gpio_direction_input(gpio + 1);
- }
-
- /*
- * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
- * high / others active low)
- */
- gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
- gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM)
- gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
- else
- gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
-
- /* DVI reset GPIO is different between beagle revisions */
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC)
- beagle_dvi_device.reset_gpio = 129;
- else
- beagle_dvi_device.reset_gpio = 170;
-
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
- /* Power on camera interface */
- gpio_request(gpio + 2, "CAM_EN");
- gpio_direction_output(gpio + 2, 1);
-
- /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
- gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
- gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
- } else {
- gpio_request(gpio + 1, "EHCI_nOC");
- gpio_direction_input(gpio + 1);
-
- /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
- gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
- gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
- }
- /* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
- gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
-
- /*
- * gpio + 1 on Xm controls the TFP410's enable line (active low)
- * gpio + 2 control varies depending on the board rev as follows:
- * P7/P8 revisions(prototype): Camera EN
- * A2+ revisions (production): LDO (supplies DVI, serial, led blocks)
- */
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM || omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XMC) {
- gpio_request(gpio + 1, "nDVI_PWR_EN");
- gpio_direction_output(gpio + 1, 0);
- gpio_request(gpio + 2, "DVI_LDO_EN");
- gpio_direction_output(gpio + 2, 1);
- }
-
- return 0;
-}
-
-static struct twl4030_gpio_platform_data beagle_gpio_data = {
- .gpio_base = OMAP_MAX_GPIO_LINES,
- .irq_base = TWL4030_GPIO_IRQ_BASE,
- .irq_end = TWL4030_GPIO_IRQ_END,
- .use_leds = true,
- .pullups = BIT(1),
- .pulldowns = BIT(2) | BIT(6) | BIT(7) | BIT(8) | BIT(13)
- | BIT(15) | BIT(16) | BIT(17),
- .setup = beagle_twl_gpio_setup,
-};
-
-/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
-static struct regulator_init_data beagle_vmmc1 = {
- .constraints = {
- .min_uV = 1850000,
- .max_uV = 3150000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &beagle_vmmc1_supply,
-};
-
-/* VSIM for MMC1 pins DAT4..DAT7 (2 mA, plus card == max 50 mA) */
-static struct regulator_init_data beagle_vsim = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 3000000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &beagle_vsim_supply,
-};
-
-/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
-static struct regulator_init_data beagle_vdac = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &beagle_vdac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_init_data beagle_vpll2 = {
- .constraints = {
- .name = "VDVI",
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &beagle_vdvi_supply,
-};
-
-/* VAUX3 for CAM_1V8 */
-static struct regulator_init_data beagle_vaux3 = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &beagle_vaux3_supply,
-};
-
- /* VAUX4 for CAM_2V8 */
-static struct regulator_init_data beagle_vaux4 = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &beagle_vaux4_supply,
-};
-
-static struct twl4030_usb_data beagle_usb_data = {
- .usb_mode = T2_USB_MODE_ULPI,
-};
-
-/**
- * Macro to configure resources
- */
-#define TWL4030_RESCONFIG(res,grp,typ1,typ2,state) \
- { \
- .resource = res, \
- .devgroup = grp, \
- .type = typ1, \
- .type2 = typ2, \
- .remap_sleep = state \
- }
-
-static struct twl4030_resconfig __initdata board_twl4030_rconfig[] = {
- TWL4030_RESCONFIG(RES_VPLL1, DEV_GRP_P1, 3, 1, RES_STATE_OFF), /* ? */
- TWL4030_RESCONFIG(RES_VINTANA1, DEV_GRP_ALL, 1, 2, RES_STATE_SLEEP),
- TWL4030_RESCONFIG(RES_VINTANA2, DEV_GRP_ALL, 0, 2, RES_STATE_SLEEP),
- TWL4030_RESCONFIG(RES_VINTDIG, DEV_GRP_ALL, 1, 2, RES_STATE_SLEEP),
- TWL4030_RESCONFIG(RES_VIO, DEV_GRP_ALL, 2, 2, RES_STATE_SLEEP),
- TWL4030_RESCONFIG(RES_VDD1, DEV_GRP_P1, 4, 1, RES_STATE_OFF), /* ? */
- TWL4030_RESCONFIG(RES_VDD2, DEV_GRP_P1, 3, 1, RES_STATE_OFF), /* ? */
- TWL4030_RESCONFIG(RES_REGEN, DEV_GRP_ALL, 2, 1, RES_STATE_SLEEP),
- TWL4030_RESCONFIG(RES_NRES_PWRON, DEV_GRP_ALL, 0, 1, RES_STATE_SLEEP),
- TWL4030_RESCONFIG(RES_CLKEN, DEV_GRP_ALL, 3, 2, RES_STATE_SLEEP),
- TWL4030_RESCONFIG(RES_SYSEN, DEV_GRP_ALL, 6, 1, RES_STATE_SLEEP),
- TWL4030_RESCONFIG(RES_HFCLKOUT, DEV_GRP_P3, 0, 2, RES_STATE_SLEEP), /* ? */
- TWL4030_RESCONFIG(0, 0, 0, 0, 0),
-};
-
-/**
- * Optimized 'Active to Sleep' sequence
- */
-static struct twl4030_ins omap3beagle_sleep_seq[] __initdata = {
- { MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_SLEEP), 20},
- { MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, RES_STATE_SLEEP), 2 },
- { MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, RES_STATE_SLEEP), 2 },
-};
-
-static struct twl4030_script omap3beagle_sleep_script __initdata = {
- .script = omap3beagle_sleep_seq,
- .size = ARRAY_SIZE(omap3beagle_sleep_seq),
- .flags = TWL4030_SLEEP_SCRIPT,
-};
-
-/**
- * Optimized 'Sleep to Active (P12)' sequence
- */
-static struct twl4030_ins omap3beagle_wake_p12_seq[] __initdata = {
- { MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1, RES_STATE_ACTIVE), 2 }
-};
-
-static struct twl4030_script omap3beagle_wake_p12_script __initdata = {
- .script = omap3beagle_wake_p12_seq,
- .size = ARRAY_SIZE(omap3beagle_wake_p12_seq),
- .flags = TWL4030_WAKEUP12_SCRIPT,
-};
-
-/**
- * Optimized 'Sleep to Active' (P3) sequence
- */
-static struct twl4030_ins omap3beagle_wake_p3_seq[] __initdata = {
- { MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, RES_STATE_ACTIVE), 2 }
-};
-
-static struct twl4030_script omap3beagle_wake_p3_script __initdata = {
- .script = omap3beagle_wake_p3_seq,
- .size = ARRAY_SIZE(omap3beagle_wake_p3_seq),
- .flags = TWL4030_WAKEUP3_SCRIPT,
-};
-
-/**
- * Optimized warm reset sequence (for less power surge)
- */
-static struct twl4030_ins omap3beagle_wrst_seq[] __initdata = {
- { MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_OFF), 0x2 },
- { MSG_SINGULAR(DEV_GRP_NULL, RES_MAIN_REF, RES_STATE_WRST), 2 },
- { MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2, RES_STATE_WRST), 0x2},
- { MSG_SINGULAR(DEV_GRP_NULL, RES_VUSB_3V1, RES_STATE_WRST), 0x2 },
- { MSG_SINGULAR(DEV_GRP_NULL, RES_VPLL1, RES_STATE_WRST), 0x2 },
- { MSG_SINGULAR(DEV_GRP_NULL, RES_VDD2, RES_STATE_WRST), 0x7 },
- { MSG_SINGULAR(DEV_GRP_NULL, RES_VDD1, RES_STATE_WRST), 0x25 },
- { MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_RC, RES_TYPE_ALL, RES_TYPE2_R0, RES_STATE_WRST), 0x2 },
- { MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_ACTIVE), 0x2 },
-
-};
-
-static struct twl4030_script omap3beagle_wrst_script __initdata = {
- .script = omap3beagle_wrst_seq,
- .size = ARRAY_SIZE(omap3beagle_wrst_seq),
- .flags = TWL4030_WRST_SCRIPT,
-};
-
-static struct twl4030_script __initdata *board_twl4030_scripts[] = {
- &omap3beagle_wake_p12_script,
- &omap3beagle_wake_p3_script,
- &omap3beagle_sleep_script,
- &omap3beagle_wrst_script
-};
-
-static struct twl4030_power_data __initdata omap3beagle_script_data = {
- .scripts = board_twl4030_scripts,
- .num = ARRAY_SIZE(board_twl4030_scripts),
- .resource_config = board_twl4030_rconfig,
-};
-
-static struct twl4030_codec_audio_data beagle_audio_data = {
- .audio_mclk = 26000000,
- .digimic_delay = 1,
- .ramp_delay_value = 1,
- .offset_cncl_path = 1,
- .check_defaults = false,
- .reset_registers = false,
- .reset_registers = false,
-};
-
-static struct twl4030_codec_data beagle_codec_data = {
- .audio_mclk = 26000000,
- .audio = &beagle_audio_data,
-};
-
-static struct twl4030_platform_data beagle_twldata = {
- .irq_base = TWL4030_IRQ_BASE,
- .irq_end = TWL4030_IRQ_END,
-
- /* platform_data for children goes here */
- .usb = &beagle_usb_data,
- .gpio = &beagle_gpio_data,
- .codec = &beagle_codec_data,
- .vmmc1 = &beagle_vmmc1,
- .vsim = &beagle_vsim,
- .vdac = &beagle_vdac,
- .vpll2 = &beagle_vpll2,
- .vaux3 = &beagle_vaux3,
- .vaux4 = &beagle_vaux4,
- .power = &omap3beagle_script_data,
-};
-
-static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
- {
- I2C_BOARD_INFO("twl4030", 0x48),
- .flags = I2C_CLIENT_WAKE,
- .irq = INT_34XX_SYS_NIRQ,
- .platform_data = &beagle_twldata,
- },
-};
-
-static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
- {
- I2C_BOARD_INFO("eeprom", 0x50),
- },
-};
-
-static int __init omap3_beagle_i2c_init(void)
-{
- omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
- ARRAY_SIZE(beagle_i2c_boardinfo));
-
- /* Bus 2 is used for Camera/Sensor interface */
- if (ARRAY_SIZE(bus2_i2c_devices))
- omap_register_i2c_bus(2, 400, bus2_i2c_devices,
- ARRAY_SIZE(bus2_i2c_devices));
- else
- omap_register_i2c_bus(2, 400, NULL, 0);
-
- /* Bus 3 is attached to the DVI port where devices like the pico DLP
- * projector don't work reliably with 400kHz */
- omap_register_i2c_bus(3, 100, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom));
-
- return 0;
-}
-
-static struct gpio_led gpio_leds[] = {
- {
- .name = "beagleboard::usr0",
- .default_trigger = "heartbeat",
- .gpio = 150,
- },
- {
- .name = "beagleboard::usr1",
- .default_trigger = "mmc0",
- .gpio = 149,
- },
- {
- .name = "beagleboard::pmu_stat",
- .gpio = -EINVAL, /* gets replaced */
- .active_low = true,
- },
-};
-
-static struct gpio_led_platform_data gpio_led_info = {
- .leds = gpio_leds,
- .num_leds = ARRAY_SIZE(gpio_leds),
-};
-
-static struct platform_device leds_gpio = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &gpio_led_info,
- },
-};
-
-static struct gpio_keys_button gpio_buttons[] = {
- {
- .code = KEY_POWER,
- .gpio = 4,
- .desc = "user",
- .wakeup = 1,
- },
-};
-
-static struct gpio_keys_platform_data gpio_key_info = {
- .buttons = gpio_buttons,
- .nbuttons = ARRAY_SIZE(gpio_buttons),
-};
-
-static struct platform_device keys_gpio = {
- .name = "gpio-keys",
- .id = -1,
- .dev = {
- .platform_data = &gpio_key_info,
- },
-};
-
-static void __init omap3_beagle_init_irq(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
- mt46h32m32lf6_sdrc_params);
- omap_init_irq();
- gpmc_init();
-#ifdef CONFIG_OMAP_32K_TIMER
- if (omap3_beagle_version == OMAP3BEAGLE_BOARD_AXBX)
- omap2_gp_clockevent_set_gptimer(12);
- else
- omap2_gp_clockevent_set_gptimer(1);
-#endif
-}
-
-static struct platform_device *omap3_beagle_devices[] __initdata = {
- &leds_gpio,
- &keys_gpio,
- &beagle_dss_device,
- &usb_mass_storage_device,
-};
-
-static void __init omap3beagle_flash_init(void)
-{
- u8 cs = 0;
- u8 nandcs = GPMC_CS_NUM + 1;
-
- /* find out the chip-select on which NAND exists */
- while (cs < GPMC_CS_NUM) {
- u32 ret = 0;
- ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
- if ((ret & 0xC00) == 0x800) {
- printk(KERN_INFO "Found NAND on CS%d\n", cs);
- if (nandcs > GPMC_CS_NUM)
- nandcs = cs;
- }
- cs++;
- }
-
- if (nandcs > GPMC_CS_NUM) {
- printk(KERN_INFO "NAND: Unable to find configuration "
- "in GPMC\n ");
- return;
- }
-
- if (nandcs < GPMC_CS_NUM) {
- printk(KERN_INFO "Registering NAND on CS%d\n", nandcs);
- board_nand_init(omap3beagle_nand_partitions,
- ARRAY_SIZE(omap3beagle_nand_partitions),
- nandcs, NAND_BUSWIDTH_16);
- }
-}
-
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-
- .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
- .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
- .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-
- .phy_reset = true,
- .reset_gpio_port[0] = -EINVAL,
- .reset_gpio_port[1] = 147,
- .reset_gpio_port[2] = -EINVAL
-};
-
-#ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
- OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP |
- OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
- OMAP_PIN_OFF_WAKEUPENABLE),
- { .reg_offset = OMAP_MUX_TERMINATOR },
-};
-#endif
-
-static struct omap_musb_board_data musb_board_data = {
- .interface_type = MUSB_INTERFACE_ULPI,
- .mode = MUSB_OTG,
- .power = 100,
-};
-
-static void __init omap3_beagle_init(void)
-{
- omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
- omap3_beagle_init_rev();
- omap3_beagle_i2c_init();
- platform_add_devices(omap3_beagle_devices,
- ARRAY_SIZE(omap3_beagle_devices));
- omap_serial_init();
-
- omap_mux_init_gpio(170, OMAP_PIN_INPUT);
- gpio_request(170, "DVI_nPD");
- /* REVISIT leave DVI powered down until it's needed ... */
- gpio_direction_output(170, true);
-
- usb_musb_init(&musb_board_data);
- usb_ehci_init(&ehci_pdata);
- omap3beagle_flash_init();
-
- /* Ensure SDRC pins are mux'd for self-refresh */
- omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
- omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
-
- beagle_display_init();
-#ifdef CONFIG_USB_ANDROID
- omap3beagle_android_gadget_init();
-#endif
- omap3_beagle_pm_init();
-}
-
-MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
- /* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
- .boot_params = 0x80000100,
- .map_io = omap3_map_io,
- .reserve = omap_reserve,
- .init_irq = omap3_beagle_init_irq,
- .init_machine = omap3_beagle_init,
- .timer = &omap_timer,
-MACHINE_END
diff --git a/kernel/arch/arm/mach-omap2/board-omap4panda.c b/kernel/arch/arm/mach-omap2/board-omap4panda.c
deleted file mode 100644
index 4f8c79ddd650..000000000000
--- a/kernel/arch/arm/mach-omap2/board-omap4panda.c
+++ /dev/null
@@ -1,1053 +0,0 @@
-/*
- * Board support file for OMAP4430 based PandaBoard.
- *
- * Copyright (C) 2010 Texas Instruments
- *
- * Author: David Anders <x0132446@ti.com>
- *
- * Based on mach-omap2/board-4430sdp.c
- *
- * Author: Santosh Shilimkar <santosh.shilimkar@ti.com>
- *
- * Based on mach-omap2/board-3430sdp.c
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/input.h>
-#include <linux/io.h>
-#include <linux/leds.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/omapfb.h>
-#include <linux/reboot.h>
-#include <linux/usb/otg.h>
-#include <linux/i2c/twl.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/wl12xx.h>
-#include <linux/memblock.h>
-#include <linux/skbuff.h>
-#include <linux/ti_wilink_st.h>
-#include <linux/platform_data/ram_console.h>
-
-#include <mach/hardware.h>
-#include <mach/omap4-common.h>
-#include <mach/emif.h>
-#include <mach/lpddr2-elpida.h>
-#include <mach/dmm.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <video/omapdss.h>
-
-#include <plat/board.h>
-#include <plat/common.h>
-#include <plat/usb.h>
-#include <plat/mmc.h>
-#include <plat/remoteproc.h>
-#include <plat/vram.h>
-#include <video/omap-panel-generic-dpi.h>
-#include "timer-gp.h"
-
-#include "hsmmc.h"
-#include "control.h"
-#include "mux.h"
-#include "common-board-devices.h"
-#include "prm-regbits-44xx.h"
-#include "prm44xx.h"
-#include "pm.h"
-#include "resetreason.h"
-
-#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4
-#include <linux/input/synaptics_dsx.h>
-#define TM_SAMPLE1 (1) // 2D only
-#define TM_SAMPLE2 (2) // 2D + 0D x 2
-#define TM_SAMPLE3 (3) // 2D + 0D x 4
-#define SYNAPTICS_MODULE TM_SAMPLE1
-#endif
-
-#define PANDA_RAMCONSOLE_START (PLAT_PHYS_OFFSET + SZ_512M)
-#define PANDA_RAMCONSOLE_SIZE SZ_2M
-
-#define GPIO_HUB_POWER 1
-#define GPIO_HUB_NRESET 62
-#define GPIO_WIFI_PMENA 43
-#define GPIO_WIFI_IRQ 53
-#define HDMI_GPIO_CT_CP_HPD 60
-#define HDMI_GPIO_HPD 63 /* Hot plug pin for HDMI */
-#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
-#define TPS62361_GPIO 7 /* VCORE1 power control */
-#define PANDA_BT_GPIO 46
-
-
-#define PHYS_ADDR_SMC_SIZE (SZ_1M * 3)
-#define PHYS_ADDR_SMC_MEM (0x80000000 + SZ_1G - PHYS_ADDR_SMC_SIZE)
-#define OMAP_ION_HEAP_SECURE_INPUT_SIZE (SZ_1M * 90)
-#define PHYS_ADDR_DUCATI_SIZE (SZ_1M * 105)
-#define PHYS_ADDR_DUCATI_MEM (PHYS_ADDR_SMC_MEM - PHYS_ADDR_DUCATI_SIZE - \
- OMAP_ION_HEAP_SECURE_INPUT_SIZE)
-
-#define WILINK_UART_DEV_NAME "/dev/ttyO1"
-
-
-/* Synaptics changes for PandaBoard */
-#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4
-static int synaptics_gpio_setup(unsigned gpio, bool configure)
-{
- int retval = 0;
-
- if (configure) {
- retval = gpio_request(gpio, "rmi4_attn");
- if (retval) {
- pr_err("%s: Failed to get attn gpio %d (code: %d)",
- __func__, gpio, retval);
- return retval;
- }
- omap_mux_init_signal("gpmc_ad15.gpio_39", OMAP_PIN_INPUT_PULLUP);
-
- retval = gpio_direction_input(gpio);
- if (retval) {
- pr_err("%s: Failed to setup attn gpio %d (code: %d)",
- __func__, gpio, retval);
- gpio_free(gpio);
- }
- } else {
- pr_warn("%s: No way to deconfigure gpio %d",
- __func__, gpio);
- }
-
- return retval;
-}
-
- #if (SYNAPTICS_MODULE == TM_SAMPLE1)
-#define TM_SAMPLE1_ADDR 0x20
-#define TM_SAMPLE1_ATTN 130
-
-static unsigned char TM_SAMPLE1_f1a_button_codes[] = {};
-
-static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE1_capacitance_button_map = {
- .nbuttons = ARRAY_SIZE(TM_SAMPLE1_f1a_button_codes),
- .map = TM_SAMPLE1_f1a_button_codes,
-};
-
-static struct synaptics_rmi4_platform_data rmi4_platformdata = {
- .irq_flags = IRQF_TRIGGER_FALLING,
- .irq_gpio = TM_SAMPLE1_ATTN,
- .gpio_config = synaptics_gpio_setup,
- .capacitance_button_map = &TM_SAMPLE1_capacitance_button_map,
-};
-
-static struct i2c_board_info bus4_i2c_devices[] = {
- {
- I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE1_ADDR),
- .platform_data = &rmi4_platformdata,
- },
-};
-
-#elif (SYNAPTICS_MODULE == TM_SAMPLE2)
-#define TM_SAMPLE2_ADDR 0x20
-#define TM_SAMPLE2_ATTN 130
-
-static unsigned char TM_SAMPLE2_f1a_button_codes[] = {KEY_MENU, KEY_BACK};
-
-static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE2_capacitance_button_map = {
- .nbuttons = ARRAY_SIZE(TM_SAMPLE2_f1a_button_codes),
- .map = TM_SAMPLE2_f1a_button_codes,
-};
-
-static struct synaptics_rmi4_platform_data rmi4_platformdata = {
- .irq_flags = IRQF_TRIGGER_FALLING,
- .irq_gpio = TM_SAMPLE2_ATTN,
- .gpio_config = synaptics_gpio_setup,
- .capacitance_button_map = &TM_SAMPLE2_capacitance_button_map,
-};
-
-static struct i2c_board_info bus4_i2c_devices[] = {
- {
- I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE2_ADDR),
- .platform_data = &rmi4_platformdata,
- },
-};
-};
-
-#elif (SYNAPTICS_MODULE == TM_SAMPLE3)
-#define TM_SAMPLE3_ADDR 0x20
-#define TM_SAMPLE3_ATTN 130
-
-static unsigned char TM_SAMPLE3_f1a_button_codes[] = {KEY_MENU, KEY_HOME,KEY_BACK,KEY_SEARCH};
-
-static struct synaptics_rmi4_capacitance_button_map TM_SAMPLE3_capacitance_button_map = {
- .nbuttons = ARRAY_SIZE(TM_SAMPLE3_f1a_button_codes),
- .map = TM_SAMPLE3_f1a_button_codes,
-};
-
-static struct synaptics_rmi4_platform_data rmi4_platformdata = {
- .irq_flags = IRQF_TRIGGER_FALLING,
- .irq_gpio = TM_SAMPLE3_ATTN,
- .gpio_config = synaptics_gpio_setup,
- .capacitance_button_map = &TM_SAMPLE3_capacitance_button_map,
-};
-
-static struct i2c_board_info bus4_i2c_devices[] = {
- {
- I2C_BOARD_INFO("synaptics_rmi4_i2c", TM_SAMPLE3_ADDR),
- .platform_data = &rmi4_platformdata,
- },
-};
-#endif
-
-void __init i2c_device_setup(void)
-{
- pr_info(">>>>I2C device setup");
- if (ARRAY_SIZE(bus4_i2c_devices)) {
- i2c_register_board_info(4, bus4_i2c_devices,
- ARRAY_SIZE(bus4_i2c_devices));
- }
-}
-#endif
-/* End of Synaptics changes for PandaBoard */
-
-static struct gpio_led gpio_leds[] = {
- {
- .name = "pandaboard::status1",
- .default_trigger = "heartbeat",
- .gpio = 7,
- },
- {
- .name = "pandaboard::status2",
- .default_trigger = "mmc0",
- .gpio = 8,
- },
-};
-
-static struct gpio_led_platform_data gpio_led_info = {
- .leds = gpio_leds,
- .num_leds = ARRAY_SIZE(gpio_leds),
-};
-
-static struct platform_device leds_gpio = {
- .name = "leds-gpio",
- .id = -1,
- .dev = {
- .platform_data = &gpio_led_info,
- },
-};
-
-/* GPIO_KEY for the panda */
-static struct gpio_keys_button panda_gpio_keys_buttons[] = {
- [0] = {
- .code = KEY_HOME,
- .gpio = 113,
- .desc = "user_button",
- .active_low = 1,
- .debounce_interval = 5,
- },
-};
-
-static struct gpio_keys_platform_data panda_gpio_keys = {
- .buttons = panda_gpio_keys_buttons,
- .nbuttons = ARRAY_SIZE(panda_gpio_keys_buttons),
- .rep = 0,
-};
-
-static struct platform_device panda_gpio_keys_device = {
- .name = "gpio-keys",
- .id = -1,
- .dev = {
- .platform_data = &panda_gpio_keys,
- },
-};
-
-/* TODO: handle suspend/resume here.
- * Upon every suspend, make sure the wilink chip is
- * capable enough to wake-up the OMAP host.
- */
-static int plat_wlink_kim_suspend(struct platform_device *pdev, pm_message_t
- state)
-{
- return 0;
-}
-
-static int plat_wlink_kim_resume(struct platform_device *pdev)
-{
- return 0;
-}
-
-/* wl128x BT, FM, GPS connectivity chip */
-static struct ti_st_plat_data wilink_pdata = {
- .nshutdown_gpio = PANDA_BT_GPIO,
- .dev_name = WILINK_UART_DEV_NAME,
- .flow_cntrl = 1,
- .baud_rate = 3686400,
- .suspend = plat_wlink_kim_suspend,
- .resume = plat_wlink_kim_resume,
-};
-
-static struct platform_device btwilink_device = {
- .name = "btwilink",
- .id = -1,
-};
-
-/* wl127x BT, FM, GPS connectivity chip */
-static struct platform_device wl1271_device = {
- .name = "kim",
- .id = -1,
- .dev.platform_data = &wilink_pdata,
-};
-
-
-static struct platform_device *panda_devices[] __initdata = {
- &leds_gpio,
- &wl1271_device,
- &btwilink_device,
- &panda_gpio_keys_device,
-};
-
-static void __init omap4_panda_init_early(void)
-{
- omap2_init_common_infrastructure();
- omap2_init_common_devices(NULL, NULL);
-}
-
-static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
- .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
- .port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
- .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
- .phy_reset = false,
- .reset_gpio_port[0] = -EINVAL,
- .reset_gpio_port[1] = -EINVAL,
- .reset_gpio_port[2] = -EINVAL
-};
-
-static struct gpio panda_ehci_gpios[] __initdata = {
- { GPIO_HUB_POWER, GPIOF_OUT_INIT_LOW, "hub_power" },
- { GPIO_HUB_NRESET, GPIOF_OUT_INIT_LOW, "hub_nreset" },
-};
-
-static void __init omap4_ehci_init(void)
-{
- int ret;
- struct clk *phy_ref_clk;
-
- /* FREF_CLK3 provides the 19.2 MHz reference clock to the PHY */
- phy_ref_clk = clk_get(NULL, "auxclk3_ck");
- if (IS_ERR(phy_ref_clk)) {
- pr_err("Cannot request auxclk3\n");
- return;
- }
- clk_set_rate(phy_ref_clk, 19200000);
- clk_enable(phy_ref_clk);
-
- /* disable the power to the usb hub prior to init and reset phy+hub */
- ret = gpio_request_array(panda_ehci_gpios,
- ARRAY_SIZE(panda_ehci_gpios));
- if (ret) {
- pr_err("Unable to initialize EHCI power/reset\n");
- return;
- }
-
- gpio_export(GPIO_HUB_POWER, 0);
- gpio_export(GPIO_HUB_NRESET, 0);
- gpio_set_value(GPIO_HUB_NRESET, 1);
-
- usbhs_init(&usbhs_bdata);
-
- /* enable power to hub */
- gpio_set_value(GPIO_HUB_POWER, 1);
-}
-
-static struct omap_musb_board_data musb_board_data = {
- .interface_type = MUSB_INTERFACE_UTMI,
-#ifdef CONFIG_USB_GADGET_MUSB_HDRC
- .mode = MUSB_PERIPHERAL,
-#else
- .mode = MUSB_OTG,
-#endif
- .power = 100,
-};
-
-static struct twl4030_usb_data omap4_usbphy_data = {
- .phy_init = omap4430_phy_init,
- .phy_exit = omap4430_phy_exit,
- .phy_power = omap4430_phy_power,
- .phy_set_clock = omap4430_phy_set_clk,
- .phy_suspend = omap4430_phy_suspend,
-};
-
-static struct omap2_hsmmc_info mmc[] = {
- {
- .mmc = 1,
- .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
- .gpio_wp = -EINVAL,
- .gpio_cd = -EINVAL,
- },
- {
- .name = "wl1271",
- .mmc = 5,
- .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
- .gpio_wp = -EINVAL,
- .gpio_cd = -EINVAL,
- .ocr_mask = MMC_VDD_165_195,
- .nonremovable = true,
- },
- {} /* Terminator */
-};
-
-static struct regulator_consumer_supply omap4_panda_vmmc_supply[] = {
- {
- .supply = "vmmc",
- .dev_name = "omap_hsmmc.0",
- },
-};
-
-static struct regulator_consumer_supply omap4_panda_vmmc5_supply = {
- .supply = "vmmc",
- .dev_name = "omap_hsmmc.4",
-};
-
-static struct regulator_init_data panda_vmmc5 = {
- .constraints = {
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = &omap4_panda_vmmc5_supply,
-};
-
-static struct fixed_voltage_config panda_vwlan = {
- .supply_name = "vwl1271",
- .microvolts = 1800000, /* 1.8V */
- .gpio = GPIO_WIFI_PMENA,
- .startup_delay = 70000, /* 70msec */
- .enable_high = 1,
- .enabled_at_boot = 0,
- .init_data = &panda_vmmc5,
-};
-
-static struct platform_device omap_vwlan_device = {
- .name = "reg-fixed-voltage",
- .id = 1,
- .dev = {
- .platform_data = &panda_vwlan,
- },
-};
-
-struct wl12xx_platform_data omap_panda_wlan_data __initdata = {
- .irq = OMAP_GPIO_IRQ(GPIO_WIFI_IRQ),
- /* PANDA ref clock is 38.4 MHz */
- .board_ref_clock = 2,
-};
-
-static int omap4_twl6030_hsmmc_late_init(struct device *dev)
-{
- int ret = 0;
- struct platform_device *pdev = container_of(dev,
- struct platform_device, dev);
- struct omap_mmc_platform_data *pdata = dev->platform_data;
-
- if (!pdata) {
- dev_err(dev, "%s: NULL platform data\n", __func__);
- return -EINVAL;
- }
- /* Setting MMC1 Card detect Irq */
- if (pdev->id == 0) {
- ret = twl6030_mmc_card_detect_config();
- if (ret)
- dev_err(dev, "%s: Error card detect config(%d)\n",
- __func__, ret);
- else
- pdata->slots[0].card_detect = twl6030_mmc_card_detect;
- }
- return ret;
-}
-
-static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
-{
- struct omap_mmc_platform_data *pdata;
-
- /* dev can be null if CONFIG_MMC_OMAP_HS is not set */
- if (!dev) {
- pr_err("Failed omap4_twl6030_hsmmc_set_late_init\n");
- return;
- }
- pdata = dev->platform_data;
-
- pdata->init = omap4_twl6030_hsmmc_late_init;
-}
-
-static int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
-{
- struct omap2_hsmmc_info *c;
-
- omap2_hsmmc_init(controllers);
- for (c = controllers; c->mmc; c++)
- omap4_twl6030_hsmmc_set_late_init(c->dev);
-
- return 0;
-}
-
-static struct regulator_init_data omap4_panda_vaux2 = {
- .constraints = {
- .min_uV = 1200000,
- .max_uV = 2800000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_init_data omap4_panda_vaux3 = {
- .constraints = {
- .min_uV = 1000000,
- .max_uV = 3000000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-/* VMMC1 for MMC1 card */
-static struct regulator_init_data omap4_panda_vmmc = {
- .constraints = {
- .min_uV = 1200000,
- .max_uV = 3000000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = 1,
- .consumer_supplies = omap4_panda_vmmc_supply,
-};
-
-static struct regulator_init_data omap4_panda_vpp = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 2500000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE
- | REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_init_data omap4_panda_vana = {
- .constraints = {
- .min_uV = 2100000,
- .max_uV = 2100000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_init_data omap4_panda_vcxio = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_consumer_supply panda_vdac_supply[] = {
- {
- .supply = "hdmi_vref",
- },
-};
-
-static struct regulator_init_data omap4_panda_vdac = {
- .constraints = {
- .min_uV = 1800000,
- .max_uV = 1800000,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
- .num_consumer_supplies = ARRAY_SIZE(panda_vdac_supply),
- .consumer_supplies = panda_vdac_supply,
-};
-
-static struct regulator_init_data omap4_panda_vusb = {
- .constraints = {
- .min_uV = 3300000,
- .max_uV = 3300000,
- .apply_uV = true,
- .valid_modes_mask = REGULATOR_MODE_NORMAL
- | REGULATOR_MODE_STANDBY,
- .valid_ops_mask = REGULATOR_CHANGE_MODE
- | REGULATOR_CHANGE_STATUS,
- },
-};
-
-static struct regulator_init_data omap4_panda_clk32kg = {
- .constraints = {
- .valid_ops_mask = REGULATOR_CHANGE_STATUS,
- .always_on = true,
- },
-};
-
-static void omap4_audio_conf(void)
-{
- /* twl6040 naudint */
- omap_mux_init_signal("sys_nirq2.sys_nirq2", \
- OMAP_PIN_INPUT_PULLUP);
-}
-
-static struct twl4030_codec_audio_data twl6040_audio = {
- /* single-step ramp for headset and handsfree */
- .hs_left_step = 0x0f,
- .hs_right_step = 0x0f,
- .hf_left_step = 0x1d,
- .hf_right_step = 0x1d,
- .hs_switch_dev = 0x1,
- .hs_forced_hs_state = 0x1
-};
-
-static struct twl4030_codec_data twl6040_codec = {
- .audio = &twl6040_audio,
- .audpwron_gpio = 127,
- .naudint_irq = OMAP44XX_IRQ_SYS_2N,
- .irq_base = TWL6040_CODEC_IRQ_BASE,
-};
-
-static struct twl4030_platform_data omap4_panda_twldata = {
- .irq_base = TWL6030_IRQ_BASE,
- .irq_end = TWL6030_IRQ_END,
-
- /* Regulators */
- .vmmc = &omap4_panda_vmmc,
- .vpp = &omap4_panda_vpp,
- .vana = &omap4_panda_vana,
- .vcxio = &omap4_panda_vcxio,
- .vdac = &omap4_panda_vdac,
- .vusb = &omap4_panda_vusb,
- .vaux2 = &omap4_panda_vaux2,
- .vaux3 = &omap4_panda_vaux3,
- .clk32kg = &omap4_panda_clk32kg,
- .usb = &omap4_usbphy_data,
-
- /* children */
- .codec = &twl6040_codec,
-};
-
-/*
- * Display monitor features are burnt in their EEPROM as EDID data. The EEPROM
- * is connected as I2C slave device, and can be accessed at address 0x50
- */
-static struct i2c_board_info __initdata panda_i2c_eeprom[] = {
- {
- I2C_BOARD_INFO("eeprom", 0x50),
- },
-};
-
-static int __init omap4_panda_i2c_init(void)
-{
- omap4_pmic_init("twl6030", &omap4_panda_twldata);
- omap_register_i2c_bus(2, 400, NULL, 0);
- /*
- * Bus 3 is attached to the DVI port where devices like the pico DLP
- * projector don't work reliably with 400kHz
- */
- omap_register_i2c_bus(3, 100, panda_i2c_eeprom,
- ARRAY_SIZE(panda_i2c_eeprom));
- if(ARRAY_SIZE(bus4_i2c_devices))
- omap_register_i2c_bus(4, 400, bus4_i2c_devices, ARRAY_SIZE(bus4_i2c_devices));
- else
- omap_register_i2c_bus(4, 400, NULL, 0);
- return 0;
-}
-
-#ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
- /* WLAN IRQ - GPIO 53 */
- OMAP4_MUX(GPMC_NCS3, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
- /* WLAN POWER ENABLE - GPIO 43 */
- OMAP4_MUX(GPMC_A19, OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT),
- /* WLAN SDIO: MMC5 CMD */
- OMAP4_MUX(SDMMC5_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
- /* WLAN SDIO: MMC5 CLK */
- OMAP4_MUX(SDMMC5_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
- /* WLAN SDIO: MMC5 DAT[0-3] */
- OMAP4_MUX(SDMMC5_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
- OMAP4_MUX(SDMMC5_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
- OMAP4_MUX(SDMMC5_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
- OMAP4_MUX(SDMMC5_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
- /* gpio 0 - TFP410 PD */
- OMAP4_MUX(KPD_COL1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE3),
- /* dispc2_data23 */
- OMAP4_MUX(USBB2_ULPITLL_STP, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data22 */
- OMAP4_MUX(USBB2_ULPITLL_DIR, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data21 */
- OMAP4_MUX(USBB2_ULPITLL_NXT, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data20 */
- OMAP4_MUX(USBB2_ULPITLL_DAT0, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data19 */
- OMAP4_MUX(USBB2_ULPITLL_DAT1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data18 */
- OMAP4_MUX(USBB2_ULPITLL_DAT2, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data15 */
- OMAP4_MUX(USBB2_ULPITLL_DAT3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data14 */
- OMAP4_MUX(USBB2_ULPITLL_DAT4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data13 */
- OMAP4_MUX(USBB2_ULPITLL_DAT5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data12 */
- OMAP4_MUX(USBB2_ULPITLL_DAT6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data11 */
- OMAP4_MUX(USBB2_ULPITLL_DAT7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data10 */
- OMAP4_MUX(DPM_EMU3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data9 */
- OMAP4_MUX(DPM_EMU4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data16 */
- OMAP4_MUX(DPM_EMU5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data17 */
- OMAP4_MUX(DPM_EMU6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_hsync */
- OMAP4_MUX(DPM_EMU7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_pclk */
- OMAP4_MUX(DPM_EMU8, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_vsync */
- OMAP4_MUX(DPM_EMU9, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_de */
- OMAP4_MUX(DPM_EMU10, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data8 */
- OMAP4_MUX(DPM_EMU11, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data7 */
- OMAP4_MUX(DPM_EMU12, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data6 */
- OMAP4_MUX(DPM_EMU13, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data5 */
- OMAP4_MUX(DPM_EMU14, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data4 */
- OMAP4_MUX(DPM_EMU15, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data3 */
- OMAP4_MUX(DPM_EMU16, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data2 */
- OMAP4_MUX(DPM_EMU17, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data1 */
- OMAP4_MUX(DPM_EMU18, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- /* dispc2_data0 */
- OMAP4_MUX(DPM_EMU19, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
- { .reg_offset = OMAP_MUX_TERMINATOR },
-};
-
-static inline void __init board_serial_init(void)
-{
- omap_serial_init();
-}
-#else
-#define board_mux NULL
-
-static inline void __init board_serial_init(void)
-{
- omap_serial_init();
-}
-#endif
-
-/* Display DVI */
-#define PANDA_DVI_TFP410_POWER_DOWN_GPIO 0
-
-static int omap4_panda_enable_dvi(struct omap_dss_device *dssdev)
-{
- gpio_set_value(dssdev->reset_gpio, 1);
- return 0;
-}
-
-static void omap4_panda_disable_dvi(struct omap_dss_device *dssdev)
-{
- gpio_set_value(dssdev->reset_gpio, 0);
-}
-
-/* Using generic display panel */
-static struct panel_generic_dpi_data omap4_dvi_panel = {
- .name = "generic_720p",
- .platform_enable = omap4_panda_enable_dvi,
- .platform_disable = omap4_panda_disable_dvi,
-};
-
-struct omap_dss_device omap4_panda_dvi_device = {
- .type = OMAP_DISPLAY_TYPE_DPI,
- .name = "dvi",
- .driver_name = "generic_dpi_panel",
- .data = &omap4_dvi_panel,
- .phy.dpi.data_lines = 24,
- .reset_gpio = PANDA_DVI_TFP410_POWER_DOWN_GPIO,
- .channel = OMAP_DSS_CHANNEL_LCD2,
-};
-
-int __init omap4_panda_dvi_init(void)
-{
- int r;
-
- /* Requesting TFP410 DVI GPIO and disabling it, at bootup */
- r = gpio_request_one(omap4_panda_dvi_device.reset_gpio,
- GPIOF_OUT_INIT_LOW, "DVI PD");
- if (r)
- pr_err("Failed to get DVI powerdown GPIO\n");
-
- return r;
-}
-
-static struct gpio panda_hdmi_gpios[] = {
- { HDMI_GPIO_CT_CP_HPD, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_hpd" },
- { HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH, "hdmi_gpio_ls_oe" },
-};
-
-static void omap4_panda_hdmi_mux_init(void)
-{
- u32 r;
- int status;
- /* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
- omap_mux_init_signal("hdmi_hpd.hdmi_hpd",
- OMAP_PIN_INPUT_PULLUP);
- omap_mux_init_signal("gpmc_wait2.gpio_100",
- OMAP_PIN_INPUT_PULLDOWN);
- omap_mux_init_signal("hdmi_cec.hdmi_cec",
- OMAP_PIN_INPUT_PULLUP);
- /* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
- omap_mux_init_signal("hdmi_ddc_scl.hdmi_ddc_scl",
- OMAP_PIN_INPUT_PULLUP);
- omap_mux_init_signal("hdmi_ddc_sda.hdmi_ddc_sda",
- OMAP_PIN_INPUT_PULLUP);
-
- /* strong pullup on DDC lines using unpublished register */
- r = ((1 << 24) | (1 << 28)) ;
- omap4_ctrl_pad_writel(r, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1);
-
- gpio_request(HDMI_GPIO_HPD, NULL);
- omap_mux_init_gpio(HDMI_GPIO_HPD, OMAP_PIN_INPUT | OMAP_PULL_ENA);
- gpio_direction_input(HDMI_GPIO_HPD);
-
- status = gpio_request_array(panda_hdmi_gpios,
- ARRAY_SIZE(panda_hdmi_gpios));
- if (status)
- pr_err("%s: Cannot request HDMI GPIOs %x \n", __func__, status);
-}
-
-static struct omap_dss_device omap4_panda_hdmi_device = {
- .name = "hdmi",
- .driver_name = "hdmi_panel",
- .type = OMAP_DISPLAY_TYPE_HDMI,
- .clocks = {
- .dispc = {
- .dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK,
- },
- .hdmi = {
- .regn = 15,
- .regm2 = 1,
- },
- },
- .hpd_gpio = HDMI_GPIO_HPD,
- .channel = OMAP_DSS_CHANNEL_DIGIT,
-};
-
-static struct omap_dss_device *omap4_panda_dss_devices[] = {
- &omap4_panda_dvi_device,
- &omap4_panda_hdmi_device,
-};
-
-static struct omap_dss_board_info omap4_panda_dss_data = {
- .num_devices = ARRAY_SIZE(omap4_panda_dss_devices),
- .devices = omap4_panda_dss_devices,
- .default_device = &omap4_panda_dvi_device,
-};
-
-/*
- * LPDDR2 Configeration Data:
- * The memory organisation is as below :
- * EMIF1 - CS0 - 2 Gb
- * CS1 - 2 Gb
- * EMIF2 - CS0 - 2 Gb
- * CS1 - 2 Gb
- * --------------------
- * TOTAL - 8 Gb
- *
- * Same devices installed on EMIF1 and EMIF2
- */
-static __initdata struct emif_device_details emif_devices = {
- .cs0_device = &lpddr2_elpida_2G_S4_dev,
- .cs1_device = &lpddr2_elpida_2G_S4_dev
-};
-
-void omap4_panda_display_init(void)
-{
- int r;
-
- r = omap4_panda_dvi_init();
- if (r)
- pr_err("error initializing panda DVI\n");
-
- omap4_panda_hdmi_mux_init();
- omap_display_init(&omap4_panda_dss_data);
-}
-
-static int panda_notifier_call(struct notifier_block *this,
- unsigned long code, void *cmd)
-{
- void __iomem *sar_base;
- u32 v = OMAP4430_RST_GLOBAL_COLD_SW_MASK;
-
- sar_base = omap4_get_sar_ram_base();
-
- if (!sar_base)
- return notifier_from_errno(-ENOMEM);
-
- if ((code == SYS_RESTART) && (cmd != NULL)) {
- /* cmd != null; case: warm boot */
- if (!strcmp(cmd, "bootloader")) {
- /* Save reboot mode in scratch memory */
- strcpy(sar_base + 0xA0C, cmd);
- v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
- } else if (!strcmp(cmd, "recovery")) {
- /* Save reboot mode in scratch memory */
- strcpy(sar_base + 0xA0C, cmd);
- v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK;
- } else {
- v |= OMAP4430_RST_GLOBAL_COLD_SW_MASK;
- }
- }
-
- omap4_prm_write_inst_reg(0xfff, OMAP4430_PRM_DEVICE_INST,
- OMAP4_RM_RSTST);
- omap4_prm_write_inst_reg(v, OMAP4430_PRM_DEVICE_INST, OMAP4_RM_RSTCTRL);
- v = omap4_prm_read_inst_reg(WKUP_MOD, OMAP4_RM_RSTCTRL);
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block panda_reboot_notifier = {
- .notifier_call = panda_notifier_call,
-};
-
-#define PANDA_FB_RAM_SIZE SZ_16M /* 1920?1080*4 * 2 */
-static struct omapfb_platform_data panda_fb_pdata = {
- .mem_desc = {
- .region_cnt = 1,
- .region = {
- [0] = {
- .size = PANDA_FB_RAM_SIZE,
- },
- },
- },
-};
-
-static struct resource ramconsole_resources[] = {
- {
- .flags = IORESOURCE_MEM,
- .start = PANDA_RAMCONSOLE_START,
- .end = PANDA_RAMCONSOLE_START + PANDA_RAMCONSOLE_SIZE - 1,
- },
-};
-
-static struct ram_console_platform_data ramconsole_pdata;
-
-static struct platform_device ramconsole_device = {
- .name = "ram_console",
- .id = -1,
- .num_resources = ARRAY_SIZE(ramconsole_resources),
- .resource = ramconsole_resources,
- .dev = {
- .platform_data = &ramconsole_pdata,
- },
-};
-
-extern void __init omap4_panda_android_init(void);
-
-static void __init omap4_panda_init(void)
-{
- int package = OMAP_PACKAGE_CBS;
- int status;
-
- omap_emif_setup_device_details(&emif_devices, &emif_devices);
-
- if (omap_rev() == OMAP4430_REV_ES1_0)
- package = OMAP_PACKAGE_CBL;
- omap4_mux_init(board_mux, NULL, package);
-
- if (wl12xx_set_platform_data(&omap_panda_wlan_data))
- pr_err("error setting wl12xx data\n");
-
- register_reboot_notifier(&panda_reboot_notifier);
- ramconsole_pdata.bootinfo = omap4_get_resetreason();
- platform_device_register(&ramconsole_device);
- omap4_panda_i2c_init();
- omap4_audio_conf();
-
- if (cpu_is_omap4430())
- panda_gpio_keys_buttons[0].gpio = 121;
-
- platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
- platform_device_register(&omap_vwlan_device);
- board_serial_init();
- omap4_twl6030_hsmmc_init(mmc);
- omap4_ehci_init();
- usb_musb_init(&musb_board_data);
-
- omap_dmm_init();
- omap_vram_set_sdram_vram(PANDA_FB_RAM_SIZE, 0);
- omapfb_set_platform_data(&panda_fb_pdata);
- omap4_panda_display_init();
-
- if (cpu_is_omap446x()) {
- /* Vsel0 = gpio, vsel1 = gnd */
- status = omap_tps6236x_board_setup(true, TPS62361_GPIO, -1,
- OMAP_PIN_OFF_OUTPUT_HIGH, -1);
- if (status)
- pr_err("TPS62361 initialization failed: %d\n", status);
- }
- omap_enable_smartreflex_on_init();
-}
-
-static void __init omap4_panda_map_io(void)
-{
- omap2_set_globals_443x();
- omap44xx_map_common_io();
-}
-
-static void __init omap4_panda_reserve(void)
-{
- /* do the static reservations first */
- memblock_remove(PANDA_RAMCONSOLE_START, PANDA_RAMCONSOLE_SIZE);
- memblock_remove(PHYS_ADDR_SMC_MEM, PHYS_ADDR_SMC_SIZE);
- memblock_remove(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE);
- /* ipu needs to recognize secure input buffer area as well */
- omap_ipu_set_static_mempool(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE +
- OMAP_ION_HEAP_SECURE_INPUT_SIZE);
-
- omap_reserve();
-}
-
-MACHINE_START(OMAP4_PANDA, "OMAP4 Panda board")
- /* Maintainer: David Anders - Texas Instruments Inc */
- .boot_params = 0x80000100,
- .reserve = omap4_panda_reserve,
- .map_io = omap4_panda_map_io,
- .init_early = omap4_panda_init_early,
- .init_irq = gic_init_irq,
- .init_machine = omap4_panda_init,
- .timer = &omap_timer,
-MACHINE_END
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index d1a7646f79c5..cb85d228b1ac 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -358,7 +358,7 @@ static int bpf_fill_super(struct super_block *sb, void *data, int silent)
static struct dentry *bpf_mount(struct file_system_type *type, int flags,
const char *dev_name, void *data)
{
- return mount_ns(type, flags, current->nsproxy->mnt_ns, bpf_fill_super);
+ return mount_nodev(type, flags, data, bpf_fill_super);
}
static struct file_system_type bpf_fs_type = {
@@ -366,7 +366,6 @@ static struct file_system_type bpf_fs_type = {
.name = "bpf",
.mount = bpf_mount,
.kill_sb = kill_litter_super,
- .fs_flags = FS_USERNS_MOUNT,
};
MODULE_ALIAS_FS("bpf");
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index e2e784ad9e0f..ae83d9602aa0 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -781,6 +781,8 @@ static void put_css_set_locked(struct css_set *cset)
static void put_css_set(struct css_set *cset)
{
+ unsigned long flags;
+
/*
* Ensure that the refcount doesn't hit zero while any readers
* can see it. Similar to atomic_dec_and_lock(), but for an
@@ -789,9 +791,9 @@ static void put_css_set(struct css_set *cset)
if (atomic_add_unless(&cset->refcount, -1, 1))
return;
- spin_lock_bh(&css_set_lock);
+ spin_lock_irqsave(&css_set_lock, flags);
put_css_set_locked(cset);
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irqrestore(&css_set_lock, flags);
}
/*
@@ -1014,11 +1016,11 @@ static struct css_set *find_css_set(struct css_set *old_cset,
/* First see if we already have a cgroup group that matches
* the desired set */
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
cset = find_existing_css_set(old_cset, cgrp, template);
if (cset)
get_css_set(cset);
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
if (cset)
return cset;
@@ -1046,7 +1048,7 @@ static struct css_set *find_css_set(struct css_set *old_cset,
* find_existing_css_set() */
memcpy(cset->subsys, template, sizeof(cset->subsys));
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
/* Add reference counts and links from the new css_set. */
list_for_each_entry(link, &old_cset->cgrp_links, cgrp_link) {
struct cgroup *c = link->cgrp;
@@ -1072,7 +1074,7 @@ static struct css_set *find_css_set(struct css_set *old_cset,
css_get(css);
}
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
return cset;
}
@@ -1136,7 +1138,7 @@ static void cgroup_destroy_root(struct cgroup_root *root)
* Release all the links from cset_links to this hierarchy's
* root cgroup
*/
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
list_for_each_entry_safe(link, tmp_link, &cgrp->cset_links, cset_link) {
list_del(&link->cset_link);
@@ -1144,7 +1146,7 @@ static void cgroup_destroy_root(struct cgroup_root *root)
kfree(link);
}
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
if (!list_empty(&root->root_list)) {
list_del(&root->root_list);
@@ -1548,11 +1550,11 @@ static int rebind_subsystems(struct cgroup_root *dst_root,
ss->root = dst_root;
css->cgroup = dcgrp;
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
hash_for_each(css_set_table, i, cset, hlist)
list_move_tail(&cset->e_cset_node[ss->id],
&dcgrp->e_csets[ss->id]);
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
src_root->subsys_mask &= ~(1 << ssid);
scgrp->subtree_control &= ~(1 << ssid);
@@ -1829,7 +1831,7 @@ static void cgroup_enable_task_cg_lists(void)
{
struct task_struct *p, *g;
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
if (use_task_css_set_links)
goto out_unlock;
@@ -1854,8 +1856,12 @@ static void cgroup_enable_task_cg_lists(void)
* entry won't be deleted though the process has exited.
* Do it while holding siglock so that we don't end up
* racing against cgroup_exit().
+ *
+ * Interrupts were already disabled while acquiring
+ * the css_set_lock, so we do not need to disable it
+ * again when acquiring the sighand->siglock here.
*/
- spin_lock_irq(&p->sighand->siglock);
+ spin_lock(&p->sighand->siglock);
if (!(p->flags & PF_EXITING)) {
struct css_set *cset = task_css_set(p);
@@ -1864,11 +1870,11 @@ static void cgroup_enable_task_cg_lists(void)
list_add_tail(&p->cg_list, &cset->tasks);
get_css_set(cset);
}
- spin_unlock_irq(&p->sighand->siglock);
+ spin_unlock(&p->sighand->siglock);
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
out_unlock:
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
}
static void init_cgroup_housekeeping(struct cgroup *cgrp)
@@ -1973,13 +1979,13 @@ static int cgroup_setup_root(struct cgroup_root *root, unsigned long ss_mask)
* Link the root cgroup in this hierarchy into all the css_set
* objects.
*/
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
hash_for_each(css_set_table, i, cset, hlist) {
link_css_set(&tmp_links, cset, root_cgrp);
if (css_set_populated(cset))
cgroup_update_populated(root_cgrp, true);
}
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
BUG_ON(!list_empty(&root_cgrp->self.children));
BUG_ON(atomic_read(&root->nr_cgrps) != 1);
@@ -2212,7 +2218,7 @@ char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen)
char *path = NULL;
mutex_lock(&cgroup_mutex);
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
root = idr_get_next(&cgroup_hierarchy_idr, &hierarchy_id);
@@ -2225,7 +2231,7 @@ char *task_cgroup_path(struct task_struct *task, char *buf, size_t buflen)
path = buf;
}
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
mutex_unlock(&cgroup_mutex);
return path;
}
@@ -2400,7 +2406,7 @@ static int cgroup_taskset_migrate(struct cgroup_taskset *tset,
* the new cgroup. There are no failure cases after here, so this
* is the commit point.
*/
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
list_for_each_entry(cset, &tset->src_csets, mg_node) {
list_for_each_entry_safe(task, tmp_task, &cset->mg_tasks, cg_list) {
struct css_set *from_cset = task_css_set(task);
@@ -2411,7 +2417,7 @@ static int cgroup_taskset_migrate(struct cgroup_taskset *tset,
put_css_set_locked(from_cset);
}
}
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
/*
* Migration is committed, all target tasks are now on dst_csets.
@@ -2440,13 +2446,13 @@ out_cancel_attach:
}
}
out_release_tset:
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
list_splice_init(&tset->dst_csets, &tset->src_csets);
list_for_each_entry_safe(cset, tmp_cset, &tset->src_csets, mg_node) {
list_splice_tail_init(&cset->mg_tasks, &cset->tasks);
list_del_init(&cset->mg_node);
}
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
return ret;
}
@@ -2463,14 +2469,14 @@ static void cgroup_migrate_finish(struct list_head *preloaded_csets)
lockdep_assert_held(&cgroup_mutex);
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
list_for_each_entry_safe(cset, tmp_cset, preloaded_csets, mg_preload_node) {
cset->mg_src_cgrp = NULL;
cset->mg_dst_cset = NULL;
list_del_init(&cset->mg_preload_node);
put_css_set_locked(cset);
}
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
}
/**
@@ -2620,7 +2626,7 @@ static int cgroup_migrate(struct task_struct *leader, bool threadgroup,
* already PF_EXITING could be freed from underneath us unless we
* take an rcu_read_lock.
*/
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
rcu_read_lock();
task = leader;
do {
@@ -2629,7 +2635,7 @@ static int cgroup_migrate(struct task_struct *leader, bool threadgroup,
break;
} while_each_thread(leader, task);
rcu_read_unlock();
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
return cgroup_taskset_migrate(&tset, cgrp);
}
@@ -2650,7 +2656,7 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp,
int ret;
/* look up all src csets */
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
rcu_read_lock();
task = leader;
do {
@@ -2660,7 +2666,7 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp,
break;
} while_each_thread(leader, task);
rcu_read_unlock();
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
/* prepare dst csets and commit */
ret = cgroup_migrate_prepare_dst(dst_cgrp, &preloaded_csets);
@@ -2748,9 +2754,9 @@ static int cgroup_procs_write_permission(struct task_struct *task,
struct cgroup *cgrp;
struct inode *inode;
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
cgrp = task_cgroup_from_root(task, &cgrp_dfl_root);
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
while (!cgroup_is_descendant(dst_cgrp, cgrp))
cgrp = cgroup_parent(cgrp);
@@ -2851,9 +2857,9 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
if (root == &cgrp_dfl_root)
continue;
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
from_cgrp = task_cgroup_from_root(from, root);
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
retval = cgroup_attach_task(from_cgrp, tsk, false);
if (retval)
@@ -2978,7 +2984,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
percpu_down_write(&cgroup_threadgroup_rwsem);
/* look up all csses currently attached to @cgrp's subtree */
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
css_for_each_descendant_pre(css, cgroup_css(cgrp, NULL)) {
struct cgrp_cset_link *link;
@@ -2990,14 +2996,14 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
cgroup_migrate_add_src(link->cset, cgrp,
&preloaded_csets);
}
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
/* NULL dst indicates self on default hierarchy */
ret = cgroup_migrate_prepare_dst(NULL, &preloaded_csets);
if (ret)
goto out_finish;
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
list_for_each_entry(src_cset, &preloaded_csets, mg_preload_node) {
struct task_struct *task, *ntask;
@@ -3009,7 +3015,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
list_for_each_entry_safe(task, ntask, &src_cset->tasks, cg_list)
cgroup_taskset_add(task, &tset);
}
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
ret = cgroup_taskset_migrate(&tset, cgrp);
out_finish:
@@ -3692,10 +3698,10 @@ static int cgroup_task_count(const struct cgroup *cgrp)
int count = 0;
struct cgrp_cset_link *link;
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
list_for_each_entry(link, &cgrp->cset_links, cset_link)
count += atomic_read(&link->cset->refcount);
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
return count;
}
@@ -4033,7 +4039,7 @@ void css_task_iter_start(struct cgroup_subsys_state *css,
memset(it, 0, sizeof(*it));
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
it->ss = css->ss;
@@ -4046,7 +4052,7 @@ void css_task_iter_start(struct cgroup_subsys_state *css,
css_task_iter_advance_css_set(it);
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
}
/**
@@ -4064,7 +4070,7 @@ struct task_struct *css_task_iter_next(struct css_task_iter *it)
it->cur_task = NULL;
}
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
if (it->task_pos) {
it->cur_task = list_entry(it->task_pos, struct task_struct,
@@ -4073,7 +4079,7 @@ struct task_struct *css_task_iter_next(struct css_task_iter *it)
css_task_iter_advance(it);
}
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
return it->cur_task;
}
@@ -4087,10 +4093,10 @@ struct task_struct *css_task_iter_next(struct css_task_iter *it)
void css_task_iter_end(struct css_task_iter *it)
{
if (it->cur_cset) {
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
list_del(&it->iters_node);
put_css_set_locked(it->cur_cset);
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
}
if (it->cur_task)
@@ -4119,10 +4125,10 @@ int cgroup_transfer_tasks(struct cgroup *to, struct cgroup *from)
mutex_lock(&cgroup_mutex);
/* all tasks in @from are being moved, all csets are source */
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
list_for_each_entry(link, &from->cset_links, cset_link)
cgroup_migrate_add_src(link->cset, to, &preloaded_csets);
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
ret = cgroup_migrate_prepare_dst(to, &preloaded_csets);
if (ret)
@@ -5226,10 +5232,10 @@ static int cgroup_destroy_locked(struct cgroup *cgrp)
*/
cgrp->self.flags &= ~CSS_ONLINE;
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
list_for_each_entry(link, &cgrp->cset_links, cset_link)
link->cset->dead = true;
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
/* initiate massacre of all css's */
for_each_css(css, ssid, cgrp)
@@ -5488,7 +5494,7 @@ int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns,
goto out;
mutex_lock(&cgroup_mutex);
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
for_each_root(root) {
struct cgroup_subsys *ss;
@@ -5540,7 +5546,7 @@ int proc_cgroup_show(struct seq_file *m, struct pid_namespace *ns,
retval = 0;
out_unlock:
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
mutex_unlock(&cgroup_mutex);
kfree(buf);
out:
@@ -5701,13 +5707,13 @@ void cgroup_post_fork(struct task_struct *child,
if (use_task_css_set_links) {
struct css_set *cset;
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
cset = task_css_set(current);
if (list_empty(&child->cg_list)) {
get_css_set(cset);
css_set_move_task(child, NULL, cset, false);
}
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
}
/*
@@ -5751,9 +5757,9 @@ void cgroup_exit(struct task_struct *tsk)
cset = task_css_set(tsk);
if (!list_empty(&tsk->cg_list)) {
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
css_set_move_task(tsk, cset, NULL, false);
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
} else {
get_css_set(cset);
}
@@ -5819,7 +5825,9 @@ static void cgroup_release_agent(struct work_struct *work)
if (!pathbuf || !agentbuf)
goto out;
+ spin_lock_irq(&css_set_lock);
path = cgroup_path(cgrp, pathbuf, PATH_MAX);
+ spin_unlock_irq(&css_set_lock);
if (!path)
goto out;
@@ -5966,7 +5974,7 @@ static int current_css_set_cg_links_read(struct seq_file *seq, void *v)
if (!name_buf)
return -ENOMEM;
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
rcu_read_lock();
cset = rcu_dereference(current->cgroups);
list_for_each_entry(link, &cset->cgrp_links, cgrp_link) {
@@ -5977,7 +5985,7 @@ static int current_css_set_cg_links_read(struct seq_file *seq, void *v)
c->root->hierarchy_id, name_buf);
}
rcu_read_unlock();
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
kfree(name_buf);
return 0;
}
@@ -5988,7 +5996,7 @@ static int cgroup_css_links_read(struct seq_file *seq, void *v)
struct cgroup_subsys_state *css = seq_css(seq);
struct cgrp_cset_link *link;
- spin_lock_bh(&css_set_lock);
+ spin_lock_irq(&css_set_lock);
list_for_each_entry(link, &css->cgroup->cset_links, cset_link) {
struct css_set *cset = link->cset;
struct task_struct *task;
@@ -6011,7 +6019,7 @@ static int cgroup_css_links_read(struct seq_file *seq, void *v)
overflow:
seq_puts(seq, " ...\n");
}
- spin_unlock_bh(&css_set_lock);
+ spin_unlock_irq(&css_set_lock);
return 0;
}
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 3c97f5b88a07..25cfcc804077 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -612,6 +612,7 @@ void __weak arch_enable_nonboot_cpus_end(void)
void enable_nonboot_cpus(void)
{
int cpu, error;
+ struct device *cpu_device;
/* Allow everyone to use the CPU hotplug again */
cpu_maps_update_begin();
@@ -629,6 +630,12 @@ void enable_nonboot_cpus(void)
trace_suspend_resume(TPS("CPU_ON"), cpu, false);
if (!error) {
pr_info("CPU%d is up\n", cpu);
+ cpu_device = get_cpu_device(cpu);
+ if (!cpu_device)
+ pr_err("%s: failed to get cpu%d device\n",
+ __func__, cpu);
+ else
+ kobject_uevent(&cpu_device->kobj, KOBJ_ONLINE);
continue;
}
pr_warn("Error taking CPU%d up: %d\n", cpu, error);
diff --git a/kernel/drivers/input/touchscreen/Kconfig b/kernel/drivers/input/touchscreen/Kconfig
deleted file mode 100644
index 18655c0b3997..000000000000
--- a/kernel/drivers/input/touchscreen/Kconfig
+++ /dev/null
@@ -1,721 +0,0 @@
-#
-# Touchscreen driver configuration
-#
-menuconfig INPUT_TOUCHSCREEN
- bool "Touchscreens"
- help
- Say Y here, and a list of supported touchscreens will be displayed.
- This option doesn't affect the kernel.
-
- If unsure, say Y.
-
-if INPUT_TOUCHSCREEN
-
-config TOUCHSCREEN_88PM860X
- tristate "Marvell 88PM860x touchscreen"
- depends on MFD_88PM860X
- help
- Say Y here if you have a 88PM860x PMIC and want to enable
- support for the built-in touchscreen.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called 88pm860x-ts.
-
-config TOUCHSCREEN_ADS7846
- tristate "ADS7846/TSC2046/AD7873 and AD(S)7843 based touchscreens"
- depends on SPI_MASTER
- depends on HWMON = n || HWMON
- help
- Say Y here if you have a touchscreen interface using the
- ADS7846/TSC2046/AD7873 or ADS7843/AD7843 controller,
- and your board-specific setup code includes that in its
- table of SPI devices.
-
- If HWMON is selected, and the driver is told the reference voltage
- on your board, you will also get hwmon interfaces for the voltage
- (and on ads7846/tsc2046/ad7873, temperature) sensors of this chip.
-
- If unsure, say N (but it's safe to say "Y").
-
- To compile this driver as a module, choose M here: the
- module will be called ads7846.
-
-config TOUCHSCREEN_AD7877
- tristate "AD7877 based touchscreens"
- depends on SPI_MASTER
- help
- Say Y here if you have a touchscreen interface using the
- AD7877 controller, and your board-specific initialization
- code includes that in its table of SPI devices.
-
- If unsure, say N (but it's safe to say "Y").
-
- To compile this driver as a module, choose M here: the
- module will be called ad7877.
-
-config TOUCHSCREEN_AD7879
- tristate "Analog Devices AD7879-1/AD7889-1 touchscreen interface"
- help
- Say Y here if you want to support a touchscreen interface using
- the AD7879-1/AD7889-1 controller.
-
- You should select a bus connection too.
-
- To compile this driver as a module, choose M here: the
- module will be called ad7879.
-
-config TOUCHSCREEN_AD7879_I2C
- tristate "support I2C bus connection"
- depends on TOUCHSCREEN_AD7879 && I2C
- help
- Say Y here if you have AD7879-1/AD7889-1 hooked to an I2C bus.
-
- To compile this driver as a module, choose M here: the
- module will be called ad7879-i2c.
-
-config TOUCHSCREEN_AD7879_SPI
- tristate "support SPI bus connection"
- depends on TOUCHSCREEN_AD7879 && SPI_MASTER
- help
- Say Y here if you have AD7879-1/AD7889-1 hooked to a SPI bus.
-
- If unsure, say N (but it's safe to say "Y").
-
- To compile this driver as a module, choose M here: the
- module will be called ad7879-spi.
-
-config TOUCHSCREEN_BITSY
- tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
- depends on SA1100_BITSY
- select SERIO
- help
- Say Y here if you have the h3600 (Bitsy) touchscreen.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called h3600_ts_input.
-
-config TOUCHSCREEN_BU21013
- tristate "BU21013 based touch panel controllers"
- depends on I2C
- help
- Say Y here if you have a bu21013 touchscreen connected to
- your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called bu21013_ts.
-
-config TOUCHSCREEN_CY8CTMG110
- tristate "cy8ctmg110 touchscreen"
- depends on I2C
- depends on GPIOLIB
-
- help
- Say Y here if you have a cy8ctmg110 capacitive touchscreen on
- an AAVA device.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called cy8ctmg110_ts.
-
-config TOUCHSCREEN_DA9034
- tristate "Touchscreen support for Dialog Semiconductor DA9034"
- depends on PMIC_DA903X
- default y
- help
- Say Y here to enable the support for the touchscreen found
- on Dialog Semiconductor DA9034 PMIC.
-
-config TOUCHSCREEN_DYNAPRO
- tristate "Dynapro serial touchscreen"
- select SERIO
- help
- Say Y here if you have a Dynapro serial touchscreen connected to
- your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called dynapro.
-
-config TOUCHSCREEN_HAMPSHIRE
- tristate "Hampshire serial touchscreen"
- select SERIO
- help
- Say Y here if you have a Hampshire serial touchscreen connected to
- your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called hampshire.
-
-config TOUCHSCREEN_EETI
- tristate "EETI touchscreen panel support"
- depends on I2C
- help
- Say Y here to enable support for I2C connected EETI touch panels.
-
- To compile this driver as a module, choose M here: the
- module will be called eeti_ts.
-
-config TOUCHSCREEN_FUJITSU
- tristate "Fujitsu serial touchscreen"
- select SERIO
- help
- Say Y here if you have the Fujitsu touchscreen (such as one
- installed in Lifebook P series laptop) connected to your
- system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called fujitsu-ts.
-
-config TOUCHSCREEN_S3C2410
- tristate "Samsung S3C2410/generic touchscreen input driver"
- depends on ARCH_S3C2410 || SAMSUNG_DEV_TS
- select S3C_ADC
- help
- Say Y here if you have the s3c2410 touchscreen.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called s3c2410_ts.
-
-config TOUCHSCREEN_GUNZE
- tristate "Gunze AHL-51S touchscreen"
- select SERIO
- help
- Say Y here if you have the Gunze AHL-51 touchscreen connected to
- your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called gunze.
-
-config TOUCHSCREEN_ELO
- tristate "Elo serial touchscreens"
- select SERIO
- help
- Say Y here if you have an Elo serial touchscreen connected to
- your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called elo.
-
-config TOUCHSCREEN_WACOM_W8001
- tristate "Wacom W8001 penabled serial touchscreen"
- select SERIO
- help
- Say Y here if you have an Wacom W8001 penabled serial touchscreen
- connected to your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called wacom_w8001.
-
-config TOUCHSCREEN_LPC32XX
- tristate "LPC32XX touchscreen controller"
- depends on ARCH_LPC32XX
- help
- Say Y here if you have a LPC32XX device and want
- to support the built-in touchscreen.
-
- To compile this driver as a module, choose M here: the
- module will be called lpc32xx_ts.
-
-config TOUCHSCREEN_MCS5000
- tristate "MELFAS MCS-5000 touchscreen"
- depends on I2C
- help
- Say Y here if you have the MELFAS MCS-5000 touchscreen controller
- chip in your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called mcs5000_ts.
-
-config TOUCHSCREEN_MTOUCH
- tristate "MicroTouch serial touchscreens"
- select SERIO
- help
- Say Y here if you have a MicroTouch (3M) serial touchscreen connected to
- your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called mtouch.
-
-config TOUCHSCREEN_INEXIO
- tristate "iNexio serial touchscreens"
- select SERIO
- help
- Say Y here if you have an iNexio serial touchscreen connected to
- your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called inexio.
-
-config TOUCHSCREEN_INTEL_MID
- tristate "Intel MID platform resistive touchscreen"
- depends on INTEL_SCU_IPC
- help
- Say Y here if you have a Intel MID based touchscreen in
- your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called intel_mid_touch.
-
-config TOUCHSCREEN_MK712
- tristate "ICS MicroClock MK712 touchscreen"
- help
- Say Y here if you have the ICS MicroClock MK712 touchscreen
- controller chip in your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called mk712.
-
-config TOUCHSCREEN_HP600
- tristate "HP Jornada 6xx touchscreen"
- depends on SH_HP6XX && SH_ADC
- help
- Say Y here if you have a HP Jornada 620/660/680/690 and want to
- support the built-in touchscreen.
-
- To compile this driver as a module, choose M here: the
- module will be called hp680_ts_input.
-
-config TOUCHSCREEN_HP7XX
- tristate "HP Jornada 7xx touchscreen"
- depends on SA1100_JORNADA720_SSP
- help
- Say Y here if you have a HP Jornada 710/720/728 and want
- to support the built-in touchscreen.
-
- To compile this driver as a module, choose M here: the
- module will be called jornada720_ts.
-
-config TOUCHSCREEN_HTCPEN
- tristate "HTC Shift X9500 touchscreen"
- depends on ISA
- help
- Say Y here if you have an HTC Shift UMPC also known as HTC X9500
- Clio / Shangrila and want to support the built-in touchscreen.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called htcpen.
-
-config TOUCHSCREEN_PENMOUNT
- tristate "Penmount serial touchscreen"
- select SERIO
- help
- Say Y here if you have a Penmount serial touchscreen connected to
- your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called penmount.
-
-config TOUCHSCREEN_QT602240
- tristate "QT602240 I2C Touchscreen"
- depends on I2C
- help
- Say Y here if you have the AT42QT602240/ATMXT224 I2C touchscreen
- connected to your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called qt602240_ts.
-
-config TOUCHSCREEN_MIGOR
- tristate "Renesas MIGO-R touchscreen"
- depends on SH_MIGOR && I2C
- help
- Say Y here to enable MIGO-R touchscreen support.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called migor_ts.
-
-config TOUCHSCREEN_TNETV107X
- tristate "TI TNETV107X touchscreen support"
- depends on ARCH_DAVINCI_TNETV107X
- help
- Say Y here if you want to use the TNETV107X touchscreen.
-
- To compile this driver as a module, choose M here: the
- module will be called tnetv107x-ts.
-
-config TOUCHSCREEN_SYNAPTICS_I2C_RMI4
- tristate "Synaptics DSX I2C touchscreen"
- depends on I2C
- help
- Say Y here if you have a Synaptics DSX I2C touchscreen
- connected to your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called synaptics_i2c_rmi4.
-
-config TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV
- tristate "Synaptics I2C touchscreen rmi device"
- depends on TOUCHSCREEN_SYNAPTICS_I2C_RMI4
- help
- This enables support for character device channel for Synaptics RMI
- touchscreens.
-
-config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE
- tristate "Synaptics I2C touchscreen firmware update"
- depends on TOUCHSCREEN_SYNAPTICS_I2C_RMI4
- help
- This enables support for firmware update for Synaptics RMI
- touchscreens.
-
-config TOUCHSCREEN_TOUCHRIGHT
- tristate "Touchright serial touchscreen"
- select SERIO
- help
- Say Y here if you have a Touchright serial touchscreen connected to
- your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called touchright.
-
-config TOUCHSCREEN_TOUCHWIN
- tristate "Touchwin serial touchscreen"
- select SERIO
- help
- Say Y here if you have a Touchwin serial touchscreen connected to
- your system.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called touchwin.
-
-config TOUCHSCREEN_ATMEL_TSADCC
- tristate "Atmel Touchscreen Interface"
- depends on ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
- help
- Say Y here if you have a 4-wire touchscreen connected to the
- ADC Controller on your Atmel SoC (such as the AT91SAM9RL).
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called atmel_tsadcc.
-
-config TOUCHSCREEN_UCB1400
- tristate "Philips UCB1400 touchscreen"
- depends on AC97_BUS
- depends on UCB1400_CORE
- help
- This enables support for the Philips UCB1400 touchscreen interface.
- The UCB1400 is an AC97 audio codec. The touchscreen interface
- will be initialized only after the ALSA subsystem has been
- brought up and the UCB1400 detected. You therefore have to
- configure ALSA support as well (either built-in or modular,
- independently of whether this driver is itself built-in or
- modular) for this driver to work.
-
- To compile this driver as a module, choose M here: the
- module will be called ucb1400_ts.
-
-config TOUCHSCREEN_WM97XX
- tristate "Support for WM97xx AC97 touchscreen controllers"
- depends on AC97_BUS
- help
- Say Y here if you have a Wolfson Microelectronics WM97xx
- touchscreen connected to your system. Note that this option
- only enables core driver, you will also need to select
- support for appropriate chip below.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called wm97xx-ts.
-
-config TOUCHSCREEN_WM9705
- bool "WM9705 Touchscreen interface support"
- depends on TOUCHSCREEN_WM97XX
- default y
- help
- Say Y here to enable support for the Wolfson Microelectronics
- WM9705 touchscreen controller.
-
-config TOUCHSCREEN_WM9712
- bool "WM9712 Touchscreen interface support"
- depends on TOUCHSCREEN_WM97XX
- default y
- help
- Say Y here to enable support for the Wolfson Microelectronics
- WM9712 touchscreen controller.
-
-config TOUCHSCREEN_WM9713
- bool "WM9713 Touchscreen interface support"
- depends on TOUCHSCREEN_WM97XX
- default y
- help
- Say Y here to enable support for the Wolfson Microelectronics
- WM9713 touchscreen controller.
-
-config TOUCHSCREEN_WM97XX_ATMEL
- tristate "WM97xx Atmel accelerated touch"
- depends on TOUCHSCREEN_WM97XX && (AVR32 || ARCH_AT91)
- help
- Say Y here for support for streaming mode with WM97xx touchscreens
- on Atmel AT91 or AVR32 systems with an AC97C module.
-
- Be aware that this will use channel B in the controller for
- streaming data, this must not conflict with other AC97C drivers.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the module will
- be called atmel-wm97xx.
-
-config TOUCHSCREEN_WM97XX_MAINSTONE
- tristate "WM97xx Mainstone/Palm accelerated touch"
- depends on TOUCHSCREEN_WM97XX && ARCH_PXA
- help
- Say Y here for support for streaming mode with WM97xx touchscreens
- on Mainstone, Palm Tungsten T5, TX and LifeDrive systems.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called mainstone-wm97xx.
-
-config TOUCHSCREEN_WM97XX_ZYLONITE
- tristate "Zylonite accelerated touch"
- depends on TOUCHSCREEN_WM97XX && MACH_ZYLONITE
- select TOUCHSCREEN_WM9713
- help
- Say Y here for support for streaming mode with the touchscreen
- on Zylonite systems.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called zylonite-wm97xx.
-
-config TOUCHSCREEN_USB_COMPOSITE
- tristate "USB Touchscreen Driver"
- depends on USB_ARCH_HAS_HCD
- select USB
- help
- USB Touchscreen driver for:
- - eGalax Touchkit USB (also includes eTurboTouch CT-410/510/700)
- - PanJit TouchSet USB
- - 3M MicroTouch USB (EX II series)
- - ITM
- - some other eTurboTouch
- - Gunze AHL61
- - DMC TSC-10/25
- - IRTOUCHSYSTEMS/UNITOP
- - IdealTEK URTC1000
- - GoTop Super_Q2/GogoPen/PenPower tablets
- - JASTEC USB Touch Controller/DigiTech DTR-02U
- - Zytronic controllers
-
- Have a look at <http://linux.chapter7.ch/touchkit/> for
- a usage description and the required user-space stuff.
-
- To compile this driver as a module, choose M here: the
- module will be called usbtouchscreen.
-
-config TOUCHSCREEN_MC13783
- tristate "Freescale MC13783 touchscreen input driver"
- depends on MFD_MC13783
- help
- Say Y here if you have an Freescale MC13783 PMIC on your
- board and want to use its touchscreen
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called mc13783_ts.
-
-config TOUCHSCREEN_USB_EGALAX
- default y
- bool "eGalax, eTurboTouch CT-410/510/700 device support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_PANJIT
- default y
- bool "PanJit device support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_3M
- default y
- bool "3M/Microtouch EX II series device support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_ITM
- default y
- bool "ITM device support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_ETURBO
- default y
- bool "eTurboTouch (non-eGalax compatible) device support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_GUNZE
- default y
- bool "Gunze AHL61 device support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_DMC_TSC10
- default y
- bool "DMC TSC-10/25 device support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_IRTOUCH
- default y
- bool "IRTOUCHSYSTEMS/UNITOP device support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_IDEALTEK
- default y
- bool "IdealTEK URTC1000 device support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_GENERAL_TOUCH
- default y
- bool "GeneralTouch Touchscreen device support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_GOTOP
- default y
- bool "GoTop Super_Q2/GogoPen/PenPower tablet device support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_JASTEC
- default y
- bool "JASTEC/DigiTech DTR-02U USB touch controller device support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_E2I
- default y
- bool "e2i Touchscreen controller (e.g. from Mimo 740)"
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_ZYTRONIC
- default y
- bool "Zytronic controller" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_ETT_TC45USB
- default y
- bool "ET&T USB series TC4UM/TC5UH touchscreen controler support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_USB_NEXIO
- default y
- bool "NEXIO/iNexio device support" if EMBEDDED
- depends on TOUCHSCREEN_USB_COMPOSITE
-
-config TOUCHSCREEN_TOUCHIT213
- tristate "Sahara TouchIT-213 touchscreen"
- select SERIO
- help
- Say Y here if you have a Sahara TouchIT-213 Tablet PC.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called touchit213.
-
-config TOUCHSCREEN_TSC2007
- tristate "TSC2007 based touchscreens"
- depends on I2C
- help
- Say Y here if you have a TSC2007 based touchscreen.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called tsc2007.
-
-config TOUCHSCREEN_TSC2004
- tristate "TSC2004 based touchscreens"
- depends on I2C
- help
- Say Y here if you have a TSC2004 based touchscreen.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called tsc2004.
-
-config TOUCHSCREEN_W90X900
- tristate "W90P910 touchscreen driver"
- depends on HAVE_CLK
- help
- Say Y here if you have a W90P910 based touchscreen.
-
- To compile this driver as a module, choose M here: the
- module will be called w90p910_ts.
-
-config TOUCHSCREEN_PCAP
- tristate "Motorola PCAP touchscreen"
- depends on EZX_PCAP
- help
- Say Y here if you have a Motorola EZX telephone and
- want to enable support for the built-in touchscreen.
-
- To compile this driver as a module, choose M here: the
- module will be called pcap_ts.
-
-config TOUCHSCREEN_TPS6507X
- tristate "TPS6507x based touchscreens"
- depends on I2C
- help
- Say Y here if you have a TPS6507x based touchscreen
- controller.
-
- If unsure, say N.
-
- To compile this driver as a module, choose M here: the
- module will be called tps6507x_ts.
-
-config TOUCHSCREEN_STMPE
- tristate "STMicroelectronics STMPE touchscreens"
- depends on MFD_STMPE
- help
- Say Y here if you want support for STMicroelectronics
- STMPE touchscreen controllers.
-
- To compile this driver as a module, choose M here: the
- module will be called stmpe-ts.
-
-endif
diff --git a/kernel/drivers/input/touchscreen/Makefile b/kernel/drivers/input/touchscreen/Makefile
deleted file mode 100644
index a6c7d9f388a6..000000000000
--- a/kernel/drivers/input/touchscreen/Makefile
+++ /dev/null
@@ -1,68 +0,0 @@
-#
-# Makefile for the touchscreen drivers.
-#
-
-# Each configuration option enables a list of files.
-
-wm97xx-ts-y := wm97xx-core.o
-
-obj-$(CONFIG_TOUCHSCREEN_88PM860X) += 88pm860x-ts.o
-obj-$(CONFIG_TOUCHSCREEN_AD7877) += ad7877.o
-obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o
-obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o
-obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o
-obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o
-obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
-obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o
-obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o
-obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o
-obj-$(CONFIG_TOUCHSCREEN_DA9034) += da9034-ts.o
-obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o
-obj-$(CONFIG_TOUCHSCREEN_HAMPSHIRE) += hampshire.o
-obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o
-obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o
-obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
-obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
-obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
-obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
-obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o
-obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
-obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
-obj-$(CONFIG_TOUCHSCREEN_MIGOR) += migor_ts.o
-obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
-obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
-obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
-obj-$(CONFIG_TOUCHSCREEN_HP7XX) += jornada720_ts.o
-obj-$(CONFIG_TOUCHSCREEN_HTCPEN) += htcpen.o
-obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE) += usbtouchscreen.o
-obj-$(CONFIG_TOUCHSCREEN_PCAP) += pcap_ts.o
-obj-$(CONFIG_TOUCHSCREEN_PENMOUNT) += penmount.o
-obj-$(CONFIG_TOUCHSCREEN_QT602240) += qt602240_ts.o
-obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
-obj-$(CONFIG_TOUCHSCREEN_STMPE) += stmpe-ts.o
-obj-$(CONFIG_TOUCHSCREEN_TNETV107X) += tnetv107x-ts.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += synaptics_i2c_rmi4.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV) += synaptics_rmi_dev.o
-obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE) += synaptics_fw_update.o
-obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213) += touchit213.o
-obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT) += touchright.o
-obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN) += touchwin.o
-obj-$(CONFIG_TOUCHSCREEN_TSC2007) += tsc2007.o
-obj-$(CONFIG_TOUCHSCREEN_TSC2004) += tsc2004.o
-obj-$(CONFIG_TOUCHSCREEN_UCB1400) += ucb1400_ts.o
-obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001) += wacom_w8001.o
-obj-$(CONFIG_TOUCHSCREEN_WM97XX) += wm97xx-ts.o
-wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705) += wm9705.o
-wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
-wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
-obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o
-obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
-obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
-obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
-obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
-
-all:
-make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
-
-clean:
-make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
diff --git a/kernel/drivers/input/touchscreen/synaptics_fw_update.c b/kernel/drivers/input/touchscreen/synaptics_fw_update.c
deleted file mode 100644
index 8b6d7c7e368d..000000000000
--- a/kernel/drivers/input/touchscreen/synaptics_fw_update.c
+++ /dev/null
@@ -1,1698 +0,0 @@
-/*
- * Synaptics RMI4 touchscreen driver
- *
- * Copyright (C) 2012 Synaptics Incorporated
- *
- * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
- * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/firmware.h>
-#include <linux/input/synaptics_dsx.h>
-#include "synaptics_i2c_rmi4.h"
-
-#define DEBUG_FW_UPDATE
-#define SHOW_PROGRESS
-#define FW_IMAGE_NAME "PR1063486-s7301_00000000.img"
-#define MAX_FIRMWARE_ID_LEN 10
-#define FORCE_UPDATE false
-#define INSIDE_FIRMWARE_UPDATE
-
-#define CHECKSUM_OFFSET 0x00
-#define BOOTLOADER_VERSION_OFFSET 0x07
-#define IMAGE_SIZE_OFFSET 0x08
-#define CONFIG_SIZE_OFFSET 0x0C
-#define PRODUCT_ID_OFFSET 0x10
-#define PRODUCT_INFO_OFFSET 0x1E
-#define FW_IMAGE_OFFSET 0x100
-#define PRODUCT_ID_SIZE 10
-
-#define BOOTLOADER_ID_OFFSET 0
-#define FLASH_PROPERTIES_OFFSET 2
-#define BLOCK_SIZE_OFFSET 3
-#define FW_BLOCK_COUNT_OFFSET 5
-
-#define REG_MAP (1 << 0)
-#define UNLOCKED (1 << 1)
-#define HAS_CONFIG_ID (1 << 2)
-#define HAS_PERM_CONFIG (1 << 3)
-#define HAS_BL_CONFIG (1 << 4)
-#define HAS_DISP_CONFIG (1 << 5)
-#define HAS_CTRL1 (1 << 6)
-
-#define BLOCK_NUMBER_OFFSET 0
-#define BLOCK_DATA_OFFSET 2
-
-#define UI_CONFIG_AREA 0x00
-#define PERM_CONFIG_AREA 0x01
-#define BL_CONFIG_AREA 0x02
-#define DISP_CONFIG_AREA 0x03
-
-enum flash_command {
- CMD_WRITE_FW_BLOCK = 0x2,
- CMD_ERASE_ALL = 0x3,
- CMD_READ_CONFIG_BLOCK = 0x5,
- CMD_WRITE_CONFIG_BLOCK = 0x6,
- CMD_ERASE_CONFIG = 0x7,
- CMD_ERASE_BL_CONFIG = 0x9,
- CMD_ERASE_DISP_CONFIG = 0xA,
- CMD_ENABLE_FLASH_PROG = 0xF,
-};
-
-enum flash_area {
- NONE,
- UI_FIRMWARE,
- CONFIG_AREA
-};
-
-#define SLEEP_MODE_NORMAL (0x00)
-#define SLEEP_MODE_SENSOR_SLEEP (0x01)
-#define SLEEP_MODE_RESERVED0 (0x02)
-#define SLEEP_MODE_RESERVED1 (0x03)
-
-#define ENABLE_WAIT_MS (1 * 1000)
-#define WRITE_WAIT_MS (3 * 1000)
-#define ERASE_WAIT_MS (5 * 1000)
-#define RESET_WAIT_MS (500)
-
-#define SLEEP_TIME_US 50
-
-static ssize_t fwu_sysfs_show_image(struct file *data_file,
- struct kobject *kobj, struct bin_attribute *attributes,
- char *buf, loff_t pos, size_t count);
-
-static ssize_t fwu_sysfs_store_image(struct file *data_file,
- struct kobject *kobj, struct bin_attribute *attributes,
- char *buf, loff_t pos, size_t count);
-
-static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-static ssize_t fwu_sysfs_write_config_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-static ssize_t fwu_sysfs_read_config_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-static ssize_t fwu_sysfs_config_area_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-static ssize_t fwu_sysfs_image_size_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-static ssize_t fwu_sysfs_block_size_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-
-static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-
-static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-
-static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-
-static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-
-static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-
-static int fwu_wait_for_idle(int timeout_ms);
-
-struct image_header {
- unsigned int checksum;
- unsigned int image_size;
- unsigned int config_size;
- unsigned char options;
- unsigned char bootloader_version;
- unsigned char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
- unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
-};
-
-struct pdt_properties {
- union {
- struct {
- unsigned char reserved_1:6;
- unsigned char has_bsr:1;
- unsigned char reserved_2:1;
- } __packed;
- unsigned char data[1];
- };
-};
-
-struct f01_device_status {
- union {
- struct {
- unsigned char status_code:4;
- unsigned char reserved:2;
- unsigned char flash_prog:1;
- unsigned char unconfigured:1;
- } __packed;
- unsigned char data[1];
- };
-};
-
-struct f01_device_control {
- union {
- struct {
- unsigned char sleep_mode:2;
- unsigned char nosleep:1;
- unsigned char reserved:2;
- unsigned char charger_connected:1;
- unsigned char report_rate:1;
- unsigned char configured:1;
- } __packed;
- unsigned char data[1];
- };
-};
-
-struct f34_flash_control {
- union {
- struct {
- unsigned char command:4;
- unsigned char status:3;
- unsigned char program_enabled:1;
- } __packed;
- unsigned char data[1];
- };
-};
-
-struct f34_flash_properties {
- union {
- struct {
- unsigned char regmap:1;
- unsigned char unlocked:1;
- unsigned char has_configid:1;
- unsigned char has_perm_config:1;
- unsigned char has_bl_config:1;
- unsigned char has_display_config:1;
- unsigned char has_blob_config:1;
- unsigned char reserved:1;
- } __packed;
- unsigned char data[1];
- };
-};
-
-struct synaptics_rmi4_fwu_handle {
- bool initialized;
- bool force_update;
- char product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
- unsigned int image_size;
- unsigned int data_pos;
- unsigned char intr_mask;
- unsigned char bootloader_id[2];
- unsigned char productinfo1;
- unsigned char productinfo2;
- unsigned char *ext_data_source;
- unsigned char *read_config_buf;
- const unsigned char *firmware_data;
- const unsigned char *config_data;
- unsigned short block_size;
- unsigned short fw_block_count;
- unsigned short config_block_count;
- unsigned short perm_config_block_count;
- unsigned short bl_config_block_count;
- unsigned short disp_config_block_count;
- unsigned short config_size;
- unsigned short config_area;
- unsigned short addr_f34_flash_control;
- unsigned short addr_f01_interrupt_register;
- struct synaptics_rmi4_fn_desc f01_fd;
- struct synaptics_rmi4_fn_desc f34_fd;
- struct synaptics_rmi4_exp_fn_ptr *fn_ptr;
- struct synaptics_rmi4_data *rmi4_data;
- struct f34_flash_control flash_control;
- struct f34_flash_properties flash_properties;
- struct workqueue_struct *fwu_workqueue;
- struct delayed_work fwu_work;
-};
-
-static struct bin_attribute dev_attr_data = {
- .attr = {
- .name = "data",
- .mode = (S_IRUGO | S_IWUGO),
- },
- .size = 0,
- .read = fwu_sysfs_show_image,
- .write = fwu_sysfs_store_image,
-};
-
-static struct device_attribute attrs[] = {
- __ATTR(doreflash, S_IWUGO,
- synaptics_rmi4_show_error,
- fwu_sysfs_do_reflash_store),
- __ATTR(writeconfig, S_IWUGO,
- synaptics_rmi4_show_error,
- fwu_sysfs_write_config_store),
- __ATTR(readconfig, S_IWUGO,
- synaptics_rmi4_show_error,
- fwu_sysfs_read_config_store),
- __ATTR(configarea, S_IWUGO,
- synaptics_rmi4_show_error,
- fwu_sysfs_config_area_store),
- __ATTR(imagesize, S_IWUGO,
- synaptics_rmi4_show_error,
- fwu_sysfs_image_size_store),
- __ATTR(blocksize, S_IRUGO,
- fwu_sysfs_block_size_show,
- synaptics_rmi4_store_error),
- __ATTR(fwblockcount, S_IRUGO,
- fwu_sysfs_firmware_block_count_show,
- synaptics_rmi4_store_error),
- __ATTR(configblockcount, S_IRUGO,
- fwu_sysfs_configuration_block_count_show,
- synaptics_rmi4_store_error),
- __ATTR(permconfigblockcount, S_IRUGO,
- fwu_sysfs_perm_config_block_count_show,
- synaptics_rmi4_store_error),
- __ATTR(blconfigblockcount, S_IRUGO,
- fwu_sysfs_bl_config_block_count_show,
- synaptics_rmi4_store_error),
- __ATTR(dispconfigblockcount, S_IRUGO,
- fwu_sysfs_disp_config_block_count_show,
- synaptics_rmi4_store_error),
-};
-
-static struct synaptics_rmi4_fwu_handle *fwu;
-
-static struct completion remove_complete;
-
-static unsigned int extract_uint(const unsigned char *ptr)
-{
- return (unsigned int)ptr[0] +
- (unsigned int)ptr[1] * 0x100 +
- (unsigned int)ptr[2] * 0x10000 +
- (unsigned int)ptr[3] * 0x1000000;
-}
-
-static void parse_header(struct image_header *header,
- const unsigned char *fw_image)
-{
- header->checksum = extract_uint(&fw_image[CHECKSUM_OFFSET]);
- header->bootloader_version = fw_image[BOOTLOADER_VERSION_OFFSET];
- header->image_size = extract_uint(&fw_image[IMAGE_SIZE_OFFSET]);
- header->config_size = extract_uint(&fw_image[CONFIG_SIZE_OFFSET]);
- memcpy(header->product_id, &fw_image[PRODUCT_ID_OFFSET],
- SYNAPTICS_RMI4_PRODUCT_ID_SIZE);
- header->product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE] = 0;
- memcpy(header->product_info, &fw_image[PRODUCT_INFO_OFFSET],
- SYNAPTICS_RMI4_PRODUCT_INFO_SIZE);
-
-#ifdef DEBUG_FW_UPDATE
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "Firwmare size %d, config size %d\n",
- header->image_size,
- header->config_size);
-#endif
- return;
-}
-
-static int fwu_read_f01_device_status(struct f01_device_status *status)
-{
- int retval;
-
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f01_fd.data_base_addr,
- status->data,
- sizeof(status->data));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read F01 device status\n",
- __func__);
- return retval;
- }
-
- return 0;
-}
-
-static int fwu_read_f34_queries(void)
-{
- int retval;
- unsigned char count = 4;
- unsigned char buf[10];
- struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
-
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.query_base_addr + BOOTLOADER_ID_OFFSET,
- fwu->bootloader_id,
- sizeof(fwu->bootloader_id));
- if (retval < 0) {
- dev_err(&i2c_client->dev,
- "%s: Failed to read bootloader ID\n",
- __func__);
- return retval;
- }
-
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.query_base_addr + FLASH_PROPERTIES_OFFSET,
- fwu->flash_properties.data,
- sizeof(fwu->flash_properties.data));
- if (retval < 0) {
- dev_err(&i2c_client->dev,
- "%s: Failed to read flash properties\n",
- __func__);
- return retval;
- }
-
- dev_info(&i2c_client->dev, "%s perm:%d, bl:%d, display:%d\n",
- __func__,
- fwu->flash_properties.has_perm_config,
- fwu->flash_properties.has_bl_config,
- fwu->flash_properties.has_display_config);
-
- if (fwu->flash_properties.has_perm_config)
- count += 2;
-
- if (fwu->flash_properties.has_bl_config)
- count += 2;
-
- if (fwu->flash_properties.has_display_config)
- count += 2;
-
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.query_base_addr + BLOCK_SIZE_OFFSET,
- buf,
- 2);
- if (retval < 0) {
- dev_err(&i2c_client->dev,
- "%s: Failed to read block size info\n",
- __func__);
- return retval;
- }
-
- batohs(&fwu->block_size, &(buf[0]));
-
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.query_base_addr + FW_BLOCK_COUNT_OFFSET,
- buf,
- count);
- if (retval < 0) {
- dev_err(&i2c_client->dev,
- "%s: Failed to read block count info\n",
- __func__);
- return retval;
- }
-
- batohs(&fwu->fw_block_count, &(buf[0]));
- batohs(&fwu->config_block_count, &(buf[2]));
-
- count = 4;
-
- if (fwu->flash_properties.has_perm_config) {
- batohs(&fwu->perm_config_block_count, &(buf[count]));
- count += 2;
- }
-
- if (fwu->flash_properties.has_bl_config) {
- batohs(&fwu->bl_config_block_count, &(buf[count]));
- count += 2;
- }
-
- if (fwu->flash_properties.has_display_config)
- batohs(&fwu->disp_config_block_count, &(buf[count]));
-
- fwu->addr_f34_flash_control = fwu->f34_fd.data_base_addr +
- BLOCK_DATA_OFFSET +
- fwu->block_size;
- return 0;
-}
-
-static int fwu_read_interrupt_status(void)
-{
- int retval;
- unsigned char interrupt_status;
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->addr_f01_interrupt_register,
- &interrupt_status,
- sizeof(interrupt_status));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read flash status\n",
- __func__);
- return retval;
- }
- return interrupt_status;
-}
-
-static int fwu_read_f34_flash_status(void)
-{
- int retval;
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->addr_f34_flash_control,
- fwu->flash_control.data,
- sizeof(fwu->flash_control.data));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read flash status\n",
- __func__);
- return retval;
- }
- return 0;
-}
-
-static int fwu_reset_device(void)
-{
- int retval;
-
-#ifdef DEBUG_FW_UPDATE
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "%s: Reset device\n",
- __func__);
-#endif
-
- retval = fwu->rmi4_data->reset_device(fwu->rmi4_data);
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to reset core driver after reflash\n",
- __func__);
- return retval;
- }
- return 0;
-}
-
-static int fwu_write_f34_command(unsigned char cmd)
-{
- int retval;
-
- fwu->flash_control.data[0] = cmd;
- retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->addr_f34_flash_control,
- fwu->flash_control.data,
- sizeof(fwu->flash_control.data));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write command 0x%02x\n",
- __func__, fwu->flash_control.data[0]);
- return retval;
- }
- return 0;
-}
-
-static int fwu_wait_for_idle(int timeout_ms)
-{
- int count = 0;
- int timeout_count = ((timeout_ms * 1000) / SLEEP_TIME_US) + 1;
- do {
- if (fwu->flash_control.command == 0x00)
- return 0;
-
- usleep_range(SLEEP_TIME_US, SLEEP_TIME_US + 100);
- } while (count++ < timeout_count);
-
- fwu_read_f34_flash_status();
- if (fwu->flash_control.command == 0x00)
- return 0;
-
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Timed out waiting for idle status\n",
- __func__);
-
- return -ETIMEDOUT;
-}
-
-static enum flash_area fwu_go_nogo(void)
-{
- int retval = 0;
- int index = 0;
- int deviceFirmwareID;
- int imageConfigID;
- int deviceConfigID;
- unsigned long imageFirmwareID;
- unsigned char firmware_id[4];
- unsigned char config_id[4];
- char *strptr;
- char *imagePR = kzalloc(sizeof(MAX_FIRMWARE_ID_LEN), GFP_KERNEL);
- enum flash_area flash_area = NONE;
- struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
- struct f01_device_status f01_device_status;
-
- if (fwu->force_update) {
- flash_area = UI_FIRMWARE;
- goto exit;
- }
-
- retval = fwu_read_f01_device_status(&f01_device_status);
- if (retval < 0) {
- flash_area = NONE;
- goto exit;
- }
-
- imagePR = kzalloc(sizeof(MAX_FIRMWARE_ID_LEN), GFP_KERNEL);
-
- /* Force update firmware when device is in bootloader mode */
- if (f01_device_status.flash_prog) {
- dev_info(&i2c_client->dev,
- "%s: In flash prog mode\n",
- __func__);
- flash_area = UI_FIRMWARE;
- goto exit;
- }
-
-
- /* device firmware id */
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f01_fd.query_base_addr + 18,
- firmware_id,
- sizeof(firmware_id));
- if (retval < 0) {
- dev_err(&i2c_client->dev,
- "Failed to read firmware ID (code %d).\n", retval);
- goto exit;
- }
- firmware_id[3] = 0;
- deviceFirmwareID = extract_uint(firmware_id);
-
- /* .img firmware id */
- strptr = strstr(FW_IMAGE_NAME, "PR");
- if (!strptr) {
- dev_err(&i2c_client->dev,
- "No valid PR number (PRxxxxxxx)" \
- "found in image file name...\n");
- goto exit;
- }
-
- strptr += 2;
- while (strptr[index] >= '0' && strptr[index] <= '9') {
- imagePR[index] = strptr[index];
- index++;
- }
- imagePR[index] = 0;
-
- retval = sstrtoul(imagePR, 10, &imageFirmwareID);
- if (retval == -EINVAL) {
- dev_err(&i2c_client->dev,
- "invalid image firmware id...\n");
- goto exit;
- }
-
- dev_info(&i2c_client->dev,
- "Device firmware id %d, .img firmware id %d\n",
- deviceFirmwareID,
- (unsigned int)imageFirmwareID);
- if (imageFirmwareID > deviceFirmwareID) {
- flash_area = UI_FIRMWARE;
- goto exit;
- }
-
- /* device config id */
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.ctrl_base_addr,
- config_id,
- sizeof(config_id));
- if (retval < 0) {
- dev_err(&i2c_client->dev,
- "Failed to read config ID (code %d).\n", retval);
- flash_area = NONE;
- goto exit;
- }
- deviceConfigID = extract_uint(config_id);
-
- dev_info(&i2c_client->dev,
- "Device config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
- config_id[0], config_id[1], config_id[2], config_id[3]);
-
- /* .img config id */
- dev_info(&i2c_client->dev,
- ".img config ID 0x%02X, 0x%02X, 0x%02X, 0x%02X\n",
- fwu->config_data[0],
- fwu->config_data[1],
- fwu->config_data[2],
- fwu->config_data[3]);
- imageConfigID = extract_uint(fwu->config_data);
-
- if (imageConfigID > deviceConfigID) {
- flash_area = CONFIG_AREA;
- goto exit;
- }
-
-exit:
- kfree(imagePR);
- if (flash_area == NONE)
- dev_info(&i2c_client->dev,
- "Nothing needs to be updated\n");
- else
- dev_info(&i2c_client->dev,
- "Update %s block\n",
- flash_area == UI_FIRMWARE ? "UI FW" : "CONFIG");
- return flash_area;
-}
-
-static int fwu_scan_pdt(void)
-{
- int retval;
- unsigned char ii;
- unsigned char intr_count = 0;
- unsigned char intr_off;
- unsigned char intr_src;
- unsigned short addr;
- bool f01found = false;
- bool f34found = false;
- struct synaptics_rmi4_fn_desc rmi_fd;
-
-#ifdef DEBUG_FW_UPDATE
- dev_info(&fwu->rmi4_data->i2c_client->dev, "Scan PDT\n");
-#endif
-
- for (addr = PDT_START; addr > PDT_END; addr -= PDT_ENTRY_SIZE) {
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- addr,
- (unsigned char *)&rmi_fd,
- sizeof(rmi_fd));
- if (retval < 0)
- return retval;
-
- if (rmi_fd.fn_number) {
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Found F%02x\n",
- __func__, rmi_fd.fn_number);
- switch (rmi_fd.fn_number) {
- case SYNAPTICS_RMI4_F01:
- f01found = true;
- fwu->f01_fd = rmi_fd;
- fwu->addr_f01_interrupt_register =
- fwu->f01_fd.data_base_addr + 1;
- break;
- case SYNAPTICS_RMI4_F34:
- f34found = true;
- fwu->f34_fd = rmi_fd;
- fwu->intr_mask = 0;
- intr_src = rmi_fd.intr_src_count;
- intr_off = intr_count % 8;
- for (ii = intr_off;
- ii < ((intr_src & MASK_3BIT) +
- intr_off);
- ii++)
- fwu->intr_mask |= 1 << ii;
- break;
- }
- } else
- break;
-
- intr_count += (rmi_fd.intr_src_count & MASK_3BIT);
- }
-
- if (!f01found || !f34found) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to find both F01 and F34\n",
- __func__);
- return -EINVAL;
- }
-
- fwu_read_interrupt_status();
- return 0;
-}
-
-static int fwu_write_blocks(unsigned char *block_ptr, unsigned short block_cnt,
- unsigned char command)
-{
- int retval;
- unsigned char block_offset[] = {0, 0};
- unsigned short block_num;
- struct i2c_client *i2c_client = fwu->rmi4_data->i2c_client;
-#ifdef SHOW_PROGRESS
- unsigned int progress = (command == CMD_WRITE_CONFIG_BLOCK) ?
- 10 : 100;
-#endif
-
-#ifdef DEBUG_FW_UPDATE
- dev_info(&i2c_client->dev,
- "%s: Start to update %s blocks\n",
- __func__,
- command == CMD_WRITE_CONFIG_BLOCK ?
- "config" : "firmware");
-#endif
- retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET,
- block_offset,
- sizeof(block_offset));
- if (retval < 0) {
- dev_err(&i2c_client->dev,
- "%s: Failed to write to block number registers\n",
- __func__);
- return retval;
- }
-
- for (block_num = 0; block_num < block_cnt; block_num++) {
-#ifdef SHOW_PROGRESS
- if (block_num % progress == 0)
- dev_info(&i2c_client->dev,
- "%s: update %s %3d / %3d\n",
- __func__,
- command == CMD_WRITE_CONFIG_BLOCK ?
- "config" : "firmware",
- block_num, block_cnt);
-#endif
- retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
- block_ptr,
- fwu->block_size);
- if (retval < 0) {
- dev_err(&i2c_client->dev,
- "%s: Failed to write block data (block %d)\n",
- __func__, block_num);
- return retval;
- }
-
- retval = fwu_write_f34_command(command);
- if (retval < 0) {
- dev_err(&i2c_client->dev,
- "%s: Failed to write command for block %d\n",
- __func__, block_num);
- return retval;
- }
-
- retval = fwu_wait_for_idle(WRITE_WAIT_MS);
- if (retval < 0) {
- dev_err(&i2c_client->dev,
- "%s: Failed to wait for idle status (block %d)\n",
- __func__, block_num);
- return retval;
- }
-
- if (fwu->flash_control.status != 0x00) {
- dev_err(&i2c_client->dev,
- "%s: Flash block %d failed, status 0x%02X\n",
- __func__, block_num, retval);
- return -1;
- }
-
- block_ptr += fwu->block_size;
- }
-#ifdef SHOW_PROGRESS
- dev_info(&i2c_client->dev,
- "%s: update %s %3d / %3d\n",
- __func__,
- command == CMD_WRITE_CONFIG_BLOCK ?
- "config" : "firmware",
- block_cnt, block_cnt);
-#endif
- return 0;
-}
-
-static int fwu_write_firmware(void)
-{
- return fwu_write_blocks((unsigned char *)fwu->firmware_data,
- fwu->fw_block_count, CMD_WRITE_FW_BLOCK);
-}
-
-static int fwu_write_configuration(void)
-{
- return fwu_write_blocks((unsigned char *)fwu->config_data,
- fwu->config_block_count, CMD_WRITE_CONFIG_BLOCK);
-}
-
-static int fwu_write_bootloader_id(void)
-{
- int retval;
-
-#ifdef DEBUG_FW_UPDATE
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "Write bootloader ID 0x%02X 0x%02X\n",
- fwu->bootloader_id[0],
- fwu->bootloader_id[1]);
-#endif
- retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
- fwu->bootloader_id,
- sizeof(fwu->bootloader_id));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write bootloader ID\n",
- __func__);
- return retval;
- }
-
- return 0;
-}
-
-static int fwu_enter_flash_prog(void)
-{
- int retval;
- struct f01_device_status f01_device_status;
- struct f01_device_control f01_device_control;
-
-#ifdef DEBUG_FW_UPDATE
- dev_info(&fwu->rmi4_data->i2c_client->dev, "Enter bootloader mode\n");
-#endif
- retval = fwu_read_f01_device_status(&f01_device_status);
- if (retval < 0)
- return retval;
-
- if (f01_device_status.flash_prog) {
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "%s: Already in flash prog mode\n",
- __func__);
- return 0;
- }
-
- retval = fwu_write_bootloader_id();
- if (retval < 0)
- return retval;
-
- retval = fwu_write_f34_command(CMD_ENABLE_FLASH_PROG);
- if (retval < 0)
- return retval;
-
- retval = fwu_wait_for_idle(ENABLE_WAIT_MS);
- if (retval < 0)
- return retval;
-
- retval = fwu_scan_pdt();
- if (retval < 0)
- return retval;
-
- retval = fwu_read_f01_device_status(&f01_device_status);
- if (retval < 0)
- return retval;
-
- if (!f01_device_status.flash_prog) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Not in flash prog mode\n",
- __func__);
- return -EINVAL;
- }
-
- retval = fwu_read_f34_queries();
- if (retval < 0)
- return retval;
-
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f01_fd.ctrl_base_addr,
- f01_device_control.data,
- sizeof(f01_device_control.data));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read F01 device control\n",
- __func__);
- return retval;
- }
-
- f01_device_control.nosleep = true;
- f01_device_control.sleep_mode = SLEEP_MODE_NORMAL;
-
- retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f01_fd.ctrl_base_addr,
- f01_device_control.data,
- sizeof(f01_device_control.data));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write F01 device control\n",
- __func__);
- return retval;
- }
-
- return retval;
-}
-
-static int fwu_do_reflash(void)
-{
- int retval;
-
- retval = fwu_enter_flash_prog();
- if (retval < 0)
- return retval;
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Entered flash prog mode\n",
- __func__);
-
- retval = fwu_write_bootloader_id();
- if (retval < 0)
- return retval;
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Bootloader ID written\n",
- __func__);
-
- retval = fwu_write_f34_command(CMD_ERASE_ALL);
- if (retval < 0)
- return retval;
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Erase all command written\n",
- __func__);
-
- retval = fwu_wait_for_idle(ERASE_WAIT_MS);
- if (retval < 0)
- return retval;
-
- if (fwu->flash_control.status != 0x00) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Erase all command failed, status 0x%02X\n",
- __func__, retval);
- return -1;
- }
-
- if (fwu->firmware_data) {
- retval = fwu_write_firmware();
- if (retval < 0)
- return retval;
- pr_notice("%s: Firmware programmed\n", __func__);
- }
-
- if (fwu->config_data) {
- retval = fwu_write_configuration();
- if (retval < 0)
- return retval;
- pr_notice("%s: Configuration programmed\n", __func__);
- }
-
- return retval;
-}
-
-static int fwu_do_write_config(void)
-{
- int retval;
-
- retval = fwu_enter_flash_prog();
- if (retval < 0)
- return retval;
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Entered flash prog mode\n",
- __func__);
-
- if (fwu->config_area == PERM_CONFIG_AREA) {
- fwu->config_block_count = fwu->perm_config_block_count;
- goto write_config;
- }
-
- retval = fwu_write_bootloader_id();
- if (retval < 0)
- return retval;
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Bootloader ID written\n",
- __func__);
-
- switch (fwu->config_area) {
- case UI_CONFIG_AREA:
- retval = fwu_write_f34_command(CMD_ERASE_CONFIG);
- break;
- case BL_CONFIG_AREA:
- retval = fwu_write_f34_command(CMD_ERASE_BL_CONFIG);
- fwu->config_block_count = fwu->bl_config_block_count;
- break;
- case DISP_CONFIG_AREA:
- retval = fwu_write_f34_command(CMD_ERASE_DISP_CONFIG);
- fwu->config_block_count = fwu->disp_config_block_count;
- break;
- }
- if (retval < 0)
- return retval;
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Erase command written\n",
- __func__);
-
- retval = fwu_wait_for_idle(ERASE_WAIT_MS);
- if (retval < 0)
- return retval;
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Idle status detected\n",
- __func__);
-
-write_config:
- retval = fwu_write_configuration();
- if (retval < 0)
- return retval;
-
- pr_notice("%s: Config written\n", __func__);
-
- return retval;
-}
-
-static int fwu_start_write_config(void)
-{
- int retval;
- struct image_header header;
-
- switch (fwu->config_area) {
- case UI_CONFIG_AREA:
- break;
- case PERM_CONFIG_AREA:
- if (!fwu->flash_properties.has_perm_config)
- return -EINVAL;
- break;
- case BL_CONFIG_AREA:
- if (!fwu->flash_properties.has_bl_config)
- return -EINVAL;
- break;
- case DISP_CONFIG_AREA:
- if (!fwu->flash_properties.has_display_config)
- return -EINVAL;
- break;
- default:
- return -EINVAL;
- }
-
- if (fwu->ext_data_source)
- fwu->config_data = fwu->ext_data_source;
- else
- return -EINVAL;
-
- if (fwu->config_area == UI_CONFIG_AREA) {
- parse_header(&header, fwu->ext_data_source);
-
- if (header.config_size) {
- fwu->config_data = fwu->ext_data_source +
- FW_IMAGE_OFFSET +
- header.image_size;
- } else {
- return -EINVAL;
- }
- }
-
- pr_notice("%s: Start of write config process\n", __func__);
-
- retval = fwu_do_write_config();
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write config\n",
- __func__);
- }
-
- fwu->rmi4_data->reset_device(fwu->rmi4_data);
-
- pr_notice("%s: End of write config process\n", __func__);
-
- return retval;
-}
-
-static int fwu_do_read_config(void)
-{
- int retval;
- unsigned char block_offset[] = {0, 0};
- unsigned short block_num;
- unsigned short block_count;
- unsigned short index = 0;
-
- retval = fwu_enter_flash_prog();
- if (retval < 0)
- goto exit;
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Entered flash prog mode\n",
- __func__);
-
- switch (fwu->config_area) {
- case UI_CONFIG_AREA:
- block_count = fwu->config_block_count;
- break;
- case PERM_CONFIG_AREA:
- if (!fwu->flash_properties.has_perm_config) {
- retval = -EINVAL;
- goto exit;
- }
- block_count = fwu->perm_config_block_count;
- break;
- case BL_CONFIG_AREA:
- if (!fwu->flash_properties.has_bl_config) {
- retval = -EINVAL;
- goto exit;
- }
- block_count = fwu->bl_config_block_count;
- break;
- case DISP_CONFIG_AREA:
- if (!fwu->flash_properties.has_display_config) {
- retval = -EINVAL;
- goto exit;
- }
- block_count = fwu->disp_config_block_count;
- break;
- default:
- retval = -EINVAL;
- goto exit;
- }
-
- fwu->config_size = fwu->block_size * block_count;
-
- kfree(fwu->read_config_buf);
- fwu->read_config_buf = kzalloc(fwu->config_size, GFP_KERNEL);
-
- block_offset[1] |= (fwu->config_area << 5);
-
- retval = fwu->fn_ptr->write(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_NUMBER_OFFSET,
- block_offset,
- sizeof(block_offset));
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write to block number registers\n",
- __func__);
- goto exit;
- }
-
- for (block_num = 0; block_num < block_count; block_num++) {
- retval = fwu_write_f34_command(CMD_READ_CONFIG_BLOCK);
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to write read config command\n",
- __func__);
- goto exit;
- }
-
- retval = fwu_wait_for_idle(WRITE_WAIT_MS);
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to wait for idle status\n",
- __func__);
- goto exit;
- }
-
- retval = fwu->fn_ptr->read(fwu->rmi4_data,
- fwu->f34_fd.data_base_addr + BLOCK_DATA_OFFSET,
- &fwu->read_config_buf[index],
- fwu->block_size);
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to read block data (block %d)\n",
- __func__, block_num);
- goto exit;
- }
-
- index += fwu->block_size;
- }
-
-exit:
- fwu->rmi4_data->reset_device(fwu->rmi4_data);
-
- return retval;
-}
-
-static int fwu_start_reflash(void)
-{
- int retval;
- struct image_header header;
- const unsigned char *fw_image;
- const struct firmware *fw_entry = NULL;
- struct f01_device_status f01_device_status;
- enum flash_area flash_area;
-
- pr_notice("%s: Start of reflash process\n", __func__);
-
- if (fwu->ext_data_source)
- fw_image = fwu->ext_data_source;
- else {
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Requesting firmware image %s\n",
- __func__, FW_IMAGE_NAME);
-
- retval = request_firmware(&fw_entry, FW_IMAGE_NAME,
- &fwu->rmi4_data->i2c_client->dev);
- if (retval != 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Firmware image %s not available\n",
- __func__, FW_IMAGE_NAME);
- retval = -EINVAL;
- goto exit;
- }
-
- dev_dbg(&fwu->rmi4_data->i2c_client->dev,
- "%s: Firmware image size = %d\n",
- __func__, fw_entry->size);
-
- fw_image = fw_entry->data;
- }
-
- parse_header(&header, fw_image);
-
- if (header.image_size)
- fwu->firmware_data = fw_image + FW_IMAGE_OFFSET;
- if (header.config_size) {
- fwu->config_data = fw_image + FW_IMAGE_OFFSET +
- header.image_size;
- }
-
- if (fwu->ext_data_source)
- flash_area = UI_FIRMWARE;
- else
- flash_area = fwu_go_nogo();
-
- switch (flash_area) {
- case NONE:
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "%s: No need to do reflash.\n",
- __func__);
- goto exit;
- case UI_FIRMWARE:
- retval = fwu_do_reflash();
- break;
- case CONFIG_AREA:
- retval = fwu_do_write_config();
- break;
- default:
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Unknown flash area\n",
- __func__);
- goto exit;
- }
-
- if (retval < 0) {
- dev_err(&fwu->rmi4_data->i2c_client->dev,
- "%s: Failed to do reflash\n",
- __func__);
- }
-
- /* reset device */
- fwu_reset_device();
-
- /* check device status */
- retval = fwu_read_f01_device_status(&f01_device_status);
- if (retval < 0)
- goto exit;
-
- dev_info(&fwu->rmi4_data->i2c_client->dev, "Device is in %s mode\n",
- f01_device_status.flash_prog == 1 ? "bootloader" : "UI");
- if (f01_device_status.flash_prog)
- dev_info(&fwu->rmi4_data->i2c_client->dev, "Flash status %d\n",
- f01_device_status.status_code);
-
- if (f01_device_status.flash_prog) {
- dev_info(&fwu->rmi4_data->i2c_client->dev,
- "%s: Device is in flash prog mode 0x%02X\n",
- __func__, f01_device_status.status_code);
- retval = 0;
- goto exit;
- }
-
- if (fw_entry)
- release_firmware(fw_entry);
-
- pr_notice("%s: End of reflash process\n", __func__);
-exit:
- return retval;
-}
-
-int synaptics_fw_updater(unsigned char *fw_data)
-{
- int retval;
-
- if (!fwu)
- return -ENODEV;
-
- if (!fwu->initialized)
- return -ENODEV;
-
- fwu->ext_data_source = fw_data;
- fwu->config_area = UI_CONFIG_AREA;
-
- retval = fwu_start_reflash();
-
- return retval;
-}
-EXPORT_SYMBOL(synaptics_fw_updater);
-
-static ssize_t fwu_sysfs_show_image(struct file *data_file,
- struct kobject *kobj, struct bin_attribute *attributes,
- char *buf, loff_t pos, size_t count)
-{
- struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
-
- if (count < fwu->config_size) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Not enough space (%d bytes) in buffer\n",
- __func__, count);
- return -EINVAL;
- }
-
- memcpy(buf, fwu->read_config_buf, fwu->config_size);
-
- return fwu->config_size;
-}
-
-static ssize_t fwu_sysfs_store_image(struct file *data_file,
- struct kobject *kobj, struct bin_attribute *attributes,
- char *buf, loff_t pos, size_t count)
-{
- memcpy((void *)(&fwu->ext_data_source[fwu->data_pos]),
- (const void *)buf,
- count);
-
- fwu->data_pos += count;
-
- return count;
-}
-
-static ssize_t fwu_sysfs_do_reflash_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int retval;
- unsigned int input;
- struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
-
- if (sscanf(buf, "%u", &input) != 1) {
- retval = -EINVAL;
- goto exit;
- }
-
- if (input != 1) {
- retval = -EINVAL;
- goto exit;
- }
-
- retval = synaptics_fw_updater(fwu->ext_data_source);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to do reflash\n",
- __func__);
- goto exit;
- }
-
- retval = count;
-
-exit:
- kfree(fwu->ext_data_source);
- fwu->ext_data_source = NULL;
- return retval;
-}
-
-static ssize_t fwu_sysfs_write_config_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int retval;
- unsigned int input;
- struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
-
- if (sscanf(buf, "%u", &input) != 1) {
- retval = -EINVAL;
- goto exit;
- }
-
- if (input != 1) {
- retval = -EINVAL;
- goto exit;
- }
-
- retval = fwu_start_write_config();
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to write config\n",
- __func__);
- goto exit;
- }
-
- retval = count;
-
-exit:
- kfree(fwu->ext_data_source);
- fwu->ext_data_source = NULL;
- return retval;
-}
-
-static ssize_t fwu_sysfs_read_config_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int retval;
- unsigned int input;
- struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
-
- if (sscanf(buf, "%u", &input) != 1)
- return -EINVAL;
-
- if (input != 1)
- return -EINVAL;
-
- retval = fwu_do_read_config();
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to read config\n",
- __func__);
- return retval;
- }
-
- return count;
-}
-
-static ssize_t fwu_sysfs_config_area_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int retval;
- unsigned long config_area;
-
- retval = sstrtoul(buf, 10, &config_area);
- if (retval)
- return retval;
-
- fwu->config_area = config_area;
-
- return count;
-}
-
-static ssize_t fwu_sysfs_image_size_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int retval;
- unsigned long size;
- struct synaptics_rmi4_data *rmi4_data = fwu->rmi4_data;
-
- retval = sstrtoul(buf, 10, &size);
- if (retval)
- return retval;
-
- fwu->image_size = size;
- fwu->data_pos = 0;
-
- kfree(fwu->ext_data_source);
- fwu->ext_data_source = kzalloc(fwu->image_size, GFP_KERNEL);
- if (!fwu->ext_data_source) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc mem for image data\n",
- __func__);
- return -ENOMEM;
- }
-
- return count;
-}
-
-static ssize_t fwu_sysfs_block_size_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%u\n", fwu->block_size);
-}
-
-static ssize_t fwu_sysfs_firmware_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%u\n", fwu->fw_block_count);
-}
-
-static ssize_t fwu_sysfs_configuration_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%u\n", fwu->config_block_count);
-}
-
-static ssize_t fwu_sysfs_perm_config_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%u\n", fwu->perm_config_block_count);
-}
-
-static ssize_t fwu_sysfs_bl_config_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%u\n", fwu->bl_config_block_count);
-}
-
-static ssize_t fwu_sysfs_disp_config_block_count_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return snprintf(buf, PAGE_SIZE, "%u\n", fwu->disp_config_block_count);
-}
-
-static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data,
- unsigned char intr_mask)
-{
- if (fwu->intr_mask & intr_mask)
- fwu_read_f34_flash_status();
-
- return;
-}
-
-static void synaptics_rmi4_fwu_work(struct work_struct *work)
-{
- fwu_start_reflash();
-}
-
-static int synaptics_rmi4_fwu_init(struct synaptics_rmi4_data *rmi4_data)
-{
- int retval;
- unsigned char attr_count;
- struct pdt_properties pdt_props;
-
- fwu = kzalloc(sizeof(*fwu), GFP_KERNEL);
- if (!fwu) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc mem for fwu\n",
- __func__);
- goto exit;
- }
-
- fwu->fn_ptr = kzalloc(sizeof(*(fwu->fn_ptr)), GFP_KERNEL);
- if (!fwu->fn_ptr) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc mem for fn_ptr\n",
- __func__);
- retval = -ENOMEM;
- goto exit_free_fwu;
- }
-
- fwu->rmi4_data = rmi4_data;
- fwu->fn_ptr->read = rmi4_data->i2c_read;
- fwu->fn_ptr->write = rmi4_data->i2c_write;
- fwu->fn_ptr->enable = rmi4_data->irq_enable;
-
- retval = fwu->fn_ptr->read(rmi4_data,
- PDT_PROPS,
- pdt_props.data,
- sizeof(pdt_props.data));
- if (retval < 0) {
- dev_dbg(&rmi4_data->i2c_client->dev,
- "%s: Failed to read PDT properties, assuming 0x00\n",
- __func__);
- } else if (pdt_props.has_bsr) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Reflash for LTS not currently supported\n",
- __func__);
- goto exit_free_mem;
- }
-
- retval = fwu_scan_pdt();
- if (retval < 0)
- goto exit_free_mem;
-
- fwu->productinfo1 = rmi4_data->rmi4_mod_info.product_info[0];
- fwu->productinfo2 = rmi4_data->rmi4_mod_info.product_info[1];
-
- memcpy(fwu->product_id, rmi4_data->rmi4_mod_info.product_id_string,
- SYNAPTICS_RMI4_PRODUCT_ID_SIZE);
- fwu->product_id[SYNAPTICS_RMI4_PRODUCT_ID_SIZE] = 0;
-
- dev_dbg(&rmi4_data->i2c_client->dev,
- "%s: F01 product info: 0x%04x 0x%04x\n",
- __func__, fwu->productinfo1, fwu->productinfo2);
- dev_dbg(&rmi4_data->i2c_client->dev,
- "%s: F01 product ID: %s\n",
- __func__, fwu->product_id);
-
- retval = fwu_read_f34_queries();
- if (retval < 0)
- goto exit_free_mem;
-
- fwu->initialized = true;
- fwu->force_update = FORCE_UPDATE;
-
- retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj,
- &dev_attr_data);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to create sysfs bin file\n",
- __func__);
- goto exit_free_mem;
- }
-
- for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
- retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj,
- &attrs[attr_count].attr);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to create sysfs attributes\n",
- __func__);
- retval = -ENODEV;
- goto exit_remove_attrs;
- }
- }
-
-#ifdef INSIDE_FIRMWARE_UPDATE
- fwu->fwu_workqueue = create_singlethread_workqueue("fwu_workqueue");
- INIT_DELAYED_WORK(&fwu->fwu_work, synaptics_rmi4_fwu_work);
- queue_delayed_work(fwu->fwu_workqueue,
- &fwu->fwu_work,
- msecs_to_jiffies(1000));
-#endif
- return 0;
-
-exit_remove_attrs:
-for (attr_count--; attr_count >= 0; attr_count--) {
- sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
- &attrs[attr_count].attr);
-}
-
-sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
-
-exit_free_mem:
- kfree(fwu->fn_ptr);
-
-exit_free_fwu:
- kfree(fwu);
-
-exit:
- return 0;
-}
-
-static void synaptics_rmi4_fwu_remove(struct synaptics_rmi4_data *rmi4_data)
-{
- unsigned char attr_count;
-
- sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
-
- for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
- sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
- &attrs[attr_count].attr);
- }
-
- kfree(fwu->fn_ptr);
- kfree(fwu);
-
- complete(&remove_complete);
-
- return;
-}
-
-static int __init rmi4_fw_update_module_init(void)
-{
- synaptics_rmi4_new_function(RMI_FW_UPDATER, true,
- synaptics_rmi4_fwu_init,
- synaptics_rmi4_fwu_remove,
- synaptics_rmi4_fwu_attn);
- return 0;
-}
-
-static void __exit rmi4_fw_update_module_exit(void)
-{
- init_completion(&remove_complete);
- synaptics_rmi4_new_function(RMI_FW_UPDATER, false,
- synaptics_rmi4_fwu_init,
- synaptics_rmi4_fwu_remove,
- synaptics_rmi4_fwu_attn);
- wait_for_completion(&remove_complete);
- return;
-}
-
-module_init(rmi4_fw_update_module_init);
-module_exit(rmi4_fw_update_module_exit);
-
-MODULE_AUTHOR("Synaptics, Inc.");
-MODULE_DESCRIPTION("RMI4 FW Update Module");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(SYNAPTICS_RMI4_DRIVER_VERSION);
diff --git a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c
deleted file mode 100644
index 76f9155bd49c..000000000000
--- a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ /dev/null
@@ -1,2162 +0,0 @@
-/*
- * Synaptics RMI4 touchscreen driver
- *
- * Copyright (C) 2012 Synaptics Incorporated
- *
- * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
- * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-#include <linux/regulator/consumer.h>
-#include <linux/input/synaptics_dsx.h>
-#include "synaptics_i2c_rmi4.h"
-#ifdef KERNEL_ABOVE_2_6_38
-#include <linux/input/mt.h>
-#endif
-
-#define DRIVER_NAME "synaptics_rmi4_i2c"
-#define INPUT_PHYS_NAME "synaptics_rmi4_i2c/input0"
-
-#ifdef KERNEL_ABOVE_2_6_38
-#define TYPE_B_PROTOCOL
-#endif
-
-#define NO_0D_WHILE_2D
-/*
-#define REPORT_2D_Z
-*/
-#define REPORT_2D_W
-
-#define RPT_TYPE (1 << 0)
-#define RPT_X_LSB (1 << 1)
-#define RPT_X_MSB (1 << 2)
-#define RPT_Y_LSB (1 << 3)
-#define RPT_Y_MSB (1 << 4)
-#define RPT_Z (1 << 5)
-#define RPT_WX (1 << 6)
-#define RPT_WY (1 << 7)
-#define RPT_DEFAULT (RPT_TYPE | RPT_X_LSB | RPT_X_MSB | RPT_Y_LSB | RPT_Y_MSB)
-
-#define EXP_FN_DET_INTERVAL 1000 /* ms */
-#define POLLING_PERIOD 1 /* ms */
-#define SYN_I2C_RETRY_TIMES 10
-#define MAX_ABS_MT_TOUCH_MAJOR 15
-
-#define F01_STD_QUERY_LEN 21
-#define F01_BUID_ID_OFFSET 18
-#define F11_STD_QUERY_LEN 9
-#define F11_STD_CTRL_LEN 10
-#define F11_STD_DATA_LEN 12
-
-#define NORMAL_OPERATION (0 << 0)
-#define SENSOR_SLEEP (1 << 0)
-#define NO_SLEEP_OFF (0 << 3)
-#define NO_SLEEP_ON (1 << 3)
-
-static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
- unsigned short addr, unsigned char *data,
- unsigned short length);
-
-static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data,
- unsigned short addr, unsigned char *data,
- unsigned short length);
-
-static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data);
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static ssize_t synaptics_rmi4_full_pm_cycle_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-
-static ssize_t synaptics_rmi4_full_pm_cycle_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-static void synaptics_rmi4_early_suspend(struct early_suspend *h);
-
-static void synaptics_rmi4_late_resume(struct early_suspend *h);
-
-static int synaptics_rmi4_suspend(struct device *dev);
-
-static int synaptics_rmi4_resume(struct device *dev);
-#endif
-
-static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-
-static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-
-static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-
-static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-
-static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-struct synaptics_rmi4_f01_device_status {
- union {
- struct {
- unsigned char status_code:4;
- unsigned char reserved:2;
- unsigned char flash_prog:1;
- unsigned char unconfigured:1;
- } __packed;
- unsigned char data[1];
- };
-};
-
-struct synaptics_rmi4_f1a_query {
- union {
- struct {
- unsigned char max_button_count:3;
- unsigned char reserved:5;
- unsigned char has_general_control:1;
- unsigned char has_interrupt_enable:1;
- unsigned char has_multibutton_select:1;
- unsigned char has_tx_rx_map:1;
- unsigned char has_perbutton_threshold:1;
- unsigned char has_release_threshold:1;
- unsigned char has_strongestbtn_hysteresis:1;
- unsigned char has_filter_strength:1;
- } __packed;
- unsigned char data[2];
- };
-};
-
-struct synaptics_rmi4_f1a_control_0 {
- union {
- struct {
- unsigned char multibutton_report:2;
- unsigned char filter_mode:2;
- unsigned char reserved:4;
- } __packed;
- unsigned char data[1];
- };
-};
-
-struct synaptics_rmi4_f1a_control_3_4 {
- unsigned char transmitterbutton;
- unsigned char receiverbutton;
-};
-
-struct synaptics_rmi4_f1a_control {
- struct synaptics_rmi4_f1a_control_0 general_control;
- unsigned char *button_int_enable;
- unsigned char *multi_button;
- struct synaptics_rmi4_f1a_control_3_4 *electrode_map;
- unsigned char *button_threshold;
- unsigned char button_release_threshold;
- unsigned char strongest_button_hysteresis;
- unsigned char filter_strength;
-};
-
-struct synaptics_rmi4_f1a_handle {
- int button_bitmask_size;
- unsigned char button_count;
- unsigned char valid_button_count;
- unsigned char *button_data_buffer;
- unsigned char *button_map;
- struct synaptics_rmi4_f1a_query button_query;
- struct synaptics_rmi4_f1a_control button_control;
-};
-
-struct synaptics_rmi4_exp_fn {
- enum exp_fn fn_type;
- bool inserted;
- int (*func_init)(struct synaptics_rmi4_data *rmi4_data);
- void (*func_remove)(struct synaptics_rmi4_data *rmi4_data);
- void (*func_attn)(struct synaptics_rmi4_data *rmi4_data,
- unsigned char intr_mask);
- struct list_head link;
-};
-
-static struct device_attribute attrs[] = {
-#ifdef CONFIG_HAS_EARLYSUSPEND
- __ATTR(full_pm_cycle, (S_IRUGO | S_IWUGO),
- synaptics_rmi4_full_pm_cycle_show,
- synaptics_rmi4_full_pm_cycle_store),
-#endif
- __ATTR(reset, S_IWUGO,
- synaptics_rmi4_show_error,
- synaptics_rmi4_f01_reset_store),
- __ATTR(productinfo, S_IRUGO,
- synaptics_rmi4_f01_productinfo_show,
- synaptics_rmi4_store_error),
- __ATTR(buildid, S_IRUGO,
- synaptics_rmi4_f01_buildid_show,
- synaptics_rmi4_store_error),
- __ATTR(flashprog, S_IRUGO,
- synaptics_rmi4_f01_flashprog_show,
- synaptics_rmi4_store_error),
- __ATTR(0dbutton, (S_IRUGO | S_IWUGO),
- synaptics_rmi4_0dbutton_show,
- synaptics_rmi4_0dbutton_store),
-};
-
-static bool exp_fn_inited;
-static struct mutex exp_fn_list_mutex;
-static struct list_head exp_fn_list;
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-static ssize_t synaptics_rmi4_full_pm_cycle_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
-
- return snprintf(buf, PAGE_SIZE, "%u\n",
- rmi4_data->full_pm_cycle);
-}
-
-static ssize_t synaptics_rmi4_full_pm_cycle_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- unsigned int input;
- struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
-
- if (sscanf(buf, "%u", &input) != 1)
- return -EINVAL;
-
- rmi4_data->full_pm_cycle = input > 0 ? 1 : 0;
-
- return count;
-}
-#endif
-
-static ssize_t synaptics_rmi4_f01_reset_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int retval;
- unsigned int reset;
- struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
-
- if (sscanf(buf, "%u", &reset) != 1)
- return -EINVAL;
-
- if (reset != 1)
- return -EINVAL;
-
- retval = synaptics_rmi4_reset_device(rmi4_data);
- if (retval < 0) {
- dev_err(dev,
- "%s: Failed to issue reset command, error = %d\n",
- __func__, retval);
- return retval;
- }
-
- return count;
-}
-
-static ssize_t synaptics_rmi4_f01_productinfo_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
-
- return snprintf(buf, PAGE_SIZE, "0x%02x 0x%02x\n",
- (rmi4_data->rmi4_mod_info.product_info[0]),
- (rmi4_data->rmi4_mod_info.product_info[1]));
-}
-
-static ssize_t synaptics_rmi4_f01_buildid_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- unsigned int build_id;
- struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
- struct synaptics_rmi4_device_info *rmi;
-
- rmi = &(rmi4_data->rmi4_mod_info);
-
- build_id = (unsigned int)rmi->build_id[0] +
- (unsigned int)rmi->build_id[1] * 0x100 +
- (unsigned int)rmi->build_id[2] * 0x10000;
-
- return snprintf(buf, PAGE_SIZE, "%u\n",
- build_id);
-}
-
-static ssize_t synaptics_rmi4_f01_flashprog_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- int retval;
- struct synaptics_rmi4_f01_device_status device_status;
- struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi4_data->f01_data_base_addr,
- device_status.data,
- sizeof(device_status.data));
- if (retval < 0) {
- dev_err(dev,
- "%s: Failed to read device status, error = %d\n",
- __func__, retval);
- return retval;
- }
-
- return snprintf(buf, PAGE_SIZE, "%u\n",
- device_status.flash_prog);
-}
-
-static ssize_t synaptics_rmi4_0dbutton_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
-
- return snprintf(buf, PAGE_SIZE, "%u\n",
- rmi4_data->button_0d_enabled);
-}
-
-static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int retval;
- unsigned int input;
- unsigned char ii;
- unsigned char intr_enable;
- struct synaptics_rmi4_fn *fhandler;
- struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
- struct synaptics_rmi4_device_info *rmi;
-
- rmi = &(rmi4_data->rmi4_mod_info);
-
- if (sscanf(buf, "%u", &input) != 1)
- return -EINVAL;
-
- input = input > 0 ? 1 : 0;
-
- if (rmi4_data->button_0d_enabled == input)
- return count;
-
- if (!list_empty(&rmi->support_fn_list)) {
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
- if (fhandler->fn_number == SYNAPTICS_RMI4_F1A) {
- ii = fhandler->intr_reg_num;
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi4_data->f01_ctrl_base_addr +
- 1 + ii,
- &intr_enable,
- sizeof(intr_enable));
- if (retval < 0)
- return retval;
-
- if (input == 1)
- intr_enable |= fhandler->intr_mask;
- else
- intr_enable &= ~fhandler->intr_mask;
-
- retval = synaptics_rmi4_i2c_write(rmi4_data,
- rmi4_data->f01_ctrl_base_addr +
- 1 + ii,
- &intr_enable,
- sizeof(intr_enable));
- if (retval < 0)
- return retval;
- }
- }
- }
-
- rmi4_data->button_0d_enabled = input;
-
- return count;
-}
-
- /**
- * synaptics_rmi4_set_page()
- *
- * Called by synaptics_rmi4_i2c_read() and synaptics_rmi4_i2c_write().
- *
- * This function writes to the page select register to switch to the
- * assigned page.
- */
-static int synaptics_rmi4_set_page(struct synaptics_rmi4_data *rmi4_data,
- unsigned int address)
-{
- int retval = 0;
- unsigned char retry;
- unsigned char buf[PAGE_SELECT_LEN];
- unsigned char page;
- struct i2c_client *i2c = rmi4_data->i2c_client;
-
- page = ((address >> 8) & MASK_8BIT);
- if (page != rmi4_data->current_page) {
- buf[0] = MASK_8BIT;
- buf[1] = page;
- for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) {
- retval = i2c_master_send(i2c, buf, PAGE_SELECT_LEN);
- if (retval != PAGE_SELECT_LEN) {
- dev_err(&i2c->dev,
- "%s: I2C retry %d\n",
- __func__, retry + 1);
- msleep(20);
- } else {
- rmi4_data->current_page = page;
- break;
- }
- }
- } else
- return PAGE_SELECT_LEN;
- return (retval == PAGE_SELECT_LEN) ? retval : -EIO;
-}
-
- /**
- * synaptics_rmi4_i2c_read()
- *
- * Called by various functions in this driver, and also exported to
- * other expansion Function modules such as rmi_dev.
- *
- * This function reads data of an arbitrary length from the sensor,
- * starting from an assigned register address of the sensor, via I2C
- * with a retry mechanism.
- */
-static int synaptics_rmi4_i2c_read(struct synaptics_rmi4_data *rmi4_data,
- unsigned short addr, unsigned char *data, unsigned short length)
-{
- int retval;
- unsigned char retry;
- unsigned char buf;
- struct i2c_msg msg[] = {
- {
- .addr = rmi4_data->i2c_client->addr,
- .flags = 0,
- .len = 1,
- .buf = &buf,
- },
- {
- .addr = rmi4_data->i2c_client->addr,
- .flags = I2C_M_RD,
- .len = length,
- .buf = data,
- },
- };
-
- buf = addr & MASK_8BIT;
-
- mutex_lock(&(rmi4_data->rmi4_io_ctrl_mutex));
-
- retval = synaptics_rmi4_set_page(rmi4_data, addr);
- if (retval != PAGE_SELECT_LEN)
- goto exit;
-
- for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) {
- if (i2c_transfer(rmi4_data->i2c_client->adapter, msg, 2) == 2) {
- retval = length;
- break;
- }
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: I2C retry %d\n",
- __func__, retry + 1);
- msleep(20);
- }
-
- if (retry == SYN_I2C_RETRY_TIMES) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: I2C read over retry limit\n",
- __func__);
- retval = -EIO;
- }
-
-exit:
- mutex_unlock(&(rmi4_data->rmi4_io_ctrl_mutex));
-
- return retval;
-}
-
- /**
- * synaptics_rmi4_i2c_write()
- *
- * Called by various functions in this driver, and also exported to
- * other expansion Function modules such as rmi_dev.
- *
- * This function writes data of an arbitrary length to the sensor,
- * starting from an assigned register address of the sensor, via I2C with
- * a retry mechanism.
- */
-static int synaptics_rmi4_i2c_write(struct synaptics_rmi4_data *rmi4_data,
- unsigned short addr, unsigned char *data, unsigned short length)
-{
- int retval;
- unsigned char retry;
- unsigned char buf[length + 1];
- struct i2c_msg msg[] = {
- {
- .addr = rmi4_data->i2c_client->addr,
- .flags = 0,
- .len = length + 1,
- .buf = buf,
- }
- };
-
- mutex_lock(&(rmi4_data->rmi4_io_ctrl_mutex));
-
- retval = synaptics_rmi4_set_page(rmi4_data, addr);
- if (retval != PAGE_SELECT_LEN)
- goto exit;
-
- buf[0] = addr & MASK_8BIT;
- memcpy(&buf[1], &data[0], length);
-
- for (retry = 0; retry < SYN_I2C_RETRY_TIMES; retry++) {
- if (i2c_transfer(rmi4_data->i2c_client->adapter, msg, 1) == 1) {
- retval = length;
- break;
- }
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: I2C retry %d\n",
- __func__, retry + 1);
- msleep(20);
- }
-
- if (retry == SYN_I2C_RETRY_TIMES) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: I2C write over retry limit\n",
- __func__);
- retval = -EIO;
- }
-
-exit:
- mutex_unlock(&(rmi4_data->rmi4_io_ctrl_mutex));
-
- return retval;
-}
-
- /**
- * synaptics_rmi4_f11_abs_report()
- *
- * Called by synaptics_rmi4_report_touch() when valid Function $11
- * finger data has been detected.
- *
- * This function reads the Function $11 data registers, determines the
- * status of each finger supported by the Function, processes any
- * necessary coordinate manipulation, reports the finger data to
- * the input subsystem, and returns the number of fingers detected.
- */
-static int synaptics_rmi4_f11_abs_report(struct synaptics_rmi4_data *rmi4_data,
- struct synaptics_rmi4_fn *fhandler)
-{
- int retval;
- unsigned char touch_count = 0; /* number of touch points */
- unsigned char reg_index;
- unsigned char finger;
- unsigned char fingers_supported;
- unsigned char num_of_finger_status_regs;
- unsigned char finger_shift;
- unsigned char finger_status;
- unsigned char data_reg_blk_size;
- unsigned char finger_status_reg[3];
- unsigned char data[F11_STD_DATA_LEN];
- unsigned short data_addr;
- unsigned short data_offset;
- int x;
- int y;
- int wx;
- int wy;
-
- /*
- * The number of finger status registers is determined by the
- * maximum number of fingers supported - 2 bits per finger. So
- * the number of finger status registers to read is:
- * register_count = ceil(max_num_of_fingers / 4)
- */
- fingers_supported = fhandler->num_of_data_points;
- num_of_finger_status_regs = (fingers_supported + 3) / 4;
- data_addr = fhandler->full_addr.data_base;
- data_reg_blk_size = fhandler->size_of_data_register_block;
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- data_addr,
- finger_status_reg,
- num_of_finger_status_regs);
- if (retval < 0)
- return 0;
-
- for (finger = 0; finger < fingers_supported; finger++) {
- reg_index = finger / 4;
- finger_shift = (finger % 4) * 2;
- finger_status = (finger_status_reg[reg_index] >> finger_shift)
- & MASK_2BIT;
-
- /*
- * Each 2-bit finger status field represents the following:
- * 00 = finger not present
- * 01 = finger present and data accurate
- * 10 = finger present but data may be inaccurate
- * 11 = reserved
- */
-#ifdef TYPE_B_PROTOCOL
- input_mt_slot(rmi4_data->input_dev, finger);
- input_mt_report_slot_state(rmi4_data->input_dev,
- MT_TOOL_FINGER, finger_status != 0);
-#endif
-
- if (finger_status) {
- data_offset = data_addr +
- num_of_finger_status_regs +
- (finger * data_reg_blk_size);
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- data_offset,
- data,
- data_reg_blk_size);
- if (retval < 0)
- return 0;
-
- x = (data[0] << 4) | (data[2] & MASK_4BIT);
- y = (data[1] << 4) | ((data[2] >> 4) & MASK_4BIT);
- wx = (data[3] & MASK_4BIT);
- wy = (data[3] >> 4) & MASK_4BIT;
-
- if (rmi4_data->board->x_flip)
- x = rmi4_data->sensor_max_x - x;
- if (rmi4_data->board->y_flip)
- y = rmi4_data->sensor_max_y - y;
-
- dev_dbg(&rmi4_data->i2c_client->dev,
- "%s: Finger %d:\n"
- "status = 0x%02x\n"
- "x = %d\n"
- "y = %d\n"
- "wx = %d\n"
- "wy = %d\n",
- __func__, finger,
- finger_status,
- x, y, wx, wy);
-
- input_report_key(rmi4_data->input_dev,
- BTN_TOUCH, 1);
- input_report_key(rmi4_data->input_dev,
- BTN_TOOL_FINGER, 1);
- input_report_abs(rmi4_data->input_dev,
- ABS_MT_POSITION_X, x);
- input_report_abs(rmi4_data->input_dev,
- ABS_MT_POSITION_Y, y);
-
-#ifdef REPORT_2D_W
- input_report_abs(rmi4_data->input_dev,
- ABS_MT_TOUCH_MAJOR, max(wx, wy));
- input_report_abs(rmi4_data->input_dev,
- ABS_MT_TOUCH_MINOR, min(wx, wy));
-#endif
-#ifndef TYPE_B_PROTOCOL
- input_mt_sync(rmi4_data->input_dev);
-#endif
- touch_count++;
- }
- }
-
-#ifndef TYPE_B_PROTOCOL
- if (!touch_count)
- input_mt_sync(rmi4_data->input_dev);
-#else
- /* sync after groups of events */
- #ifdef KERNEL_ABOVE_3_7
- input_mt_sync_frame(rmi4_data->input_dev);
- #endif
-#endif
-
- input_sync(rmi4_data->input_dev);
-
- return touch_count;
-}
-
-static void synaptics_rmi4_f1a_report(struct synaptics_rmi4_data *rmi4_data,
- struct synaptics_rmi4_fn *fhandler)
-{
- int retval;
- unsigned char button;
- unsigned char index;
- unsigned char shift;
- unsigned char status;
- unsigned char *data;
- unsigned short data_addr = fhandler->full_addr.data_base;
- struct synaptics_rmi4_f1a_handle *f1a = fhandler->data;
- static unsigned char do_once = 1;
- static bool current_status[MAX_NUMBER_OF_BUTTONS];
-#ifdef NO_0D_WHILE_2D
- static bool before_2d_status[MAX_NUMBER_OF_BUTTONS];
- static bool while_2d_status[MAX_NUMBER_OF_BUTTONS];
-#endif
-
- if (do_once) {
- memset(current_status, 0, sizeof(current_status));
-#ifdef NO_0D_WHILE_2D
- memset(before_2d_status, 0, sizeof(before_2d_status));
- memset(while_2d_status, 0, sizeof(while_2d_status));
-#endif
- do_once = 0;
- }
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- data_addr,
- f1a->button_data_buffer,
- f1a->button_bitmask_size);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to read button data registers\n",
- __func__);
- return;
- }
-
- data = f1a->button_data_buffer;
-
- for (button = 0; button < f1a->valid_button_count; button++) {
- index = button / 8;
- shift = button % 8;
- status = ((data[index] >> shift) & MASK_1BIT);
-
- if (current_status[button] == status)
- continue;
- else
- current_status[button] = status;
-
- dev_dbg(&rmi4_data->i2c_client->dev,
- "%s: Button %d (code %d) ->%d\n",
- __func__, button,
- f1a->button_map[button],
- status);
-#ifdef NO_0D_WHILE_2D
- if (rmi4_data->fingers_on_2d == false) {
- if (status == 1) {
- before_2d_status[button] = 1;
- } else {
- if (while_2d_status[button] == 1) {
- while_2d_status[button] = 0;
- continue;
- } else {
- before_2d_status[button] = 0;
- }
- }
- input_report_key(rmi4_data->input_dev,
- f1a->button_map[button],
- status);
- } else {
- if (before_2d_status[button] == 1) {
- before_2d_status[button] = 0;
- input_report_key(rmi4_data->input_dev,
- f1a->button_map[button],
- status);
- } else {
- if (status == 1)
- while_2d_status[button] = 1;
- else
- while_2d_status[button] = 0;
- }
- }
-#else
- input_report_key(rmi4_data->input_dev,
- f1a->button_map[button],
- status);
-#endif
- }
-
- input_sync(rmi4_data->input_dev);
-
- return;
-}
-
- /**
- * synaptics_rmi4_report_touch()
- *
- * Called by synaptics_rmi4_sensor_report().
- *
- * This function calls the appropriate finger data reporting function
- * based on the function handler it receives and returns the number of
- * fingers detected.
- */
-static void synaptics_rmi4_report_touch(struct synaptics_rmi4_data *rmi4_data,
- struct synaptics_rmi4_fn *fhandler,
- unsigned char *touch_count)
-{
- unsigned char touch_count_2d;
-
- dev_dbg(&rmi4_data->i2c_client->dev,
- "%s: Function %02x reporting\n",
- __func__, fhandler->fn_number);
-
- switch (fhandler->fn_number) {
- case SYNAPTICS_RMI4_F11:
- touch_count_2d = synaptics_rmi4_f11_abs_report(rmi4_data,
- fhandler);
-
- *touch_count += touch_count_2d;
-
- if (touch_count_2d)
- rmi4_data->fingers_on_2d = true;
- else
- rmi4_data->fingers_on_2d = false;
- break;
-
- case SYNAPTICS_RMI4_F1A:
- synaptics_rmi4_f1a_report(rmi4_data, fhandler);
- break;
-
- default:
- break;
- }
-
- return;
-}
-
- /**
- * synaptics_rmi4_sensor_report()
- *
- * Called by synaptics_rmi4_irq().
- *
- * This function determines the interrupt source(s) from the sensor
- * and calls synaptics_rmi4_report_touch() with the appropriate
- * function handler for each function with valid data inputs.
- */
-static int synaptics_rmi4_sensor_report(struct synaptics_rmi4_data *rmi4_data)
-{
- int retval;
- unsigned char touch_count = 0;
- unsigned char intr[MAX_INTR_REGISTERS];
- struct synaptics_rmi4_fn *fhandler;
- struct synaptics_rmi4_exp_fn *exp_fhandler;
- struct synaptics_rmi4_device_info *rmi;
-
- rmi = &(rmi4_data->rmi4_mod_info);
-
- /*
- * Get interrupt status information from F01 Data1 register to
- * determine the source(s) that are flagging the interrupt.
- */
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi4_data->f01_data_base_addr + 1,
- intr,
- rmi4_data->num_of_intr_regs);
- if (retval < 0)
- return retval;
-
- /*
- * Traverse the function handler list and service the source(s)
- * of the interrupt accordingly.
- */
- if (!list_empty(&rmi->support_fn_list)) {
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
- if (fhandler->num_of_data_sources) {
- if (fhandler->intr_mask &
- intr[fhandler->intr_reg_num]) {
- synaptics_rmi4_report_touch(rmi4_data,
- fhandler, &touch_count);
- }
- }
- }
- }
-
- mutex_lock(&exp_fn_list_mutex);
- if (!list_empty(&exp_fn_list)) {
- list_for_each_entry(exp_fhandler, &exp_fn_list, link) {
- if (exp_fhandler->inserted &&
- (exp_fhandler->func_attn != NULL))
- exp_fhandler->func_attn(rmi4_data, intr[0]);
- }
- }
- mutex_unlock(&exp_fn_list_mutex);
-
- return touch_count;
-}
-
- /**
- * synaptics_rmi4_irq()
- *
- * Called by the kernel when an interrupt occurs (when the sensor
- * asserts the attention irq).
- *
- * This function is the ISR thread and handles the acquisition
- * and the reporting of finger data when the presence of fingers
- * is detected.
- */
-static irqreturn_t synaptics_rmi4_irq(int irq, void *data)
-{
- struct synaptics_rmi4_data *rmi4_data = data;
-
- synaptics_rmi4_sensor_report(rmi4_data);
-
- return IRQ_HANDLED;
-}
-
- /**
- * synaptics_rmi4_irq_enable()
- *
- * Called by synaptics_rmi4_probe() and the power management functions
- * in this driver and also exported to other expansion Function modules
- * such as rmi_dev.
- *
- * This function handles the enabling and disabling of the attention
- * irq including the setting up of the ISR thread.
- */
-static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data,
- bool enable)
-{
- int retval = 0;
- unsigned char intr_status;
- const struct synaptics_rmi4_platform_data *platform_data =
- rmi4_data->i2c_client->dev.platform_data;
-
- if (enable) {
- if (rmi4_data->irq_enabled)
- return retval;
-
- /* Clear interrupts first */
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi4_data->f01_data_base_addr + 1,
- &intr_status,
- rmi4_data->num_of_intr_regs);
- if (retval < 0)
- return retval;
-
- retval = request_threaded_irq(rmi4_data->irq, NULL,
- synaptics_rmi4_irq, platform_data->irq_flags,
- DRIVER_NAME, rmi4_data);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to create irq thread\n",
- __func__);
- return retval;
- }
-
- rmi4_data->irq_enabled = true;
- } else {
- if (rmi4_data->irq_enabled) {
- disable_irq(rmi4_data->irq);
- free_irq(rmi4_data->irq, rmi4_data);
- rmi4_data->irq_enabled = false;
- }
- }
-
- return retval;
-}
-
- /**
- * synaptics_rmi4_f11_init()
- *
- * Called by synaptics_rmi4_query_device().
- *
- * This funtion parses information from the Function 11 registers
- * and determines the number of fingers supported, x and y data ranges,
- * offset to the associated interrupt status register, interrupt bit
- * mask, and gathers finger data acquisition capabilities from the query
- * registers.
- */
-static int synaptics_rmi4_f11_init(struct synaptics_rmi4_data *rmi4_data,
- struct synaptics_rmi4_fn *fhandler,
- struct synaptics_rmi4_fn_desc *fd,
- unsigned int intr_count)
-{
- int retval;
- unsigned char ii;
- unsigned char intr_offset;
- unsigned char abs_data_size;
- unsigned char abs_data_blk_size;
- unsigned char query[F11_STD_QUERY_LEN];
- unsigned char control[F11_STD_CTRL_LEN];
-
- fhandler->fn_number = fd->fn_number;
- fhandler->num_of_data_sources = fd->intr_src_count;
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- fhandler->full_addr.query_base,
- query,
- sizeof(query));
- if (retval < 0)
- return retval;
-
- /* Maximum number of fingers supported */
- if ((query[1] & MASK_3BIT) <= 4)
- fhandler->num_of_data_points = (query[1] & MASK_3BIT) + 1;
- else if ((query[1] & MASK_3BIT) == 5)
- fhandler->num_of_data_points = 10;
-
- rmi4_data->num_of_fingers = fhandler->num_of_data_points;
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- fhandler->full_addr.ctrl_base,
- control,
- sizeof(control));
- if (retval < 0)
- return retval;
-
- /* Maximum x and y */
- rmi4_data->sensor_max_x = ((control[6] & MASK_8BIT) << 0) |
- ((control[7] & MASK_4BIT) << 8);
- rmi4_data->sensor_max_y = ((control[8] & MASK_8BIT) << 0) |
- ((control[9] & MASK_4BIT) << 8);
- dev_dbg(&rmi4_data->i2c_client->dev,
- "%s: Function %02x max x = %d max y = %d\n",
- __func__, fhandler->fn_number,
- rmi4_data->sensor_max_x,
- rmi4_data->sensor_max_y);
-
- fhandler->intr_reg_num = (intr_count + 7) / 8;
- if (fhandler->intr_reg_num != 0)
- fhandler->intr_reg_num -= 1;
-
- /* Set an enable bit for each data source */
- intr_offset = intr_count % 8;
- fhandler->intr_mask = 0;
- for (ii = intr_offset;
- ii < ((fd->intr_src_count & MASK_3BIT) +
- intr_offset);
- ii++)
- fhandler->intr_mask |= 1 << ii;
-
- abs_data_size = query[5] & MASK_2BIT;
- abs_data_blk_size = 3 + (2 * (abs_data_size == 0 ? 1 : 0));
- fhandler->size_of_data_register_block = abs_data_blk_size;
-
- return retval;
-}
-
-static int synaptics_rmi4_f1a_alloc_mem(struct synaptics_rmi4_data *rmi4_data,
- struct synaptics_rmi4_fn *fhandler)
-{
- int retval;
- struct synaptics_rmi4_f1a_handle *f1a;
-
- f1a = kzalloc(sizeof(*f1a), GFP_KERNEL);
- if (!f1a) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc mem for function handle\n",
- __func__);
- return -ENOMEM;
- }
-
- fhandler->data = (void *)f1a;
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- fhandler->full_addr.query_base,
- f1a->button_query.data,
- sizeof(f1a->button_query.data));
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to read query registers\n",
- __func__);
- return retval;
- }
-
- f1a->button_count = f1a->button_query.max_button_count + 1;
- f1a->button_bitmask_size = (f1a->button_count + 7) / 8;
-
- f1a->button_data_buffer = kcalloc(f1a->button_bitmask_size,
- sizeof(*(f1a->button_data_buffer)), GFP_KERNEL);
- if (!f1a->button_data_buffer) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc mem for data buffer\n",
- __func__);
- return -ENOMEM;
- }
-
- f1a->button_map = kcalloc(f1a->button_count,
- sizeof(*(f1a->button_map)), GFP_KERNEL);
- if (!f1a->button_map) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc mem for button map\n",
- __func__);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int synaptics_rmi4_capacitance_button_map(
- struct synaptics_rmi4_data *rmi4_data,
- struct synaptics_rmi4_fn *fhandler)
-{
- unsigned char ii;
- struct synaptics_rmi4_f1a_handle *f1a = fhandler->data;
- const struct synaptics_rmi4_platform_data *pdata = rmi4_data->board;
-
- if (!pdata->capacitance_button_map) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: capacitance_button_map is" \
- "NULL in board file\n",
- __func__);
- return -ENODEV;
- } else if (!pdata->capacitance_button_map->map) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Button map is missing in board file\n",
- __func__);
- return -ENODEV;
- } else {
- if (pdata->capacitance_button_map->nbuttons !=
- f1a->button_count) {
- f1a->valid_button_count = min(f1a->button_count,
- pdata->capacitance_button_map->nbuttons);
- } else {
- f1a->valid_button_count = f1a->button_count;
- }
-
- for (ii = 0; ii < f1a->valid_button_count; ii++)
- f1a->button_map[ii] =
- pdata->capacitance_button_map->map[ii];
- }
-
- return 0;
-}
-
-static void synaptics_rmi4_f1a_kfree(struct synaptics_rmi4_fn *fhandler)
-{
- struct synaptics_rmi4_f1a_handle *f1a = fhandler->data;
-
- if (f1a) {
- kfree(f1a->button_data_buffer);
- kfree(f1a->button_map);
- kfree(f1a);
- fhandler->data = NULL;
- }
-
- return;
-}
-
-static int synaptics_rmi4_f1a_init(struct synaptics_rmi4_data *rmi4_data,
- struct synaptics_rmi4_fn *fhandler,
- struct synaptics_rmi4_fn_desc *fd,
- unsigned int intr_count)
-{
- int retval;
- unsigned char ii;
- unsigned short intr_offset;
-
- fhandler->fn_number = fd->fn_number;
- fhandler->num_of_data_sources = fd->intr_src_count;
-
- fhandler->intr_reg_num = (intr_count + 7) / 8;
- if (fhandler->intr_reg_num != 0)
- fhandler->intr_reg_num -= 1;
-
- /* Set an enable bit for each data source */
- intr_offset = intr_count % 8;
- fhandler->intr_mask = 0;
- for (ii = intr_offset;
- ii < ((fd->intr_src_count & MASK_3BIT) +
- intr_offset);
- ii++)
- fhandler->intr_mask |= 1 << ii;
-
- retval = synaptics_rmi4_f1a_alloc_mem(rmi4_data, fhandler);
- if (retval < 0)
- goto error_exit;
-
- retval = synaptics_rmi4_capacitance_button_map(rmi4_data, fhandler);
- if (retval < 0)
- goto error_exit;
-
- rmi4_data->button_0d_enabled = 1;
-
- return 0;
-
-error_exit:
- synaptics_rmi4_f1a_kfree(fhandler);
-
- return retval;
-}
-
-static int synaptics_rmi4_alloc_fh(struct synaptics_rmi4_fn **fhandler,
- struct synaptics_rmi4_fn_desc *rmi_fd, int page_number)
-{
- *fhandler = kmalloc(sizeof(**fhandler), GFP_KERNEL);
- if (!(*fhandler))
- return -ENOMEM;
-
- (*fhandler)->full_addr.data_base =
- (rmi_fd->data_base_addr |
- (page_number << 8));
- (*fhandler)->full_addr.ctrl_base =
- (rmi_fd->ctrl_base_addr |
- (page_number << 8));
- (*fhandler)->full_addr.cmd_base =
- (rmi_fd->cmd_base_addr |
- (page_number << 8));
- (*fhandler)->full_addr.query_base =
- (rmi_fd->query_base_addr |
- (page_number << 8));
-
- return 0;
-}
-
-
- /**
- * synaptics_rmi4_query_device_info()
- *
- * Called by synaptics_rmi4_query_device().
- *
- */
-static int synaptics_rmi4_query_device_info(
- struct synaptics_rmi4_data *rmi4_data)
-{
- int retval;
- unsigned char f01_query[F01_STD_QUERY_LEN];
- struct synaptics_rmi4_device_info *rmi = &(rmi4_data->rmi4_mod_info);
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi4_data->f01_query_base_addr,
- f01_query,
- sizeof(f01_query));
- if (retval < 0)
- return retval;
-
- /* RMI Version 4.0 currently supported */
- rmi->version_major = 4;
- rmi->version_minor = 0;
-
- rmi->manufacturer_id = f01_query[0];
- rmi->product_props = f01_query[1];
- rmi->product_info[0] = f01_query[2] & MASK_7BIT;
- rmi->product_info[1] = f01_query[3] & MASK_7BIT;
- rmi->date_code[0] = f01_query[4] & MASK_5BIT;
- rmi->date_code[1] = f01_query[5] & MASK_4BIT;
- rmi->date_code[2] = f01_query[6] & MASK_5BIT;
- rmi->tester_id = ((f01_query[7] & MASK_7BIT) << 8) |
- (f01_query[8] & MASK_7BIT);
- rmi->serial_number = ((f01_query[9] & MASK_7BIT) << 8) |
- (f01_query[10] & MASK_7BIT);
- memcpy(rmi->product_id_string, &f01_query[11], 10);
-
- if (rmi->manufacturer_id != 1) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Non-Synaptics device found, manufacturer ID = %d\n",
- __func__, rmi->manufacturer_id);
- }
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi4_data->f01_query_base_addr + F01_BUID_ID_OFFSET,
- rmi->build_id,
- sizeof(rmi->build_id));
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to read firmware build id (code %d)\n",
- __func__, retval);
- return retval;
- }
- return retval;
-}
-
- /**
- * synaptics_rmi4_query_device()
- *
- * Called by synaptics_rmi4_probe().
- *
- * This funtion scans the page description table, records the offsets
- * to the register types of Function $01, sets up the function handlers
- * for Function $11 and Function $12, determines the number of interrupt
- * sources from the sensor, adds valid Functions with data inputs to the
- * Function linked list, parses information from the query registers of
- * Function $01, and enables the interrupt sources from the valid Functions
- * with data inputs.
- */
-static int synaptics_rmi4_query_device(struct synaptics_rmi4_data *rmi4_data)
-{
- int retval;
- unsigned char ii;
- unsigned char page_number;
- unsigned char intr_count = 0;
- unsigned char data_sources = 0;
- unsigned short pdt_entry_addr;
- unsigned short intr_addr;
- struct synaptics_rmi4_f01_device_status status;
- struct synaptics_rmi4_fn_desc rmi_fd;
- struct synaptics_rmi4_fn *fhandler;
- struct synaptics_rmi4_device_info *rmi;
-
- rmi = &(rmi4_data->rmi4_mod_info);
-
- INIT_LIST_HEAD(&rmi->support_fn_list);
-
- /* Scan the page description tables of the pages to service */
- for (page_number = 0; page_number < PAGES_TO_SERVICE; page_number++) {
- for (pdt_entry_addr = PDT_START; pdt_entry_addr > PDT_END;
- pdt_entry_addr -= PDT_ENTRY_SIZE) {
- pdt_entry_addr |= (page_number << 8);
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- pdt_entry_addr,
- (unsigned char *)&rmi_fd,
- sizeof(rmi_fd));
- if (retval < 0)
- return retval;
-
- fhandler = NULL;
-
- if (rmi_fd.fn_number == 0) {
- dev_dbg(&rmi4_data->i2c_client->dev,
- "%s: Reached end of PDT\n",
- __func__);
- break;
- }
-
- dev_dbg(&rmi4_data->i2c_client->dev,
- "%s: F%02x found (page %d)\n",
- __func__, rmi_fd.fn_number,
- page_number);
-
- switch (rmi_fd.fn_number) {
- case SYNAPTICS_RMI4_F01:
- rmi4_data->f01_query_base_addr =
- rmi_fd.query_base_addr;
- rmi4_data->f01_ctrl_base_addr =
- rmi_fd.ctrl_base_addr;
- rmi4_data->f01_data_base_addr =
- rmi_fd.data_base_addr;
- rmi4_data->f01_cmd_base_addr =
- rmi_fd.cmd_base_addr;
-
- retval =
- synaptics_rmi4_query_device_info(rmi4_data);
- if (retval < 0)
- return retval;
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi4_data->f01_data_base_addr,
- status.data,
- sizeof(status.data));
- if (retval < 0)
- return retval;
-
- if (status.flash_prog == 1) {
- pr_notice("%s: In flash prog mode, status = 0x%02x\n",
- __func__,
- status.status_code);
- goto flash_prog_mode;
- }
- break;
-
- case SYNAPTICS_RMI4_F34:
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi_fd.ctrl_base_addr,
- rmi->config_id,
- sizeof(rmi->config_id));
- if (retval < 0)
- return retval;
- break;
-
- case SYNAPTICS_RMI4_F11:
- if (rmi_fd.intr_src_count == 0)
- break;
-
- retval = synaptics_rmi4_alloc_fh(&fhandler,
- &rmi_fd, page_number);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc for F%d\n",
- __func__,
- rmi_fd.fn_number);
- return retval;
- }
-
- retval = synaptics_rmi4_f11_init(rmi4_data,
- fhandler, &rmi_fd, intr_count);
- if (retval < 0)
- return retval;
- break;
-
- case SYNAPTICS_RMI4_F1A:
- if (rmi_fd.intr_src_count == 0)
- break;
-
- retval = synaptics_rmi4_alloc_fh(&fhandler,
- &rmi_fd, page_number);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc for F%d\n",
- __func__,
- rmi_fd.fn_number);
- return retval;
- }
-
- retval = synaptics_rmi4_f1a_init(rmi4_data,
- fhandler, &rmi_fd, intr_count);
- if (retval < 0)
- return retval;
- break;
- }
-
- /* Accumulate the interrupt count */
- intr_count += (rmi_fd.intr_src_count & MASK_3BIT);
-
- if (fhandler && rmi_fd.intr_src_count) {
- list_add_tail(&fhandler->link,
- &rmi->support_fn_list);
- }
- }
- }
-
-flash_prog_mode:
- rmi4_data->num_of_intr_regs = (intr_count + 7) / 8;
- dev_dbg(&rmi4_data->i2c_client->dev,
- "%s: Number of interrupt registers = %d\n",
- __func__, rmi4_data->num_of_intr_regs);
-
- memset(rmi4_data->intr_mask, 0x00, sizeof(rmi4_data->intr_mask));
-
- /*
- * Map out the interrupt bit masks for the interrupt sources
- * from the registered function handlers.
- */
- if (!list_empty(&rmi->support_fn_list)) {
- list_for_each_entry(fhandler, &rmi->support_fn_list, link)
- data_sources += fhandler->num_of_data_sources;
- }
- if (data_sources) {
- if (!list_empty(&rmi->support_fn_list)) {
- list_for_each_entry(fhandler,
- &rmi->support_fn_list, link) {
- if (fhandler->num_of_data_sources) {
- rmi4_data->intr_mask[fhandler->intr_reg_num] |=
- fhandler->intr_mask;
- }
- }
- }
- }
-
- /* Enable the interrupt sources */
- for (ii = 0; ii < rmi4_data->num_of_intr_regs; ii++) {
- if (rmi4_data->intr_mask[ii] != 0x00) {
- dev_dbg(&rmi4_data->i2c_client->dev,
- "%s: Interrupt enable mask %d = 0x%02x\n",
- __func__, ii, rmi4_data->intr_mask[ii]);
- intr_addr = rmi4_data->f01_ctrl_base_addr + 1 + ii;
- retval = synaptics_rmi4_i2c_write(rmi4_data,
- intr_addr,
- &(rmi4_data->intr_mask[ii]),
- sizeof(rmi4_data->intr_mask[ii]));
- if (retval < 0)
- return retval;
- }
- }
-
- return 0;
-}
-
-static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data)
-{
- int retval;
- unsigned char command = 0x01;
- struct synaptics_rmi4_fn *fhandler;
- struct synaptics_rmi4_device_info *rmi;
-
- rmi = &(rmi4_data->rmi4_mod_info);
-
- retval = synaptics_rmi4_i2c_write(rmi4_data,
- rmi4_data->f01_cmd_base_addr,
- &command,
- sizeof(command));
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to issue reset command, error = %d\n",
- __func__, retval);
- return retval;
- }
-
- msleep(100);
-
- if (!list_empty(&rmi->support_fn_list)) {
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
- if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
- synaptics_rmi4_f1a_kfree(fhandler);
- else
- kfree(fhandler->data);
- kfree(fhandler);
- }
- }
-
- retval = synaptics_rmi4_query_device(rmi4_data);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to query device\n",
- __func__);
- return retval;
- }
-
- return 0;
-}
-
-/**
-* synaptics_rmi4_detection_work()
-*
-* Called by the kernel at the scheduled time.
-*
-* This function is a self-rearming work thread that checks for the
-* insertion and removal of other expansion Function modules such as
-* rmi_dev and calls their initialization and removal callback functions
-* accordingly.
-*/
-static void synaptics_rmi4_detection_work(struct work_struct *work)
-{
- struct synaptics_rmi4_exp_fn *exp_fhandler, *next_list_entry;
- struct synaptics_rmi4_data *rmi4_data =
- container_of(work, struct synaptics_rmi4_data,
- det_work.work);
-
- queue_delayed_work(rmi4_data->det_workqueue,
- &rmi4_data->det_work,
- msecs_to_jiffies(EXP_FN_DET_INTERVAL));
-
- mutex_lock(&exp_fn_list_mutex);
- if (!list_empty(&exp_fn_list)) {
- list_for_each_entry_safe(exp_fhandler,
- next_list_entry,
- &exp_fn_list,
- link) {
- if ((exp_fhandler->func_init != NULL) &&
- (exp_fhandler->inserted == false)) {
- exp_fhandler->func_init(rmi4_data);
- exp_fhandler->inserted = true;
- } else if ((exp_fhandler->func_init == NULL) &&
- (exp_fhandler->inserted == true)) {
- exp_fhandler->func_remove(rmi4_data);
- list_del(&exp_fhandler->link);
- kfree(exp_fhandler);
- }
- }
- }
- mutex_unlock(&exp_fn_list_mutex);
-
- return;
-}
-
-/**
-* synaptics_rmi4_new_function()
-*
-* Called by other expansion Function modules in their module init and
-* module exit functions.
-*
-* This function is used by other expansion Function modules such as
-* rmi_dev to register themselves with the driver by providing their
-* initialization and removal callback function pointers so that they
-* can be inserted or removed dynamically at module init and exit times,
-* respectively.
-*/
-void synaptics_rmi4_new_function(enum exp_fn fn_type, bool insert,
- int (*func_init)(struct synaptics_rmi4_data *rmi4_data),
- void (*func_remove)(struct synaptics_rmi4_data *rmi4_data),
- void (*func_attn)(struct synaptics_rmi4_data *rmi4_data,
- unsigned char intr_mask))
-{
- struct synaptics_rmi4_exp_fn *exp_fhandler;
-
- if (!exp_fn_inited) {
- mutex_init(&exp_fn_list_mutex);
- INIT_LIST_HEAD(&exp_fn_list);
- exp_fn_inited = 1;
- }
-
- mutex_lock(&exp_fn_list_mutex);
- if (insert) {
- exp_fhandler = kzalloc(sizeof(*exp_fhandler), GFP_KERNEL);
- if (!exp_fhandler) {
- pr_err("%s: Failed to alloc mem for expansion function\n",
- __func__);
- goto exit;
- }
- exp_fhandler->fn_type = fn_type;
- exp_fhandler->func_init = func_init;
- exp_fhandler->func_attn = func_attn;
- exp_fhandler->func_remove = func_remove;
- exp_fhandler->inserted = false;
- list_add_tail(&exp_fhandler->link, &exp_fn_list);
- } else {
- if (!list_empty(&exp_fn_list)) {
- list_for_each_entry(exp_fhandler, &exp_fn_list, link) {
- if (exp_fhandler->func_init == func_init) {
- exp_fhandler->inserted = false;
- exp_fhandler->func_init = NULL;
- exp_fhandler->func_attn = NULL;
- goto exit;
- }
- }
- }
- }
-
-exit:
- mutex_unlock(&exp_fn_list_mutex);
-
- return;
-}
-EXPORT_SYMBOL(synaptics_rmi4_new_function);
-
- /**
- * synaptics_rmi4_probe()
- *
- * Called by the kernel when an association with an I2C device of the
- * same name is made (after doing i2c_add_driver).
- *
- * This funtion allocates and initializes the resources for the driver
- * as an input driver, turns on the power to the sensor, queries the
- * sensor for its supported Functions and characteristics, registers
- * the driver to the input subsystem, sets up the interrupt, handles
- * the registration of the early_suspend and late_resume functions,
- * and creates a work queue for detection of other expansion Function
- * modules.
- */
-static int __devinit synaptics_rmi4_probe(struct i2c_client *client,
- const struct i2c_device_id *dev_id)
-{
- int retval;
- unsigned char ii;
- unsigned char attr_count;
- struct synaptics_rmi4_f1a_handle *f1a;
- struct synaptics_rmi4_fn *fhandler;
- struct synaptics_rmi4_data *rmi4_data;
- struct synaptics_rmi4_device_info *rmi;
- const struct synaptics_rmi4_platform_data *platform_data =
- client->dev.platform_data;
-
- if (!i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_BYTE_DATA)) {
- dev_err(&client->dev,
- "%s: SMBus byte data not supported\n",
- __func__);
- return -EIO;
- }
-
- if (!platform_data) {
- dev_err(&client->dev,
- "%s: No platform data found\n",
- __func__);
- return -EINVAL;
- }
-
- rmi4_data = kzalloc(sizeof(*rmi4_data) * 2, GFP_KERNEL);
- if (!rmi4_data) {
- dev_err(&client->dev,
- "%s: Failed to alloc mem for rmi4_data\n",
- __func__);
- return -ENOMEM;
- }
-
- rmi = &(rmi4_data->rmi4_mod_info);
-
- rmi4_data->input_dev = input_allocate_device();
- if (rmi4_data->input_dev == NULL) {
- dev_err(&client->dev,
- "%s: Failed to allocate input device\n",
- __func__);
- retval = -ENOMEM;
- goto err_input_device;
- }
-
- if (platform_data->regulator_en) {
- rmi4_data->regulator = regulator_get(&client->dev, "vdd");
- if (IS_ERR(rmi4_data->regulator)) {
- dev_err(&client->dev,
- "%s: Failed to get regulator\n",
- __func__);
- retval = PTR_ERR(rmi4_data->regulator);
- goto err_regulator;
- }
- regulator_enable(rmi4_data->regulator);
- }
-
- rmi4_data->i2c_client = client;
- rmi4_data->current_page = MASK_8BIT;
- rmi4_data->board = platform_data;
- rmi4_data->touch_stopped = false;
- rmi4_data->sensor_sleep = false;
- rmi4_data->irq_enabled = false;
-
- rmi4_data->i2c_read = synaptics_rmi4_i2c_read;
- rmi4_data->i2c_write = synaptics_rmi4_i2c_write;
- rmi4_data->irq_enable = synaptics_rmi4_irq_enable;
- rmi4_data->reset_device = synaptics_rmi4_reset_device;
-
- init_waitqueue_head(&rmi4_data->wait);
- mutex_init(&(rmi4_data->rmi4_io_ctrl_mutex));
-
- retval = synaptics_rmi4_query_device(rmi4_data);
- if (retval < 0) {
- dev_err(&client->dev,
- "%s: Failed to query device\n",
- __func__);
- goto err_query_device;
- }
-
- i2c_set_clientdata(client, rmi4_data);
-
- rmi4_data->input_dev->name = DRIVER_NAME;
- rmi4_data->input_dev->phys = INPUT_PHYS_NAME;
- rmi4_data->input_dev->id.bustype = BUS_I2C;
- rmi4_data->input_dev->id.product = SYNAPTICS_RMI4_DRIVER_PRODUCT;
- rmi4_data->input_dev->id.version = SYNAPTICS_RMI4_DRIVER_VERSION;
- rmi4_data->input_dev->dev.parent = &client->dev;
- input_set_drvdata(rmi4_data->input_dev, rmi4_data);
-
- set_bit(EV_SYN, rmi4_data->input_dev->evbit);
- set_bit(EV_KEY, rmi4_data->input_dev->evbit);
- set_bit(EV_ABS, rmi4_data->input_dev->evbit);
- set_bit(BTN_TOUCH, rmi4_data->input_dev->keybit);
- set_bit(BTN_TOOL_FINGER, rmi4_data->input_dev->keybit);
-
-#ifdef INPUT_PROP_DIRECT
- set_bit(INPUT_PROP_DIRECT, rmi4_data->input_dev->propbit);
-#endif
-
- input_set_abs_params(rmi4_data->input_dev,
- ABS_MT_POSITION_X, 0,
- rmi4_data->sensor_max_x, 0, 0);
- input_set_abs_params(rmi4_data->input_dev,
- ABS_MT_POSITION_Y, 0,
- rmi4_data->sensor_max_y, 0, 0);
-#ifdef REPORT_2D_W
- input_set_abs_params(rmi4_data->input_dev,
- ABS_MT_TOUCH_MAJOR, 0,
- MAX_ABS_MT_TOUCH_MAJOR, 0, 0);
-#endif
-
-#ifdef TYPE_B_PROTOCOL
- input_mt_init_slots(rmi4_data->input_dev,
- rmi4_data->num_of_fingers);
-#endif
-
- f1a = NULL;
- if (!list_empty(&rmi->support_fn_list)) {
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
- if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
- f1a = fhandler->data;
- }
- }
-
- if (f1a) {
- for (ii = 0; ii < f1a->valid_button_count; ii++) {
- set_bit(f1a->button_map[ii],
- rmi4_data->input_dev->keybit);
- input_set_capability(rmi4_data->input_dev,
- EV_KEY, f1a->button_map[ii]);
- }
- }
-
- retval = input_register_device(rmi4_data->input_dev);
- if (retval) {
- dev_err(&client->dev,
- "%s: Failed to register input device\n",
- __func__);
- goto err_register_input;
- }
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
- rmi4_data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
- rmi4_data->early_suspend.suspend = synaptics_rmi4_early_suspend;
- rmi4_data->early_suspend.resume = synaptics_rmi4_late_resume;
- register_early_suspend(&rmi4_data->early_suspend);
-#endif
-
- if (!exp_fn_inited) {
- mutex_init(&exp_fn_list_mutex);
- INIT_LIST_HEAD(&exp_fn_list);
- exp_fn_inited = 1;
- }
-
- rmi4_data->det_workqueue =
- create_singlethread_workqueue("rmi_det_workqueue");
- INIT_DELAYED_WORK(&rmi4_data->det_work,
- synaptics_rmi4_detection_work);
- queue_delayed_work(rmi4_data->det_workqueue,
- &rmi4_data->det_work,
- msecs_to_jiffies(EXP_FN_DET_INTERVAL));
-
- if (platform_data->gpio_config) {
- retval = platform_data->gpio_config(platform_data->irq_gpio,
- true);
- if (retval < 0) {
- dev_err(&client->dev,
- "%s: Failed to configure GPIO\n",
- __func__);
- goto err_gpio;
- }
- }
-
- rmi4_data->irq = gpio_to_irq(platform_data->irq_gpio);
-
- retval = synaptics_rmi4_irq_enable(rmi4_data, true);
- if (retval < 0) {
- dev_err(&client->dev,
- "%s: Failed to enable attention interrupt\n",
- __func__);
- goto err_enable_irq;
- }
-
- for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
- retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj,
- &attrs[attr_count].attr);
- if (retval < 0) {
- dev_err(&client->dev,
- "%s: Failed to create sysfs attributes\n",
- __func__);
- goto err_sysfs;
- }
- }
-
- return retval;
-
-err_sysfs:
- for (attr_count--; attr_count >= 0; attr_count--) {
- sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
- &attrs[attr_count].attr);
- }
-
-err_enable_irq:
-err_gpio:
- input_unregister_device(rmi4_data->input_dev);
-
-err_register_input:
-err_query_device:
- if (platform_data->regulator_en) {
- regulator_disable(rmi4_data->regulator);
- regulator_put(rmi4_data->regulator);
- }
-
- if (!list_empty(&rmi->support_fn_list)) {
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
- if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
- synaptics_rmi4_f1a_kfree(fhandler);
- else
- kfree(fhandler->data);
- kfree(fhandler);
- }
- }
-
-err_regulator:
- input_free_device(rmi4_data->input_dev);
- rmi4_data->input_dev = NULL;
-
-err_input_device:
- kfree(rmi4_data);
-
- return retval;
-}
-
- /**
- * synaptics_rmi4_remove()
- *
- * Called by the kernel when the association with an I2C device of the
- * same name is broken (when the driver is unloaded).
- *
- * This funtion terminates the work queue, stops sensor data acquisition,
- * frees the interrupt, unregisters the driver from the input subsystem,
- * turns off the power to the sensor, and frees other allocated resources.
- */
-static int __devexit synaptics_rmi4_remove(struct i2c_client *client)
-{
- unsigned char attr_count;
- struct synaptics_rmi4_fn *fhandler;
- struct synaptics_rmi4_data *rmi4_data = i2c_get_clientdata(client);
- struct synaptics_rmi4_device_info *rmi;
- const struct synaptics_rmi4_platform_data *platform_data =
- rmi4_data->board;
-
- rmi = &(rmi4_data->rmi4_mod_info);
-
- cancel_delayed_work_sync(&rmi4_data->det_work);
- flush_workqueue(rmi4_data->det_workqueue);
- destroy_workqueue(rmi4_data->det_workqueue);
-
- rmi4_data->touch_stopped = true;
- wake_up(&rmi4_data->wait);
-
- synaptics_rmi4_irq_enable(rmi4_data, false);
-
- for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
- sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
- &attrs[attr_count].attr);
- }
-
- input_unregister_device(rmi4_data->input_dev);
-
- if (platform_data->regulator_en) {
- regulator_disable(rmi4_data->regulator);
- regulator_put(rmi4_data->regulator);
- }
-
- if (!list_empty(&rmi->support_fn_list)) {
- list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
- if (fhandler->fn_number == SYNAPTICS_RMI4_F1A)
- synaptics_rmi4_f1a_kfree(fhandler);
- else
- kfree(fhandler->data);
- kfree(fhandler);
- }
- }
- input_free_device(rmi4_data->input_dev);
-
- kfree(rmi4_data);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
- /**
- * synaptics_rmi4_sensor_sleep()
- *
- * Called by synaptics_rmi4_early_suspend() and synaptics_rmi4_suspend().
- *
- * This function stops finger data acquisition and puts the sensor to sleep.
- */
-static void synaptics_rmi4_sensor_sleep(struct synaptics_rmi4_data *rmi4_data)
-{
- int retval;
- unsigned char device_ctrl;
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
- if (retval < 0) {
- dev_err(&(rmi4_data->input_dev->dev),
- "%s: Failed to enter sleep mode\n",
- __func__);
- rmi4_data->sensor_sleep = false;
- return;
- }
-
- device_ctrl = (device_ctrl & ~MASK_3BIT);
- device_ctrl = (device_ctrl | NO_SLEEP_OFF | SENSOR_SLEEP);
-
- retval = synaptics_rmi4_i2c_write(rmi4_data,
- rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
- if (retval < 0) {
- dev_err(&(rmi4_data->input_dev->dev),
- "%s: Failed to enter sleep mode\n",
- __func__);
- rmi4_data->sensor_sleep = false;
- return;
- } else {
- rmi4_data->sensor_sleep = true;
- }
-
- return;
-}
-
- /**
- * synaptics_rmi4_sensor_wake()
- *
- * Called by synaptics_rmi4_resume() and synaptics_rmi4_late_resume().
- *
- * This function wakes the sensor from sleep.
- */
-static void synaptics_rmi4_sensor_wake(struct synaptics_rmi4_data *rmi4_data)
-{
- int retval;
- unsigned char device_ctrl;
-
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
- if (retval < 0) {
- dev_err(&(rmi4_data->input_dev->dev),
- "%s: Failed to wake from sleep mode\n",
- __func__);
- rmi4_data->sensor_sleep = true;
- return;
- }
-
- device_ctrl = (device_ctrl & ~MASK_3BIT);
- device_ctrl = (device_ctrl | NO_SLEEP_OFF | NORMAL_OPERATION);
-
- retval = synaptics_rmi4_i2c_write(rmi4_data,
- rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
- if (retval < 0) {
- dev_err(&(rmi4_data->input_dev->dev),
- "%s: Failed to wake from sleep mode\n",
- __func__);
- rmi4_data->sensor_sleep = true;
- return;
- } else {
- rmi4_data->sensor_sleep = false;
- }
-
- return;
-}
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
- /**
- * synaptics_rmi4_early_suspend()
- *
- * Called by the kernel during the early suspend phase when the system
- * enters suspend.
- *
- * This function calls synaptics_rmi4_sensor_sleep() to stop finger
- * data acquisition and put the sensor to sleep.
- */
-static void synaptics_rmi4_early_suspend(struct early_suspend *h)
-{
- struct synaptics_rmi4_data *rmi4_data =
- container_of(h, struct synaptics_rmi4_data,
- early_suspend);
-
- rmi4_data->touch_stopped = true;
- wake_up(&rmi4_data->wait);
- synaptics_rmi4_irq_enable(rmi4_data, false);
- synaptics_rmi4_sensor_sleep(rmi4_data);
-
- if (rmi4_data->full_pm_cycle)
- synaptics_rmi4_suspend(&(rmi4_data->input_dev->dev));
-
- return;
-}
-
- /**
- * synaptics_rmi4_late_resume()
- *
- * Called by the kernel during the late resume phase when the system
- * wakes up from suspend.
- *
- * This function goes through the sensor wake process if the system wakes
- * up from early suspend (without going into suspend).
- */
-static void synaptics_rmi4_late_resume(struct early_suspend *h)
-{
- struct synaptics_rmi4_data *rmi4_data =
- container_of(h, struct synaptics_rmi4_data,
- early_suspend);
-
- if (rmi4_data->full_pm_cycle)
- synaptics_rmi4_resume(&(rmi4_data->input_dev->dev));
-
- if (rmi4_data->sensor_sleep == true) {
- synaptics_rmi4_sensor_wake(rmi4_data);
- rmi4_data->touch_stopped = false;
- synaptics_rmi4_irq_enable(rmi4_data, true);
- }
-
- return;
-}
-#endif
-
- /**
- * synaptics_rmi4_suspend()
- *
- * Called by the kernel during the suspend phase when the system
- * enters suspend.
- *
- * This function stops finger data acquisition and puts the sensor to
- * sleep (if not already done so during the early suspend phase),
- * disables the interrupt, and turns off the power to the sensor.
- */
-static int synaptics_rmi4_suspend(struct device *dev)
-{
- struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
- const struct synaptics_rmi4_platform_data *platform_data =
- rmi4_data->board;
-
- if (!rmi4_data->sensor_sleep) {
- rmi4_data->touch_stopped = true;
- wake_up(&rmi4_data->wait);
- synaptics_rmi4_irq_enable(rmi4_data, false);
- synaptics_rmi4_sensor_sleep(rmi4_data);
- }
-
- if (platform_data->regulator_en)
- regulator_disable(rmi4_data->regulator);
-
- return 0;
-}
-
- /**
- * synaptics_rmi4_resume()
- *
- * Called by the kernel during the resume phase when the system
- * wakes up from suspend.
- *
- * This function turns on the power to the sensor, wakes the sensor
- * from sleep, enables the interrupt, and starts finger data
- * acquisition.
- */
-static int synaptics_rmi4_resume(struct device *dev)
-{
- struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
- const struct synaptics_rmi4_platform_data *platform_data =
- rmi4_data->board;
-
- if (platform_data->regulator_en)
- regulator_enable(rmi4_data->regulator);
-
- synaptics_rmi4_sensor_wake(rmi4_data);
- rmi4_data->touch_stopped = false;
- synaptics_rmi4_irq_enable(rmi4_data, true);
-
- return 0;
-}
-
-static const struct dev_pm_ops synaptics_rmi4_dev_pm_ops = {
- .suspend = synaptics_rmi4_suspend,
- .resume = synaptics_rmi4_resume,
-};
-#endif
-
-static const struct i2c_device_id synaptics_rmi4_id_table[] = {
- {DRIVER_NAME, 0},
- {},
-};
-MODULE_DEVICE_TABLE(i2c, synaptics_rmi4_id_table);
-
-static struct i2c_driver synaptics_rmi4_driver = {
- .driver = {
- .name = DRIVER_NAME,
- .owner = THIS_MODULE,
-#ifdef CONFIG_PM
- .pm = &synaptics_rmi4_dev_pm_ops,
-#endif
- },
- .probe = synaptics_rmi4_probe,
- .remove = __devexit_p(synaptics_rmi4_remove),
- .id_table = synaptics_rmi4_id_table,
-};
-
- /**
- * synaptics_rmi4_init()
- *
- * Called by the kernel during do_initcalls (if built-in)
- * or when the driver is loaded (if a module).
- *
- * This function registers the driver to the I2C subsystem.
- *
- */
-static int __init synaptics_rmi4_init(void)
-{
- return i2c_add_driver(&synaptics_rmi4_driver);
-}
-
- /**
- * synaptics_rmi4_exit()
- *
- * Called by the kernel when the driver is unloaded.
- *
- * This funtion unregisters the driver from the I2C subsystem.
- *
- */
-static void __exit synaptics_rmi4_exit(void)
-{
- i2c_del_driver(&synaptics_rmi4_driver);
-}
-
-module_init(synaptics_rmi4_init);
-module_exit(synaptics_rmi4_exit);
-
-MODULE_AUTHOR("Synaptics, Inc.");
-MODULE_DESCRIPTION("Synaptics RMI4 I2C Touch Driver");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION(SYNAPTICS_RMI4_DRIVER_VERSION);
diff --git a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h
deleted file mode 100644
index ecb9b9415e8a..000000000000
--- a/kernel/drivers/input/touchscreen/synaptics_i2c_rmi4.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Synaptics RMI4 touchscreen driver
- *
- * Copyright (C) 2012 Synaptics Incorporated
- *
- * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
- * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SYNAPTICS_DSX_RMI4_H_
-#define _SYNAPTICS_DSX_RMI4_H_
-
-#define SYNAPTICS_RMI4_DS4 0x0001
-#define SYNAPTICS_RMI4_DS5 0x0002
-#define SYNAPTICS_RMI4_DRIVER_PRODUCT SYNAPTICS_RMI4_DS4
-#define SYNAPTICS_RMI4_DRIVER_VERSION 0x1001
-
-#include <linux/version.h>
-#ifdef CONFIG_HAS_EARLYSUSPEND
-#include <linux/earlysuspend.h>
-#endif
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 38))
-#define KERNEL_ABOVE_2_6_38
-#endif
-
-#ifdef KERNEL_ABOVE_2_6_38
-#define sstrtoul(...) kstrtoul(__VA_ARGS__)
-#else
-#define sstrtoul(...) strict_strtoul(__VA_ARGS__)
-#endif
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 7, 0))
-#define KERNEL_ABOVE_3_7
-#endif
-
-#define PDT_PROPS (0x00EF)
-#define PDT_START (0x00E9)
-#define PDT_END (0x000A)
-#define PDT_ENTRY_SIZE (0x0006)
-#define PAGES_TO_SERVICE (10)
-#define PAGE_SELECT_LEN (2)
-
-#define SYNAPTICS_RMI4_F01 (0x01)
-#define SYNAPTICS_RMI4_F11 (0x11)
-#define SYNAPTICS_RMI4_F1A (0x1a)
-#define SYNAPTICS_RMI4_F34 (0x34)
-#define SYNAPTICS_RMI4_F54 (0x54)
-#define SYNAPTICS_RMI4_F55 (0x55)
-
-#define SYNAPTICS_RMI4_PRODUCT_INFO_SIZE 2
-#define SYNAPTICS_RMI4_DATE_CODE_SIZE 3
-#define SYNAPTICS_RMI4_PRODUCT_ID_SIZE 10
-#define SYNAPTICS_RMI4_BUILD_ID_SIZE 3
-
-#define MAX_NUMBER_OF_FINGERS 10
-#define MAX_NUMBER_OF_BUTTONS 4
-#define MAX_INTR_REGISTERS 4
-
-#define MASK_16BIT 0xFFFF
-#define MASK_8BIT 0xFF
-#define MASK_7BIT 0x7F
-#define MASK_6BIT 0x3F
-#define MASK_5BIT 0x1F
-#define MASK_4BIT 0x0F
-#define MASK_3BIT 0x07
-#define MASK_2BIT 0x03
-#define MASK_1BIT 0x01
-
-/*
- * struct synaptics_rmi4_fn_desc - function descriptor fields in PDT
- * @query_base_addr: base address for query registers
- * @cmd_base_addr: base address for command registers
- * @ctrl_base_addr: base address for control registers
- * @data_base_addr: base address for data registers
- * @intr_src_count: number of interrupt sources
- * @fn_number: function number
- */
-struct synaptics_rmi4_fn_desc {
- unsigned char query_base_addr;
- unsigned char cmd_base_addr;
- unsigned char ctrl_base_addr;
- unsigned char data_base_addr;
- unsigned char intr_src_count;
- unsigned char fn_number;
-};
-
-/*
- * synaptics_rmi4_fn_full_addr - full 16-bit base addresses
- * @query_base: 16-bit base address for query registers
- * @cmd_base: 16-bit base address for data registers
- * @ctrl_base: 16-bit base address for command registers
- * @data_base: 16-bit base address for control registers
- */
-struct synaptics_rmi4_fn_full_addr {
- unsigned short query_base;
- unsigned short cmd_base;
- unsigned short ctrl_base;
- unsigned short data_base;
-};
-
-/*
- * struct synaptics_rmi4_fn - function handler data structure
- * @fn_number: function number
- * @num_of_data_sources: number of data sources
- * @num_of_data_points: maximum number of fingers supported
- * @size_of_data_register_block: data register block size
- * @data1_offset: offset to data1 register from data base address
- * @intr_reg_num: index to associated interrupt register
- * @intr_mask: interrupt mask
- * @full_addr: full 16-bit base addresses of function registers
- * @link: linked list for function handlers
- * @data_size: size of private data
- * @data: pointer to private data
- */
-struct synaptics_rmi4_fn {
- unsigned char fn_number;
- unsigned char num_of_data_sources;
- unsigned char num_of_data_points;
- unsigned char size_of_data_register_block;
- unsigned char data1_offset;
- unsigned char intr_reg_num;
- unsigned char intr_mask;
- struct synaptics_rmi4_fn_full_addr full_addr;
- struct list_head link;
- int data_size;
- void *data;
-};
-
-/*
- * struct synaptics_rmi4_device_info - device information
- * @version_major: rmi protocol major version number
- * @version_minor: rmi protocol minor version number
- * @manufacturer_id: manufacturer id
- * @product_props: product properties information
- * @product_info: product info array
- * @date_code: device manufacture date
- * @tester_id: tester id array
- * @serial_number: device serial number
- * @product_id_string: device product id
- * @support_fn_list: linked list for function handlers
- */
-struct synaptics_rmi4_device_info {
- unsigned int version_major;
- unsigned int version_minor;
- unsigned char manufacturer_id;
- unsigned char product_props;
- unsigned char product_info[SYNAPTICS_RMI4_PRODUCT_INFO_SIZE];
- unsigned char date_code[SYNAPTICS_RMI4_DATE_CODE_SIZE];
- unsigned short tester_id;
- unsigned short serial_number;
- unsigned char product_id_string[SYNAPTICS_RMI4_PRODUCT_ID_SIZE + 1];
- unsigned char build_id[SYNAPTICS_RMI4_BUILD_ID_SIZE];
- unsigned char config_id[3];
- struct list_head support_fn_list;
-};
-
-/*
- * struct synaptics_rmi4_data - rmi4 device instance data
- * @i2c_client: pointer to associated i2c client
- * @input_dev: pointer to associated input device
- * @board: constant pointer to platform data
- * @rmi4_mod_info: device information
- * @regulator: pointer to associated regulator
- * @rmi4_io_ctrl_mutex: mutex for i2c i/o control
- * @det_work: work thread instance for expansion function detection
- * @det_workqueue: pointer to work queue for work thread instance
- * @early_suspend: instance to support early suspend power management
- * @current_page: current page in sensor to acess
- * @button_0d_enabled: flag for 0d button support
- * @full_pm_cycle: flag for full power management cycle in early suspend stage
- * @num_of_intr_regs: number of interrupt registers
- * @f01_query_base_addr: query base address for f01
- * @f01_cmd_base_addr: command base address for f01
- * @f01_ctrl_base_addr: control base address for f01
- * @f01_data_base_addr: data base address for f01
- * @irq: attention interrupt
- * @sensor_max_x: sensor maximum x value
- * @sensor_max_y: sensor maximum y value
- * @irq_enabled: flag for indicating interrupt enable status
- * @touch_stopped: flag to stop interrupt thread processing
- * @fingers_on_2d: flag to indicate presence of fingers in 2d area
- * @sensor_sleep: flag to indicate sleep state of sensor
- * @wait: wait queue for touch data polling in interrupt thread
- * @i2c_read: pointer to i2c read function
- * @i2c_write: pointer to i2c write function
- * @irq_enable: pointer to irq enable function
- */
-struct synaptics_rmi4_data {
- struct i2c_client *i2c_client;
- struct input_dev *input_dev;
- const struct synaptics_rmi4_platform_data *board;
- struct synaptics_rmi4_device_info rmi4_mod_info;
- struct regulator *regulator;
- struct mutex rmi4_io_ctrl_mutex;
- struct delayed_work det_work;
- struct workqueue_struct *det_workqueue;
- struct early_suspend early_suspend;
- unsigned char current_page;
- unsigned char button_0d_enabled;
- unsigned char full_pm_cycle;
- unsigned char num_of_rx;
- unsigned char num_of_tx;
- unsigned char num_of_fingers;
- unsigned char intr_mask[MAX_INTR_REGISTERS];
- unsigned short num_of_intr_regs;
- unsigned short f01_query_base_addr;
- unsigned short f01_cmd_base_addr;
- unsigned short f01_ctrl_base_addr;
- unsigned short f01_data_base_addr;
- int irq;
- int sensor_max_x;
- int sensor_max_y;
- bool irq_enabled;
- bool touch_stopped;
- bool fingers_on_2d;
- bool sensor_sleep;
- wait_queue_head_t wait;
- int (*i2c_read)(struct synaptics_rmi4_data *pdata, unsigned short addr,
- unsigned char *data, unsigned short length);
- int (*i2c_write)(struct synaptics_rmi4_data *pdata, unsigned short addr,
- unsigned char *data, unsigned short length);
- int (*irq_enable)(struct synaptics_rmi4_data *rmi4_data, bool enable);
- int (*reset_device)(struct synaptics_rmi4_data *rmi4_data);
-};
-
-enum exp_fn {
- RMI_DEV = 0,
- RMI_F34,
- RMI_F54,
- RMI_FW_UPDATER,
- RMI_LAST,
-};
-
-struct synaptics_rmi4_exp_fn_ptr {
- int (*read)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr,
- unsigned char *data, unsigned short length);
- int (*write)(struct synaptics_rmi4_data *rmi4_data, unsigned short addr,
- unsigned char *data, unsigned short length);
- int (*enable)(struct synaptics_rmi4_data *rmi4_data, bool enable);
-};
-
-void synaptics_rmi4_new_function(enum exp_fn fn_type, bool insert,
- int (*func_init)(struct synaptics_rmi4_data *rmi4_data),
- void (*func_remove)(struct synaptics_rmi4_data *rmi4_data),
- void (*func_attn)(struct synaptics_rmi4_data *rmi4_data,
- unsigned char intr_mask));
-
-static inline ssize_t synaptics_rmi4_show_error(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- dev_warn(dev, "%s Attempted to read from write-only attribute %s\n",
- __func__, attr->attr.name);
- return -EPERM;
-}
-
-static inline ssize_t synaptics_rmi4_store_error(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- dev_warn(dev, "%s Attempted to write to read-only attribute %s\n",
- __func__, attr->attr.name);
- return -EPERM;
-}
-
-static inline void batohs(unsigned short *dest, unsigned char *src)
-{
- *dest = src[1] * 0x100 + src[0];
-}
-
-static inline void hstoba(unsigned char *dest, unsigned short src)
-{
- dest[0] = src % 0x100;
- dest[1] = src / 0x100;
-}
-
-#endif
diff --git a/kernel/drivers/input/touchscreen/synaptics_rmi_dev.c b/kernel/drivers/input/touchscreen/synaptics_rmi_dev.c
deleted file mode 100644
index 75857802c97a..000000000000
--- a/kernel/drivers/input/touchscreen/synaptics_rmi_dev.c
+++ /dev/null
@@ -1,710 +0,0 @@
-/*
- * Synaptics RMI4 touchscreen driver
- *
- * Copyright (C) 2012 Synaptics Incorporated
- *
- * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
- * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/gpio.h>
-#include <linux/uaccess.h>
-#include <linux/cdev.h>
-#include <linux/input/synaptics_dsx.h>
-#include "synaptics_i2c_rmi4.h"
-
-#define CHAR_DEVICE_NAME "rmi"
-#define DEVICE_CLASS_NAME "rmidev"
-#define DEV_NUMBER 1
-#define REG_ADDR_LIMIT 0xFFFF
-
-static ssize_t rmidev_sysfs_open_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-static ssize_t rmidev_sysfs_release_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-static ssize_t rmidev_sysfs_address_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-static ssize_t rmidev_sysfs_length_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-static ssize_t rmidev_sysfs_data_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-
-static ssize_t rmidev_sysfs_data_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count);
-
-struct rmidev_handle {
- dev_t dev_no;
- unsigned short address;
- unsigned int length;
- struct device dev;
- struct synaptics_rmi4_data *rmi4_data;
- struct synaptics_rmi4_exp_fn_ptr *fn_ptr;
- struct kobject *sysfs_dir;
- void *data;
-};
-
-struct rmidev_data {
- int ref_count;
- struct cdev main_dev;
- struct class *device_class;
- struct mutex file_mutex;
- struct rmidev_handle *rmi_dev;
-};
-
-static struct device_attribute attrs[] = {
- __ATTR(open, S_IWUGO,
- synaptics_rmi4_show_error,
- rmidev_sysfs_open_store),
- __ATTR(release, S_IWUGO,
- synaptics_rmi4_show_error,
- rmidev_sysfs_release_store),
- __ATTR(address, S_IWUGO,
- synaptics_rmi4_show_error,
- rmidev_sysfs_address_store),
- __ATTR(length, S_IWUGO,
- synaptics_rmi4_show_error,
- rmidev_sysfs_length_store),
- __ATTR(data, (S_IRUGO | S_IWUGO),
- rmidev_sysfs_data_show,
- rmidev_sysfs_data_store),
-};
-
-static int rmidev_major_num;
-
-static struct class *rmidev_device_class;
-
-static struct rmidev_handle *rmidev;
-
-static struct completion remove_complete;
-
-static ssize_t rmidev_sysfs_open_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- unsigned int input;
-
- if (sscanf(buf, "%u", &input) != 1)
- return -EINVAL;
-
- if (input != 1)
- return -EINVAL;
-
- rmidev->fn_ptr->enable(rmidev->rmi4_data, false);
- dev_dbg(&rmidev->rmi4_data->i2c_client->dev,
- "%s: Attention interrupt disabled\n",
- __func__);
-
- return count;
-}
-
-static ssize_t rmidev_sysfs_release_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- unsigned int input;
-
- if (sscanf(buf, "%u", &input) != 1)
- return -EINVAL;
-
- if (input != 1)
- return -EINVAL;
-
- rmidev->fn_ptr->enable(rmidev->rmi4_data, true);
- dev_dbg(&rmidev->rmi4_data->i2c_client->dev,
- "%s: Attention interrupt enabled\n",
- __func__);
-
- return count;
-}
-
-static ssize_t rmidev_sysfs_address_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- unsigned int input;
-
- if (sscanf(buf, "%u", &input) != 1)
- return -EINVAL;
-
- if (input > REG_ADDR_LIMIT)
- return -EINVAL;
-
- rmidev->address = (unsigned short)input;
-
- return count;
-}
-
-static ssize_t rmidev_sysfs_length_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- unsigned int input;
-
- if (sscanf(buf, "%u", &input) != 1)
- return -EINVAL;
-
- if (input > REG_ADDR_LIMIT)
- return -EINVAL;
-
- rmidev->length = input;
-
- return count;
-}
-
-static ssize_t rmidev_sysfs_data_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- int retval;
- unsigned int data_length = rmidev->length;
-
- if (data_length > (REG_ADDR_LIMIT - rmidev->address))
- data_length = REG_ADDR_LIMIT - rmidev->address;
-
- if (data_length) {
- retval = rmidev->fn_ptr->read(rmidev->rmi4_data,
- rmidev->address,
- (unsigned char *)buf,
- data_length);
- if (retval < 0) {
- dev_err(&rmidev->rmi4_data->i2c_client->dev,
- "%s: Failed to read data\n",
- __func__);
- return retval;
- }
- } else {
- return -EINVAL;
- }
-
- return data_length;
-}
-
-static ssize_t rmidev_sysfs_data_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int retval;
- unsigned int data_length = rmidev->length;
-
- if (data_length > (REG_ADDR_LIMIT - rmidev->address))
- data_length = REG_ADDR_LIMIT - rmidev->address;
-
- if (data_length) {
- retval = rmidev->fn_ptr->write(rmidev->rmi4_data,
- rmidev->address,
- (unsigned char *)buf,
- data_length);
- if (retval < 0) {
- dev_err(&rmidev->rmi4_data->i2c_client->dev,
- "%s: Failed to write data\n",
- __func__);
- return retval;
- }
- } else {
- return -EINVAL;
- }
-
- return data_length;
-}
-
-/*
- * rmidev_llseek - used to set up register address
- *
- * @filp: file structure for seek
- * @off: offset
- * if whence == SEEK_SET,
- * high 16 bits: page address
- * low 16 bits: register address
- * if whence == SEEK_CUR,
- * offset from current position
- * if whence == SEEK_END,
- * offset from end position (0xFFFF)
- * @whence: SEEK_SET, SEEK_CUR, or SEEK_END
- */
-static loff_t rmidev_llseek(struct file *filp, loff_t off, int whence)
-{
- loff_t newpos;
- struct rmidev_data *dev_data = filp->private_data;
-
- if (IS_ERR(dev_data)) {
- pr_err("%s: Pointer of char device data is invalid", __func__);
- return -EBADF;
- }
-
- mutex_lock(&(dev_data->file_mutex));
-
- switch (whence) {
- case SEEK_SET:
- newpos = off;
- break;
- case SEEK_CUR:
- newpos = filp->f_pos + off;
- break;
- case SEEK_END:
- newpos = REG_ADDR_LIMIT + off;
- break;
- default:
- newpos = -EINVAL;
- goto clean_up;
- }
-
- if (newpos < 0 || newpos > REG_ADDR_LIMIT) {
- dev_err(&rmidev->rmi4_data->i2c_client->dev,
- "%s: New position 0x%04x is invalid\n",
- __func__, (unsigned int)newpos);
- newpos = -EINVAL;
- goto clean_up;
- }
-
- filp->f_pos = newpos;
-
-clean_up:
- mutex_unlock(&(dev_data->file_mutex));
-
- return newpos;
-}
-
-/*
- * rmidev_read: - use to read data from rmi device
- *
- * @filp: file structure for read
- * @buf: user space buffer pointer
- * @count: number of bytes to read
- * @f_pos: offset (starting register address)
- */
-static ssize_t rmidev_read(struct file *filp, char __user *buf,
- size_t count, loff_t *f_pos)
-{
- ssize_t retval;
- unsigned char tmpbuf[count + 1];
- struct rmidev_data *dev_data = filp->private_data;
-
- if (IS_ERR(dev_data)) {
- pr_err("%s: Pointer of char device data is invalid", __func__);
- return -EBADF;
- }
-
- if (count == 0)
- return 0;
-
- if (count > (REG_ADDR_LIMIT - *f_pos))
- count = REG_ADDR_LIMIT - *f_pos;
-
- mutex_lock(&(dev_data->file_mutex));
-
- retval = rmidev->fn_ptr->read(rmidev->rmi4_data,
- *f_pos,
- tmpbuf,
- count);
- if (retval < 0)
- goto clean_up;
-
- if (copy_to_user(buf, tmpbuf, count))
- retval = -EFAULT;
- else
- *f_pos += retval;
-
-clean_up:
- mutex_unlock(&(dev_data->file_mutex));
-
- return retval;
-}
-
-/*
- * rmidev_write: - used to write data to rmi device
- *
- * @filep: file structure for write
- * @buf: user space buffer pointer
- * @count: number of bytes to write
- * @f_pos: offset (starting register address)
- */
-static ssize_t rmidev_write(struct file *filp, const char __user *buf,
- size_t count, loff_t *f_pos)
-{
- ssize_t retval;
- unsigned char tmpbuf[count + 1];
- struct rmidev_data *dev_data = filp->private_data;
-
- if (IS_ERR(dev_data)) {
- pr_err("%s: Pointer of char device data is invalid", __func__);
- return -EBADF;
- }
-
- if (count == 0)
- return 0;
-
- if (count > (REG_ADDR_LIMIT - *f_pos))
- count = REG_ADDR_LIMIT - *f_pos;
-
- if (copy_from_user(tmpbuf, buf, count))
- return -EFAULT;
-
- mutex_lock(&(dev_data->file_mutex));
-
- retval = rmidev->fn_ptr->write(rmidev->rmi4_data,
- *f_pos,
- tmpbuf,
- count);
- if (retval >= 0)
- *f_pos += retval;
-
- mutex_unlock(&(dev_data->file_mutex));
-
- return retval;
-}
-
-/*
- * rmidev_open: enable access to rmi device
- * @inp: inode struture
- * @filp: file structure
- */
-static int rmidev_open(struct inode *inp, struct file *filp)
-{
- int retval = 0;
- struct rmidev_data *dev_data =
- container_of(inp->i_cdev, struct rmidev_data, main_dev);
-
- if (!dev_data)
- return -EACCES;
-
- filp->private_data = dev_data;
-
- mutex_lock(&(dev_data->file_mutex));
-
- rmidev->fn_ptr->enable(rmidev->rmi4_data, false);
- dev_dbg(&rmidev->rmi4_data->i2c_client->dev,
- "%s: Attention interrupt disabled\n",
- __func__);
-
- if (dev_data->ref_count < 1)
- dev_data->ref_count++;
- else
- retval = -EACCES;
-
- mutex_unlock(&(dev_data->file_mutex));
-
- return retval;
-}
-
-/*
- * rmidev_release: - release access to rmi device
- * @inp: inode structure
- * @filp: file structure
- */
-static int rmidev_release(struct inode *inp, struct file *filp)
-{
- struct rmidev_data *dev_data =
- container_of(inp->i_cdev, struct rmidev_data, main_dev);
-
- if (!dev_data)
- return -EACCES;
-
- mutex_lock(&(dev_data->file_mutex));
-
- dev_data->ref_count--;
- if (dev_data->ref_count < 0)
- dev_data->ref_count = 0;
-
- rmidev->fn_ptr->enable(rmidev->rmi4_data, true);
- dev_dbg(&rmidev->rmi4_data->i2c_client->dev,
- "%s: Attention interrupt enabled\n",
- __func__);
-
- mutex_unlock(&(dev_data->file_mutex));
-
- return 0;
-}
-
-static const struct file_operations rmidev_fops = {
- .owner = THIS_MODULE,
- .llseek = rmidev_llseek,
- .read = rmidev_read,
- .write = rmidev_write,
- .open = rmidev_open,
- .release = rmidev_release,
-};
-
-static void rmidev_device_cleanup(struct rmidev_data *dev_data)
-{
- dev_t devno;
-
- if (dev_data) {
- devno = dev_data->main_dev.dev;
-
- if (dev_data->device_class)
- device_destroy(dev_data->device_class, devno);
-
- cdev_del(&dev_data->main_dev);
-
- unregister_chrdev_region(devno, 1);
-
- dev_dbg(&rmidev->rmi4_data->i2c_client->dev,
- "%s: rmidev device removed\n",
- __func__);
- }
-
- return;
-}
-
-static char *rmi_char_devnode(struct device *dev, mode_t *mode)
-{
- if (!mode)
- return NULL;
-
- *mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
-
- return kasprintf(GFP_KERNEL, "rmi/%s", dev_name(dev));
-}
-
-static int rmidev_create_device_class(void)
-{
- rmidev_device_class = class_create(THIS_MODULE, DEVICE_CLASS_NAME);
-
- if (IS_ERR(rmidev_device_class)) {
- pr_err("%s: Failed to create /dev/%s\n",
- __func__, CHAR_DEVICE_NAME);
- return -ENODEV;
- }
-
- rmidev_device_class->devnode = rmi_char_devnode;
-
- return 0;
-}
-
-static int rmidev_init_device(struct synaptics_rmi4_data *rmi4_data)
-{
- int retval;
- dev_t dev_no;
- unsigned char attr_count;
- struct rmidev_data *dev_data;
- struct device *device_ptr;
-
- rmidev = kzalloc(sizeof(*rmidev), GFP_KERNEL);
- if (!rmidev) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc mem for rmidev\n",
- __func__);
- retval = -ENOMEM;
- goto err_rmidev;
- }
-
- rmidev->fn_ptr = kzalloc(sizeof(*(rmidev->fn_ptr)), GFP_KERNEL);
- if (!rmidev) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc mem for fn_ptr\n",
- __func__);
- retval = -ENOMEM;
- goto err_fn_ptr;
- }
-
- rmidev->fn_ptr->read = rmi4_data->i2c_read;
- rmidev->fn_ptr->write = rmi4_data->i2c_write;
- rmidev->fn_ptr->enable = rmi4_data->irq_enable;
- rmidev->rmi4_data = rmi4_data;
-
- retval = rmidev_create_device_class();
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to create device class\n",
- __func__);
- goto err_device_class;
- }
-
- if (rmidev_major_num) {
- dev_no = MKDEV(rmidev_major_num, DEV_NUMBER);
- retval = register_chrdev_region(dev_no, 1, CHAR_DEVICE_NAME);
- } else {
- retval = alloc_chrdev_region(&dev_no, 0, 1, CHAR_DEVICE_NAME);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to allocate char device region\n",
- __func__);
- goto err_device_region;
- }
-
- rmidev_major_num = MAJOR(dev_no);
- dev_dbg(&rmi4_data->i2c_client->dev,
- "%s: Major number of rmidev = %d\n",
- __func__, rmidev_major_num);
- }
-
- dev_data = kzalloc(sizeof(*dev_data), GFP_KERNEL);
- if (!dev_data) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to alloc mem for dev_data\n",
- __func__);
- retval = -ENOMEM;
- goto err_dev_data;
- }
-
- mutex_init(&dev_data->file_mutex);
- dev_data->rmi_dev = rmidev;
- rmidev->data = dev_data;
-
- cdev_init(&dev_data->main_dev, &rmidev_fops);
-
- retval = cdev_add(&dev_data->main_dev, dev_no, 1);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to add rmi char device\n",
- __func__);
- goto err_char_device;
- }
-
- dev_set_name(&rmidev->dev, "rmidev%d", MINOR(dev_no));
- dev_data->device_class = rmidev_device_class;
-
- device_ptr = device_create(dev_data->device_class, NULL, dev_no,
- NULL, CHAR_DEVICE_NAME"%d", MINOR(dev_no));
- if (IS_ERR(device_ptr)) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to create rmi char device\n",
- __func__);
- retval = -ENODEV;
- goto err_char_device;
- }
-
- retval = gpio_export(rmi4_data->board->irq_gpio, false);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to export attention gpio\n",
- __func__);
- } else {
- retval = gpio_export_link(&(rmi4_data->input_dev->dev),
- "attn", rmi4_data->board->irq_gpio);
- if (retval < 0) {
- dev_err(&rmi4_data->input_dev->dev,
- "%s Failed to create gpio symlink\n",
- __func__);
- } else {
- dev_dbg(&rmi4_data->input_dev->dev,
- "%s: Exported attention gpio %d\n",
- __func__, rmi4_data->board->irq_gpio);
- }
- }
-
- rmidev->sysfs_dir = kobject_create_and_add("rmidev",
- &rmi4_data->input_dev->dev.kobj);
- if (!rmidev->sysfs_dir) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to create sysfs directory\n",
- __func__);
- goto err_sysfs_dir;
- }
-
- for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
- retval = sysfs_create_file(rmidev->sysfs_dir,
- &attrs[attr_count].attr);
- if (retval < 0) {
- dev_err(&rmi4_data->input_dev->dev,
- "%s: Failed to create sysfs attributes\n",
- __func__);
- retval = -ENODEV;
- goto err_sysfs_attrs;
- }
- }
-
- return 0;
-
-err_sysfs_attrs:
- for (attr_count--; attr_count >= 0; attr_count--) {
- sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
- &attrs[attr_count].attr);
- }
-
- kobject_put(rmidev->sysfs_dir);
-
-err_sysfs_dir:
-err_char_device:
- rmidev_device_cleanup(dev_data);
- kfree(dev_data);
-
-err_dev_data:
- unregister_chrdev_region(dev_no, 1);
-
-err_device_region:
- class_destroy(rmidev_device_class);
-
-err_device_class:
- kfree(rmidev->fn_ptr);
-
-err_fn_ptr:
- kfree(rmidev);
-
-err_rmidev:
- return retval;
-}
-
-static void rmidev_remove_device(struct synaptics_rmi4_data *rmi4_data)
-{
- unsigned char attr_count;
- struct rmidev_data *dev_data;
-
- if (!rmidev)
- return;
-
- for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++)
- sysfs_remove_file(rmidev->sysfs_dir, &attrs[attr_count].attr);
-
- kobject_put(rmidev->sysfs_dir);
-
- dev_data = rmidev->data;
- if (dev_data) {
- rmidev_device_cleanup(dev_data);
- kfree(dev_data);
- }
-
- unregister_chrdev_region(rmidev->dev_no, 1);
-
- class_destroy(rmidev_device_class);
-
- kfree(rmidev->fn_ptr);
- kfree(rmidev);
-
- complete(&remove_complete);
-
- return;
-}
-
-static int __init rmidev_module_init(void)
-{
- synaptics_rmi4_new_function(RMI_DEV, true,
- rmidev_init_device,
- rmidev_remove_device,
- NULL);
- return 0;
-}
-
-static void __exit rmidev_module_exit(void)
-{
- init_completion(&remove_complete);
- synaptics_rmi4_new_function(RMI_DEV, false,
- rmidev_init_device,
- rmidev_remove_device,
- NULL);
- wait_for_completion(&remove_complete);
- return;
-}
-
-module_init(rmidev_module_init);
-module_exit(rmidev_module_exit);
-
-MODULE_AUTHOR("Synaptics, Inc.");
-MODULE_DESCRIPTION("RMI4 RMI_Dev Module");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(SYNAPTICS_RMI4_DRIVER_VERSION);
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 5beb88f11671..446dbad75e60 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -954,6 +954,7 @@ static void put_ctx(struct perf_event_context *ctx)
* function.
*
* Lock order:
+ * cred_guard_mutex
* task_struct::perf_event_mutex
* perf_event_context::mutex
* perf_event_context::lock
@@ -1923,8 +1924,13 @@ event_sched_in(struct perf_event *event,
if (event->state <= PERF_EVENT_STATE_OFF)
return 0;
- event->state = PERF_EVENT_STATE_ACTIVE;
- event->oncpu = smp_processor_id();
+ WRITE_ONCE(event->oncpu, smp_processor_id());
+ /*
+ * Order event::oncpu write to happen before the ACTIVE state
+ * is visible.
+ */
+ smp_wmb();
+ WRITE_ONCE(event->state, PERF_EVENT_STATE_ACTIVE);
/*
* Unthrottle events, since we scheduled we might have missed several
@@ -2405,6 +2411,29 @@ void perf_event_enable(struct perf_event *event)
}
EXPORT_SYMBOL_GPL(perf_event_enable);
+static int __perf_event_stop(void *info)
+{
+ struct perf_event *event = info;
+
+ /* for AUX events, our job is done if the event is already inactive */
+ if (READ_ONCE(event->state) != PERF_EVENT_STATE_ACTIVE)
+ return 0;
+
+ /* matches smp_wmb() in event_sched_in() */
+ smp_rmb();
+
+ /*
+ * There is a window with interrupts enabled before we get here,
+ * so we need to check again lest we try to stop another CPU's event.
+ */
+ if (READ_ONCE(event->oncpu) != smp_processor_id())
+ return -EAGAIN;
+
+ event->pmu->stop(event, PERF_EF_UPDATE);
+
+ return 0;
+}
+
static int _perf_event_refresh(struct perf_event *event, int refresh)
{
/*
@@ -3461,7 +3490,6 @@ static struct task_struct *
find_lively_task_by_vpid(pid_t vpid)
{
struct task_struct *task;
- int err;
rcu_read_lock();
if (!vpid)
@@ -3475,16 +3503,7 @@ find_lively_task_by_vpid(pid_t vpid)
if (!task)
return ERR_PTR(-ESRCH);
- /* Reuse ptrace permission checks for now. */
- err = -EACCES;
- if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS))
- goto errout;
-
return task;
-errout:
- put_task_struct(task);
- return ERR_PTR(err);
-
}
/*
@@ -3745,6 +3764,9 @@ static void __free_event(struct perf_event *event)
if (event->destroy)
event->destroy(event);
+ if (event->pmu->free_drv_configs)
+ event->pmu->free_drv_configs(event);
+
if (event->ctx)
put_ctx(event->ctx);
@@ -4306,6 +4328,8 @@ static int perf_event_set_output(struct perf_event *event,
struct perf_event *output_event);
static int perf_event_set_filter(struct perf_event *event, void __user *arg);
static int perf_event_set_bpf_prog(struct perf_event *event, u32 prog_fd);
+static int perf_event_drv_configs(struct perf_event *event,
+ void __user *arg);
static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned long arg)
{
@@ -4362,6 +4386,9 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon
case PERF_EVENT_IOC_SET_BPF:
return perf_event_set_bpf_prog(event, arg);
+ case PERF_EVENT_IOC_SET_DRV_CONFIGS:
+ return perf_event_drv_configs(event, (void __user *)arg);
+
default:
return -ENOTTY;
}
@@ -4394,6 +4421,7 @@ static long perf_compat_ioctl(struct file *file, unsigned int cmd,
switch (_IOC_NR(cmd)) {
case _IOC_NR(PERF_EVENT_IOC_SET_FILTER):
case _IOC_NR(PERF_EVENT_IOC_ID):
+ case _IOC_NR(PERF_EVENT_IOC_SET_DRV_CONFIGS):
/* Fix up pointer size (usually 4 -> 8 in 32-on-64-bit case */
if (_IOC_SIZE(cmd) == sizeof(compat_uptr_t)) {
cmd &= ~IOCSIZE_MASK;
@@ -4678,6 +4706,8 @@ static void perf_mmap_open(struct vm_area_struct *vma)
event->pmu->event_mapped(event);
}
+static void perf_pmu_output_stop(struct perf_event *event);
+
/*
* A buffer can be mmap()ed multiple times; either directly through the same
* event, or through other events by use of perf_event_set_output().
@@ -4705,10 +4735,22 @@ static void perf_mmap_close(struct vm_area_struct *vma)
*/
if (rb_has_aux(rb) && vma->vm_pgoff == rb->aux_pgoff &&
atomic_dec_and_mutex_lock(&rb->aux_mmap_count, &event->mmap_mutex)) {
+ /*
+ * Stop all AUX events that are writing to this buffer,
+ * so that we can free its AUX pages and corresponding PMU
+ * data. Note that after rb::aux_mmap_count dropped to zero,
+ * they won't start any more (see perf_aux_output_begin()).
+ */
+ perf_pmu_output_stop(event);
+
+ /* now it's safe to free the pages */
atomic_long_sub(rb->aux_nr_pages, &mmap_user->locked_vm);
vma->vm_mm->pinned_vm -= rb->aux_mmap_locked;
+ /* this has to be the last one */
rb_free_aux(rb);
+ WARN_ON_ONCE(atomic_read(&rb->aux_refcount));
+
mutex_unlock(&event->mmap_mutex);
}
@@ -5779,6 +5821,80 @@ next:
rcu_read_unlock();
}
+struct remote_output {
+ struct ring_buffer *rb;
+ int err;
+};
+
+static void __perf_event_output_stop(struct perf_event *event, void *data)
+{
+ struct perf_event *parent = event->parent;
+ struct remote_output *ro = data;
+ struct ring_buffer *rb = ro->rb;
+
+ if (!has_aux(event))
+ return;
+
+ if (!parent)
+ parent = event;
+
+ /*
+ * In case of inheritance, it will be the parent that links to the
+ * ring-buffer, but it will be the child that's actually using it:
+ */
+ if (rcu_dereference(parent->rb) == rb)
+ ro->err = __perf_event_stop(event);
+}
+
+static int __perf_pmu_output_stop(void *info)
+{
+ struct perf_event *event = info;
+ struct pmu *pmu = event->pmu;
+ struct perf_cpu_context *cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+ struct remote_output ro = {
+ .rb = event->rb,
+ };
+
+ rcu_read_lock();
+ perf_event_aux_ctx(&cpuctx->ctx, __perf_event_output_stop, &ro);
+ if (cpuctx->task_ctx)
+ perf_event_aux_ctx(cpuctx->task_ctx, __perf_event_output_stop,
+ &ro);
+ rcu_read_unlock();
+
+ return ro.err;
+}
+
+static void perf_pmu_output_stop(struct perf_event *event)
+{
+ struct perf_event *iter;
+ int err, cpu;
+
+restart:
+ rcu_read_lock();
+ list_for_each_entry_rcu(iter, &event->rb->event_list, rb_entry) {
+ /*
+ * For per-CPU events, we need to make sure that neither they
+ * nor their children are running; for cpu==-1 events it's
+ * sufficient to stop the event itself if it's active, since
+ * it can't have children.
+ */
+ cpu = iter->cpu;
+ if (cpu == -1)
+ cpu = READ_ONCE(iter->oncpu);
+
+ if (cpu == -1)
+ continue;
+
+ err = cpu_function_call(cpu, __perf_pmu_output_stop, event);
+ if (err == -EAGAIN) {
+ rcu_read_unlock();
+ goto restart;
+ }
+ }
+ rcu_read_unlock();
+}
+
/*
* task tracking -- fork/exit
*
@@ -7167,7 +7283,7 @@ static void perf_event_free_bpf_prog(struct perf_event *event)
prog = event->tp_event->prog;
if (prog) {
event->tp_event->prog = NULL;
- bpf_prog_put(prog);
+ bpf_prog_put_rcu(prog);
}
}
@@ -7209,6 +7325,15 @@ void perf_bp_event(struct perf_event *bp, void *data)
}
#endif
+static int perf_event_drv_configs(struct perf_event *event,
+ void __user *arg)
+{
+ if (!event->pmu->get_drv_configs)
+ return -EINVAL;
+
+ return event->pmu->get_drv_configs(event, arg);
+}
+
/*
* hrtimer based swevent callback
*/
@@ -7949,6 +8074,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
INIT_LIST_HEAD(&event->sibling_list);
INIT_LIST_HEAD(&event->rb_entry);
INIT_LIST_HEAD(&event->active_entry);
+ INIT_LIST_HEAD(&event->drv_configs);
INIT_HLIST_NODE(&event->hlist_entry);
@@ -8395,6 +8521,24 @@ SYSCALL_DEFINE5(perf_event_open,
get_online_cpus();
+ if (task) {
+ err = mutex_lock_interruptible(&task->signal->cred_guard_mutex);
+ if (err)
+ goto err_cpus;
+
+ /*
+ * Reuse ptrace permission checks for now.
+ *
+ * We must hold cred_guard_mutex across this and any potential
+ * perf_install_in_context() call for this new event to
+ * serialize against exec() altering our credentials (and the
+ * perf_event_exit_task() that could imply).
+ */
+ err = -EACCES;
+ if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS))
+ goto err_cred;
+ }
+
if (flags & PERF_FLAG_PID_CGROUP)
cgroup_fd = pid;
@@ -8402,7 +8546,7 @@ SYSCALL_DEFINE5(perf_event_open,
NULL, NULL, cgroup_fd);
if (IS_ERR(event)) {
err = PTR_ERR(event);
- goto err_cpus;
+ goto err_cred;
}
if (is_sampling_event(event)) {
@@ -8461,11 +8605,6 @@ SYSCALL_DEFINE5(perf_event_open,
goto err_context;
}
- if (task) {
- put_task_struct(task);
- task = NULL;
- }
-
/*
* Look up the group leader (we will attach this event to it):
*/
@@ -8524,6 +8663,7 @@ SYSCALL_DEFINE5(perf_event_open,
f_flags);
if (IS_ERR(event_file)) {
err = PTR_ERR(event_file);
+ event_file = NULL;
goto err_context;
}
@@ -8553,6 +8693,11 @@ SYSCALL_DEFINE5(perf_event_open,
WARN_ON_ONCE(ctx->parent_ctx);
+ /*
+ * This is the point on no return; we cannot fail hereafter. This is
+ * where we start modifying current state.
+ */
+
if (move_group) {
/*
* See perf_event_ctx_lock() for comments on the details
@@ -8622,6 +8767,11 @@ SYSCALL_DEFINE5(perf_event_open,
mutex_unlock(&gctx->mutex);
mutex_unlock(&ctx->mutex);
+ if (task) {
+ mutex_unlock(&task->signal->cred_guard_mutex);
+ put_task_struct(task);
+ }
+
put_online_cpus();
event->owner = current;
@@ -8656,6 +8806,9 @@ err_alloc:
*/
if (!event_file)
free_event(event);
+err_cred:
+ if (task)
+ mutex_unlock(&task->signal->cred_guard_mutex);
err_cpus:
put_online_cpus();
err_task:
@@ -8935,6 +9088,9 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
/*
* When a child task exits, feed back event values to parent events.
+ *
+ * Can be called with cred_guard_mutex held when called from
+ * install_exec_creds().
*/
void perf_event_exit_task(struct task_struct *child)
{
diff --git a/kernel/events/internal.h b/kernel/events/internal.h
index 2bbad9c1274c..2b229fdcfc09 100644
--- a/kernel/events/internal.h
+++ b/kernel/events/internal.h
@@ -11,7 +11,6 @@
struct ring_buffer {
atomic_t refcount;
struct rcu_head rcu_head;
- struct irq_work irq_work;
#ifdef CONFIG_PERF_USE_VMALLOC
struct work_struct work;
int page_order; /* allocation order */
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index 014b69528194..8c60a4eb4080 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -221,8 +221,6 @@ void perf_output_end(struct perf_output_handle *handle)
rcu_read_unlock();
}
-static void rb_irq_work(struct irq_work *work);
-
static void
ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
{
@@ -243,16 +241,6 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
INIT_LIST_HEAD(&rb->event_list);
spin_lock_init(&rb->event_lock);
- init_irq_work(&rb->irq_work, rb_irq_work);
-}
-
-static void ring_buffer_put_async(struct ring_buffer *rb)
-{
- if (!atomic_dec_and_test(&rb->refcount))
- return;
-
- rb->rcu_head.next = (void *)rb;
- irq_work_queue(&rb->irq_work);
}
/*
@@ -264,6 +252,10 @@ static void ring_buffer_put_async(struct ring_buffer *rb)
* The ordering is similar to that of perf_output_{begin,end}, with
* the exception of (B), which should be taken care of by the pmu
* driver, since ordering rules will differ depending on hardware.
+ *
+ * Call this from pmu::start(); see the comment in perf_aux_output_end()
+ * about its use in pmu callbacks. Both can also be called from the PMI
+ * handler if needed.
*/
void *perf_aux_output_begin(struct perf_output_handle *handle,
struct perf_event *event)
@@ -288,6 +280,13 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
goto err;
/*
+ * If rb::aux_mmap_count is zero (and rb_has_aux() above went through),
+ * the aux buffer is in perf_mmap_close(), about to get freed.
+ */
+ if (!atomic_read(&rb->aux_mmap_count))
+ goto err_put;
+
+ /*
* Nesting is not supported for AUX area, make sure nested
* writers are caught early
*/
@@ -328,10 +327,11 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
return handle->rb->aux_priv;
err_put:
+ /* can't be last */
rb_free_aux(rb);
err:
- ring_buffer_put_async(rb);
+ ring_buffer_put(rb);
handle->event = NULL;
return NULL;
@@ -342,6 +342,10 @@ err:
* aux_head and posting a PERF_RECORD_AUX into the perf buffer. It is the
* pmu driver's responsibility to observe ordering rules of the hardware,
* so that all the data is externally visible before this is called.
+ *
+ * Note: this has to be called from pmu::stop() callback, as the assumption
+ * of the AUX buffer management code is that after pmu::stop(), the AUX
+ * transaction must be stopped and therefore drop the AUX reference count.
*/
void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size,
bool truncated)
@@ -389,8 +393,9 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size,
handle->event = NULL;
local_set(&rb->aux_nest, 0);
+ /* can't be last */
rb_free_aux(rb);
- ring_buffer_put_async(rb);
+ ring_buffer_put(rb);
}
/*
@@ -467,6 +472,33 @@ static void rb_free_aux_page(struct ring_buffer *rb, int idx)
__free_page(page);
}
+static void __rb_free_aux(struct ring_buffer *rb)
+{
+ int pg;
+
+ /*
+ * Should never happen, the last reference should be dropped from
+ * perf_mmap_close() path, which first stops aux transactions (which
+ * in turn are the atomic holders of aux_refcount) and then does the
+ * last rb_free_aux().
+ */
+ WARN_ON_ONCE(in_atomic());
+
+ if (rb->aux_priv) {
+ rb->free_aux(rb->aux_priv);
+ rb->free_aux = NULL;
+ rb->aux_priv = NULL;
+ }
+
+ if (rb->aux_nr_pages) {
+ for (pg = 0; pg < rb->aux_nr_pages; pg++)
+ rb_free_aux_page(rb, pg);
+
+ kfree(rb->aux_pages);
+ rb->aux_nr_pages = 0;
+ }
+}
+
int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event,
pgoff_t pgoff, int nr_pages, long watermark, int flags)
{
@@ -530,7 +562,7 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event,
goto out;
}
- rb->aux_priv = event->pmu->setup_aux(event->cpu, rb->aux_pages, nr_pages,
+ rb->aux_priv = event->pmu->setup_aux(event, rb->aux_pages, nr_pages,
overwrite);
if (!rb->aux_priv)
goto out;
@@ -555,45 +587,15 @@ out:
if (!ret)
rb->aux_pgoff = pgoff;
else
- rb_free_aux(rb);
+ __rb_free_aux(rb);
return ret;
}
-static void __rb_free_aux(struct ring_buffer *rb)
-{
- int pg;
-
- if (rb->aux_priv) {
- rb->free_aux(rb->aux_priv);
- rb->free_aux = NULL;
- rb->aux_priv = NULL;
- }
-
- if (rb->aux_nr_pages) {
- for (pg = 0; pg < rb->aux_nr_pages; pg++)
- rb_free_aux_page(rb, pg);
-
- kfree(rb->aux_pages);
- rb->aux_nr_pages = 0;
- }
-}
-
void rb_free_aux(struct ring_buffer *rb)
{
if (atomic_dec_and_test(&rb->aux_refcount))
- irq_work_queue(&rb->irq_work);
-}
-
-static void rb_irq_work(struct irq_work *work)
-{
- struct ring_buffer *rb = container_of(work, struct ring_buffer, irq_work);
-
- if (!atomic_read(&rb->aux_refcount))
__rb_free_aux(rb);
-
- if (rb->rcu_head.next == (void *)rb)
- call_rcu(&rb->rcu_head, rb_free_rcu);
}
#ifndef CONFIG_PERF_USE_VMALLOC
diff --git a/kernel/exit.c b/kernel/exit.c
index a32e83d567b9..d61f001c5788 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -931,17 +931,28 @@ static int eligible_pid(struct wait_opts *wo, struct task_struct *p)
task_pid_type(p, wo->wo_type) == wo->wo_pid;
}
-static int eligible_child(struct wait_opts *wo, struct task_struct *p)
+static int
+eligible_child(struct wait_opts *wo, bool ptrace, struct task_struct *p)
{
if (!eligible_pid(wo, p))
return 0;
- /* Wait for all children (clone and not) if __WALL is set;
- * otherwise, wait for clone children *only* if __WCLONE is
- * set; otherwise, wait for non-clone children *only*. (Note:
- * A "clone" child here is one that reports to its parent
- * using a signal other than SIGCHLD.) */
- if (((p->exit_signal != SIGCHLD) ^ !!(wo->wo_flags & __WCLONE))
- && !(wo->wo_flags & __WALL))
+
+ /*
+ * Wait for all children (clone and not) if __WALL is set or
+ * if it is traced by us.
+ */
+ if (ptrace || (wo->wo_flags & __WALL))
+ return 1;
+
+ /*
+ * Otherwise, wait for clone children *only* if __WCLONE is set;
+ * otherwise, wait for non-clone children *only*.
+ *
+ * Note: a "clone" child here is one that reports to its parent
+ * using a signal other than SIGCHLD, or a non-leader thread which
+ * we can only see if it is traced by us.
+ */
+ if ((p->exit_signal != SIGCHLD) ^ !!(wo->wo_flags & __WCLONE))
return 0;
return 1;
@@ -1314,7 +1325,7 @@ static int wait_consider_task(struct wait_opts *wo, int ptrace,
if (unlikely(exit_state == EXIT_DEAD))
return 0;
- ret = eligible_child(wo, p);
+ ret = eligible_child(wo, ptrace, p);
if (!ret)
return ret;
diff --git a/kernel/fork.c b/kernel/fork.c
index 8a5962276788..a46ce4505066 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1654,6 +1654,7 @@ bad_fork_cleanup_audit:
bad_fork_cleanup_perf:
perf_event_free_task(p);
bad_fork_cleanup_policy:
+ free_task_load_ptrs(p);
#ifdef CONFIG_NUMA
mpol_put(p->mempolicy);
bad_fork_cleanup_threadgroup_lock:
diff --git a/kernel/include/linux/input/synaptics_dsx.h b/kernel/include/linux/input/synaptics_dsx.h
deleted file mode 100644
index b779e42a9bac..000000000000
--- a/kernel/include/linux/input/synaptics_dsx.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Synaptics RMI4 touchscreen driver
- *
- * Copyright (C) 2012 Synaptics Incorporated
- *
- * Copyright (C) 2012 Alexandra Chin <alexandra.chin@tw.synaptics.com>
- * Copyright (C) 2012 Scott Lin <scott.lin@tw.synaptics.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SYNAPTICS_DSX_H_
-#define _SYNAPTICS_DSX_H_
-
-/*
- * struct synaptics_rmi4_capacitance_button_map - 0d button map
- * @nbuttons: number of buttons
- * @map: button map
- */
-struct synaptics_rmi4_capacitance_button_map {
- unsigned char nbuttons;
- unsigned char *map;
-};
-
-/*
- * struct synaptics_rmi4_platform_data - rmi4 platform data
- * @x_flip: x flip flag
- * @y_flip: y flip flag
- * @regulator_en: regulator enable flag
- * @irq_gpio: attention interrupt gpio
- * @irq_flags: flags used by the irq
- * @reset_gpio: reset gpio
- * @panel_x: panel maximum values on the x
- * @panel_y: panel maximum values on the y
- * @gpio_config: pointer to gpio configuration function
- * @capacitance_button_map: pointer to 0d button map
- */
-struct synaptics_rmi4_platform_data {
- bool x_flip;
- bool y_flip;
- bool regulator_en;
- unsigned irq_gpio;
- unsigned long irq_flags;
- unsigned reset_gpio;
- unsigned panel_x;
- unsigned panel_y;
- int (*gpio_config)(unsigned gpio, bool configure);
- struct synaptics_rmi4_capacitance_button_map *capacitance_button_map;
-};
-
-#endif
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index 05254eeb4b4e..4b353e0be121 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -58,13 +58,36 @@ static void jump_label_update(struct static_key *key);
void static_key_slow_inc(struct static_key *key)
{
+ int v, v1;
+
STATIC_KEY_CHECK_USE();
- if (atomic_inc_not_zero(&key->enabled))
- return;
+
+ /*
+ * Careful if we get concurrent static_key_slow_inc() calls;
+ * later calls must wait for the first one to _finish_ the
+ * jump_label_update() process. At the same time, however,
+ * the jump_label_update() call below wants to see
+ * static_key_enabled(&key) for jumps to be updated properly.
+ *
+ * So give a special meaning to negative key->enabled: it sends
+ * static_key_slow_inc() down the slow path, and it is non-zero
+ * so it counts as "enabled" in jump_label_update(). Note that
+ * atomic_inc_unless_negative() checks >= 0, so roll our own.
+ */
+ for (v = atomic_read(&key->enabled); v > 0; v = v1) {
+ v1 = atomic_cmpxchg(&key->enabled, v, v + 1);
+ if (likely(v1 == v))
+ return;
+ }
jump_label_lock();
- if (atomic_inc_return(&key->enabled) == 1)
+ if (atomic_read(&key->enabled) == 0) {
+ atomic_set(&key->enabled, -1);
jump_label_update(key);
+ atomic_set(&key->enabled, 1);
+ } else {
+ atomic_inc(&key->enabled);
+ }
jump_label_unlock();
}
EXPORT_SYMBOL_GPL(static_key_slow_inc);
@@ -72,6 +95,13 @@ EXPORT_SYMBOL_GPL(static_key_slow_inc);
static void __static_key_slow_dec(struct static_key *key,
unsigned long rate_limit, struct delayed_work *work)
{
+ /*
+ * The negative count check is valid even when a negative
+ * key->enabled is in use by static_key_slow_inc(); a
+ * __static_key_slow_dec() before the first static_key_slow_inc()
+ * returns is unbalanced, because all other static_key_slow_inc()
+ * instances block while the update is in progress.
+ */
if (!atomic_dec_and_mutex_lock(&key->enabled, &jump_label_mutex)) {
WARN(atomic_read(&key->enabled) < 0,
"jump label: negative count!\n");
diff --git a/kernel/locking/mutex.c b/kernel/locking/mutex.c
index fb42418507ae..14b9cca36b05 100644
--- a/kernel/locking/mutex.c
+++ b/kernel/locking/mutex.c
@@ -498,9 +498,6 @@ __ww_mutex_lock_check_stamp(struct mutex *lock, struct ww_acquire_ctx *ctx)
if (!hold_ctx)
return 0;
- if (unlikely(ctx == hold_ctx))
- return -EALREADY;
-
if (ctx->stamp - hold_ctx->stamp <= LONG_MAX &&
(ctx->stamp != hold_ctx->stamp || ctx > hold_ctx)) {
#ifdef CONFIG_DEBUG_MUTEXES
@@ -526,6 +523,12 @@ __mutex_lock_common(struct mutex *lock, long state, unsigned int subclass,
unsigned long flags;
int ret;
+ if (use_ww_ctx) {
+ struct ww_mutex *ww = container_of(lock, struct ww_mutex, base);
+ if (unlikely(ww_ctx == READ_ONCE(ww->ctx)))
+ return -EALREADY;
+ }
+
preempt_disable();
mutex_acquire_nest(&lock->dep_map, subclass, 0, nest_lock, ip);
diff --git a/kernel/locking/qspinlock.c b/kernel/locking/qspinlock.c
index 87e9ce6a63c5..8173bc7fec92 100644
--- a/kernel/locking/qspinlock.c
+++ b/kernel/locking/qspinlock.c
@@ -255,6 +255,66 @@ static __always_inline void __pv_wait_head(struct qspinlock *lock,
#define queued_spin_lock_slowpath native_queued_spin_lock_slowpath
#endif
+/*
+ * queued_spin_lock_slowpath() can (load-)ACQUIRE the lock before
+ * issuing an _unordered_ store to set _Q_LOCKED_VAL.
+ *
+ * This means that the store can be delayed, but no later than the
+ * store-release from the unlock. This means that simply observing
+ * _Q_LOCKED_VAL is not sufficient to determine if the lock is acquired.
+ *
+ * There are two paths that can issue the unordered store:
+ *
+ * (1) clear_pending_set_locked(): *,1,0 -> *,0,1
+ *
+ * (2) set_locked(): t,0,0 -> t,0,1 ; t != 0
+ * atomic_cmpxchg_relaxed(): t,0,0 -> 0,0,1
+ *
+ * However, in both cases we have other !0 state we've set before to queue
+ * ourseves:
+ *
+ * For (1) we have the atomic_cmpxchg_acquire() that set _Q_PENDING_VAL, our
+ * load is constrained by that ACQUIRE to not pass before that, and thus must
+ * observe the store.
+ *
+ * For (2) we have a more intersting scenario. We enqueue ourselves using
+ * xchg_tail(), which ends up being a RELEASE. This in itself is not
+ * sufficient, however that is followed by an smp_cond_acquire() on the same
+ * word, giving a RELEASE->ACQUIRE ordering. This again constrains our load and
+ * guarantees we must observe that store.
+ *
+ * Therefore both cases have other !0 state that is observable before the
+ * unordered locked byte store comes through. This means we can use that to
+ * wait for the lock store, and then wait for an unlock.
+ */
+#ifndef queued_spin_unlock_wait
+void queued_spin_unlock_wait(struct qspinlock *lock)
+{
+ u32 val;
+
+ for (;;) {
+ val = atomic_read(&lock->val);
+
+ if (!val) /* not locked, we're done */
+ goto done;
+
+ if (val & _Q_LOCKED_MASK) /* locked, go wait for unlock */
+ break;
+
+ /* not locked, but pending, wait until we observe the lock */
+ cpu_relax();
+ }
+
+ /* any unlock is good */
+ while (atomic_read(&lock->val) & _Q_LOCKED_MASK)
+ cpu_relax();
+
+done:
+ smp_rmb(); /* CTRL + RMB -> ACQUIRE */
+}
+EXPORT_SYMBOL(queued_spin_unlock_wait);
+#endif
+
#endif /* _GEN_PV_LOCK_SLOWPATH */
/**
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index f3b1688b3be7..862eb8fd3860 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1912,7 +1912,7 @@ void scheduler_ipi(void)
/*
* Check if someone kicked us for doing the nohz idle load balance.
*/
- if (unlikely(got_nohz_idle_kick())) {
+ if (unlikely(got_nohz_idle_kick()) && !cpu_isolated(cpu)) {
this_rq()->idle_balance = 1;
raise_softirq_irqoff(SCHED_SOFTIRQ);
}
@@ -2269,17 +2269,7 @@ void sched_exit(struct task_struct *p)
reset_task_stats(p);
p->ravg.mark_start = wallclock;
p->ravg.sum_history[0] = EXITING_TASK_MARKER;
-
- kfree(p->ravg.curr_window_cpu);
- kfree(p->ravg.prev_window_cpu);
-
- /*
- * update_task_ravg() can be called for exiting tasks. While the
- * function itself ensures correct behavior, the corresponding
- * trace event requires that these pointers be NULL.
- */
- p->ravg.curr_window_cpu = NULL;
- p->ravg.prev_window_cpu = NULL;
+ free_task_load_ptrs(p);
enqueue_task(rq, p, 0);
clear_ed_task(p, rq);
@@ -2384,10 +2374,12 @@ int sysctl_numa_balancing(struct ctl_table *table, int write,
int sched_fork(unsigned long clone_flags, struct task_struct *p)
{
unsigned long flags;
- int cpu = get_cpu();
+ int cpu;
- __sched_fork(clone_flags, p);
init_new_task_load(p, false);
+ cpu = get_cpu();
+
+ __sched_fork(clone_flags, p);
/*
* We mark the process as running here. This guarantees that
* nobody will actually run it, and a signal or other external
@@ -5505,7 +5497,7 @@ static void migrate_tasks(struct rq *dead_rq, bool migrate_pinned_tasks)
*/
if ((migrate_pinned_tasks && rq->nr_running == 1) ||
(!migrate_pinned_tasks &&
- rq->nr_running == num_pinned_kthreads))
+ rq->nr_running <= num_pinned_kthreads))
break;
/*
@@ -5541,8 +5533,12 @@ static void migrate_tasks(struct rq *dead_rq, bool migrate_pinned_tasks)
* Since we're inside stop-machine, _nothing_ should have
* changed the task, WARN if weird stuff happened, because in
* that case the above rq->lock drop is a fail too.
+ * However, during cpu isolation the load balancer might have
+ * interferred since we don't stop all CPUs. Ignore warning for
+ * this case.
*/
- if (WARN_ON(task_rq(next) != rq || !task_on_rq_queued(next))) {
+ if (WARN_ON((task_rq(next) != rq || !task_on_rq_queued(next)) &&
+ migrate_pinned_tasks)) {
raw_spin_unlock(&next->pi_lock);
continue;
}
@@ -5570,7 +5566,6 @@ static void set_rq_offline(struct rq *rq);
int do_isolation_work_cpu_stop(void *data)
{
- unsigned long flags;
unsigned int cpu = smp_processor_id();
struct rq *rq = cpu_rq(cpu);
@@ -5578,23 +5573,35 @@ int do_isolation_work_cpu_stop(void *data)
irq_migrate_all_off_this_cpu();
+ local_irq_disable();
+
sched_ttwu_pending();
- /* Update our root-domain */
- raw_spin_lock_irqsave(&rq->lock, flags);
+ raw_spin_lock(&rq->lock);
+
+ /*
+ * Temporarily mark the rq as offline. This will allow us to
+ * move tasks off the CPU.
+ */
if (rq->rd) {
BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
set_rq_offline(rq);
}
migrate_tasks(rq, false);
- raw_spin_unlock_irqrestore(&rq->lock, flags);
+
+ if (rq->rd)
+ set_rq_online(rq);
+ raw_spin_unlock(&rq->lock);
/*
* We might have been in tickless state. Clear NOHZ flags to avoid
* us being kicked for helping out with balancing
*/
nohz_balance_clear_nohz_mask(cpu);
+
+ clear_hmp_request(cpu);
+ local_irq_enable();
return 0;
}
@@ -5693,6 +5700,22 @@ int sched_isolate_cpu(int cpu)
if (++cpu_isolation_vote[cpu] > 1)
goto out;
+ /*
+ * There is a race between watchdog being enabled by hotplug and
+ * core isolation disabling the watchdog. When a CPU is hotplugged in
+ * and the hotplug lock has been released the watchdog thread might
+ * not have run yet to enable the watchdog.
+ * We have to wait for the watchdog to be enabled before proceeding.
+ */
+ if (!watchdog_configured(cpu)) {
+ msleep(20);
+ if (!watchdog_configured(cpu)) {
+ --cpu_isolation_vote[cpu];
+ ret_code = -EBUSY;
+ goto out;
+ }
+ }
+
set_cpu_isolated(cpu, true);
cpumask_clear_cpu(cpu, &avail_cpus);
@@ -5703,7 +5726,6 @@ int sched_isolate_cpu(int cpu)
migrate_sync_cpu(cpu, cpumask_first(&avail_cpus));
stop_cpus(cpumask_of(cpu), do_isolation_work_cpu_stop, 0);
- clear_hmp_request(cpu);
calc_load_migrate(rq);
update_max_interval();
sched_update_group_capacities(cpu);
@@ -5745,10 +5767,6 @@ int sched_unisolate_cpu_unlocked(int cpu)
raw_spin_lock_irqsave(&rq->lock, flags);
rq->age_stamp = sched_clock_cpu(cpu);
- if (rq->rd) {
- BUG_ON(!cpumask_test_cpu(cpu, rq->rd->span));
- set_rq_online(rq);
- }
raw_spin_unlock_irqrestore(&rq->lock, flags);
}
diff --git a/kernel/sched/core_ctl.c b/kernel/sched/core_ctl.c
index 0db85a4fa9c8..ecf6c568f0b5 100644
--- a/kernel/sched/core_ctl.c
+++ b/kernel/sched/core_ctl.c
@@ -719,8 +719,18 @@ static void move_cpu_lru(struct cpu_data *cpu_data)
static void try_to_isolate(struct cluster_data *cluster, unsigned int need)
{
struct cpu_data *c, *tmp;
+ unsigned long flags;
+ unsigned int num_cpus = cluster->num_cpus;
+ /*
+ * Protect against entry being removed (and added at tail) by other
+ * thread (hotplug).
+ */
+ spin_lock_irqsave(&state_lock, flags);
list_for_each_entry_safe(c, tmp, &cluster->lru, sib) {
+ if (!num_cpus--)
+ break;
+
if (!is_active(c))
continue;
if (cluster->active_cpus == need)
@@ -729,6 +739,8 @@ static void try_to_isolate(struct cluster_data *cluster, unsigned int need)
if (c->is_busy)
continue;
+ spin_unlock_irqrestore(&state_lock, flags);
+
pr_debug("Trying to isolate CPU%u\n", c->cpu);
if (!sched_isolate_cpu(c->cpu)) {
c->isolated_by_us = true;
@@ -738,7 +750,9 @@ static void try_to_isolate(struct cluster_data *cluster, unsigned int need)
pr_debug("Unable to isolate CPU%u\n", c->cpu);
}
cluster->active_cpus = get_active_cpu_count(cluster);
+ spin_lock_irqsave(&state_lock, flags);
}
+ spin_unlock_irqrestore(&state_lock, flags);
/*
* If the number of active CPUs is within the limits, then
@@ -747,12 +761,19 @@ static void try_to_isolate(struct cluster_data *cluster, unsigned int need)
if (cluster->active_cpus <= cluster->max_cpus)
return;
+ num_cpus = cluster->num_cpus;
+ spin_lock_irqsave(&state_lock, flags);
list_for_each_entry_safe(c, tmp, &cluster->lru, sib) {
+ if (!num_cpus--)
+ break;
+
if (!is_active(c))
continue;
if (cluster->active_cpus <= cluster->max_cpus)
break;
+ spin_unlock_irqrestore(&state_lock, flags);
+
pr_debug("Trying to isolate CPU%u\n", c->cpu);
if (!sched_isolate_cpu(c->cpu)) {
c->isolated_by_us = true;
@@ -762,15 +783,28 @@ static void try_to_isolate(struct cluster_data *cluster, unsigned int need)
pr_debug("Unable to isolate CPU%u\n", c->cpu);
}
cluster->active_cpus = get_active_cpu_count(cluster);
+ spin_lock_irqsave(&state_lock, flags);
}
+ spin_unlock_irqrestore(&state_lock, flags);
+
}
static void __try_to_unisolate(struct cluster_data *cluster,
unsigned int need, bool force)
{
struct cpu_data *c, *tmp;
+ unsigned long flags;
+ unsigned int num_cpus = cluster->num_cpus;
+ /*
+ * Protect against entry being removed (and added at tail) by other
+ * thread (hotplug).
+ */
+ spin_lock_irqsave(&state_lock, flags);
list_for_each_entry_safe(c, tmp, &cluster->lru, sib) {
+ if (!num_cpus--)
+ break;
+
if (!c->isolated_by_us)
continue;
if ((c->online && !cpu_isolated(c->cpu)) ||
@@ -779,6 +813,8 @@ static void __try_to_unisolate(struct cluster_data *cluster,
if (cluster->active_cpus == need)
break;
+ spin_unlock_irqrestore(&state_lock, flags);
+
pr_debug("Trying to unisolate CPU%u\n", c->cpu);
if (!sched_unisolate_cpu(c->cpu)) {
c->isolated_by_us = false;
@@ -787,7 +823,9 @@ static void __try_to_unisolate(struct cluster_data *cluster,
pr_debug("Unable to unisolate CPU%u\n", c->cpu);
}
cluster->active_cpus = get_active_cpu_count(cluster);
+ spin_lock_irqsave(&state_lock, flags);
}
+ spin_unlock_irqrestore(&state_lock, flags);
}
static void try_to_unisolate(struct cluster_data *cluster, unsigned int need)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index e0f212743c77..1674b1054f83 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -3721,6 +3721,23 @@ static inline void update_tg_load_avg(struct cfs_rq *cfs_rq, int force) {}
static inline u64 cfs_rq_clock_task(struct cfs_rq *cfs_rq);
+/*
+ * Unsigned subtract and clamp on underflow.
+ *
+ * Explicitly do a load-store to ensure the intermediate value never hits
+ * memory. This allows lockless observations without ever seeing the negative
+ * values.
+ */
+#define sub_positive(_ptr, _val) do { \
+ typeof(_ptr) ptr = (_ptr); \
+ typeof(*ptr) val = (_val); \
+ typeof(*ptr) res, var = READ_ONCE(*ptr); \
+ res = var - val; \
+ if (res > var) \
+ res = 0; \
+ WRITE_ONCE(*ptr, res); \
+} while (0)
+
/* Group cfs_rq's load_avg is used for task_h_load and update_cfs_share */
static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
{
@@ -3729,15 +3746,15 @@ static inline int update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq)
if (atomic_long_read(&cfs_rq->removed_load_avg)) {
s64 r = atomic_long_xchg(&cfs_rq->removed_load_avg, 0);
- sa->load_avg = max_t(long, sa->load_avg - r, 0);
- sa->load_sum = max_t(s64, sa->load_sum - r * LOAD_AVG_MAX, 0);
+ sub_positive(&sa->load_avg, r);
+ sub_positive(&sa->load_sum, r * LOAD_AVG_MAX);
removed = 1;
}
if (atomic_long_read(&cfs_rq->removed_util_avg)) {
long r = atomic_long_xchg(&cfs_rq->removed_util_avg, 0);
- sa->util_avg = max_t(long, sa->util_avg - r, 0);
- sa->util_sum = max_t(s32, sa->util_sum - r * LOAD_AVG_MAX, 0);
+ sub_positive(&sa->util_avg, r);
+ sub_positive(&sa->util_sum, r * LOAD_AVG_MAX);
}
decayed = __update_load_avg(now, cpu_of(rq_of(cfs_rq)), sa,
@@ -3803,10 +3820,10 @@ static void detach_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *s
&se->avg, se->on_rq * scale_load_down(se->load.weight),
cfs_rq->curr == se, NULL);
- cfs_rq->avg.load_avg = max_t(long, cfs_rq->avg.load_avg - se->avg.load_avg, 0);
- cfs_rq->avg.load_sum = max_t(s64, cfs_rq->avg.load_sum - se->avg.load_sum, 0);
- cfs_rq->avg.util_avg = max_t(long, cfs_rq->avg.util_avg - se->avg.util_avg, 0);
- cfs_rq->avg.util_sum = max_t(s32, cfs_rq->avg.util_sum - se->avg.util_sum, 0);
+ sub_positive(&cfs_rq->avg.load_avg, se->avg.load_avg);
+ sub_positive(&cfs_rq->avg.load_sum, se->avg.load_sum);
+ sub_positive(&cfs_rq->avg.util_avg, se->avg.util_avg);
+ sub_positive(&cfs_rq->avg.util_sum, se->avg.util_sum);
}
/* Add the load generated by se into cfs_rq's load average */
@@ -8104,8 +8121,11 @@ static struct rq *find_busiest_queue_hmp(struct lb_env *env,
int max_nr_big = 0, nr_big;
bool find_big = !!(env->flags & LBF_BIG_TASK_ACTIVE_BALANCE);
int i;
+ cpumask_t cpus;
- for_each_cpu(i, sched_group_cpus(group)) {
+ cpumask_andnot(&cpus, sched_group_cpus(group), cpu_isolated_mask);
+
+ for_each_cpu(i, &cpus) {
struct rq *rq = cpu_rq(i);
u64 cumulative_runnable_avg =
rq->hmp_stats.cumulative_runnable_avg;
@@ -8268,6 +8288,15 @@ static int need_active_balance(struct lb_env *env)
sd->cache_nice_tries + NEED_ACTIVE_BALANCE_THRESHOLD);
}
+static int group_balance_cpu_not_isolated(struct sched_group *sg)
+{
+ cpumask_t cpus;
+
+ cpumask_and(&cpus, sched_group_cpus(sg), sched_group_mask(sg));
+ cpumask_andnot(&cpus, &cpus, cpu_isolated_mask);
+ return cpumask_first(&cpus);
+}
+
static int should_we_balance(struct lb_env *env)
{
struct sched_group *sg = env->sd->groups;
@@ -8285,7 +8314,8 @@ static int should_we_balance(struct lb_env *env)
sg_mask = sched_group_mask(sg);
/* Try to find first idle cpu */
for_each_cpu_and(cpu, sg_cpus, env->cpus) {
- if (!cpumask_test_cpu(cpu, sg_mask) || !idle_cpu(cpu))
+ if (!cpumask_test_cpu(cpu, sg_mask) || !idle_cpu(cpu) ||
+ cpu_isolated(cpu))
continue;
balance_cpu = cpu;
@@ -8293,7 +8323,7 @@ static int should_we_balance(struct lb_env *env)
}
if (balance_cpu == -1)
- balance_cpu = group_balance_cpu(sg);
+ balance_cpu = group_balance_cpu_not_isolated(sg);
/*
* First idle cpu or the first cpu(busiest) in this sched group
@@ -8513,7 +8543,8 @@ no_move:
* ->active_balance_work. Once set, it's cleared
* only after active load balance is finished.
*/
- if (!busiest->active_balance) {
+ if (!busiest->active_balance &&
+ !cpu_isolated(cpu_of(busiest))) {
busiest->active_balance = 1;
busiest->push_cpu = this_cpu;
active_balance = 1;
@@ -9181,12 +9212,15 @@ static void nohz_idle_balance(struct rq *this_rq, enum cpu_idle_type idle)
/* Earliest time when we have to do rebalance again */
unsigned long next_balance = jiffies + 60*HZ;
int update_next_balance = 0;
+ cpumask_t cpus;
if (idle != CPU_IDLE ||
!test_bit(NOHZ_BALANCE_KICK, nohz_flags(this_cpu)))
goto end;
- for_each_cpu(balance_cpu, nohz.idle_cpus_mask) {
+ cpumask_andnot(&cpus, nohz.idle_cpus_mask, cpu_isolated_mask);
+
+ for_each_cpu(balance_cpu, &cpus) {
if (balance_cpu == this_cpu || !idle_cpu(balance_cpu))
continue;
diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c
index 56f4c60d4d5d..30391aae0822 100644
--- a/kernel/sched/hmp.c
+++ b/kernel/sched/hmp.c
@@ -1624,6 +1624,20 @@ unsigned int cpu_temp(int cpu)
return 0;
}
+void free_task_load_ptrs(struct task_struct *p)
+{
+ kfree(p->ravg.curr_window_cpu);
+ kfree(p->ravg.prev_window_cpu);
+
+ /*
+ * update_task_ravg() can be called for exiting tasks. While the
+ * function itself ensures correct behavior, the corresponding
+ * trace event requires that these pointers be NULL.
+ */
+ p->ravg.curr_window_cpu = NULL;
+ p->ravg.prev_window_cpu = NULL;
+}
+
void init_new_task_load(struct task_struct *p, bool idle_task)
{
int i;
@@ -1636,8 +1650,8 @@ void init_new_task_load(struct task_struct *p, bool idle_task)
memset(&p->ravg, 0, sizeof(struct ravg));
p->cpu_cycles = 0;
- p->ravg.curr_window_cpu = kcalloc(nr_cpu_ids, sizeof(u32), GFP_ATOMIC);
- p->ravg.prev_window_cpu = kcalloc(nr_cpu_ids, sizeof(u32), GFP_ATOMIC);
+ p->ravg.curr_window_cpu = kcalloc(nr_cpu_ids, sizeof(u32), GFP_KERNEL);
+ p->ravg.prev_window_cpu = kcalloc(nr_cpu_ids, sizeof(u32), GFP_KERNEL);
/* Don't have much choice. CPU frequency would be bogus */
BUG_ON(!p->ravg.curr_window_cpu || !p->ravg.prev_window_cpu);
@@ -1814,6 +1828,7 @@ static void group_load_in_freq_domain(struct cpumask *cpus,
}
}
+static inline u64 freq_policy_load(struct rq *rq, u64 load);
/*
* Should scheduler alert governor for changing frequency?
*
@@ -1864,6 +1879,7 @@ static int send_notification(struct rq *rq, int check_pred, int check_groups)
_group_load_in_cpu(cpu_of(rq), &group_load, NULL);
new_load = rq->prev_runnable_sum + group_load;
+ new_load = freq_policy_load(rq, new_load);
raw_spin_unlock_irqrestore(&rq->lock, flags);
read_unlock(&related_thread_group_lock);
@@ -3150,14 +3166,14 @@ void reset_all_window_stats(u64 window_start, unsigned int window_size)
unsigned int old = 0, new = 0;
struct related_thread_group *grp;
+ read_lock(&related_thread_group_lock);
+
disable_window_stats();
reset_all_task_stats();
local_irq_save(flags);
- read_lock(&related_thread_group_lock);
-
for_each_possible_cpu(cpu)
raw_spin_lock(&cpu_rq(cpu)->lock);
@@ -3223,10 +3239,10 @@ void reset_all_window_stats(u64 window_start, unsigned int window_size)
for_each_possible_cpu(cpu)
raw_spin_unlock(&cpu_rq(cpu)->lock);
- read_unlock(&related_thread_group_lock);
-
local_irq_restore(flags);
+ read_unlock(&related_thread_group_lock);
+
trace_sched_reset_all_window_stats(window_start, window_size,
sched_ktime_clock() - start_ts, reason, old, new);
}
@@ -3296,7 +3312,7 @@ void sched_get_cpus_busy(struct sched_load *busy,
u64 load[cpus], group_load[cpus];
u64 nload[cpus], ngload[cpus];
u64 pload[cpus];
- unsigned int cur_freq[cpus], max_freq[cpus];
+ unsigned int max_freq[cpus];
int notifier_sent = 0;
int early_detection[cpus];
int cpu, i = 0;
@@ -3336,10 +3352,9 @@ void sched_get_cpus_busy(struct sched_load *busy,
update_task_ravg(rq->curr, rq, TASK_UPDATE, sched_ktime_clock(),
0);
- cur_freq[i] = cpu_cycles_to_freq(rq->cc.cycles, rq->cc.time);
account_load_subtractions(rq);
- load[i] = rq->old_busy_time = rq->prev_runnable_sum;
+ load[i] = rq->prev_runnable_sum;
nload[i] = rq->nt_prev_runnable_sum;
pload[i] = rq->hmp_stats.pred_demands_sum;
rq->old_estimated_time = pload[i];
@@ -3360,7 +3375,6 @@ void sched_get_cpus_busy(struct sched_load *busy,
rq->cluster->notifier_sent = 0;
}
early_detection[i] = (rq->ed_task != NULL);
- cur_freq[i] = cpu_cur_freq(cpu);
max_freq[i] = cpu_max_freq(cpu);
i++;
}
@@ -3403,6 +3417,8 @@ void sched_get_cpus_busy(struct sched_load *busy,
nload[i] += ngload[i];
load[i] = freq_policy_load(rq, load[i]);
+ rq->old_busy_time = load[i];
+
/*
* Scale load in reference to cluster max_possible_freq.
*
@@ -3433,33 +3449,11 @@ skip_early:
goto exit_early;
}
- /*
- * When the load aggregation is controlled by
- * sched_freq_aggregate_threshold, allow reporting loads
- * greater than 100 @ Fcur to ramp up the frequency
- * faster.
- */
- if (notifier_sent || (aggregate_load &&
- sched_freq_aggregate_threshold)) {
- load[i] = scale_load_to_freq(load[i], max_freq[i],
- cpu_max_possible_freq(cpu));
- nload[i] = scale_load_to_freq(nload[i], max_freq[i],
- cpu_max_possible_freq(cpu));
- } else {
- load[i] = scale_load_to_freq(load[i], max_freq[i],
- cur_freq[i]);
- nload[i] = scale_load_to_freq(nload[i], max_freq[i],
- cur_freq[i]);
- if (load[i] > window_size)
- load[i] = window_size;
- if (nload[i] > window_size)
- nload[i] = window_size;
-
- load[i] = scale_load_to_freq(load[i], cur_freq[i],
- cpu_max_possible_freq(cpu));
- nload[i] = scale_load_to_freq(nload[i], cur_freq[i],
- cpu_max_possible_freq(cpu));
- }
+ load[i] = scale_load_to_freq(load[i], max_freq[i],
+ cpu_max_possible_freq(cpu));
+ nload[i] = scale_load_to_freq(nload[i], max_freq[i],
+ cpu_max_possible_freq(cpu));
+
pload[i] = scale_load_to_freq(pload[i], max_freq[i],
rq->cluster->max_possible_freq);
diff --git a/kernel/sched/loadavg.c b/kernel/sched/loadavg.c
index ef7159012cf3..b0b93fd33af9 100644
--- a/kernel/sched/loadavg.c
+++ b/kernel/sched/loadavg.c
@@ -99,10 +99,13 @@ long calc_load_fold_active(struct rq *this_rq)
static unsigned long
calc_load(unsigned long load, unsigned long exp, unsigned long active)
{
- load *= exp;
- load += active * (FIXED_1 - exp);
- load += 1UL << (FSHIFT - 1);
- return load >> FSHIFT;
+ unsigned long newload;
+
+ newload = load * exp + active * (FIXED_1 - exp);
+ if (active >= load)
+ newload += FIXED_1-1;
+
+ return newload / FIXED_1;
}
#ifdef CONFIG_NO_HZ_COMMON
diff --git a/kernel/sys.c b/kernel/sys.c
index b5a8e844a968..ba3ddb43dd9f 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2319,7 +2319,10 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
error = perf_event_task_enable();
break;
case PR_GET_TIMERSLACK:
- error = current->timer_slack_ns;
+ if (current->timer_slack_ns > ULONG_MAX)
+ error = ULONG_MAX;
+ else
+ error = current->timer_slack_ns;
break;
case PR_SET_TIMERSLACK:
if (arg2 <= 0)
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index c72cb2053da7..574316f1c344 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2022,6 +2022,20 @@ static struct ctl_table fs_table[] = {
.proc_handler = &pipe_proc_fn,
.extra1 = &pipe_min_size,
},
+ {
+ .procname = "pipe-user-pages-hard",
+ .data = &pipe_user_pages_hard,
+ .maxlen = sizeof(pipe_user_pages_hard),
+ .mode = 0644,
+ .proc_handler = proc_doulongvec_minmax,
+ },
+ {
+ .procname = "pipe-user-pages-soft",
+ .data = &pipe_user_pages_soft,
+ .maxlen = sizeof(pipe_user_pages_soft),
+ .mode = 0644,
+ .proc_handler = proc_doulongvec_minmax,
+ },
{ }
};
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 9e1349fc5bbe..c3914e8f87b0 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -49,6 +49,7 @@
#include <linux/sched/deadline.h>
#include <linux/timer.h>
#include <linux/freezer.h>
+#include <linux/delay.h>
#include <asm/uaccess.h>
@@ -985,7 +986,7 @@ static inline ktime_t hrtimer_update_lowres(struct hrtimer *timer, ktime_t tim,
* relative (HRTIMER_MODE_REL)
*/
void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
- unsigned long delta_ns, const enum hrtimer_mode mode)
+ u64 delta_ns, const enum hrtimer_mode mode)
{
struct hrtimer_clock_base *base, *new_base;
unsigned long flags;
@@ -1558,7 +1559,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
struct restart_block *restart;
struct hrtimer_sleeper t;
int ret = 0;
- unsigned long slack;
+ u64 slack;
slack = current->timer_slack_ns;
if (dl_task(current) || rt_task(current))
@@ -1648,6 +1649,12 @@ static void migrate_hrtimer_list(struct hrtimer_cpu_base *old_base,
raw_spin_unlock(&old_base->lock);
raw_spin_unlock(&new_base->lock);
cpu_relax();
+ /*
+ * cpu_relax may just be a barrier. Grant the
+ * run_hrtimer_list code some time to obtain the
+ * spinlock.
+ */
+ udelay(2);
raw_spin_lock(&new_base->lock);
raw_spin_lock_nested(&old_base->lock,
SINGLE_DEPTH_NESTING);
@@ -1780,7 +1787,7 @@ void __init hrtimers_init(void)
* @clock: timer clock, CLOCK_MONOTONIC or CLOCK_REALTIME
*/
int __sched
-schedule_hrtimeout_range_clock(ktime_t *expires, unsigned long delta,
+schedule_hrtimeout_range_clock(ktime_t *expires, u64 delta,
const enum hrtimer_mode mode, int clock)
{
struct hrtimer_sleeper t;
@@ -1848,7 +1855,7 @@ schedule_hrtimeout_range_clock(ktime_t *expires, unsigned long delta,
*
* Returns 0 when the timer has expired otherwise -EINTR
*/
-int __sched schedule_hrtimeout_range(ktime_t *expires, unsigned long delta,
+int __sched schedule_hrtimeout_range(ktime_t *expires, u64 delta,
const enum hrtimer_mode mode)
{
return schedule_hrtimeout_range_clock(expires, delta, mode,
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 0efb3916f5a4..5ebefc7cfa4f 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -1640,7 +1640,7 @@ static void migrate_timer_list(struct tvec_base *new_base,
}
}
-static void __migrate_timers(int cpu, bool wait, bool remove_pinned)
+static void __migrate_timers(int cpu, bool remove_pinned)
{
struct tvec_base *old_base;
struct tvec_base *new_base;
@@ -1656,18 +1656,14 @@ static void __migrate_timers(int cpu, bool wait, bool remove_pinned)
spin_lock_irqsave(&new_base->lock, flags);
spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
- if (wait) {
- /* Ensure timers are done running before continuing */
- while (old_base->running_timer) {
- spin_unlock(&old_base->lock);
- spin_unlock_irqrestore(&new_base->lock, flags);
- cpu_relax();
- spin_lock_irqsave(&new_base->lock, flags);
- spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING);
- }
- } else {
+ /*
+ * If we're in the hotplug path, kill the system if there's a running
+ * timer. It's ok to have a running timer in the isolation case - the
+ * currently running or just expired timers are off of the timer wheel
+ * and so everything else can be migrated off.
+ */
+ if (!cpu_online(cpu))
BUG_ON(old_base->running_timer);
- }
for (i = 0; i < TVR_SIZE; i++)
migrate_timer_list(new_base, old_base->tv1.vec + i,
@@ -1692,12 +1688,12 @@ static void __migrate_timers(int cpu, bool wait, bool remove_pinned)
static void migrate_timers(int cpu)
{
BUG_ON(cpu_online(cpu));
- __migrate_timers(cpu, false, true);
+ __migrate_timers(cpu, true);
}
void timer_quiesce_cpu(void *cpup)
{
- __migrate_timers(*(int *)cpup, true, false);
+ __migrate_timers(*(int *)cpup, false);
}
static int timer_cpu_notify(struct notifier_block *self,
@@ -1784,10 +1780,10 @@ EXPORT_SYMBOL(msleep_interruptible);
static void __sched do_usleep_range(unsigned long min, unsigned long max)
{
ktime_t kmin;
- unsigned long delta;
+ u64 delta;
kmin = ktime_set(0, min * NSEC_PER_USEC);
- delta = (max - min) * NSEC_PER_USEC;
+ delta = (u64)(max - min) * NSEC_PER_USEC;
schedule_hrtimeout_range(&kmin, delta, HRTIMER_MODE_REL);
}
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 9c6045a27ba3..acbb0e73d3a2 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -437,7 +437,7 @@ struct ring_buffer_per_cpu {
raw_spinlock_t reader_lock; /* serialize readers */
arch_spinlock_t lock;
struct lock_class_key lock_key;
- unsigned int nr_pages;
+ unsigned long nr_pages;
unsigned int current_context;
struct list_head *pages;
struct buffer_page *head_page; /* read from head */
@@ -458,7 +458,7 @@ struct ring_buffer_per_cpu {
u64 write_stamp;
u64 read_stamp;
/* ring buffer pages to update, > 0 to add, < 0 to remove */
- int nr_pages_to_update;
+ long nr_pages_to_update;
struct list_head new_pages; /* new pages to add */
struct work_struct update_pages_work;
struct completion update_done;
@@ -1137,10 +1137,10 @@ static int rb_check_pages(struct ring_buffer_per_cpu *cpu_buffer)
return 0;
}
-static int __rb_allocate_pages(int nr_pages, struct list_head *pages, int cpu)
+static int __rb_allocate_pages(long nr_pages, struct list_head *pages, int cpu)
{
- int i;
struct buffer_page *bpage, *tmp;
+ long i;
for (i = 0; i < nr_pages; i++) {
struct page *page;
@@ -1177,7 +1177,7 @@ free_pages:
}
static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
- unsigned nr_pages)
+ unsigned long nr_pages)
{
LIST_HEAD(pages);
@@ -1202,7 +1202,7 @@ static int rb_allocate_pages(struct ring_buffer_per_cpu *cpu_buffer,
}
static struct ring_buffer_per_cpu *
-rb_allocate_cpu_buffer(struct ring_buffer *buffer, int nr_pages, int cpu)
+rb_allocate_cpu_buffer(struct ring_buffer *buffer, long nr_pages, int cpu)
{
struct ring_buffer_per_cpu *cpu_buffer;
struct buffer_page *bpage;
@@ -1302,8 +1302,9 @@ struct ring_buffer *__ring_buffer_alloc(unsigned long size, unsigned flags,
struct lock_class_key *key)
{
struct ring_buffer *buffer;
+ long nr_pages;
int bsize;
- int cpu, nr_pages;
+ int cpu;
/* keep it in its own cache line */
buffer = kzalloc(ALIGN(sizeof(*buffer), cache_line_size()),
@@ -1429,12 +1430,12 @@ static inline unsigned long rb_page_write(struct buffer_page *bpage)
}
static int
-rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned int nr_pages)
+rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned long nr_pages)
{
struct list_head *tail_page, *to_remove, *next_page;
struct buffer_page *to_remove_page, *tmp_iter_page;
struct buffer_page *last_page, *first_page;
- unsigned int nr_removed;
+ unsigned long nr_removed;
unsigned long head_bit;
int page_entries;
@@ -1651,7 +1652,7 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size,
int cpu_id)
{
struct ring_buffer_per_cpu *cpu_buffer;
- unsigned nr_pages;
+ unsigned long nr_pages;
int cpu, err = 0;
/*
@@ -1665,14 +1666,13 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size,
!cpumask_test_cpu(cpu_id, buffer->cpumask))
return size;
- size = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
- size *= BUF_PAGE_SIZE;
+ nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
/* we need a minimum of two pages */
- if (size < BUF_PAGE_SIZE * 2)
- size = BUF_PAGE_SIZE * 2;
+ if (nr_pages < 2)
+ nr_pages = 2;
- nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE);
+ size = nr_pages * BUF_PAGE_SIZE;
/*
* Don't succeed if resizing is disabled, as a reader might be
@@ -4645,8 +4645,9 @@ static int rb_cpu_notify(struct notifier_block *self,
struct ring_buffer *buffer =
container_of(self, struct ring_buffer, cpu_notify);
long cpu = (long)hcpu;
- int cpu_i, nr_pages_same;
- unsigned int nr_pages;
+ long nr_pages_same;
+ int cpu_i;
+ unsigned long nr_pages;
switch (action) {
case CPU_UP_PREPARE:
diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c
index f96f0383f6c6..ad1d6164e946 100644
--- a/kernel/trace/trace_printk.c
+++ b/kernel/trace/trace_printk.c
@@ -36,6 +36,10 @@ struct trace_bprintk_fmt {
static inline struct trace_bprintk_fmt *lookup_format(const char *fmt)
{
struct trace_bprintk_fmt *pos;
+
+ if (!fmt)
+ return ERR_PTR(-EINVAL);
+
list_for_each_entry(pos, &trace_bprintk_fmt_list, list) {
if (!strcmp(pos->fmt, fmt))
return pos;
@@ -57,7 +61,8 @@ void hold_module_trace_bprintk_format(const char **start, const char **end)
for (iter = start; iter < end; iter++) {
struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter);
if (tb_fmt) {
- *iter = tb_fmt->fmt;
+ if (!IS_ERR(tb_fmt))
+ *iter = tb_fmt->fmt;
continue;
}
diff --git a/kernel/watchdog.c b/kernel/watchdog.c
index 7f21591c8ec5..f2813e137b23 100644
--- a/kernel/watchdog.c
+++ b/kernel/watchdog.c
@@ -588,17 +588,13 @@ static void watchdog_set_prio(unsigned int policy, unsigned int prio)
sched_setscheduler(current, policy, &param);
}
-/* Must be called with hotplug lock (lock_device_hotplug()) held. */
void watchdog_enable(unsigned int cpu)
{
struct hrtimer *hrtimer = raw_cpu_ptr(&watchdog_hrtimer);
unsigned int *enabled = raw_cpu_ptr(&watchdog_en);
- lock_device_hotplug_assert();
-
if (*enabled)
return;
- *enabled = 1;
/* kick off the timer for the hardlockup detector */
hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
@@ -614,24 +610,40 @@ void watchdog_enable(unsigned int cpu)
/* initialize timestamp */
watchdog_set_prio(SCHED_FIFO, MAX_RT_PRIO - 1);
__touch_watchdog();
+
+ /*
+ * Need to ensure above operations are observed by other CPUs before
+ * indicating that timer is enabled. This is to synchronize core
+ * isolation and hotplug. Core isolation will wait for this flag to be
+ * set.
+ */
+ mb();
+ *enabled = 1;
}
-/* Must be called with hotplug lock (lock_device_hotplug()) held. */
void watchdog_disable(unsigned int cpu)
{
struct hrtimer *hrtimer = raw_cpu_ptr(&watchdog_hrtimer);
unsigned int *enabled = raw_cpu_ptr(&watchdog_en);
- lock_device_hotplug_assert();
-
if (!*enabled)
return;
- *enabled = 0;
watchdog_set_prio(SCHED_NORMAL, 0);
hrtimer_cancel(hrtimer);
/* disable the perf event */
watchdog_nmi_disable(cpu);
+
+ /*
+ * No need for barrier here since disabling the watchdog is
+ * synchronized with hotplug lock
+ */
+ *enabled = 0;
+}
+
+bool watchdog_configured(unsigned int cpu)
+{
+ return *per_cpu_ptr(&watchdog_en, cpu);
}
static void watchdog_cleanup(unsigned int cpu, bool online)
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 4a1515f4b452..51a76af25c66 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -657,9 +657,9 @@ static struct dma_debug_entry *dma_entry_alloc(void)
spin_lock_irqsave(&free_entries_lock, flags);
if (list_empty(&free_entries)) {
- pr_err("DMA-API: debugging out of memory - disabling\n");
global_disable = true;
spin_unlock_irqrestore(&free_entries_lock, flags);
+ pr_err("DMA-API: debugging out of memory - disabling\n");
return NULL;
}
diff --git a/mm/debug-pagealloc.c b/mm/debug-pagealloc.c
index e060c7cdf24c..100963091cc6 100644
--- a/mm/debug-pagealloc.c
+++ b/mm/debug-pagealloc.c
@@ -113,6 +113,7 @@ static void check_poison_mem(struct page *page,
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start,
end - start + 1, 1);
+ BUG_ON(PANIC_CORRUPTION);
dump_stack();
}
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index d1f6dc5a715d..08806bb1f070 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3661,6 +3661,7 @@ static void memcg_deactivate_kmem(struct mem_cgroup *memcg)
* ordering is imposed by list_lru_node->lock taken by
* memcg_drain_all_list_lrus().
*/
+ rcu_read_lock(); /* can be called from css_free w/o cgroup_mutex */
css_for_each_descendant_pre(css, &memcg->css) {
child = mem_cgroup_from_css(css);
BUG_ON(child->kmemcg_id != kmemcg_id);
@@ -3668,6 +3669,8 @@ static void memcg_deactivate_kmem(struct mem_cgroup *memcg)
if (!memcg->use_hierarchy)
break;
}
+ rcu_read_unlock();
+
memcg_drain_all_list_lrus(kmemcg_id, parent->kmemcg_id);
memcg_free_cache_id(kmemcg_id);
diff --git a/mm/migrate.c b/mm/migrate.c
index 3db1b0277eb4..a9ce3783361a 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -429,6 +429,7 @@ int migrate_page_move_mapping(struct address_space *mapping,
return MIGRATEPAGE_SUCCESS;
}
+EXPORT_SYMBOL(migrate_page_move_mapping);
/*
* The expected number of remaining references is the same as that
@@ -579,6 +580,7 @@ void migrate_page_copy(struct page *newpage, struct page *page)
if (PageWriteback(newpage))
end_page_writeback(newpage);
}
+EXPORT_SYMBOL(migrate_page_copy);
/************************************************************
* Migration functions
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 8bf8e06a56a6..6b4fa64a5c91 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -359,8 +359,9 @@ static void domain_dirty_limits(struct dirty_throttle_control *dtc)
struct dirty_throttle_control *gdtc = mdtc_gdtc(dtc);
unsigned long bytes = vm_dirty_bytes;
unsigned long bg_bytes = dirty_background_bytes;
- unsigned long ratio = vm_dirty_ratio;
- unsigned long bg_ratio = dirty_background_ratio;
+ /* convert ratios to per-PAGE_SIZE for higher precision */
+ unsigned long ratio = (vm_dirty_ratio * PAGE_SIZE) / 100;
+ unsigned long bg_ratio = (dirty_background_ratio * PAGE_SIZE) / 100;
unsigned long thresh;
unsigned long bg_thresh;
struct task_struct *tsk;
@@ -372,26 +373,28 @@ static void domain_dirty_limits(struct dirty_throttle_control *dtc)
/*
* The byte settings can't be applied directly to memcg
* domains. Convert them to ratios by scaling against
- * globally available memory.
+ * globally available memory. As the ratios are in
+ * per-PAGE_SIZE, they can be obtained by dividing bytes by
+ * number of pages.
*/
if (bytes)
- ratio = min(DIV_ROUND_UP(bytes, PAGE_SIZE) * 100 /
- global_avail, 100UL);
+ ratio = min(DIV_ROUND_UP(bytes, global_avail),
+ PAGE_SIZE);
if (bg_bytes)
- bg_ratio = min(DIV_ROUND_UP(bg_bytes, PAGE_SIZE) * 100 /
- global_avail, 100UL);
+ bg_ratio = min(DIV_ROUND_UP(bg_bytes, global_avail),
+ PAGE_SIZE);
bytes = bg_bytes = 0;
}
if (bytes)
thresh = DIV_ROUND_UP(bytes, PAGE_SIZE);
else
- thresh = (ratio * available_memory) / 100;
+ thresh = (ratio * available_memory) / PAGE_SIZE;
if (bg_bytes)
bg_thresh = DIV_ROUND_UP(bg_bytes, PAGE_SIZE);
else
- bg_thresh = (bg_ratio * available_memory) / 100;
+ bg_thresh = (bg_ratio * available_memory) / PAGE_SIZE;
if (bg_thresh >= thresh)
bg_thresh = thresh / 2;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index c8a31783c2d6..f12a0bde548b 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -967,7 +967,7 @@ static inline void init_reserved_page(unsigned long pfn)
* marks the pages PageReserved. The remaining valid pages are later
* sent to the buddy page allocator.
*/
-void __meminit reserve_bootmem_region(unsigned long start, unsigned long end)
+void __meminit reserve_bootmem_region(phys_addr_t start, phys_addr_t end)
{
unsigned long start_pfn = PFN_DOWN(start);
unsigned long end_pfn = PFN_UP(end);
diff --git a/mm/percpu.c b/mm/percpu.c
index 8a943b97a053..1f376bce413c 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -110,7 +110,7 @@ struct pcpu_chunk {
int map_used; /* # of map entries used before the sentry */
int map_alloc; /* # of map entries allocated */
int *map; /* allocation map */
- struct work_struct map_extend_work;/* async ->map[] extension */
+ struct list_head map_extend_list;/* on pcpu_map_extend_chunks */
void *data; /* chunk data */
int first_free; /* no free below this */
@@ -160,10 +160,13 @@ static struct pcpu_chunk *pcpu_reserved_chunk;
static int pcpu_reserved_chunk_limit;
static DEFINE_SPINLOCK(pcpu_lock); /* all internal data structures */
-static DEFINE_MUTEX(pcpu_alloc_mutex); /* chunk create/destroy, [de]pop */
+static DEFINE_MUTEX(pcpu_alloc_mutex); /* chunk create/destroy, [de]pop, map ext */
static struct list_head *pcpu_slot __read_mostly; /* chunk list slots */
+/* chunks which need their map areas extended, protected by pcpu_lock */
+static LIST_HEAD(pcpu_map_extend_chunks);
+
/*
* The number of empty populated pages, protected by pcpu_lock. The
* reserved chunk doesn't contribute to the count.
@@ -397,13 +400,19 @@ static int pcpu_need_to_extend(struct pcpu_chunk *chunk, bool is_atomic)
{
int margin, new_alloc;
+ lockdep_assert_held(&pcpu_lock);
+
if (is_atomic) {
margin = 3;
if (chunk->map_alloc <
- chunk->map_used + PCPU_ATOMIC_MAP_MARGIN_LOW &&
- pcpu_async_enabled)
- schedule_work(&chunk->map_extend_work);
+ chunk->map_used + PCPU_ATOMIC_MAP_MARGIN_LOW) {
+ if (list_empty(&chunk->map_extend_list)) {
+ list_add_tail(&chunk->map_extend_list,
+ &pcpu_map_extend_chunks);
+ pcpu_schedule_balance_work();
+ }
+ }
} else {
margin = PCPU_ATOMIC_MAP_MARGIN_HIGH;
}
@@ -437,6 +446,8 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk, int new_alloc)
size_t old_size = 0, new_size = new_alloc * sizeof(new[0]);
unsigned long flags;
+ lockdep_assert_held(&pcpu_alloc_mutex);
+
new = pcpu_mem_zalloc(new_size);
if (!new)
return -ENOMEM;
@@ -469,20 +480,6 @@ out_unlock:
return 0;
}
-static void pcpu_map_extend_workfn(struct work_struct *work)
-{
- struct pcpu_chunk *chunk = container_of(work, struct pcpu_chunk,
- map_extend_work);
- int new_alloc;
-
- spin_lock_irq(&pcpu_lock);
- new_alloc = pcpu_need_to_extend(chunk, false);
- spin_unlock_irq(&pcpu_lock);
-
- if (new_alloc)
- pcpu_extend_area_map(chunk, new_alloc);
-}
-
/**
* pcpu_fit_in_area - try to fit the requested allocation in a candidate area
* @chunk: chunk the candidate area belongs to
@@ -742,7 +739,7 @@ static struct pcpu_chunk *pcpu_alloc_chunk(void)
chunk->map_used = 1;
INIT_LIST_HEAD(&chunk->list);
- INIT_WORK(&chunk->map_extend_work, pcpu_map_extend_workfn);
+ INIT_LIST_HEAD(&chunk->map_extend_list);
chunk->free_size = pcpu_unit_size;
chunk->contig_hint = pcpu_unit_size;
@@ -897,6 +894,9 @@ static void __percpu *pcpu_alloc(size_t size, size_t align, bool reserved,
return NULL;
}
+ if (!is_atomic)
+ mutex_lock(&pcpu_alloc_mutex);
+
spin_lock_irqsave(&pcpu_lock, flags);
/* serve reserved allocations from the reserved chunk if available */
@@ -969,12 +969,9 @@ restart:
if (is_atomic)
goto fail;
- mutex_lock(&pcpu_alloc_mutex);
-
if (list_empty(&pcpu_slot[pcpu_nr_slots - 1])) {
chunk = pcpu_create_chunk();
if (!chunk) {
- mutex_unlock(&pcpu_alloc_mutex);
err = "failed to allocate new chunk";
goto fail;
}
@@ -985,7 +982,6 @@ restart:
spin_lock_irqsave(&pcpu_lock, flags);
}
- mutex_unlock(&pcpu_alloc_mutex);
goto restart;
area_found:
@@ -995,8 +991,6 @@ area_found:
if (!is_atomic) {
int page_start, page_end, rs, re;
- mutex_lock(&pcpu_alloc_mutex);
-
page_start = PFN_DOWN(off);
page_end = PFN_UP(off + size);
@@ -1007,7 +1001,6 @@ area_found:
spin_lock_irqsave(&pcpu_lock, flags);
if (ret) {
- mutex_unlock(&pcpu_alloc_mutex);
pcpu_free_area(chunk, off, &occ_pages);
err = "failed to populate";
goto fail_unlock;
@@ -1047,6 +1040,8 @@ fail:
/* see the flag handling in pcpu_blance_workfn() */
pcpu_atomic_alloc_failed = true;
pcpu_schedule_balance_work();
+ } else {
+ mutex_unlock(&pcpu_alloc_mutex);
}
return NULL;
}
@@ -1131,6 +1126,7 @@ static void pcpu_balance_workfn(struct work_struct *work)
if (chunk == list_first_entry(free_head, struct pcpu_chunk, list))
continue;
+ list_del_init(&chunk->map_extend_list);
list_move(&chunk->list, &to_free);
}
@@ -1148,6 +1144,25 @@ static void pcpu_balance_workfn(struct work_struct *work)
pcpu_destroy_chunk(chunk);
}
+ /* service chunks which requested async area map extension */
+ do {
+ int new_alloc = 0;
+
+ spin_lock_irq(&pcpu_lock);
+
+ chunk = list_first_entry_or_null(&pcpu_map_extend_chunks,
+ struct pcpu_chunk, map_extend_list);
+ if (chunk) {
+ list_del_init(&chunk->map_extend_list);
+ new_alloc = pcpu_need_to_extend(chunk, false);
+ }
+
+ spin_unlock_irq(&pcpu_lock);
+
+ if (new_alloc)
+ pcpu_extend_area_map(chunk, new_alloc);
+ } while (chunk);
+
/*
* Ensure there are certain number of free populated pages for
* atomic allocs. Fill up from the most packed so that atomic
@@ -1646,7 +1661,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
*/
schunk = memblock_virt_alloc(pcpu_chunk_struct_size, 0);
INIT_LIST_HEAD(&schunk->list);
- INIT_WORK(&schunk->map_extend_work, pcpu_map_extend_workfn);
+ INIT_LIST_HEAD(&schunk->map_extend_list);
schunk->base_addr = base_addr;
schunk->map = smap;
schunk->map_alloc = ARRAY_SIZE(smap);
@@ -1675,7 +1690,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
if (dyn_size) {
dchunk = memblock_virt_alloc(pcpu_chunk_struct_size, 0);
INIT_LIST_HEAD(&dchunk->list);
- INIT_WORK(&dchunk->map_extend_work, pcpu_map_extend_workfn);
+ INIT_LIST_HEAD(&dchunk->map_extend_list);
dchunk->base_addr = base_addr;
dchunk->map = dmap;
dchunk->map_alloc = ARRAY_SIZE(dmap);
diff --git a/mm/shmem.c b/mm/shmem.c
index b82e56ebabdd..79997e8cf807 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -2153,9 +2153,11 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
NULL);
if (error) {
/* Remove the !PageUptodate pages we added */
- shmem_undo_range(inode,
- (loff_t)start << PAGE_CACHE_SHIFT,
- (loff_t)index << PAGE_CACHE_SHIFT, true);
+ if (index > start) {
+ shmem_undo_range(inode,
+ (loff_t)start << PAGE_CACHE_SHIFT,
+ ((loff_t)index << PAGE_CACHE_SHIFT) - 1, true);
+ }
goto undone;
}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index d5c3ef60a71e..ff408638fd95 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -46,7 +46,6 @@
#include <linux/oom.h>
#include <linux/prefetch.h>
#include <linux/printk.h>
-#include <linux/debugfs.h>
#include <asm/tlbflush.h>
#include <asm/div64.h>
@@ -234,39 +233,6 @@ static unsigned long get_lru_size(struct lruvec *lruvec, enum lru_list lru)
return zone_page_state(lruvec_zone(lruvec), NR_LRU_BASE + lru);
}
-struct dentry *debug_file;
-
-static int debug_shrinker_show(struct seq_file *s, void *unused)
-{
- struct shrinker *shrinker;
- struct shrink_control sc;
-
- sc.gfp_mask = -1;
- sc.nr_to_scan = 0;
-
- down_read(&shrinker_rwsem);
- list_for_each_entry(shrinker, &shrinker_list, list) {
- int num_objs;
-
- num_objs = shrinker->count_objects(shrinker, &sc);
- seq_printf(s, "%pf %d\n", shrinker->scan_objects, num_objs);
- }
- up_read(&shrinker_rwsem);
- return 0;
-}
-
-static int debug_shrinker_open(struct inode *inode, struct file *file)
-{
- return single_open(file, debug_shrinker_show, inode->i_private);
-}
-
-static const struct file_operations debug_shrinker_fops = {
- .open = debug_shrinker_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
/*
* Add a shrinker callback to be called from the vm.
*/
@@ -296,15 +262,6 @@ int register_shrinker(struct shrinker *shrinker)
}
EXPORT_SYMBOL(register_shrinker);
-static int __init add_shrinker_debug(void)
-{
- debugfs_create_file("shrinker", 0644, NULL, NULL,
- &debug_shrinker_fops);
- return 0;
-}
-
-late_initcall(add_shrinker_debug);
-
/*
* Remove one
*/
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index fbd0acf80b13..2fdebabbfacd 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -976,7 +976,8 @@ static int ax25_release(struct socket *sock)
release_sock(sk);
ax25_disconnect(ax25, 0);
lock_sock(sk);
- ax25_destroy_socket(ax25);
+ if (!sock_flag(ax25->sk, SOCK_DESTROY))
+ ax25_destroy_socket(ax25);
break;
case AX25_STATE_3:
diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c
index 951cd57bb07d..5237dff6941d 100644
--- a/net/ax25/ax25_ds_timer.c
+++ b/net/ax25/ax25_ds_timer.c
@@ -102,6 +102,7 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25)
switch (ax25->state) {
case AX25_STATE_0:
+ case AX25_STATE_2:
/* Magic here: If we listen() and a new link dies before it
is accepted() it isn't 'dead' so doesn't get removed. */
if (!sk || sock_flag(sk, SOCK_DESTROY) ||
@@ -111,6 +112,7 @@ void ax25_ds_heartbeat_expiry(ax25_cb *ax25)
sock_hold(sk);
ax25_destroy_socket(ax25);
bh_unlock_sock(sk);
+ /* Ungrab socket and destroy it */
sock_put(sk);
} else
ax25_destroy_socket(ax25);
@@ -213,7 +215,8 @@ void ax25_ds_t1_timeout(ax25_cb *ax25)
case AX25_STATE_2:
if (ax25->n2count == ax25->n2) {
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
- ax25_disconnect(ax25, ETIMEDOUT);
+ if (!sock_flag(ax25->sk, SOCK_DESTROY))
+ ax25_disconnect(ax25, ETIMEDOUT);
return;
} else {
ax25->n2count++;
diff --git a/net/ax25/ax25_std_timer.c b/net/ax25/ax25_std_timer.c
index 004467c9e6e1..2c0d6ef66f9d 100644
--- a/net/ax25/ax25_std_timer.c
+++ b/net/ax25/ax25_std_timer.c
@@ -38,6 +38,7 @@ void ax25_std_heartbeat_expiry(ax25_cb *ax25)
switch (ax25->state) {
case AX25_STATE_0:
+ case AX25_STATE_2:
/* Magic here: If we listen() and a new link dies before it
is accepted() it isn't 'dead' so doesn't get removed. */
if (!sk || sock_flag(sk, SOCK_DESTROY) ||
@@ -47,6 +48,7 @@ void ax25_std_heartbeat_expiry(ax25_cb *ax25)
sock_hold(sk);
ax25_destroy_socket(ax25);
bh_unlock_sock(sk);
+ /* Ungrab socket and destroy it */
sock_put(sk);
} else
ax25_destroy_socket(ax25);
@@ -144,7 +146,8 @@ void ax25_std_t1timer_expiry(ax25_cb *ax25)
case AX25_STATE_2:
if (ax25->n2count == ax25->n2) {
ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
- ax25_disconnect(ax25, ETIMEDOUT);
+ if (!sock_flag(ax25->sk, SOCK_DESTROY))
+ ax25_disconnect(ax25, ETIMEDOUT);
return;
} else {
ax25->n2count++;
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
index 3b78e8473a01..655a7d4c96e1 100644
--- a/net/ax25/ax25_subr.c
+++ b/net/ax25/ax25_subr.c
@@ -264,7 +264,8 @@ void ax25_disconnect(ax25_cb *ax25, int reason)
{
ax25_clear_queues(ax25);
- ax25_stop_heartbeat(ax25);
+ if (!sock_flag(ax25->sk, SOCK_DESTROY))
+ ax25_stop_heartbeat(ax25);
ax25_stop_t1timer(ax25);
ax25_stop_t2timer(ax25);
ax25_stop_t3timer(ax25);
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index a642bb829d09..09442e0f7f67 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -278,6 +278,8 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
* change from under us.
*/
list_for_each_entry(v, &vg->vlan_list, vlist) {
+ if (!br_vlan_should_use(v))
+ continue;
f = __br_fdb_get(br, br->dev->dev_addr, v->vid);
if (f && f->is_local && !f->dst)
fdb_delete_local(br, NULL, f);
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index ea9893743a0f..7173a685309a 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -464,8 +464,11 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
if (ipv6_dev_get_saddr(dev_net(br->dev), br->dev, &ip6h->daddr, 0,
&ip6h->saddr)) {
kfree_skb(skb);
+ br->has_ipv6_addr = 0;
return NULL;
}
+
+ br->has_ipv6_addr = 1;
ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
hopopt = (u8 *)(ip6h + 1);
@@ -1736,6 +1739,7 @@ void br_multicast_init(struct net_bridge *br)
br->ip6_other_query.delay_time = 0;
br->ip6_querier.port = NULL;
#endif
+ br->has_ipv6_addr = 1;
spin_lock_init(&br->multicast_lock);
setup_timer(&br->multicast_router_timer,
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 216018c76018..1001a1b7df9b 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -301,6 +301,7 @@ struct net_bridge
u8 multicast_disabled:1;
u8 multicast_querier:1;
u8 multicast_query_use_ifaddr:1;
+ u8 has_ipv6_addr:1;
u32 hash_elasticity;
u32 hash_max;
@@ -574,10 +575,22 @@ static inline bool br_multicast_is_router(struct net_bridge *br)
static inline bool
__br_multicast_querier_exists(struct net_bridge *br,
- struct bridge_mcast_other_query *querier)
+ struct bridge_mcast_other_query *querier,
+ const bool is_ipv6)
{
+ bool own_querier_enabled;
+
+ if (br->multicast_querier) {
+ if (is_ipv6 && !br->has_ipv6_addr)
+ own_querier_enabled = false;
+ else
+ own_querier_enabled = true;
+ } else {
+ own_querier_enabled = false;
+ }
+
return time_is_before_jiffies(querier->delay_time) &&
- (br->multicast_querier || timer_pending(&querier->timer));
+ (own_querier_enabled || timer_pending(&querier->timer));
}
static inline bool br_multicast_querier_exists(struct net_bridge *br,
@@ -585,10 +598,12 @@ static inline bool br_multicast_querier_exists(struct net_bridge *br,
{
switch (eth->h_proto) {
case (htons(ETH_P_IP)):
- return __br_multicast_querier_exists(br, &br->ip4_other_query);
+ return __br_multicast_querier_exists(br,
+ &br->ip4_other_query, false);
#if IS_ENABLED(CONFIG_IPV6)
case (htons(ETH_P_IPV6)):
- return __br_multicast_querier_exists(br, &br->ip6_other_query);
+ return __br_multicast_querier_exists(br,
+ &br->ip6_other_query, true);
#endif
default:
return false;
diff --git a/net/core/filter.c b/net/core/filter.c
index f393a22b9d50..75e9b2b2336d 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -1275,9 +1275,7 @@ static u64 bpf_skb_store_bytes(u64 r1, u64 r2, u64 r3, u64 r4, u64 flags)
*/
if (unlikely((u32) offset > 0xffff || len > sizeof(buf)))
return -EFAULT;
-
- if (unlikely(skb_cloned(skb) &&
- !skb_clone_writable(skb, offset + len)))
+ if (unlikely(skb_try_make_writable(skb, offset + len)))
return -EFAULT;
ptr = skb_header_pointer(skb, offset, len, buf);
@@ -1321,8 +1319,7 @@ static u64 bpf_l3_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags)
if (unlikely((u32) offset > 0xffff))
return -EFAULT;
- if (unlikely(skb_cloned(skb) &&
- !skb_clone_writable(skb, offset + sizeof(sum))))
+ if (unlikely(skb_try_make_writable(skb, offset + sizeof(sum))))
return -EFAULT;
ptr = skb_header_pointer(skb, offset, sizeof(sum), &sum);
@@ -1367,9 +1364,7 @@ static u64 bpf_l4_csum_replace(u64 r1, u64 r2, u64 from, u64 to, u64 flags)
if (unlikely((u32) offset > 0xffff))
return -EFAULT;
-
- if (unlikely(skb_cloned(skb) &&
- !skb_clone_writable(skb, offset + sizeof(sum))))
+ if (unlikely(skb_try_make_writable(skb, offset + sizeof(sum))))
return -EFAULT;
ptr = skb_header_pointer(skb, offset, sizeof(sum), &sum);
@@ -1554,6 +1549,13 @@ bool bpf_helper_changes_skb_data(void *func)
return true;
if (func == bpf_skb_vlan_pop)
return true;
+ if (func == bpf_skb_store_bytes)
+ return true;
+ if (func == bpf_l3_csum_replace)
+ return true;
+ if (func == bpf_l4_csum_replace)
+ return true;
+
return false;
}
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 08764a380f9a..4509cba1d0e6 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -697,6 +697,23 @@ void make_flow_keys_digest(struct flow_keys_digest *digest,
}
EXPORT_SYMBOL(make_flow_keys_digest);
+static struct flow_dissector flow_keys_dissector_symmetric __read_mostly;
+
+u32 __skb_get_hash_symmetric(struct sk_buff *skb)
+{
+ struct flow_keys keys;
+
+ __flow_hash_secret_init();
+
+ memset(&keys, 0, sizeof(keys));
+ __skb_flow_dissect(skb, &flow_keys_dissector_symmetric, &keys,
+ NULL, 0, 0, 0,
+ FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);
+
+ return __flow_hash_from_keys(&keys, hashrnd);
+}
+EXPORT_SYMBOL_GPL(__skb_get_hash_symmetric);
+
/**
* __skb_get_hash: calculate a flow hash
* @skb: sk_buff to calculate flow hash from
@@ -909,6 +926,29 @@ static const struct flow_dissector_key flow_keys_dissector_keys[] = {
},
};
+static const struct flow_dissector_key flow_keys_dissector_symmetric_keys[] = {
+ {
+ .key_id = FLOW_DISSECTOR_KEY_CONTROL,
+ .offset = offsetof(struct flow_keys, control),
+ },
+ {
+ .key_id = FLOW_DISSECTOR_KEY_BASIC,
+ .offset = offsetof(struct flow_keys, basic),
+ },
+ {
+ .key_id = FLOW_DISSECTOR_KEY_IPV4_ADDRS,
+ .offset = offsetof(struct flow_keys, addrs.v4addrs),
+ },
+ {
+ .key_id = FLOW_DISSECTOR_KEY_IPV6_ADDRS,
+ .offset = offsetof(struct flow_keys, addrs.v6addrs),
+ },
+ {
+ .key_id = FLOW_DISSECTOR_KEY_PORTS,
+ .offset = offsetof(struct flow_keys, ports),
+ },
+};
+
static const struct flow_dissector_key flow_keys_buf_dissector_keys[] = {
{
.key_id = FLOW_DISSECTOR_KEY_CONTROL,
@@ -930,6 +970,9 @@ static int __init init_default_flow_dissectors(void)
skb_flow_dissector_init(&flow_keys_dissector,
flow_keys_dissector_keys,
ARRAY_SIZE(flow_keys_dissector_keys));
+ skb_flow_dissector_init(&flow_keys_dissector_symmetric,
+ flow_keys_dissector_symmetric_keys,
+ ARRAY_SIZE(flow_keys_dissector_symmetric_keys));
skb_flow_dissector_init(&flow_keys_buf_dissector,
flow_keys_buf_dissector_keys,
ARRAY_SIZE(flow_keys_buf_dissector_keys));
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 436822c109d5..f1e575d7f21a 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2467,13 +2467,17 @@ int neigh_xmit(int index, struct net_device *dev,
tbl = neigh_tables[index];
if (!tbl)
goto out;
+ rcu_read_lock_bh();
neigh = __neigh_lookup_noref(tbl, addr, dev);
if (!neigh)
neigh = __neigh_create(tbl, addr, dev, false);
err = PTR_ERR(neigh);
- if (IS_ERR(neigh))
+ if (IS_ERR(neigh)) {
+ rcu_read_unlock_bh();
goto out_kfree_skb;
+ }
err = neigh->output(neigh, skb);
+ rcu_read_unlock_bh();
}
else if (index == NEIGH_LINK_TABLE) {
err = dev_hard_header(skb, dev, ntohs(skb->protocol),
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 38467f386b14..46e60923221f 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2965,24 +2965,6 @@ int skb_append_pagefrags(struct sk_buff *skb, struct page *page,
EXPORT_SYMBOL_GPL(skb_append_pagefrags);
/**
- * skb_push_rcsum - push skb and update receive checksum
- * @skb: buffer to update
- * @len: length of data pulled
- *
- * This function performs an skb_push on the packet and updates
- * the CHECKSUM_COMPLETE checksum. It should be used on
- * receive path processing instead of skb_push unless you know
- * that the checksum difference is zero (e.g., a valid IP header)
- * or you are setting ip_summed to CHECKSUM_NONE.
- */
-static unsigned char *skb_push_rcsum(struct sk_buff *skb, unsigned len)
-{
- skb_push(skb, len);
- skb_postpush_rcsum(skb, skb->data, len);
- return skb->data;
-}
-
-/**
* skb_pull_rcsum - pull skb and update receive checksum
* @skb: buffer to update
* @len: length of data pulled
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index c600403137b7..1021e770355b 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -888,7 +888,6 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSIFPFLAGS:
case SIOCGIFPFLAGS:
case SIOCSIFFLAGS:
- case SIOCKILLADDR:
err = devinet_ioctl(net, cmd, (void __user *)arg);
break;
default:
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 926169c94a0b..0212591b0077 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -59,7 +59,6 @@
#include <net/arp.h>
#include <net/ip.h>
-#include <net/tcp.h>
#include <net/route.h>
#include <net/ip_fib.h>
#include <net/rtnetlink.h>
@@ -969,7 +968,6 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
case SIOCSIFBRDADDR: /* Set the broadcast address */
case SIOCSIFDSTADDR: /* Set the destination address */
case SIOCSIFNETMASK: /* Set the netmask for the interface */
- case SIOCKILLADDR: /* Nuke all sockets on this address */
ret = -EPERM;
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
goto out;
@@ -1021,8 +1019,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
}
ret = -EADDRNOTAVAIL;
- if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS
- && cmd != SIOCKILLADDR)
+ if (!ifa && cmd != SIOCSIFADDR && cmd != SIOCSIFFLAGS)
goto done;
switch (cmd) {
@@ -1149,9 +1146,6 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
inet_insert_ifa(ifa);
}
break;
- case SIOCKILLADDR: /* Nuke all connections on this address */
- ret = tcp_nuke_addr(net, (struct sockaddr *) sin);
- break;
}
done:
rtnl_unlock();
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index 477937465a20..d95631d09248 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -23,6 +23,11 @@ struct esp_skb_cb {
void *tmp;
};
+struct esp_output_extra {
+ __be32 seqhi;
+ u32 esphoff;
+};
+
#define ESP_SKB_CB(__skb) ((struct esp_skb_cb *)&((__skb)->cb[0]))
static u32 esp4_get_mtu(struct xfrm_state *x, int mtu);
@@ -35,11 +40,11 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu);
*
* TODO: Use spare space in skb for this where possible.
*/
-static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqhilen)
+static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int extralen)
{
unsigned int len;
- len = seqhilen;
+ len = extralen;
len += crypto_aead_ivsize(aead);
@@ -57,15 +62,16 @@ static void *esp_alloc_tmp(struct crypto_aead *aead, int nfrags, int seqhilen)
return kmalloc(len, GFP_ATOMIC);
}
-static inline __be32 *esp_tmp_seqhi(void *tmp)
+static inline void *esp_tmp_extra(void *tmp)
{
- return PTR_ALIGN((__be32 *)tmp, __alignof__(__be32));
+ return PTR_ALIGN(tmp, __alignof__(struct esp_output_extra));
}
-static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int seqhilen)
+
+static inline u8 *esp_tmp_iv(struct crypto_aead *aead, void *tmp, int extralen)
{
return crypto_aead_ivsize(aead) ?
- PTR_ALIGN((u8 *)tmp + seqhilen,
- crypto_aead_alignmask(aead) + 1) : tmp + seqhilen;
+ PTR_ALIGN((u8 *)tmp + extralen,
+ crypto_aead_alignmask(aead) + 1) : tmp + extralen;
}
static inline struct aead_request *esp_tmp_req(struct crypto_aead *aead, u8 *iv)
@@ -99,7 +105,7 @@ static void esp_restore_header(struct sk_buff *skb, unsigned int offset)
{
struct ip_esp_hdr *esph = (void *)(skb->data + offset);
void *tmp = ESP_SKB_CB(skb)->tmp;
- __be32 *seqhi = esp_tmp_seqhi(tmp);
+ __be32 *seqhi = esp_tmp_extra(tmp);
esph->seq_no = esph->spi;
esph->spi = *seqhi;
@@ -107,7 +113,11 @@ static void esp_restore_header(struct sk_buff *skb, unsigned int offset)
static void esp_output_restore_header(struct sk_buff *skb)
{
- esp_restore_header(skb, skb_transport_offset(skb) - sizeof(__be32));
+ void *tmp = ESP_SKB_CB(skb)->tmp;
+ struct esp_output_extra *extra = esp_tmp_extra(tmp);
+
+ esp_restore_header(skb, skb_transport_offset(skb) + extra->esphoff -
+ sizeof(__be32));
}
static void esp_output_done_esn(struct crypto_async_request *base, int err)
@@ -121,6 +131,7 @@ static void esp_output_done_esn(struct crypto_async_request *base, int err)
static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
{
int err;
+ struct esp_output_extra *extra;
struct ip_esp_hdr *esph;
struct crypto_aead *aead;
struct aead_request *req;
@@ -137,8 +148,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
int tfclen;
int nfrags;
int assoclen;
- int seqhilen;
- __be32 *seqhi;
+ int extralen;
__be64 seqno;
/* skb is pure payload to encrypt */
@@ -166,21 +176,21 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
nfrags = err;
assoclen = sizeof(*esph);
- seqhilen = 0;
+ extralen = 0;
if (x->props.flags & XFRM_STATE_ESN) {
- seqhilen += sizeof(__be32);
- assoclen += seqhilen;
+ extralen += sizeof(*extra);
+ assoclen += sizeof(__be32);
}
- tmp = esp_alloc_tmp(aead, nfrags, seqhilen);
+ tmp = esp_alloc_tmp(aead, nfrags, extralen);
if (!tmp) {
err = -ENOMEM;
goto error;
}
- seqhi = esp_tmp_seqhi(tmp);
- iv = esp_tmp_iv(aead, tmp, seqhilen);
+ extra = esp_tmp_extra(tmp);
+ iv = esp_tmp_iv(aead, tmp, extralen);
req = esp_tmp_req(aead, iv);
sg = esp_req_sg(aead, req);
@@ -247,8 +257,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
* encryption.
*/
if ((x->props.flags & XFRM_STATE_ESN)) {
- esph = (void *)(skb_transport_header(skb) - sizeof(__be32));
- *seqhi = esph->spi;
+ extra->esphoff = (unsigned char *)esph -
+ skb_transport_header(skb);
+ esph = (struct ip_esp_hdr *)((unsigned char *)esph - 4);
+ extra->seqhi = esph->spi;
esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.hi);
aead_request_set_callback(req, 0, esp_output_done_esn, skb);
}
@@ -445,7 +457,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
goto out;
ESP_SKB_CB(skb)->tmp = tmp;
- seqhi = esp_tmp_seqhi(tmp);
+ seqhi = esp_tmp_extra(tmp);
iv = esp_tmp_iv(aead, tmp, seqhilen);
req = esp_tmp_req(aead, iv);
sg = esp_req_sg(aead, req);
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 7dc962b89fa1..3e4184088082 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -1247,6 +1247,14 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
err = ipgre_newlink(net, dev, tb, NULL);
if (err < 0)
goto out;
+
+ /* openvswitch users expect packet sizes to be unrestricted,
+ * so set the largest MTU we can.
+ */
+ err = __ip_tunnel_change_mtu(dev, IP_MAX_MTU, false);
+ if (err)
+ goto out;
+
return dev;
out:
free_netdev(dev);
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index ce30c8b72457..3310ac75e3f3 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -948,17 +948,31 @@ done:
}
EXPORT_SYMBOL_GPL(ip_tunnel_ioctl);
-int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
+int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict)
{
struct ip_tunnel *tunnel = netdev_priv(dev);
int t_hlen = tunnel->hlen + sizeof(struct iphdr);
+ int max_mtu = 0xFFF8 - dev->hard_header_len - t_hlen;
- if (new_mtu < 68 ||
- new_mtu > 0xFFF8 - dev->hard_header_len - t_hlen)
+ if (new_mtu < 68)
return -EINVAL;
+
+ if (new_mtu > max_mtu) {
+ if (strict)
+ return -EINVAL;
+
+ new_mtu = max_mtu;
+ }
+
dev->mtu = new_mtu;
return 0;
}
+EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu);
+
+int ip_tunnel_change_mtu(struct net_device *dev, int new_mtu)
+{
+ return __ip_tunnel_change_mtu(dev, new_mtu, true);
+}
EXPORT_SYMBOL_GPL(ip_tunnel_change_mtu);
static void ip_tunnel_dev_free(struct net_device *dev)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index c3a38353f5dc..9d1e555496e3 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -882,8 +882,10 @@ static struct mfc_cache *ipmr_cache_alloc(void)
{
struct mfc_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
- if (c)
+ if (c) {
+ c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
c->mfc_un.res.minvif = MAXVIFS;
+ }
return c;
}
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 36a30fab8625..6e3e0e8b1ce3 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -367,6 +367,18 @@ static inline bool unconditional(const struct arpt_entry *e)
memcmp(&e->arp, &uncond, sizeof(uncond)) == 0;
}
+static bool find_jump_target(const struct xt_table_info *t,
+ const struct arpt_entry *target)
+{
+ struct arpt_entry *iter;
+
+ xt_entry_foreach(iter, t->entries, t->size) {
+ if (iter == target)
+ return true;
+ }
+ return false;
+}
+
/* Figures out from what hook each rule can be called: returns 0 if
* there are loops. Puts hook bitmask in comefrom.
*/
@@ -439,6 +451,8 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
size = e->next_offset;
e = (struct arpt_entry *)
(entry0 + pos + size);
+ if (pos + size >= newinfo->size)
+ return 0;
e->counters.pcnt = pos;
pos += size;
} else {
@@ -458,9 +472,15 @@ static int mark_source_chains(const struct xt_table_info *newinfo,
/* This a jump; chase it. */
duprintf("Jump rule %u -> %u\n",
pos, newpos);
+ e = (struct arpt_entry *)
+ (entry0 + newpos);
+ if (!find_jump_target(newinfo, e))
+ return 0;
} else {
/* ... this is a fallthru */
newpos = pos + e->next_offset;
+ if (newpos >= newinfo->size)
+ return 0;
}
e = (struct arpt_entry *)
(entry0 + newpos);
@@ -474,23 +494,6 @@ next:
return 1;
}
-static inline int check_entry(const struct arpt_entry *e)
-{
- const struct xt_entry_target *t;
-
- if (!arp_checkentry(&e->arp))
- return -EINVAL;
-
- if (e->target_offset + sizeof(struct xt_entry_target) > e->next_offset)
- return -EINVAL;
-
- t = arpt_get_target_c(e);
- if (e->target_offset + t->u.target_size > e->next_offset)
- return -EINVAL;
-
- return 0;
-}
-
static inline int check_target(struct arpt_entry *e, const char *name)
{
struct xt_entry_target *t = arpt_get_target(e);
@@ -586,7 +589,11 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
return -EINVAL;
}
- err = check_entry(e);
+ if (!arp_checkentry(&e->arp))
+ return -EINVAL;
+
+ err = xt_check_entry_offsets(e, e->elems, e->target_offset,
+ e->next_offset);
if (err)
return err;
@@ -691,10 +698,8 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
}
}
- if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) {
- duprintf("Looping hook\n");
+ if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))
return -ELOOP;
- }
/* Finally, each sanity check must pass */
i = 0;
@@ -1125,55 +1130,17 @@ static int do_add_counters(struct net *net, const void __user *user,
unsigned int i;
struct xt_counters_info tmp;
struct xt_counters *paddc;
- unsigned int num_counters;
- const char *name;
- int size;
- void *ptmp;
struct xt_table *t;
const struct xt_table_info *private;
int ret = 0;
struct arpt_entry *iter;
unsigned int addend;
-#ifdef CONFIG_COMPAT
- struct compat_xt_counters_info compat_tmp;
- if (compat) {
- ptmp = &compat_tmp;
- size = sizeof(struct compat_xt_counters_info);
- } else
-#endif
- {
- ptmp = &tmp;
- size = sizeof(struct xt_counters_info);
- }
+ paddc = xt_copy_counters_from_user(user, len, &tmp, compat);
+ if (IS_ERR(paddc))
+ return PTR_ERR(paddc);
- if (copy_from_user(ptmp, user, size) != 0)
- return -EFAULT;
-
-#ifdef CONFIG_COMPAT
- if (compat) {
- num_counters = compat_tmp.num_counters;
- name = compat_tmp.name;
- } else
-#endif
- {
- num_counters = tmp.num_counters;
- name = tmp.name;
- }
-
- if (len != size + num_counters * sizeof(struct xt_counters))
- return -EINVAL;
-
- paddc = vmalloc(len - size);
- if (!paddc)
- return -ENOMEM;
-
- if (copy_from_user(paddc, user + size, len - size) != 0) {
- ret = -EFAULT;
- goto free;
- }
-
- t = xt_find_table_lock(net, NFPROTO_ARP, name);
+ t = xt_find_table_lock(net, NFPROTO_ARP, tmp.name);
if (IS_ERR_OR_NULL(t)) {
ret = t ? PTR_ERR(t) : -ENOENT;
goto free;
@@ -1181,7 +1148,7 @@ static int do_add_counters(struct net *net, const void __user *user,
local_bh_disable();
private = t->private;
- if (private->number != num_counters) {
+ if (private->number != tmp.num_counters) {
ret = -EINVAL;
goto unlock_up_free;
}
@@ -1208,6 +1175,18 @@ static int do_add_counters(struct net *net, const void __user *user,
}
#ifdef CONFIG_COMPAT
+struct compat_arpt_replace {
+ char name[XT_TABLE_MAXNAMELEN];
+ u32 valid_hooks;
+ u32 num_entries;
+ u32 size;
+ u32 hook_entry[NF_ARP_NUMHOOKS];
+ u32 underflow[NF_ARP_NUMHOOKS];
+ u32 num_counters;
+ compat_uptr_t counters;
+ struct compat_arpt_entry entries[0];
+};
+
static inline void compat_release_entry(struct compat_arpt_entry *e)
{
struct xt_entry_target *t;
@@ -1216,20 +1195,17 @@ static inline void compat_release_entry(struct compat_arpt_entry *e)
module_put(t->u.kernel.target->me);
}
-static inline int
+static int
check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
struct xt_table_info *newinfo,
unsigned int *size,
const unsigned char *base,
- const unsigned char *limit,
- const unsigned int *hook_entries,
- const unsigned int *underflows,
- const char *name)
+ const unsigned char *limit)
{
struct xt_entry_target *t;
struct xt_target *target;
unsigned int entry_offset;
- int ret, off, h;
+ int ret, off;
duprintf("check_compat_entry_size_and_hooks %p\n", e);
if ((unsigned long)e % __alignof__(struct compat_arpt_entry) != 0 ||
@@ -1246,8 +1222,11 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
return -EINVAL;
}
- /* For purposes of check_entry casting the compat entry is fine */
- ret = check_entry((struct arpt_entry *)e);
+ if (!arp_checkentry(&e->arp))
+ return -EINVAL;
+
+ ret = xt_compat_check_entry_offsets(e, e->elems, e->target_offset,
+ e->next_offset);
if (ret)
return ret;
@@ -1271,17 +1250,6 @@ check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
if (ret)
goto release_target;
- /* Check hooks & underflows */
- for (h = 0; h < NF_ARP_NUMHOOKS; h++) {
- if ((unsigned char *)e - base == hook_entries[h])
- newinfo->hook_entry[h] = hook_entries[h];
- if ((unsigned char *)e - base == underflows[h])
- newinfo->underflow[h] = underflows[h];
- }
-
- /* Clear counters and comefrom */
- memset(&e->counters, 0, sizeof(e->counters));
- e->comefrom = 0;
return 0;
release_target:
@@ -1290,18 +1258,17 @@ out:
return ret;
}
-static int
+static void
compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
- unsigned int *size, const char *name,
+ unsigned int *size,
struct xt_table_info *newinfo, unsigned char *base)
{
struct xt_entry_target *t;
struct xt_target *target;
struct arpt_entry *de;
unsigned int origsize;
- int ret, h;
+ int h;
- ret = 0;
origsize = *size;
de = (struct arpt_entry *)*dstptr;
memcpy(de, e, sizeof(struct arpt_entry));
@@ -1322,148 +1289,82 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
if ((unsigned char *)de - base < newinfo->underflow[h])
newinfo->underflow[h] -= origsize - *size;
}
- return ret;
}
-static int translate_compat_table(const char *name,
- unsigned int valid_hooks,
- struct xt_table_info **pinfo,
+static int translate_compat_table(struct xt_table_info **pinfo,
void **pentry0,
- unsigned int total_size,
- unsigned int number,
- unsigned int *hook_entries,
- unsigned int *underflows)
+ const struct compat_arpt_replace *compatr)
{
unsigned int i, j;
struct xt_table_info *newinfo, *info;
void *pos, *entry0, *entry1;
struct compat_arpt_entry *iter0;
- struct arpt_entry *iter1;
+ struct arpt_replace repl;
unsigned int size;
int ret = 0;
info = *pinfo;
entry0 = *pentry0;
- size = total_size;
- info->number = number;
-
- /* Init all hooks to impossible value. */
- for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
- info->hook_entry[i] = 0xFFFFFFFF;
- info->underflow[i] = 0xFFFFFFFF;
- }
+ size = compatr->size;
+ info->number = compatr->num_entries;
duprintf("translate_compat_table: size %u\n", info->size);
j = 0;
xt_compat_lock(NFPROTO_ARP);
- xt_compat_init_offsets(NFPROTO_ARP, number);
+ xt_compat_init_offsets(NFPROTO_ARP, compatr->num_entries);
/* Walk through entries, checking offsets. */
- xt_entry_foreach(iter0, entry0, total_size) {
+ xt_entry_foreach(iter0, entry0, compatr->size) {
ret = check_compat_entry_size_and_hooks(iter0, info, &size,
entry0,
- entry0 + total_size,
- hook_entries,
- underflows,
- name);
+ entry0 + compatr->size);
if (ret != 0)
goto out_unlock;
++j;
}
ret = -EINVAL;
- if (j != number) {
+ if (j != compatr->num_entries) {
duprintf("translate_compat_table: %u not %u entries\n",
- j, number);
+ j, compatr->num_entries);
goto out_unlock;
}
- /* Check hooks all assigned */
- for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
- /* Only hooks which are valid */
- if (!(valid_hooks & (1 << i)))
- continue;
- if (info->hook_entry[i] == 0xFFFFFFFF) {
- duprintf("Invalid hook entry %u %u\n",
- i, hook_entries[i]);
- goto out_unlock;
- }
- if (info->underflow[i] == 0xFFFFFFFF) {
- duprintf("Invalid underflow %u %u\n",
- i, underflows[i]);
- goto out_unlock;
- }
- }
-
ret = -ENOMEM;
newinfo = xt_alloc_table_info(size);
if (!newinfo)
goto out_unlock;
- newinfo->number = number;
+ newinfo->number = compatr->num_entries;
for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
newinfo->hook_entry[i] = info->hook_entry[i];
newinfo->underflow[i] = info->underflow[i];
}
entry1 = newinfo->entries;
pos = entry1;
- size = total_size;
- xt_entry_foreach(iter0, entry0, total_size) {
- ret = compat_copy_entry_from_user(iter0, &pos, &size,
- name, newinfo, entry1);
- if (ret != 0)
- break;
- }
+ size = compatr->size;
+ xt_entry_foreach(iter0, entry0, compatr->size)
+ compat_copy_entry_from_user(iter0, &pos, &size,
+ newinfo, entry1);
+
+ /* all module references in entry0 are now gone */
+
xt_compat_flush_offsets(NFPROTO_ARP);
xt_compat_unlock(NFPROTO_ARP);
- if (ret)
- goto free_newinfo;
- ret = -ELOOP;
- if (!mark_source_chains(newinfo, valid_hooks, entry1))
- goto free_newinfo;
+ memcpy(&repl, compatr, sizeof(*compatr));
- i = 0;
- xt_entry_foreach(iter1, entry1, newinfo->size) {
- iter1->counters.pcnt = xt_percpu_counter_alloc();
- if (IS_ERR_VALUE(iter1->counters.pcnt)) {
- ret = -ENOMEM;
- break;
- }
-
- ret = check_target(iter1, name);
- if (ret != 0) {
- xt_percpu_counter_free(iter1->counters.pcnt);
- break;
- }
- ++i;
- if (strcmp(arpt_get_target(iter1)->u.user.name,
- XT_ERROR_TARGET) == 0)
- ++newinfo->stacksize;
- }
- if (ret) {
- /*
- * The first i matches need cleanup_entry (calls ->destroy)
- * because they had called ->check already. The other j-i
- * entries need only release.
- */
- int skip = i;
- j -= i;
- xt_entry_foreach(iter0, entry0, newinfo->size) {
- if (skip-- > 0)
- continue;
- if (j-- == 0)
- break;
- compat_release_entry(iter0);
- }
- xt_entry_foreach(iter1, entry1, newinfo->size) {
- if (i-- == 0)
- break;
- cleanup_entry(iter1);
- }
- xt_free_table_info(newinfo);
- return ret;
+ for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
+ repl.hook_entry[i] = newinfo->hook_entry[i];
+ repl.underflow[i] = newinfo->underflow[i];
}
+ repl.num_counters = 0;
+ repl.counters = NULL;
+ repl.size = newinfo->size;
+ ret = translate_table(newinfo, entry1, &repl);
+ if (ret)
+ goto free_newinfo;
+
*pinfo = newinfo;
*pentry0 = entry1;
xt_free_table_info(info);
@@ -1471,31 +1372,18 @@ static int translate_compat_table(const char *name,
free_newinfo:
xt_free_table_info(newinfo);
-out:
- xt_entry_foreach(iter0, entry0, total_size) {
+ return ret;
+out_unlock:
+ xt_compat_flush_offsets(NFPROTO_ARP);
+ xt_compat_unlock(NFPROTO_ARP);
+ xt_entry_foreach(iter0, entry0, compatr->size) {
if (j-- == 0)
break;
compat_release_entry(iter0);
}
return ret;
-out_unlock:
- xt_compat_flush_offsets(NFPROTO_ARP);
- xt_compat_unlock(NFPROTO_ARP);
- goto out;
}
-struct compat_arpt_replace {
- char name[XT_TABLE_MAXNAMELEN];
- u32 valid_hooks;
- u32 num_entries;
- u32 size;
- u32 hook_entry[NF_ARP_NUMHOOKS];
- u32 underflow[NF_ARP_NUMHOOKS];
- u32 num_counters;
- compat_uptr_t counters;
- struct compat_arpt_entry entries[0];
-};
-
static int compat_do_replace(struct net *net, void __user *user,
unsigned int len)
{
@@ -1528,10 +1416,7 @@ static int compat_do_replace(struct net *net, void __user *user,
goto free_newinfo;
}
- ret = translate_compat_table(tmp.name, tmp.valid_hooks,
- &newinfo, &loc_cpu_entry, tmp.size,
- tmp.num_entries, tmp.hook_entry,
- tmp.underflow);
+ ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp);
if (ret != 0)
goto free_newinfo;
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 99d46b0a4ead..a399c5419622 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -443,6 +443,18 @@ ipt_do_table(struct sk_buff *skb,
#endif
}
+static bool find_jump_target(const struct xt_table_info *t,
+ const struct ipt_entry *target)
+{
+ struct ipt_entry *iter;
+
+ xt_entry_foreach(iter, t->entries, t->size) {
+ if (iter == target)
+ return true;
+ }
+ return false;
+}
+
/* Figures out from what hook each rule can be called: returns 0 if
there are loops. Puts hook bitmask in comefrom. */
static int
@@ -520,6 +532,8 @@ mark_source_chains(const struct xt_table_info *newinfo,
size = e->next_offset;
e = (struct ipt_entry *)
(entry0 + pos + size);
+ if (pos + size >= newinfo->size)
+ return 0;
e->counters.pcnt = pos;
pos += size;
} else {
@@ -538,9 +552,15 @@ mark_source_chains(const struct xt_table_info *newinfo,
/* This a jump; chase it. */
duprintf("Jump rule %u -> %u\n",
pos, newpos);
+ e = (struct ipt_entry *)
+ (entry0 + newpos);
+ if (!find_jump_target(newinfo, e))
+ return 0;
} else {
/* ... this is a fallthru */
newpos = pos + e->next_offset;
+ if (newpos >= newinfo->size)
+ return 0;
}
e = (struct ipt_entry *)
(entry0 + newpos);
@@ -568,25 +588,6 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net)
}
static int
-check_entry(const struct ipt_entry *e)
-{
- const struct xt_entry_target *t;
-
- if (!ip_checkentry(&e->ip))
- return -EINVAL;
-
- if (e->target_offset + sizeof(struct xt_entry_target) >
- e->next_offset)
- return -EINVAL;
-
- t = ipt_get_target_c(e);
- if (e->target_offset + t->u.target_size > e->next_offset)
- return -EINVAL;
-
- return 0;
-}
-
-static int
check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
{
const struct ipt_ip *ip = par->entryinfo;
@@ -750,7 +751,11 @@ check_entry_size_and_hooks(struct ipt_entry *e,
return -EINVAL;
}
- err = check_entry(e);
+ if (!ip_checkentry(&e->ip))
+ return -EINVAL;
+
+ err = xt_check_entry_offsets(e, e->elems, e->target_offset,
+ e->next_offset);
if (err)
return err;
@@ -1308,55 +1313,17 @@ do_add_counters(struct net *net, const void __user *user,
unsigned int i;
struct xt_counters_info tmp;
struct xt_counters *paddc;
- unsigned int num_counters;
- const char *name;
- int size;
- void *ptmp;
struct xt_table *t;
const struct xt_table_info *private;
int ret = 0;
struct ipt_entry *iter;
unsigned int addend;
-#ifdef CONFIG_COMPAT
- struct compat_xt_counters_info compat_tmp;
- if (compat) {
- ptmp = &compat_tmp;
- size = sizeof(struct compat_xt_counters_info);
- } else
-#endif
- {
- ptmp = &tmp;
- size = sizeof(struct xt_counters_info);
- }
-
- if (copy_from_user(ptmp, user, size) != 0)
- return -EFAULT;
-
-#ifdef CONFIG_COMPAT
- if (compat) {
- num_counters = compat_tmp.num_counters;
- name = compat_tmp.name;
- } else
-#endif
- {
- num_counters = tmp.num_counters;
- name = tmp.name;
- }
+ paddc = xt_copy_counters_from_user(user, len, &tmp, compat);
+ if (IS_ERR(paddc))
+ return PTR_ERR(paddc);
- if (len != size + num_counters * sizeof(struct xt_counters))
- return -EINVAL;
-
- paddc = vmalloc(len - size);
- if (!paddc)
- return -ENOMEM;
-
- if (copy_from_user(paddc, user + size, len - size) != 0) {
- ret = -EFAULT;
- goto free;
- }
-
- t = xt_find_table_lock(net, AF_INET, name);
+ t = xt_find_table_lock(net, AF_INET, tmp.name);
if (IS_ERR_OR_NULL(t)) {
ret = t ? PTR_ERR(t) : -ENOENT;
goto free;
@@ -1364,7 +1331,7 @@ do_add_counters(struct net *net, const void __user *user,
local_bh_disable();
private = t->private;
- if (private->number != num_counters) {
+ if (private->number != tmp.num_counters) {
ret = -EINVAL;
goto unlock_up_free;
}
@@ -1443,7 +1410,6 @@ compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,
static int
compat_find_calc_match(struct xt_entry_match *m,
- const char *name,
const struct ipt_ip *ip,
int *size)
{
@@ -1478,17 +1444,14 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
struct xt_table_info *newinfo,
unsigned int *size,
const unsigned char *base,
- const unsigned char *limit,
- const unsigned int *hook_entries,
- const unsigned int *underflows,
- const char *name)
+ const unsigned char *limit)
{
struct xt_entry_match *ematch;
struct xt_entry_target *t;
struct xt_target *target;
unsigned int entry_offset;
unsigned int j;
- int ret, off, h;
+ int ret, off;
duprintf("check_compat_entry_size_and_hooks %p\n", e);
if ((unsigned long)e % __alignof__(struct compat_ipt_entry) != 0 ||
@@ -1505,8 +1468,11 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
return -EINVAL;
}
- /* For purposes of check_entry casting the compat entry is fine */
- ret = check_entry((struct ipt_entry *)e);
+ if (!ip_checkentry(&e->ip))
+ return -EINVAL;
+
+ ret = xt_compat_check_entry_offsets(e, e->elems,
+ e->target_offset, e->next_offset);
if (ret)
return ret;
@@ -1514,7 +1480,7 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
entry_offset = (void *)e - (void *)base;
j = 0;
xt_ematch_foreach(ematch, e) {
- ret = compat_find_calc_match(ematch, name, &e->ip, &off);
+ ret = compat_find_calc_match(ematch, &e->ip, &off);
if (ret != 0)
goto release_matches;
++j;
@@ -1537,17 +1503,6 @@ check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
if (ret)
goto out;
- /* Check hooks & underflows */
- for (h = 0; h < NF_INET_NUMHOOKS; h++) {
- if ((unsigned char *)e - base == hook_entries[h])
- newinfo->hook_entry[h] = hook_entries[h];
- if ((unsigned char *)e - base == underflows[h])
- newinfo->underflow[h] = underflows[h];
- }
-
- /* Clear counters and comefrom */
- memset(&e->counters, 0, sizeof(e->counters));
- e->comefrom = 0;
return 0;
out:
@@ -1561,19 +1516,18 @@ release_matches:
return ret;
}
-static int
+static void
compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
- unsigned int *size, const char *name,
+ unsigned int *size,
struct xt_table_info *newinfo, unsigned char *base)
{
struct xt_entry_target *t;
struct xt_target *target;
struct ipt_entry *de;
unsigned int origsize;
- int ret, h;
+ int h;
struct xt_entry_match *ematch;
- ret = 0;
origsize = *size;
de = (struct ipt_entry *)*dstptr;
memcpy(de, e, sizeof(struct ipt_entry));
@@ -1582,201 +1536,105 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
*dstptr += sizeof(struct ipt_entry);
*size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
- xt_ematch_foreach(ematch, e) {
- ret = xt_compat_match_from_user(ematch, dstptr, size);
- if (ret != 0)
- return ret;
- }
+ xt_ematch_foreach(ematch, e)
+ xt_compat_match_from_user(ematch, dstptr, size);
+
de->target_offset = e->target_offset - (origsize - *size);
t = compat_ipt_get_target(e);
target = t->u.kernel.target;
xt_compat_target_from_user(t, dstptr, size);
de->next_offset = e->next_offset - (origsize - *size);
+
for (h = 0; h < NF_INET_NUMHOOKS; h++) {
if ((unsigned char *)de - base < newinfo->hook_entry[h])
newinfo->hook_entry[h] -= origsize - *size;
if ((unsigned char *)de - base < newinfo->underflow[h])
newinfo->underflow[h] -= origsize - *size;
}
- return ret;
-}
-
-static int
-compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)
-{
- struct xt_entry_match *ematch;
- struct xt_mtchk_param mtpar;
- unsigned int j;
- int ret = 0;
-
- e->counters.pcnt = xt_percpu_counter_alloc();
- if (IS_ERR_VALUE(e->counters.pcnt))
- return -ENOMEM;
-
- j = 0;
- mtpar.net = net;
- mtpar.table = name;
- mtpar.entryinfo = &e->ip;
- mtpar.hook_mask = e->comefrom;
- mtpar.family = NFPROTO_IPV4;
- xt_ematch_foreach(ematch, e) {
- ret = check_match(ematch, &mtpar);
- if (ret != 0)
- goto cleanup_matches;
- ++j;
- }
-
- ret = check_target(e, net, name);
- if (ret)
- goto cleanup_matches;
- return 0;
-
- cleanup_matches:
- xt_ematch_foreach(ematch, e) {
- if (j-- == 0)
- break;
- cleanup_match(ematch, net);
- }
-
- xt_percpu_counter_free(e->counters.pcnt);
-
- return ret;
}
static int
translate_compat_table(struct net *net,
- const char *name,
- unsigned int valid_hooks,
struct xt_table_info **pinfo,
void **pentry0,
- unsigned int total_size,
- unsigned int number,
- unsigned int *hook_entries,
- unsigned int *underflows)
+ const struct compat_ipt_replace *compatr)
{
unsigned int i, j;
struct xt_table_info *newinfo, *info;
void *pos, *entry0, *entry1;
struct compat_ipt_entry *iter0;
- struct ipt_entry *iter1;
+ struct ipt_replace repl;
unsigned int size;
int ret;
info = *pinfo;
entry0 = *pentry0;
- size = total_size;
- info->number = number;
-
- /* Init all hooks to impossible value. */
- for (i = 0; i < NF_INET_NUMHOOKS; i++) {
- info->hook_entry[i] = 0xFFFFFFFF;
- info->underflow[i] = 0xFFFFFFFF;
- }
+ size = compatr->size;
+ info->number = compatr->num_entries;
duprintf("translate_compat_table: size %u\n", info->size);
j = 0;
xt_compat_lock(AF_INET);
- xt_compat_init_offsets(AF_INET, number);
+ xt_compat_init_offsets(AF_INET, compatr->num_entries);
/* Walk through entries, checking offsets. */
- xt_entry_foreach(iter0, entry0, total_size) {
+ xt_entry_foreach(iter0, entry0, compatr->size) {
ret = check_compat_entry_size_and_hooks(iter0, info, &size,
entry0,
- entry0 + total_size,
- hook_entries,
- underflows,
- name);
+ entry0 + compatr->size);
if (ret != 0)
goto out_unlock;
++j;
}
ret = -EINVAL;
- if (j != number) {
+ if (j != compatr->num_entries) {
duprintf("translate_compat_table: %u not %u entries\n",
- j, number);
+ j, compatr->num_entries);
goto out_unlock;
}
- /* Check hooks all assigned */
- for (i = 0; i < NF_INET_NUMHOOKS; i++) {
- /* Only hooks which are valid */
- if (!(valid_hooks & (1 << i)))
- continue;
- if (info->hook_entry[i] == 0xFFFFFFFF) {
- duprintf("Invalid hook entry %u %u\n",
- i, hook_entries[i]);
- goto out_unlock;
- }
- if (info->underflow[i] == 0xFFFFFFFF) {
- duprintf("Invalid underflow %u %u\n",
- i, underflows[i]);
- goto out_unlock;
- }
- }
-
ret = -ENOMEM;
newinfo = xt_alloc_table_info(size);
if (!newinfo)
goto out_unlock;
- newinfo->number = number;
+ newinfo->number = compatr->num_entries;
for (i = 0; i < NF_INET_NUMHOOKS; i++) {
- newinfo->hook_entry[i] = info->hook_entry[i];
- newinfo->underflow[i] = info->underflow[i];
+ newinfo->hook_entry[i] = compatr->hook_entry[i];
+ newinfo->underflow[i] = compatr->underflow[i];
}
entry1 = newinfo->entries;
pos = entry1;
- size = total_size;
- xt_entry_foreach(iter0, entry0, total_size) {
- ret = compat_copy_entry_from_user(iter0, &pos, &size,
- name, newinfo, entry1);
- if (ret != 0)
- break;
- }
+ size = compatr->size;
+ xt_entry_foreach(iter0, entry0, compatr->size)
+ compat_copy_entry_from_user(iter0, &pos, &size,
+ newinfo, entry1);
+
+ /* all module references in entry0 are now gone.
+ * entry1/newinfo contains a 64bit ruleset that looks exactly as
+ * generated by 64bit userspace.
+ *
+ * Call standard translate_table() to validate all hook_entrys,
+ * underflows, check for loops, etc.
+ */
xt_compat_flush_offsets(AF_INET);
xt_compat_unlock(AF_INET);
- if (ret)
- goto free_newinfo;
- ret = -ELOOP;
- if (!mark_source_chains(newinfo, valid_hooks, entry1))
- goto free_newinfo;
+ memcpy(&repl, compatr, sizeof(*compatr));
- i = 0;
- xt_entry_foreach(iter1, entry1, newinfo->size) {
- ret = compat_check_entry(iter1, net, name);
- if (ret != 0)
- break;
- ++i;
- if (strcmp(ipt_get_target(iter1)->u.user.name,
- XT_ERROR_TARGET) == 0)
- ++newinfo->stacksize;
- }
- if (ret) {
- /*
- * The first i matches need cleanup_entry (calls ->destroy)
- * because they had called ->check already. The other j-i
- * entries need only release.
- */
- int skip = i;
- j -= i;
- xt_entry_foreach(iter0, entry0, newinfo->size) {
- if (skip-- > 0)
- continue;
- if (j-- == 0)
- break;
- compat_release_entry(iter0);
- }
- xt_entry_foreach(iter1, entry1, newinfo->size) {
- if (i-- == 0)
- break;
- cleanup_entry(iter1, net);
- }
- xt_free_table_info(newinfo);
- return ret;
+ for (i = 0; i < NF_INET_NUMHOOKS; i++) {
+ repl.hook_entry[i] = newinfo->hook_entry[i];
+ repl.underflow[i] = newinfo->underflow[i];
}
+ repl.num_counters = 0;
+ repl.counters = NULL;
+ repl.size = newinfo->size;
+ ret = translate_table(net, newinfo, entry1, &repl);
+ if (ret)
+ goto free_newinfo;
+
*pinfo = newinfo;
*pentry0 = entry1;
xt_free_table_info(info);
@@ -1784,17 +1642,16 @@ translate_compat_table(struct net *net,
free_newinfo:
xt_free_table_info(newinfo);
-out:
- xt_entry_foreach(iter0, entry0, total_size) {
+ return ret;
+out_unlock:
+ xt_compat_flush_offsets(AF_INET);
+ xt_compat_unlock(AF_INET);
+ xt_entry_foreach(iter0, entry0, compatr->size) {
if (j-- == 0)
break;
compat_release_entry(iter0);
}
return ret;
-out_unlock:
- xt_compat_flush_offsets(AF_INET);
- xt_compat_unlock(AF_INET);
- goto out;
}
static int
@@ -1830,10 +1687,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
goto free_newinfo;
}
- ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
- &newinfo, &loc_cpu_entry, tmp.size,
- tmp.num_entries, tmp.hook_entry,
- tmp.underflow);
+ ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp);
if (ret != 0)
goto free_newinfo;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 2ee7b830a35e..d5bd460a13f1 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -275,9 +275,6 @@
#include <net/tcp.h>
#include <net/xfrm.h>
#include <net/ip.h>
-#include <net/ip6_route.h>
-#include <net/ipv6.h>
-#include <net/transp_v6.h>
#include <net/sock.h>
#include <asm/uaccess.h>
@@ -3257,125 +3254,3 @@ void __init tcp_init(void)
BUG_ON(tcp_register_congestion_control(&tcp_reno) != 0);
tcp_tasklet_init();
}
-
-static int tcp_is_local(struct net *net, __be32 addr) {
- struct rtable *rt;
- struct flowi4 fl4 = { .daddr = addr };
- rt = ip_route_output_key(net, &fl4);
- if (IS_ERR_OR_NULL(rt))
- return 0;
- return rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK);
-}
-
-#if defined(CONFIG_IPV6)
-static int tcp_is_local6(struct net *net, struct in6_addr *addr) {
- struct rt6_info *rt6 = rt6_lookup(net, addr, addr, 0, 0);
- return rt6 && rt6->dst.dev && (rt6->dst.dev->flags & IFF_LOOPBACK);
-}
-#endif
-
-/*
- * tcp_nuke_addr - destroy all sockets on the given local address
- * if local address is the unspecified address (0.0.0.0 or ::), destroy all
- * sockets with local addresses that are not configured.
- */
-int tcp_nuke_addr(struct net *net, struct sockaddr *addr)
-{
- int family = addr->sa_family;
- unsigned int bucket;
-
- struct in_addr *in = NULL;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- struct in6_addr *in6 = NULL;
-#endif
- if (family == AF_INET) {
- in = &((struct sockaddr_in *)addr)->sin_addr;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- } else if (family == AF_INET6) {
- in6 = &((struct sockaddr_in6 *)addr)->sin6_addr;
-#endif
- } else {
- return -EAFNOSUPPORT;
- }
-
- for (bucket = 0; bucket <= tcp_hashinfo.ehash_mask; bucket++) {
- struct hlist_nulls_node *node;
- struct sock *sk;
- spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, bucket);
-
-restart:
- spin_lock_bh(lock);
- sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) {
- struct inet_sock *inet = inet_sk(sk);
-
- if (sk->sk_state == TCP_TIME_WAIT) {
- /*
- * Sockets that are in TIME_WAIT state are
- * instances of lightweight inet_timewait_sock,
- * we should simply skip them (or we'll try to
- * access non-existing fields and crash).
- */
- continue;
- }
-
- if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT)
- continue;
-
- if (sock_flag(sk, SOCK_DEAD))
- continue;
-
- if (family == AF_INET) {
- __be32 s4 = inet->inet_rcv_saddr;
- if (s4 == LOOPBACK4_IPV6)
- continue;
-
- if (in && in->s_addr != s4 &&
- !(in->s_addr == INADDR_ANY &&
- !tcp_is_local(net, s4)))
- continue;
- }
-
-#if defined(CONFIG_IPV6)
- if (family == AF_INET6) {
- struct in6_addr *s6;
- if (!inet->pinet6)
- continue;
-
- s6 = &sk->sk_v6_rcv_saddr;
- if (ipv6_addr_type(s6) == IPV6_ADDR_MAPPED)
- continue;
-
- if (!ipv6_addr_equal(in6, s6) &&
- !(ipv6_addr_equal(in6, &in6addr_any) &&
- !tcp_is_local6(net, s6)))
- continue;
- }
-#endif
-
- sock_hold(sk);
- spin_unlock_bh(lock);
-
- lock_sock(sk);
- local_bh_disable();
- bh_lock_sock(sk);
-
- if (!sock_flag(sk, SOCK_DEAD)) {
- smp_wmb(); /* be consistent with tcp_reset */
- sk->sk_err = ETIMEDOUT;
- sk->sk_error_report(sk);
- tcp_done(sk);
- }
-
- bh_unlock_sock(sk);
- local_bh_enable();
- release_sock(sk);
- sock_put(sk);
-
- goto restart;
- }
- spin_unlock_bh(lock);
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(tcp_nuke_addr);
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index eeac33e94527..04822b7d7966 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1537,7 +1537,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
/* if we're overly short, let UDP handle it */
encap_rcv = ACCESS_ONCE(up->encap_rcv);
- if (skb->len > sizeof(struct udphdr) && encap_rcv) {
+ if (encap_rcv) {
int ret;
/* Verify checksum before giving to encap */
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 99fccad391e0..d9b25bd17bf1 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -495,21 +495,6 @@ int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
}
EXPORT_SYMBOL(inet6_getname);
-int inet6_killaddr_ioctl(struct net *net, void __user *arg) {
- struct in6_ifreq ireq;
- struct sockaddr_in6 sin6;
-
- if (!capable(CAP_NET_ADMIN))
- return -EACCES;
-
- if (copy_from_user(&ireq, arg, sizeof(struct in6_ifreq)))
- return -EFAULT;
-
- sin6.sin6_family = AF_INET6;
- sin6.sin6_addr = ireq.ifr6_addr;
- return tcp_nuke_addr(net, (struct sockaddr *) &sin6);
-}
-
int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
@@ -533,8 +518,6 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
return addrconf_del_ifaddr(net, (void __user *) arg);
case SIOCSIFDSTADDR:
return addrconf_set_dstaddr(net, (void __user *) arg);
- case SIOCKILLADDR:
- return inet6_killaddr_ioctl(net, (void __user *) arg);
default:
if (!sk->sk_prot->ioctl)
return -ENOIOCTLCMD;
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 0c7e276c230e..34cf46d74554 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -179,6 +179,7 @@ static void rt6_free_pcpu(struct rt6_info *non_pcpu_rt)
}
}
+ free_percpu(non_pcpu_rt->rt6i_pcpu);
non_pcpu_rt->rt6i_pcpu = NULL;
}
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index c87ca6987f9c..cd96a01032a2 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1071,17 +1071,12 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6,
const struct in6_addr *final_dst)
{
struct dst_entry *dst = sk_dst_check(sk, inet6_sk(sk)->dst_cookie);
- int err;
dst = ip6_sk_dst_check(sk, dst, fl6);
+ if (!dst)
+ dst = ip6_dst_lookup_flow(sk, fl6, final_dst);
- err = ip6_dst_lookup_tail(sock_net(sk), sk, &dst, fl6);
- if (err)
- return ERR_PTR(err);
- if (final_dst)
- fl6->daddr = *final_dst;
-
- return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0);
+ return dst;
}
EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow);
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index a10e77103c88..e207cb2468da 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1074,6 +1074,7 @@ static struct mfc6_cache *ip6mr_cache_alloc(void)
struct mfc6_cache *c = kmem_cache_zalloc(mrt_cachep, GFP_KERNEL);
if (!c)
return NULL;
+ c->mfc_un.res.last_assert = jiffies - MFC_ASSERT_THRESH - 1;
c->mfc_un.res.minvif = MAXMIFS;
return c;
}
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 6198807e06f4..22f39e00bef3 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -455,6 +455,18 @@ ip6t_do_table(struct sk_buff *skb,
#endif
}
+static bool find_jump_target(const struct xt_table_info *t,
+ const struct ip6t_entry *target)
+{
+ struct ip6t_entry *iter;
+
+ xt_entry_foreach(iter, t->entries, t->size) {
+ if (iter == target)
+ return true;
+ }
+ return false;
+}
+
/* Figures out from what hook each rule can be called: returns 0 if
there are loops. Puts hook bitmask in comefrom. */
static int
@@ -532,6 +544,8 @@ mark_source_chains(const struct xt_table_info *newinfo,
size = e->next_offset;
e = (struct ip6t_entry *)
(entry0 + pos + size);
+ if (pos + size >= newinfo->size)
+ return 0;
e->counters.pcnt = pos;
pos += size;
} else {
@@ -550,9 +564,15 @@ mark_source_chains(const struct xt_table_info *newinfo,
/* This a jump; chase it. */
duprintf("Jump rule %u -> %u\n",
pos, newpos);
+ e = (struct ip6t_entry *)
+ (entry0 + newpos);
+ if (!find_jump_target(newinfo, e))
+ return 0;
} else {
/* ... this is a fallthru */
newpos = pos + e->next_offset;
+ if (newpos >= newinfo->size)
+ return 0;
}
e = (struct ip6t_entry *)
(entry0 + newpos);
@@ -579,25 +599,6 @@ static void cleanup_match(struct xt_entry_match *m, struct net *net)
module_put(par.match->me);
}
-static int
-check_entry(const struct ip6t_entry *e)
-{
- const struct xt_entry_target *t;
-
- if (!ip6_checkentry(&e->ipv6))
- return -EINVAL;
-
- if (e->target_offset + sizeof(struct xt_entry_target) >
- e->next_offset)
- return -EINVAL;
-
- t = ip6t_get_target_c(e);
- if (e->target_offset + t->u.target_size > e->next_offset)
- return -EINVAL;
-
- return 0;
-}
-
static int check_match(struct xt_entry_match *m, struct xt_mtchk_param *par)
{
const struct ip6t_ip6 *ipv6 = par->entryinfo;
@@ -762,7 +763,11 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
return -EINVAL;
}
- err = check_entry(e);
+ if (!ip6_checkentry(&e->ipv6))
+ return -EINVAL;
+
+ err = xt_check_entry_offsets(e, e->elems, e->target_offset,
+ e->next_offset);
if (err)
return err;
@@ -1320,55 +1325,16 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,
unsigned int i;
struct xt_counters_info tmp;
struct xt_counters *paddc;
- unsigned int num_counters;
- char *name;
- int size;
- void *ptmp;
struct xt_table *t;
const struct xt_table_info *private;
int ret = 0;
struct ip6t_entry *iter;
unsigned int addend;
-#ifdef CONFIG_COMPAT
- struct compat_xt_counters_info compat_tmp;
-
- if (compat) {
- ptmp = &compat_tmp;
- size = sizeof(struct compat_xt_counters_info);
- } else
-#endif
- {
- ptmp = &tmp;
- size = sizeof(struct xt_counters_info);
- }
-
- if (copy_from_user(ptmp, user, size) != 0)
- return -EFAULT;
-
-#ifdef CONFIG_COMPAT
- if (compat) {
- num_counters = compat_tmp.num_counters;
- name = compat_tmp.name;
- } else
-#endif
- {
- num_counters = tmp.num_counters;
- name = tmp.name;
- }
-
- if (len != size + num_counters * sizeof(struct xt_counters))
- return -EINVAL;
-
- paddc = vmalloc(len - size);
- if (!paddc)
- return -ENOMEM;
- if (copy_from_user(paddc, user + size, len - size) != 0) {
- ret = -EFAULT;
- goto free;
- }
-
- t = xt_find_table_lock(net, AF_INET6, name);
+ paddc = xt_copy_counters_from_user(user, len, &tmp, compat);
+ if (IS_ERR(paddc))
+ return PTR_ERR(paddc);
+ t = xt_find_table_lock(net, AF_INET6, tmp.name);
if (IS_ERR_OR_NULL(t)) {
ret = t ? PTR_ERR(t) : -ENOENT;
goto free;
@@ -1376,7 +1342,7 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len,
local_bh_disable();
private = t->private;
- if (private->number != num_counters) {
+ if (private->number != tmp.num_counters) {
ret = -EINVAL;
goto unlock_up_free;
}
@@ -1455,7 +1421,6 @@ compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,
static int
compat_find_calc_match(struct xt_entry_match *m,
- const char *name,
const struct ip6t_ip6 *ipv6,
int *size)
{
@@ -1490,17 +1455,14 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
struct xt_table_info *newinfo,
unsigned int *size,
const unsigned char *base,
- const unsigned char *limit,
- const unsigned int *hook_entries,
- const unsigned int *underflows,
- const char *name)
+ const unsigned char *limit)
{
struct xt_entry_match *ematch;
struct xt_entry_target *t;
struct xt_target *target;
unsigned int entry_offset;
unsigned int j;
- int ret, off, h;
+ int ret, off;
duprintf("check_compat_entry_size_and_hooks %p\n", e);
if ((unsigned long)e % __alignof__(struct compat_ip6t_entry) != 0 ||
@@ -1517,8 +1479,11 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
return -EINVAL;
}
- /* For purposes of check_entry casting the compat entry is fine */
- ret = check_entry((struct ip6t_entry *)e);
+ if (!ip6_checkentry(&e->ipv6))
+ return -EINVAL;
+
+ ret = xt_compat_check_entry_offsets(e, e->elems,
+ e->target_offset, e->next_offset);
if (ret)
return ret;
@@ -1526,7 +1491,7 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
entry_offset = (void *)e - (void *)base;
j = 0;
xt_ematch_foreach(ematch, e) {
- ret = compat_find_calc_match(ematch, name, &e->ipv6, &off);
+ ret = compat_find_calc_match(ematch, &e->ipv6, &off);
if (ret != 0)
goto release_matches;
++j;
@@ -1549,17 +1514,6 @@ check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
if (ret)
goto out;
- /* Check hooks & underflows */
- for (h = 0; h < NF_INET_NUMHOOKS; h++) {
- if ((unsigned char *)e - base == hook_entries[h])
- newinfo->hook_entry[h] = hook_entries[h];
- if ((unsigned char *)e - base == underflows[h])
- newinfo->underflow[h] = underflows[h];
- }
-
- /* Clear counters and comefrom */
- memset(&e->counters, 0, sizeof(e->counters));
- e->comefrom = 0;
return 0;
out:
@@ -1573,18 +1527,17 @@ release_matches:
return ret;
}
-static int
+static void
compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
- unsigned int *size, const char *name,
+ unsigned int *size,
struct xt_table_info *newinfo, unsigned char *base)
{
struct xt_entry_target *t;
struct ip6t_entry *de;
unsigned int origsize;
- int ret, h;
+ int h;
struct xt_entry_match *ematch;
- ret = 0;
origsize = *size;
de = (struct ip6t_entry *)*dstptr;
memcpy(de, e, sizeof(struct ip6t_entry));
@@ -1593,11 +1546,9 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
*dstptr += sizeof(struct ip6t_entry);
*size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
- xt_ematch_foreach(ematch, e) {
- ret = xt_compat_match_from_user(ematch, dstptr, size);
- if (ret != 0)
- return ret;
- }
+ xt_ematch_foreach(ematch, e)
+ xt_compat_match_from_user(ematch, dstptr, size);
+
de->target_offset = e->target_offset - (origsize - *size);
t = compat_ip6t_get_target(e);
xt_compat_target_from_user(t, dstptr, size);
@@ -1609,183 +1560,83 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
if ((unsigned char *)de - base < newinfo->underflow[h])
newinfo->underflow[h] -= origsize - *size;
}
- return ret;
-}
-
-static int compat_check_entry(struct ip6t_entry *e, struct net *net,
- const char *name)
-{
- unsigned int j;
- int ret = 0;
- struct xt_mtchk_param mtpar;
- struct xt_entry_match *ematch;
-
- e->counters.pcnt = xt_percpu_counter_alloc();
- if (IS_ERR_VALUE(e->counters.pcnt))
- return -ENOMEM;
- j = 0;
- mtpar.net = net;
- mtpar.table = name;
- mtpar.entryinfo = &e->ipv6;
- mtpar.hook_mask = e->comefrom;
- mtpar.family = NFPROTO_IPV6;
- xt_ematch_foreach(ematch, e) {
- ret = check_match(ematch, &mtpar);
- if (ret != 0)
- goto cleanup_matches;
- ++j;
- }
-
- ret = check_target(e, net, name);
- if (ret)
- goto cleanup_matches;
- return 0;
-
- cleanup_matches:
- xt_ematch_foreach(ematch, e) {
- if (j-- == 0)
- break;
- cleanup_match(ematch, net);
- }
-
- xt_percpu_counter_free(e->counters.pcnt);
-
- return ret;
}
static int
translate_compat_table(struct net *net,
- const char *name,
- unsigned int valid_hooks,
struct xt_table_info **pinfo,
void **pentry0,
- unsigned int total_size,
- unsigned int number,
- unsigned int *hook_entries,
- unsigned int *underflows)
+ const struct compat_ip6t_replace *compatr)
{
unsigned int i, j;
struct xt_table_info *newinfo, *info;
void *pos, *entry0, *entry1;
struct compat_ip6t_entry *iter0;
- struct ip6t_entry *iter1;
+ struct ip6t_replace repl;
unsigned int size;
int ret = 0;
info = *pinfo;
entry0 = *pentry0;
- size = total_size;
- info->number = number;
-
- /* Init all hooks to impossible value. */
- for (i = 0; i < NF_INET_NUMHOOKS; i++) {
- info->hook_entry[i] = 0xFFFFFFFF;
- info->underflow[i] = 0xFFFFFFFF;
- }
+ size = compatr->size;
+ info->number = compatr->num_entries;
duprintf("translate_compat_table: size %u\n", info->size);
j = 0;
xt_compat_lock(AF_INET6);
- xt_compat_init_offsets(AF_INET6, number);
+ xt_compat_init_offsets(AF_INET6, compatr->num_entries);
/* Walk through entries, checking offsets. */
- xt_entry_foreach(iter0, entry0, total_size) {
+ xt_entry_foreach(iter0, entry0, compatr->size) {
ret = check_compat_entry_size_and_hooks(iter0, info, &size,
entry0,
- entry0 + total_size,
- hook_entries,
- underflows,
- name);
+ entry0 + compatr->size);
if (ret != 0)
goto out_unlock;
++j;
}
ret = -EINVAL;
- if (j != number) {
+ if (j != compatr->num_entries) {
duprintf("translate_compat_table: %u not %u entries\n",
- j, number);
+ j, compatr->num_entries);
goto out_unlock;
}
- /* Check hooks all assigned */
- for (i = 0; i < NF_INET_NUMHOOKS; i++) {
- /* Only hooks which are valid */
- if (!(valid_hooks & (1 << i)))
- continue;
- if (info->hook_entry[i] == 0xFFFFFFFF) {
- duprintf("Invalid hook entry %u %u\n",
- i, hook_entries[i]);
- goto out_unlock;
- }
- if (info->underflow[i] == 0xFFFFFFFF) {
- duprintf("Invalid underflow %u %u\n",
- i, underflows[i]);
- goto out_unlock;
- }
- }
-
ret = -ENOMEM;
newinfo = xt_alloc_table_info(size);
if (!newinfo)
goto out_unlock;
- newinfo->number = number;
+ newinfo->number = compatr->num_entries;
for (i = 0; i < NF_INET_NUMHOOKS; i++) {
- newinfo->hook_entry[i] = info->hook_entry[i];
- newinfo->underflow[i] = info->underflow[i];
+ newinfo->hook_entry[i] = compatr->hook_entry[i];
+ newinfo->underflow[i] = compatr->underflow[i];
}
entry1 = newinfo->entries;
pos = entry1;
- size = total_size;
- xt_entry_foreach(iter0, entry0, total_size) {
- ret = compat_copy_entry_from_user(iter0, &pos, &size,
- name, newinfo, entry1);
- if (ret != 0)
- break;
- }
+ size = compatr->size;
+ xt_entry_foreach(iter0, entry0, compatr->size)
+ compat_copy_entry_from_user(iter0, &pos, &size,
+ newinfo, entry1);
+
+ /* all module references in entry0 are now gone. */
xt_compat_flush_offsets(AF_INET6);
xt_compat_unlock(AF_INET6);
- if (ret)
- goto free_newinfo;
- ret = -ELOOP;
- if (!mark_source_chains(newinfo, valid_hooks, entry1))
- goto free_newinfo;
+ memcpy(&repl, compatr, sizeof(*compatr));
- i = 0;
- xt_entry_foreach(iter1, entry1, newinfo->size) {
- ret = compat_check_entry(iter1, net, name);
- if (ret != 0)
- break;
- ++i;
- if (strcmp(ip6t_get_target(iter1)->u.user.name,
- XT_ERROR_TARGET) == 0)
- ++newinfo->stacksize;
- }
- if (ret) {
- /*
- * The first i matches need cleanup_entry (calls ->destroy)
- * because they had called ->check already. The other j-i
- * entries need only release.
- */
- int skip = i;
- j -= i;
- xt_entry_foreach(iter0, entry0, newinfo->size) {
- if (skip-- > 0)
- continue;
- if (j-- == 0)
- break;
- compat_release_entry(iter0);
- }
- xt_entry_foreach(iter1, entry1, newinfo->size) {
- if (i-- == 0)
- break;
- cleanup_entry(iter1, net);
- }
- xt_free_table_info(newinfo);
- return ret;
+ for (i = 0; i < NF_INET_NUMHOOKS; i++) {
+ repl.hook_entry[i] = newinfo->hook_entry[i];
+ repl.underflow[i] = newinfo->underflow[i];
}
+ repl.num_counters = 0;
+ repl.counters = NULL;
+ repl.size = newinfo->size;
+ ret = translate_table(net, newinfo, entry1, &repl);
+ if (ret)
+ goto free_newinfo;
+
*pinfo = newinfo;
*pentry0 = entry1;
xt_free_table_info(info);
@@ -1793,17 +1644,16 @@ translate_compat_table(struct net *net,
free_newinfo:
xt_free_table_info(newinfo);
-out:
- xt_entry_foreach(iter0, entry0, total_size) {
+ return ret;
+out_unlock:
+ xt_compat_flush_offsets(AF_INET6);
+ xt_compat_unlock(AF_INET6);
+ xt_entry_foreach(iter0, entry0, compatr->size) {
if (j-- == 0)
break;
compat_release_entry(iter0);
}
return ret;
-out_unlock:
- xt_compat_flush_offsets(AF_INET6);
- xt_compat_unlock(AF_INET6);
- goto out;
}
static int
@@ -1839,10 +1689,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
goto free_newinfo;
}
- ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
- &newinfo, &loc_cpu_entry, tmp.size,
- tmp.num_entries, tmp.hook_entry,
- tmp.underflow);
+ ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp);
if (ret != 0)
goto free_newinfo;
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index dcccae86190f..ba3d2f3d66d2 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -560,13 +560,13 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
ipv4_update_pmtu(skb, dev_net(skb->dev), info,
- t->parms.link, 0, IPPROTO_IPV6, 0);
+ t->parms.link, 0, iph->protocol, 0);
err = 0;
goto out;
}
if (type == ICMP_REDIRECT) {
ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0,
- IPPROTO_IPV6, 0);
+ iph->protocol, 0);
err = 0;
goto out;
}
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index dab6da85a10e..04955a5d2350 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1708,7 +1708,9 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i)
destp = ntohs(inet->inet_dport);
srcp = ntohs(inet->inet_sport);
- if (icsk->icsk_pending == ICSK_TIME_RETRANS) {
+ if (icsk->icsk_pending == ICSK_TIME_RETRANS ||
+ icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS ||
+ icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) {
timer_active = 1;
timer_expires = icsk->icsk_timeout;
} else if (icsk->icsk_pending == ICSK_TIME_PROBE0) {
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 9cb0ff304336..ed7f4a81a932 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -647,7 +647,7 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
/* if we're overly short, let UDP handle it */
encap_rcv = ACCESS_ONCE(up->encap_rcv);
- if (skb->len > sizeof(struct udphdr) && encap_rcv) {
+ if (encap_rcv) {
int ret;
/* Verify checksum before giving to encap */
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index afca2eb4dfa7..ec17cbe8a02b 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -1581,7 +1581,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
/* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
tunnel->encap = encap;
if (encap == L2TP_ENCAPTYPE_UDP) {
- struct udp_tunnel_sock_cfg udp_cfg;
+ struct udp_tunnel_sock_cfg udp_cfg = { };
udp_cfg.sk_user_data = tunnel;
udp_cfg.encap_type = UDP_ENCAP_L2TPINUDP;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 6f85b6ab8e51..f7bb6829b415 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -151,19 +151,26 @@ u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata)
void mesh_sta_cleanup(struct sta_info *sta)
{
struct ieee80211_sub_if_data *sdata = sta->sdata;
- u32 changed;
+ u32 changed = 0;
/*
* maybe userspace handles peer allocation and peering, but in either
* case the beacon is still generated by the kernel and we might need
* an update.
*/
- changed = mesh_accept_plinks_update(sdata);
+ if (sdata->u.mesh.user_mpm &&
+ sta->mesh->plink_state == NL80211_PLINK_ESTAB)
+ changed |= mesh_plink_dec_estab_count(sdata);
+ changed |= mesh_accept_plinks_update(sdata);
if (!sdata->u.mesh.user_mpm) {
changed |= mesh_plink_deactivate(sta);
del_timer_sync(&sta->mesh->plink_timer);
}
+ /* make sure no readers can access nexthop sta from here on */
+ mesh_path_flush_by_nexthop(sta);
+ synchronize_net();
+
if (changed)
ieee80211_mbss_info_change_notify(sdata, changed);
}
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index c6be0b4f4058..b6dc2d7cd650 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -530,7 +530,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
const u8 *target_addr, *orig_addr;
const u8 *da;
u8 target_flags, ttl, flags;
- u32 orig_sn, target_sn, lifetime, target_metric;
+ u32 orig_sn, target_sn, lifetime, target_metric = 0;
bool reply = false;
bool forward = true;
bool root_is_gate;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2cafb21b422f..15b0150283b6 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -269,7 +269,7 @@ struct ieee80211_fast_tx {
u8 sa_offs, da_offs, pn_offs;
u8 band;
u8 hdr[30 + 2 + IEEE80211_FAST_XMIT_MAX_IV +
- sizeof(rfc1042_header)];
+ sizeof(rfc1042_header)] __aligned(2);
struct rcu_head rcu_head;
};
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 53b592ec040f..f83c255d7da2 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -1368,7 +1368,6 @@ config NETFILTER_XT_MATCH_QUOTA2
config NETFILTER_XT_MATCH_QUOTA2_LOG
bool '"quota2" Netfilter LOG support'
depends on NETFILTER_XT_MATCH_QUOTA2
- depends on IP_NF_TARGET_ULOG=n # not yes, not module, just no
default n
help
This option allows `quota2' to log ONCE when a quota limit
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index d4aaad747ea9..25391fb25516 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -415,6 +415,47 @@ int xt_check_match(struct xt_mtchk_param *par,
}
EXPORT_SYMBOL_GPL(xt_check_match);
+/** xt_check_entry_match - check that matches end before start of target
+ *
+ * @match: beginning of xt_entry_match
+ * @target: beginning of this rules target (alleged end of matches)
+ * @alignment: alignment requirement of match structures
+ *
+ * Validates that all matches add up to the beginning of the target,
+ * and that each match covers at least the base structure size.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+static int xt_check_entry_match(const char *match, const char *target,
+ const size_t alignment)
+{
+ const struct xt_entry_match *pos;
+ int length = target - match;
+
+ if (length == 0) /* no matches */
+ return 0;
+
+ pos = (struct xt_entry_match *)match;
+ do {
+ if ((unsigned long)pos % alignment)
+ return -EINVAL;
+
+ if (length < (int)sizeof(struct xt_entry_match))
+ return -EINVAL;
+
+ if (pos->u.match_size < sizeof(struct xt_entry_match))
+ return -EINVAL;
+
+ if (pos->u.match_size > length)
+ return -EINVAL;
+
+ length -= pos->u.match_size;
+ pos = ((void *)((char *)(pos) + (pos)->u.match_size));
+ } while (length > 0);
+
+ return 0;
+}
+
#ifdef CONFIG_COMPAT
int xt_compat_add_offset(u_int8_t af, unsigned int offset, int delta)
{
@@ -484,13 +525,14 @@ int xt_compat_match_offset(const struct xt_match *match)
}
EXPORT_SYMBOL_GPL(xt_compat_match_offset);
-int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
- unsigned int *size)
+void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
+ unsigned int *size)
{
const struct xt_match *match = m->u.kernel.match;
struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m;
int pad, off = xt_compat_match_offset(match);
u_int16_t msize = cm->u.user.match_size;
+ char name[sizeof(m->u.user.name)];
m = *dstptr;
memcpy(m, cm, sizeof(*cm));
@@ -504,10 +546,12 @@ int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
msize += off;
m->u.user.match_size = msize;
+ strlcpy(name, match->name, sizeof(name));
+ module_put(match->me);
+ strncpy(m->u.user.name, name, sizeof(m->u.user.name));
*size += off;
*dstptr += msize;
- return 0;
}
EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
@@ -538,8 +582,125 @@ int xt_compat_match_to_user(const struct xt_entry_match *m,
return 0;
}
EXPORT_SYMBOL_GPL(xt_compat_match_to_user);
+
+/* non-compat version may have padding after verdict */
+struct compat_xt_standard_target {
+ struct compat_xt_entry_target t;
+ compat_uint_t verdict;
+};
+
+int xt_compat_check_entry_offsets(const void *base, const char *elems,
+ unsigned int target_offset,
+ unsigned int next_offset)
+{
+ long size_of_base_struct = elems - (const char *)base;
+ const struct compat_xt_entry_target *t;
+ const char *e = base;
+
+ if (target_offset < size_of_base_struct)
+ return -EINVAL;
+
+ if (target_offset + sizeof(*t) > next_offset)
+ return -EINVAL;
+
+ t = (void *)(e + target_offset);
+ if (t->u.target_size < sizeof(*t))
+ return -EINVAL;
+
+ if (target_offset + t->u.target_size > next_offset)
+ return -EINVAL;
+
+ if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 &&
+ COMPAT_XT_ALIGN(target_offset + sizeof(struct compat_xt_standard_target)) != next_offset)
+ return -EINVAL;
+
+ /* compat_xt_entry match has less strict aligment requirements,
+ * otherwise they are identical. In case of padding differences
+ * we need to add compat version of xt_check_entry_match.
+ */
+ BUILD_BUG_ON(sizeof(struct compat_xt_entry_match) != sizeof(struct xt_entry_match));
+
+ return xt_check_entry_match(elems, base + target_offset,
+ __alignof__(struct compat_xt_entry_match));
+}
+EXPORT_SYMBOL(xt_compat_check_entry_offsets);
#endif /* CONFIG_COMPAT */
+/**
+ * xt_check_entry_offsets - validate arp/ip/ip6t_entry
+ *
+ * @base: pointer to arp/ip/ip6t_entry
+ * @elems: pointer to first xt_entry_match, i.e. ip(6)t_entry->elems
+ * @target_offset: the arp/ip/ip6_t->target_offset
+ * @next_offset: the arp/ip/ip6_t->next_offset
+ *
+ * validates that target_offset and next_offset are sane and that all
+ * match sizes (if any) align with the target offset.
+ *
+ * This function does not validate the targets or matches themselves, it
+ * only tests that all the offsets and sizes are correct, that all
+ * match structures are aligned, and that the last structure ends where
+ * the target structure begins.
+ *
+ * Also see xt_compat_check_entry_offsets for CONFIG_COMPAT version.
+ *
+ * The arp/ip/ip6t_entry structure @base must have passed following tests:
+ * - it must point to a valid memory location
+ * - base to base + next_offset must be accessible, i.e. not exceed allocated
+ * length.
+ *
+ * A well-formed entry looks like this:
+ *
+ * ip(6)t_entry match [mtdata] match [mtdata] target [tgdata] ip(6)t_entry
+ * e->elems[]-----' | |
+ * matchsize | |
+ * matchsize | |
+ * | |
+ * target_offset---------------------------------' |
+ * next_offset---------------------------------------------------'
+ *
+ * elems[]: flexible array member at end of ip(6)/arpt_entry struct.
+ * This is where matches (if any) and the target reside.
+ * target_offset: beginning of target.
+ * next_offset: start of the next rule; also: size of this rule.
+ * Since targets have a minimum size, target_offset + minlen <= next_offset.
+ *
+ * Every match stores its size, sum of sizes must not exceed target_offset.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int xt_check_entry_offsets(const void *base,
+ const char *elems,
+ unsigned int target_offset,
+ unsigned int next_offset)
+{
+ long size_of_base_struct = elems - (const char *)base;
+ const struct xt_entry_target *t;
+ const char *e = base;
+
+ /* target start is within the ip/ip6/arpt_entry struct */
+ if (target_offset < size_of_base_struct)
+ return -EINVAL;
+
+ if (target_offset + sizeof(*t) > next_offset)
+ return -EINVAL;
+
+ t = (void *)(e + target_offset);
+ if (t->u.target_size < sizeof(*t))
+ return -EINVAL;
+
+ if (target_offset + t->u.target_size > next_offset)
+ return -EINVAL;
+
+ if (strcmp(t->u.user.name, XT_STANDARD_TARGET) == 0 &&
+ XT_ALIGN(target_offset + sizeof(struct xt_standard_target)) != next_offset)
+ return -EINVAL;
+
+ return xt_check_entry_match(elems, base + target_offset,
+ __alignof__(struct xt_entry_match));
+}
+EXPORT_SYMBOL(xt_check_entry_offsets);
+
int xt_check_target(struct xt_tgchk_param *par,
unsigned int size, u_int8_t proto, bool inv_proto)
{
@@ -590,6 +751,80 @@ int xt_check_target(struct xt_tgchk_param *par,
}
EXPORT_SYMBOL_GPL(xt_check_target);
+/**
+ * xt_copy_counters_from_user - copy counters and metadata from userspace
+ *
+ * @user: src pointer to userspace memory
+ * @len: alleged size of userspace memory
+ * @info: where to store the xt_counters_info metadata
+ * @compat: true if we setsockopt call is done by 32bit task on 64bit kernel
+ *
+ * Copies counter meta data from @user and stores it in @info.
+ *
+ * vmallocs memory to hold the counters, then copies the counter data
+ * from @user to the new memory and returns a pointer to it.
+ *
+ * If @compat is true, @info gets converted automatically to the 64bit
+ * representation.
+ *
+ * The metadata associated with the counters is stored in @info.
+ *
+ * Return: returns pointer that caller has to test via IS_ERR().
+ * If IS_ERR is false, caller has to vfree the pointer.
+ */
+void *xt_copy_counters_from_user(const void __user *user, unsigned int len,
+ struct xt_counters_info *info, bool compat)
+{
+ void *mem;
+ u64 size;
+
+#ifdef CONFIG_COMPAT
+ if (compat) {
+ /* structures only differ in size due to alignment */
+ struct compat_xt_counters_info compat_tmp;
+
+ if (len <= sizeof(compat_tmp))
+ return ERR_PTR(-EINVAL);
+
+ len -= sizeof(compat_tmp);
+ if (copy_from_user(&compat_tmp, user, sizeof(compat_tmp)) != 0)
+ return ERR_PTR(-EFAULT);
+
+ strlcpy(info->name, compat_tmp.name, sizeof(info->name));
+ info->num_counters = compat_tmp.num_counters;
+ user += sizeof(compat_tmp);
+ } else
+#endif
+ {
+ if (len <= sizeof(*info))
+ return ERR_PTR(-EINVAL);
+
+ len -= sizeof(*info);
+ if (copy_from_user(info, user, sizeof(*info)) != 0)
+ return ERR_PTR(-EFAULT);
+
+ info->name[sizeof(info->name) - 1] = '\0';
+ user += sizeof(*info);
+ }
+
+ size = sizeof(struct xt_counters);
+ size *= info->num_counters;
+
+ if (size != (u64)len)
+ return ERR_PTR(-EINVAL);
+
+ mem = vmalloc(len);
+ if (!mem)
+ return ERR_PTR(-ENOMEM);
+
+ if (copy_from_user(mem, user, len) == 0)
+ return mem;
+
+ vfree(mem);
+ return ERR_PTR(-EFAULT);
+}
+EXPORT_SYMBOL_GPL(xt_copy_counters_from_user);
+
#ifdef CONFIG_COMPAT
int xt_compat_target_offset(const struct xt_target *target)
{
@@ -605,6 +840,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t;
int pad, off = xt_compat_target_offset(target);
u_int16_t tsize = ct->u.user.target_size;
+ char name[sizeof(t->u.user.name)];
t = *dstptr;
memcpy(t, ct, sizeof(*ct));
@@ -618,6 +854,9 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
tsize += off;
t->u.user.target_size = tsize;
+ strlcpy(name, target->name, sizeof(name));
+ module_put(target->me);
+ strncpy(t->u.user.name, name, sizeof(t->u.user.name));
*size += off;
*dstptr += tsize;
diff --git a/net/netfilter/xt_quota2.c b/net/netfilter/xt_quota2.c
index 90604d8a8b4f..94663440d160 100644
--- a/net/netfilter/xt_quota2.c
+++ b/net/netfilter/xt_quota2.c
@@ -26,6 +26,28 @@
#define QUOTA2_SYSFS_WORK_MAX_SIZE 64
#define QUOTA2_SYSFS_NUM_ENVP 3
+#ifdef CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG
+/* For compatibility, these definitions are copied from the
+ * deprecated header file <linux/netfilter_ipv4/ipt_ULOG.h> */
+#define ULOG_MAC_LEN 80
+#define ULOG_PREFIX_LEN 32
+
+/* Format of the ULOG packets passed through netlink */
+typedef struct ulog_packet_msg {
+ unsigned long mark;
+ long timestamp_sec;
+ long timestamp_usec;
+ unsigned int hook;
+ char indev_name[IFNAMSIZ];
+ char outdev_name[IFNAMSIZ];
+ size_t data_len;
+ char prefix[ULOG_PREFIX_LEN];
+ unsigned char mac_len;
+ unsigned char mac[ULOG_MAC_LEN];
+ unsigned char payload[0];
+} ulog_packet_msg_t;
+#endif
+
/**
* @lock: lock to protect quota writers from each other
*/
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 992b35fb8615..7a5fa0c98377 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2784,6 +2784,7 @@ static int netlink_dump(struct sock *sk)
struct netlink_callback *cb;
struct sk_buff *skb = NULL;
struct nlmsghdr *nlh;
+ struct module *module;
int len, err = -ENOBUFS;
int alloc_min_size;
int alloc_size;
@@ -2863,9 +2864,11 @@ static int netlink_dump(struct sock *sk)
cb->done(cb);
nlk->cb_running = false;
+ module = cb->module;
+ skb = cb->skb;
mutex_unlock(nlk->cb_mutex);
- module_put(cb->module);
- consume_skb(cb->skb);
+ module_put(module);
+ consume_skb(skb);
return 0;
errout_skb:
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c
index d933cb89efac..5eb7694348b5 100644
--- a/net/openvswitch/vport-vxlan.c
+++ b/net/openvswitch/vport-vxlan.c
@@ -91,6 +91,8 @@ static struct vport *vxlan_tnl_create(const struct vport_parms *parms)
struct vxlan_config conf = {
.no_share = true,
.flags = VXLAN_F_COLLECT_METADATA | VXLAN_F_UDP_ZERO_CSUM6_RX,
+ /* Don't restrict the packets that can be sent by MTU */
+ .mtu = IP_MAX_MTU,
};
if (!options) {
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 9cc7b512b472..a86f26d05bc2 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1341,7 +1341,7 @@ static unsigned int fanout_demux_hash(struct packet_fanout *f,
struct sk_buff *skb,
unsigned int num)
{
- return reciprocal_scale(skb_get_hash(skb), num);
+ return reciprocal_scale(__skb_get_hash_symmetric(skb), num);
}
static unsigned int fanout_demux_lb(struct packet_fanout *f,
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index b07c535ba8e7..eeb3eb3ea9eb 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -105,9 +105,7 @@ static void *tcf_csum_skb_nextlayer(struct sk_buff *skb,
int hl = ihl + jhl;
if (!pskb_may_pull(skb, ipl + ntkoff) || (ipl < hl) ||
- (skb_cloned(skb) &&
- !skb_clone_writable(skb, hl + ntkoff) &&
- pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+ skb_try_make_writable(skb, hl + ntkoff))
return NULL;
else
return (void *)(skb_network_header(skb) + ihl);
@@ -365,9 +363,7 @@ static int tcf_csum_ipv4(struct sk_buff *skb, u32 update_flags)
}
if (update_flags & TCA_CSUM_UPDATE_FLAG_IPV4HDR) {
- if (skb_cloned(skb) &&
- !skb_clone_writable(skb, sizeof(*iph) + ntkoff) &&
- pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+ if (skb_try_make_writable(skb, sizeof(*iph) + ntkoff))
goto fail;
ip_send_check(ip_hdr(skb));
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 32fcdecdb9e2..e384d6aefa3a 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -170,7 +170,7 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a,
if (!(at & AT_EGRESS)) {
if (m->tcfm_ok_push)
- skb_push(skb2, skb->mac_len);
+ skb_push_rcsum(skb2, skb->mac_len);
}
/* mirror is always swallowed */
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index b7c4ead8b5a8..27607b863aba 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -126,9 +126,7 @@ static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
addr = iph->daddr;
if (!((old_addr ^ addr) & mask)) {
- if (skb_cloned(skb) &&
- !skb_clone_writable(skb, sizeof(*iph) + noff) &&
- pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+ if (skb_try_make_writable(skb, sizeof(*iph) + noff))
goto drop;
new_addr &= mask;
@@ -156,9 +154,7 @@ static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
struct tcphdr *tcph;
if (!pskb_may_pull(skb, ihl + sizeof(*tcph) + noff) ||
- (skb_cloned(skb) &&
- !skb_clone_writable(skb, ihl + sizeof(*tcph) + noff) &&
- pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+ skb_try_make_writable(skb, ihl + sizeof(*tcph) + noff))
goto drop;
tcph = (void *)(skb_network_header(skb) + ihl);
@@ -171,9 +167,7 @@ static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
struct udphdr *udph;
if (!pskb_may_pull(skb, ihl + sizeof(*udph) + noff) ||
- (skb_cloned(skb) &&
- !skb_clone_writable(skb, ihl + sizeof(*udph) + noff) &&
- pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))
+ skb_try_make_writable(skb, ihl + sizeof(*udph) + noff))
goto drop;
udph = (void *)(skb_network_header(skb) + ihl);
@@ -213,10 +207,8 @@ static int tcf_nat(struct sk_buff *skb, const struct tc_action *a,
if ((old_addr ^ addr) & mask)
break;
- if (skb_cloned(skb) &&
- !skb_clone_writable(skb, ihl + sizeof(*icmph) +
- sizeof(*iph) + noff) &&
- pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
+ if (skb_try_make_writable(skb, ihl + sizeof(*icmph) +
+ sizeof(*iph) + noff))
goto drop;
icmph = (void *)(skb_network_header(skb) + ihl);
diff --git a/net/sched/sch_fifo.c b/net/sched/sch_fifo.c
index 2177eac0a61e..2e4bd2c0a50c 100644
--- a/net/sched/sch_fifo.c
+++ b/net/sched/sch_fifo.c
@@ -37,14 +37,18 @@ static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc *sch)
static int pfifo_tail_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
+ unsigned int prev_backlog;
+
if (likely(skb_queue_len(&sch->q) < sch->limit))
return qdisc_enqueue_tail(skb, sch);
+ prev_backlog = sch->qstats.backlog;
/* queue full, remove one skb to fulfill the limit */
__qdisc_queue_drop_head(sch, &sch->q);
qdisc_qstats_drop(sch);
qdisc_enqueue_tail(skb, sch);
+ qdisc_tree_reduce_backlog(sch, 0, prev_backlog - sch->qstats.backlog);
return NET_XMIT_CN;
}
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index 4befe97a9034..b7c29d5b6f04 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -650,14 +650,14 @@ deliver:
#endif
if (q->qdisc) {
+ unsigned int pkt_len = qdisc_pkt_len(skb);
int err = qdisc_enqueue(skb, q->qdisc);
- if (unlikely(err != NET_XMIT_SUCCESS)) {
- if (net_xmit_drop_count(err)) {
- qdisc_qstats_drop(sch);
- qdisc_tree_reduce_backlog(sch, 1,
- qdisc_pkt_len(skb));
- }
+ if (err != NET_XMIT_SUCCESS &&
+ net_xmit_drop_count(err)) {
+ qdisc_qstats_drop(sch);
+ qdisc_tree_reduce_backlog(sch, 1,
+ pkt_len);
}
goto tfifo_dequeue;
}
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
index 1095be9c80ab..4605dc73def6 100644
--- a/net/sunrpc/auth_gss/svcauth_gss.c
+++ b/net/sunrpc/auth_gss/svcauth_gss.c
@@ -857,8 +857,8 @@ unwrap_integ_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct g
goto out;
if (svc_getnl(&buf->head[0]) != seq)
goto out;
- /* trim off the mic at the end before returning */
- xdr_buf_trim(buf, mic.len + 4);
+ /* trim off the mic and padding at the end before returning */
+ xdr_buf_trim(buf, round_up_to_quad(mic.len) + 4);
stat = 0;
out:
kfree(mic.data);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 23608eb0ded2..7a93922457ff 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -442,7 +442,7 @@ out_no_rpciod:
return ERR_PTR(err);
}
-struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
+static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
struct rpc_xprt *xprt)
{
struct rpc_clnt *clnt = NULL;
@@ -474,7 +474,6 @@ struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
return clnt;
}
-EXPORT_SYMBOL_GPL(rpc_create_xprt);
/**
* rpc_create - create an RPC client and transport with one call
@@ -500,6 +499,15 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
};
char servername[48];
+ if (args->bc_xprt) {
+ WARN_ON(args->protocol != XPRT_TRANSPORT_BC_TCP);
+ xprt = args->bc_xprt->xpt_bc_xprt;
+ if (xprt) {
+ xprt_get(xprt);
+ return rpc_create_xprt(args, xprt);
+ }
+ }
+
if (args->flags & RPC_CLNT_CREATE_INFINITE_SLOTS)
xprtargs.flags |= XPRT_CREATE_INFINITE_SLOTS;
if (args->flags & RPC_CLNT_CREATE_NO_IDLE_TIMEOUT)
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index d5d7132ac847..1b58866175e6 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -1169,6 +1169,7 @@ int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi,
.obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB,
.dst = dst,
.dst_len = dst_len,
+ .fi = fi,
.tos = tos,
.type = type,
.nlflags = nlflags,
@@ -1177,8 +1178,6 @@ int switchdev_fib_ipv4_add(u32 dst, int dst_len, struct fib_info *fi,
struct net_device *dev;
int err = 0;
- memcpy(&ipv4_fib.fi, fi, sizeof(ipv4_fib.fi));
-
/* Don't offload route if using custom ip rules or if
* IPv4 FIB offloading has been disabled completely.
*/
@@ -1222,6 +1221,7 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi,
.obj.id = SWITCHDEV_OBJ_ID_IPV4_FIB,
.dst = dst,
.dst_len = dst_len,
+ .fi = fi,
.tos = tos,
.type = type,
.nlflags = 0,
@@ -1230,8 +1230,6 @@ int switchdev_fib_ipv4_del(u32 dst, int dst_len, struct fib_info *fi,
struct net_device *dev;
int err = 0;
- memcpy(&ipv4_fib.fi, fi, sizeof(ipv4_fib.fi));
-
if (!(fi->fib_flags & RTNH_F_OFFLOAD))
return 0;
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
index 1eadc95e1132..2ed732bfe94b 100644
--- a/net/tipc/netlink_compat.c
+++ b/net/tipc/netlink_compat.c
@@ -802,7 +802,7 @@ static int tipc_nl_compat_name_table_dump(struct tipc_nl_compat_msg *msg,
goto out;
tipc_tlv_sprintf(msg->rep, "%-10u %s",
- nla_get_u32(publ[TIPC_NLA_PUBL_REF]),
+ nla_get_u32(publ[TIPC_NLA_PUBL_KEY]),
scope_str[nla_get_u32(publ[TIPC_NLA_PUBL_SCOPE])]);
out:
tipc_tlv_sprintf(msg->rep, "\n");
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index e53003cf7703..9b713e0ce00d 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -2814,6 +2814,9 @@ int tipc_nl_publ_dump(struct sk_buff *skb, struct netlink_callback *cb)
if (err)
return err;
+ if (!attrs[TIPC_NLA_SOCK])
+ return -EINVAL;
+
err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX,
attrs[TIPC_NLA_SOCK],
tipc_nl_sock_policy);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 898a53a562b8..6579fd6e7459 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -315,7 +315,7 @@ static struct sock *unix_find_socket_byinode(struct inode *i)
&unix_socket_table[i->i_ino & (UNIX_HASH_SIZE - 1)]) {
struct dentry *dentry = unix_sk(s)->path.dentry;
- if (dentry && d_backing_inode(dentry) == i) {
+ if (dentry && d_real_inode(dentry) == i) {
sock_hold(s);
goto found;
}
@@ -911,7 +911,7 @@ static struct sock *unix_find_other(struct net *net,
err = kern_path(sunname->sun_path, LOOKUP_FOLLOW, &path);
if (err)
goto fail;
- inode = d_backing_inode(path.dentry);
+ inode = d_real_inode(path.dentry);
err = inode_permission(inode, MAY_WRITE);
if (err)
goto put_fail;
@@ -1048,7 +1048,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
goto out_up;
}
addr->hash = UNIX_HASH_SIZE;
- hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1);
+ hash = d_real_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1);
spin_lock(&unix_table_lock);
u->path = u_path;
list = &unix_socket_table[hash];
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index b50ee5d622e1..c753211cb83f 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -955,8 +955,29 @@ static int wireless_process_ioctl(struct net *net, struct ifreq *ifr,
return private(dev, iwr, cmd, info, handler);
}
/* Old driver API : call driver ioctl handler */
- if (dev->netdev_ops->ndo_do_ioctl)
- return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
+ if (dev->netdev_ops->ndo_do_ioctl) {
+#ifdef CONFIG_COMPAT
+ if (info->flags & IW_REQUEST_FLAG_COMPAT) {
+ int ret = 0;
+ struct iwreq iwr_lcl;
+ struct compat_iw_point *iwp_compat = (void *) &iwr->u.data;
+
+ memcpy(&iwr_lcl, iwr, sizeof(struct iwreq));
+ iwr_lcl.u.data.pointer = compat_ptr(iwp_compat->pointer);
+ iwr_lcl.u.data.length = iwp_compat->length;
+ iwr_lcl.u.data.flags = iwp_compat->flags;
+
+ ret = dev->netdev_ops->ndo_do_ioctl(dev, (void *) &iwr_lcl, cmd);
+
+ iwp_compat->pointer = ptr_to_compat(iwr_lcl.u.data.pointer);
+ iwp_compat->length = iwr_lcl.u.data.length;
+ iwp_compat->flags = iwr_lcl.u.data.flags;
+
+ return ret;
+ } else
+#endif
+ return dev->netdev_ops->ndo_do_ioctl(dev, ifr, cmd);
+ }
return -EOPNOTSUPP;
}
diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn
index 4efedcbe4165..da3386a9d244 100644
--- a/scripts/Makefile.extrawarn
+++ b/scripts/Makefile.extrawarn
@@ -24,6 +24,7 @@ warning-1 += $(call cc-option, -Wmissing-prototypes)
warning-1 += -Wold-style-definition
warning-1 += $(call cc-option, -Wmissing-include-dirs)
warning-1 += $(call cc-option, -Wunused-but-set-variable)
+warning-1 += $(call cc-option, -Wunused-const-variable)
warning-1 += $(call cc-disable-warning, missing-field-initializers)
warning-2 := -Waggregate-return
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 5b96206e9aab..9f5cdd49ff0b 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -695,7 +695,7 @@ static int do_of_entry (const char *filename, void *symval, char *alias)
len = sprintf(alias, "of:N%sT%s", (*name)[0] ? *name : "*",
(*type)[0] ? *type : "*");
- if (compatible[0])
+ if ((*compatible)[0])
sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "",
*compatible);
diff --git a/scripts/package/Makefile b/scripts/package/Makefile
index 1aca224e8597..493e226356ca 100644
--- a/scripts/package/Makefile
+++ b/scripts/package/Makefile
@@ -52,7 +52,7 @@ rpm-pkg rpm: FORCE
$(call cmd,src_tar,$(KERNELPATH),kernel.spec)
$(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version
mv -f $(objtree)/.tmp_version $(objtree)/.version
- rpmbuild --target $(UTS_MACHINE) -ta $(KERNELPATH).tar.gz
+ rpmbuild $(RPMOPTS) --target $(UTS_MACHINE) -ta $(KERNELPATH).tar.gz
rm $(KERNELPATH).tar.gz kernel.spec
# binrpm-pkg
@@ -63,7 +63,7 @@ binrpm-pkg: FORCE
$(CONFIG_SHELL) $(srctree)/scripts/mkversion > $(objtree)/.tmp_version
mv -f $(objtree)/.tmp_version $(objtree)/.version
- rpmbuild --define "_builddir $(objtree)" --target \
+ rpmbuild $(RPMOPTS) --define "_builddir $(objtree)" --target \
$(UTS_MACHINE) -bb $(objtree)/binkernel.spec
rm binkernel.spec
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 89fea87feafb..bbfdfee59b38 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -467,13 +467,6 @@ static int sb_finish_set_opts(struct super_block *sb)
if (selinux_is_sblabel_mnt(sb))
sbsec->flags |= SBLABEL_MNT;
- /*
- * Special handling for rootfs. Is genfs but supports
- * setting SELinux context on in-core inodes.
- */
- if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
- sbsec->flags |= SBLABEL_MNT;
-
/* Initialize the root inode. */
rc = inode_doinit_with_dentry(root_inode, root);
@@ -3711,6 +3704,38 @@ static int selinux_kernel_module_request(char *kmod_name)
SYSTEM__MODULE_REQUEST, &ad);
}
+static int selinux_kernel_module_from_file(struct file *file)
+{
+ struct common_audit_data ad;
+ struct inode_security_struct *isec;
+ struct file_security_struct *fsec;
+ struct inode *inode;
+ u32 sid = current_sid();
+ int rc;
+
+ /* init_module */
+ if (file == NULL)
+ return avc_has_perm(sid, sid, SECCLASS_SYSTEM,
+ SYSTEM__MODULE_LOAD, NULL);
+
+ /* finit_module */
+ ad.type = LSM_AUDIT_DATA_PATH;
+ ad.u.path = file->f_path;
+
+ inode = file_inode(file);
+ isec = inode->i_security;
+ fsec = file->f_security;
+
+ if (sid != fsec->sid) {
+ rc = avc_has_perm(sid, fsec->sid, SECCLASS_FD, FD__USE, &ad);
+ if (rc)
+ return rc;
+ }
+
+ return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM,
+ SYSTEM__MODULE_LOAD, &ad);
+}
+
static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
{
return current_has_perm(p, PROCESS__SETPGID);
@@ -6003,6 +6028,7 @@ static struct security_hook_list selinux_hooks[] = {
LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
+ LSM_HOOK_INIT(kernel_module_from_file, selinux_kernel_module_from_file),
LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
LSM_HOOK_INIT(task_getsid, selinux_task_getsid),
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index 5a4eef59aeff..b393d29ae857 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -32,7 +32,7 @@ struct security_class_mapping secclass_map[] = {
"setsockcreate", NULL } },
{ "system",
{ "ipc_info", "syslog_read", "syslog_mod",
- "syslog_console", "module_request", NULL } },
+ "syslog_console", "module_request", "module_load", NULL } },
{ "capability",
{ "chown", "dac_override", "dac_read_search",
"fowner", "fsetid", "kill", "setgid", "setuid", "setpcap",
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 9e4743e833be..a2c2f06060df 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -849,7 +849,7 @@ int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
}
EXPORT_SYMBOL(snd_pcm_new_internal);
-static void free_pcm_kctl(struct snd_pcm_str *pstr)
+static void free_chmap(struct snd_pcm_str *pstr)
{
if (pstr->chmap_kctl) {
snd_ctl_remove(pstr->pcm->card, pstr->chmap_kctl);
@@ -887,7 +887,7 @@ static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
kfree(setup);
}
#endif
- free_pcm_kctl(pstr);
+ free_chmap(pstr);
if (pstr->substream_count)
put_device(&pstr->dev);
}
@@ -1152,7 +1152,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
for (cidx = 0; cidx < 2; cidx++) {
if (!pcm->internal)
snd_unregister_device(&pcm->streams[cidx].dev);
- free_pcm_kctl(&pcm->streams[cidx]);
+ free_chmap(&pcm->streams[cidx]);
}
mutex_unlock(&pcm->open_mutex);
mutex_unlock(&register_mutex);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 3f26597d8d46..1f062aaa5414 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -2017,7 +2017,7 @@ static int snd_pcm_hw_rule_sample_bits(struct snd_pcm_hw_params *params,
static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
48000, 64000, 88200, 96000, 176400, 192000,
- 384000 };
+ 352800, 384000 };
const struct snd_pcm_hw_constraint_list snd_pcm_known_rates = {
.count = ARRAY_SIZE(rates),
diff --git a/sound/core/timer.c b/sound/core/timer.c
index f420cd8583da..12768f55f8d5 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -1968,6 +1968,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
qhead = tu->qhead++;
tu->qhead %= tu->queue_size;
+ tu->qused--;
spin_unlock_irq(&tu->qlock);
if (tu->tread) {
@@ -1981,7 +1982,6 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
}
spin_lock_irq(&tu->qlock);
- tu->qused--;
if (err < 0)
goto _error;
result += unit;
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index a9f7a75702d2..67628616506e 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -420,6 +420,7 @@ static int dummy_hrtimer_stop(struct snd_pcm_substream *substream)
static inline void dummy_hrtimer_sync(struct dummy_hrtimer_pcm *dpcm)
{
+ hrtimer_cancel(&dpcm->timer);
tasklet_kill(&dpcm->tasklet);
}
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 4667c3232b7f..74177189063c 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -1444,9 +1444,8 @@ static int vortex_wtdma_bufshift(vortex_t * vortex, int wtdma)
int page, p, pp, delta, i;
page =
- (hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2)) &
- WT_SUBBUF_MASK)
- >> WT_SUBBUF_SHIFT;
+ (hwread(vortex->mmio, VORTEX_WTDMA_STAT + (wtdma << 2))
+ >> WT_SUBBUF_SHIFT) & WT_SUBBUF_MASK;
if (dma->nr_periods >= 4)
delta = (page - dma->period_real) & 3;
else {
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 1cb85aeb0cea..286f5e3686a3 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -2200,11 +2200,11 @@ static int snd_echo_resume(struct device *dev)
u32 pipe_alloc_mask;
int err;
- commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL);
+ commpage_bak = kmalloc(sizeof(*commpage), GFP_KERNEL);
if (commpage_bak == NULL)
return -ENOMEM;
commpage = chip->comm_page;
- memcpy(commpage_bak, commpage, sizeof(struct comm_page));
+ memcpy(commpage_bak, commpage, sizeof(*commpage));
err = init_hw(chip, chip->pci->device, chip->pci->subsystem_device);
if (err < 0) {
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 367dbf0d285e..dc2fa576d60d 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -3994,6 +3994,8 @@ static hda_nid_t set_path_power(struct hda_codec *codec, hda_nid_t nid,
for (n = 0; n < spec->paths.used; n++) {
path = snd_array_elem(&spec->paths, n);
+ if (!path->depth)
+ continue;
if (path->path[0] == nid ||
path->path[path->depth - 1] == nid) {
bool pin_old = path->pin_enabled;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 411630e9c034..8218cace8fea 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -359,8 +359,12 @@ enum {
#define IS_SKL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa170)
#define IS_SKL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d70)
+#define IS_KBL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa171)
+#define IS_KBL_LP(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x9d71)
+#define IS_KBL_H(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa2f0)
#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
-#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci))
+#define IS_SKL_PLUS(pci) (IS_SKL(pci) || IS_SKL_LP(pci) || IS_BXT(pci)) || \
+ IS_KBL(pci) || IS_KBL_LP(pci) || IS_KBL_H(pci)
static char *driver_short_names[] = {
[AZX_DRIVER_ICH] = "HDA Intel",
@@ -1252,8 +1256,10 @@ static int azx_free(struct azx *chip)
if (use_vga_switcheroo(hda)) {
if (chip->disabled && hda->probe_continued)
snd_hda_unlock_devices(&chip->bus);
- if (hda->vga_switcheroo_registered)
+ if (hda->vga_switcheroo_registered) {
vga_switcheroo_unregister_client(chip->pci);
+ vga_switcheroo_fini_domain_pm_ops(chip->card->dev);
+ }
}
if (bus->chip_init) {
@@ -2204,6 +2210,15 @@ static const struct pci_device_id azx_ids[] = {
/* Sunrise Point-LP */
{ PCI_DEVICE(0x8086, 0x9d70),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+ /* Kabylake */
+ { PCI_DEVICE(0x8086, 0xa171),
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+ /* Kabylake-LP */
+ { PCI_DEVICE(0x8086, 0x9d71),
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
+ /* Kabylake-H */
+ { PCI_DEVICE(0x8086, 0xa2f0),
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_SKYLAKE },
/* Broxton-P(Apollolake) */
{ PCI_DEVICE(0x8086, 0x5a98),
.driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_BROXTON },
@@ -2277,6 +2292,8 @@ static const struct pci_device_id azx_ids[] = {
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
{ PCI_DEVICE(0x1002, 0x157a),
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+ { PCI_DEVICE(0x1002, 0x15b3),
+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
{ PCI_DEVICE(0x1002, 0x793b),
.driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
{ PCI_DEVICE(0x1002, 0x7919),
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 4918ffa5ba68..abcb5a6a1cd9 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -335,6 +335,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
case 0x10ec0283:
case 0x10ec0286:
case 0x10ec0288:
+ case 0x10ec0295:
case 0x10ec0298:
alc_update_coef_idx(codec, 0x10, 1<<9, 0);
break;
@@ -342,6 +343,14 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
case 0x10ec0293:
alc_update_coef_idx(codec, 0xa, 1<<13, 0);
break;
+ case 0x10ec0234:
+ case 0x10ec0274:
+ case 0x10ec0294:
+ case 0x10ec0700:
+ case 0x10ec0701:
+ case 0x10ec0703:
+ alc_update_coef_idx(codec, 0x10, 1<<15, 0);
+ break;
case 0x10ec0662:
if ((coef & 0x00f0) == 0x0030)
alc_update_coef_idx(codec, 0x4, 1<<10, 0); /* EAPD Ctrl */
@@ -902,6 +911,7 @@ static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
{ 0x10ec0298, 0x1028, 0, "ALC3266" },
{ 0x10ec0256, 0x1028, 0, "ALC3246" },
{ 0x10ec0225, 0x1028, 0, "ALC3253" },
+ { 0x10ec0295, 0x1028, 0, "ALC3254" },
{ 0x10ec0670, 0x1025, 0, "ALC669X" },
{ 0x10ec0676, 0x1025, 0, "ALC679X" },
{ 0x10ec0282, 0x1043, 0, "ALC3229" },
@@ -2647,6 +2657,8 @@ enum {
ALC269_TYPE_ALC255,
ALC269_TYPE_ALC256,
ALC269_TYPE_ALC225,
+ ALC269_TYPE_ALC294,
+ ALC269_TYPE_ALC700,
};
/*
@@ -2677,6 +2689,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
case ALC269_TYPE_ALC255:
case ALC269_TYPE_ALC256:
case ALC269_TYPE_ALC225:
+ case ALC269_TYPE_ALC294:
+ case ALC269_TYPE_ALC700:
ssids = alc269_ssids;
break;
default:
@@ -3609,13 +3623,20 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
static void alc_headset_mode_unplugged(struct hda_codec *codec)
{
static struct coef_fw coef0255[] = {
- WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */
WRITE_COEFEX(0x57, 0x03, 0x8aa6), /* Direct Drive HP Amp control */
{}
};
+ static struct coef_fw coef0255_1[] = {
+ WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
+ {}
+ };
+ static struct coef_fw coef0256[] = {
+ WRITE_COEF(0x1b, 0x0c4b), /* LDO and MISC control */
+ {}
+ };
static struct coef_fw coef0233[] = {
WRITE_COEF(0x1b, 0x0c0b),
WRITE_COEF(0x45, 0xc429),
@@ -3668,7 +3689,11 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
switch (codec->core.vendor_id) {
case 0x10ec0255:
+ alc_process_coef_fw(codec, coef0255_1);
+ alc_process_coef_fw(codec, coef0255);
+ break;
case 0x10ec0256:
+ alc_process_coef_fw(codec, coef0256);
alc_process_coef_fw(codec, coef0255);
break;
case 0x10ec0233:
@@ -3690,6 +3715,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
alc_process_coef_fw(codec, coef0668);
break;
case 0x10ec0225:
+ case 0x10ec0295:
alc_process_coef_fw(codec, coef0225);
break;
}
@@ -3790,6 +3816,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
break;
case 0x10ec0225:
+ case 0x10ec0295:
alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10);
snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
alc_process_coef_fw(codec, coef0225);
@@ -3847,6 +3874,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
switch (codec->core.vendor_id) {
case 0x10ec0225:
+ case 0x10ec0295:
alc_process_coef_fw(codec, coef0225);
break;
case 0x10ec0255:
@@ -3884,6 +3912,12 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
WRITE_COEFEX(0x57, 0x03, 0x8ea6),
{}
};
+ static struct coef_fw coef0256[] = {
+ WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
+ WRITE_COEF(0x1b, 0x0c6b),
+ WRITE_COEFEX(0x57, 0x03, 0x8ea6),
+ {}
+ };
static struct coef_fw coef0233[] = {
WRITE_COEF(0x45, 0xd429),
WRITE_COEF(0x1b, 0x0c2b),
@@ -3924,9 +3958,11 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
switch (codec->core.vendor_id) {
case 0x10ec0255:
- case 0x10ec0256:
alc_process_coef_fw(codec, coef0255);
break;
+ case 0x10ec0256:
+ alc_process_coef_fw(codec, coef0256);
+ break;
case 0x10ec0233:
case 0x10ec0283:
alc_process_coef_fw(codec, coef0233);
@@ -3950,6 +3986,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
alc_process_coef_fw(codec, coef0688);
break;
case 0x10ec0225:
+ case 0x10ec0295:
alc_process_coef_fw(codec, coef0225);
break;
}
@@ -3965,6 +4002,12 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
WRITE_COEFEX(0x57, 0x03, 0x8ea6),
{}
};
+ static struct coef_fw coef0256[] = {
+ WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
+ WRITE_COEF(0x1b, 0x0c6b),
+ WRITE_COEFEX(0x57, 0x03, 0x8ea6),
+ {}
+ };
static struct coef_fw coef0233[] = {
WRITE_COEF(0x45, 0xe429),
WRITE_COEF(0x1b, 0x0c2b),
@@ -4005,9 +4048,11 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
switch (codec->core.vendor_id) {
case 0x10ec0255:
- case 0x10ec0256:
alc_process_coef_fw(codec, coef0255);
break;
+ case 0x10ec0256:
+ alc_process_coef_fw(codec, coef0256);
+ break;
case 0x10ec0233:
case 0x10ec0283:
alc_process_coef_fw(codec, coef0233);
@@ -4031,6 +4076,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
alc_process_coef_fw(codec, coef0688);
break;
case 0x10ec0225:
+ case 0x10ec0295:
alc_process_coef_fw(codec, coef0225);
break;
}
@@ -4114,6 +4160,7 @@ static void alc_determine_headset_type(struct hda_codec *codec)
is_ctia = (val & 0x1c02) == 0x1c02;
break;
case 0x10ec0225:
+ case 0x10ec0295:
alc_process_coef_fw(codec, coef0225);
msleep(800);
val = alc_read_coef_idx(codec, 0x46);
@@ -4251,7 +4298,7 @@ static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
static void alc255_set_default_jack_type(struct hda_codec *codec)
{
/* Set to iphone type */
- static struct coef_fw fw[] = {
+ static struct coef_fw alc255fw[] = {
WRITE_COEF(0x1b, 0x880b),
WRITE_COEF(0x45, 0xd089),
WRITE_COEF(0x1b, 0x080b),
@@ -4259,7 +4306,22 @@ static void alc255_set_default_jack_type(struct hda_codec *codec)
WRITE_COEF(0x1b, 0x0c0b),
{}
};
- alc_process_coef_fw(codec, fw);
+ static struct coef_fw alc256fw[] = {
+ WRITE_COEF(0x1b, 0x884b),
+ WRITE_COEF(0x45, 0xd089),
+ WRITE_COEF(0x1b, 0x084b),
+ WRITE_COEF(0x46, 0x0004),
+ WRITE_COEF(0x1b, 0x0c4b),
+ {}
+ };
+ switch (codec->core.vendor_id) {
+ case 0x10ec0255:
+ alc_process_coef_fw(codec, alc255fw);
+ break;
+ case 0x10ec0256:
+ alc_process_coef_fw(codec, alc256fw);
+ break;
+ }
msleep(30);
}
@@ -5459,8 +5521,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
SND_PCI_QUIRK(0x1028, 0x06df, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
SND_PCI_QUIRK(0x1028, 0x06e0, "Dell", ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK),
- SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
+ SND_PCI_QUIRK(0x1028, 0x0704, "Dell XPS 13 9350", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
SND_PCI_QUIRK(0x1028, 0x0725, "Dell Inspiron 3162", ALC255_FIXUP_DELL_SPK_NOISE),
+ SND_PCI_QUIRK(0x1028, 0x075b, "Dell XPS 13 9360", ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE),
SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -5571,6 +5634,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x2218, "Thinkpad X1 Carbon 2nd", ALC292_FIXUP_TPT440_DOCK),
SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
+ SND_PCI_QUIRK(0x17aa, 0x2231, "Thinkpad T560", ALC292_FIXUP_TPT460),
SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC292_FIXUP_TPT460),
SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
@@ -5586,6 +5650,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x503c, "Thinkpad L450", ALC292_FIXUP_TPT440_DOCK),
SND_PCI_QUIRK(0x17aa, 0x504a, "ThinkPad X260", ALC292_FIXUP_TPT440_DOCK),
SND_PCI_QUIRK(0x17aa, 0x504b, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
+ SND_PCI_QUIRK(0x17aa, 0x5050, "Thinkpad T560p", ALC292_FIXUP_TPT460),
+ SND_PCI_QUIRK(0x17aa, 0x5051, "Thinkpad L460", ALC292_FIXUP_TPT460),
+ SND_PCI_QUIRK(0x17aa, 0x5053, "Thinkpad T460", ALC292_FIXUP_TPT460),
SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
@@ -5671,7 +5738,6 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{}
};
#define ALC225_STANDARD_PINS \
- {0x12, 0xb7a60130}, \
{0x21, 0x04211020}
#define ALC256_STANDARD_PINS \
@@ -5696,14 +5762,31 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC225_STANDARD_PINS,
+ {0x12, 0xb7a60130},
+ {0x14, 0x901701a0}),
+ SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
+ ALC225_STANDARD_PINS,
+ {0x12, 0xb7a60130},
+ {0x14, 0x901701b0}),
+ SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
+ ALC225_STANDARD_PINS,
+ {0x12, 0xb7a60150},
{0x14, 0x901701a0}),
SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC225_STANDARD_PINS,
+ {0x12, 0xb7a60150},
{0x14, 0x901701b0}),
+ SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
+ ALC225_STANDARD_PINS,
+ {0x12, 0xb7a60130},
+ {0x1b, 0x90170110}),
SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
{0x14, 0x90170110},
{0x21, 0x02211020}),
SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ {0x14, 0x90170130},
+ {0x21, 0x02211040}),
+ SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
{0x12, 0x90a60140},
{0x14, 0x90170110},
{0x21, 0x02211020}),
@@ -5756,11 +5839,19 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
{0x12, 0x90a60180},
{0x14, 0x90170130},
{0x21, 0x02211040}),
+ SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell Inspiron 5565", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ {0x12, 0x90a60180},
+ {0x14, 0x90170120},
+ {0x21, 0x02211030}),
SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
{0x12, 0x90a60160},
{0x14, 0x90170120},
{0x21, 0x02211030}),
SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ {0x12, 0x90a60170},
+ {0x14, 0x90170120},
+ {0x21, 0x02211030}),
+ SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC256_STANDARD_PINS),
SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
{0x12, 0x90a60130},
@@ -6026,8 +6117,22 @@ static int patch_alc269(struct hda_codec *codec)
alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/
break;
case 0x10ec0225:
+ case 0x10ec0295:
spec->codec_variant = ALC269_TYPE_ALC225;
break;
+ case 0x10ec0234:
+ case 0x10ec0274:
+ case 0x10ec0294:
+ spec->codec_variant = ALC269_TYPE_ALC294;
+ break;
+ case 0x10ec0700:
+ case 0x10ec0701:
+ case 0x10ec0703:
+ spec->codec_variant = ALC269_TYPE_ALC700;
+ spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
+ alc_update_coef_idx(codec, 0x4a, 0, 1 << 15); /* Combo jack auto trigger control */
+ break;
+
}
if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
@@ -6942,6 +7047,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269),
+ HDA_CODEC_ENTRY(0x10ec0234, "ALC234", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0235, "ALC233", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0255, "ALC255", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0256, "ALC256", patch_alc269),
@@ -6952,6 +7058,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
HDA_CODEC_ENTRY(0x10ec0269, "ALC269", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0270, "ALC270", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0272, "ALC272", patch_alc662),
+ HDA_CODEC_ENTRY(0x10ec0274, "ALC274", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0275, "ALC275", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0276, "ALC276", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0280, "ALC280", patch_alc269),
@@ -6964,6 +7071,8 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
HDA_CODEC_ENTRY(0x10ec0290, "ALC290", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0292, "ALC292", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0293, "ALC293", patch_alc269),
+ HDA_CODEC_ENTRY(0x10ec0294, "ALC294", patch_alc269),
+ HDA_CODEC_ENTRY(0x10ec0295, "ALC295", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269),
HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861),
HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
@@ -6979,6 +7088,9 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
HDA_CODEC_ENTRY(0x10ec0670, "ALC670", patch_alc662),
HDA_CODEC_ENTRY(0x10ec0671, "ALC671", patch_alc662),
HDA_CODEC_ENTRY(0x10ec0680, "ALC680", patch_alc680),
+ HDA_CODEC_ENTRY(0x10ec0700, "ALC700", patch_alc269),
+ HDA_CODEC_ENTRY(0x10ec0701, "ALC701", patch_alc269),
+ HDA_CODEC_ENTRY(0x10ec0703, "ALC703", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0867, "ALC891", patch_alc882),
HDA_CODEC_ENTRY(0x10ec0880, "ALC880", patch_alc880),
HDA_CODEC_ENTRY(0x10ec0882, "ALC882", patch_alc882),
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index cda27c22812a..eb8fe212e163 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -560,6 +560,7 @@ static const struct regmap_config ak4642_regmap = {
.max_register = FIL1_3,
.reg_defaults = ak4642_reg,
.num_reg_defaults = NUM_AK4642_REG_DEFAULTS,
+ .cache_type = REGCACHE_RBTREE,
};
static const struct regmap_config ak4643_regmap = {
@@ -568,6 +569,7 @@ static const struct regmap_config ak4643_regmap = {
.max_register = SPK_MS,
.reg_defaults = ak4643_reg,
.num_reg_defaults = ARRAY_SIZE(ak4643_reg),
+ .cache_type = REGCACHE_RBTREE,
};
static const struct regmap_config ak4648_regmap = {
@@ -576,6 +578,7 @@ static const struct regmap_config ak4648_regmap = {
.max_register = EQ_FBEQE,
.reg_defaults = ak4648_reg,
.num_reg_defaults = ARRAY_SIZE(ak4648_reg),
+ .cache_type = REGCACHE_RBTREE,
};
static const struct ak4642_drvdata ak4642_drvdata = {
diff --git a/sound/soc/codecs/msm8x16/msm8x16-wcd.c b/sound/soc/codecs/msm8x16/msm8x16-wcd.c
index 481e1efdf015..c73414681c5a 100644
--- a/sound/soc/codecs/msm8x16/msm8x16-wcd.c
+++ b/sound/soc/codecs/msm8x16/msm8x16-wcd.c
@@ -40,9 +40,10 @@
#include <sound/tlv.h>
#include <sound/q6core.h>
#include <soc/qcom/subsystem_notif.h>
-#include "msm8x16-wcd.h"
+#include "../../msm/msmfalcon-common.h"
#include "../wcd-mbhc-v2.h"
#include "msm8916-wcd-irq.h"
+#include "msm8x16-wcd.h"
#define DRV_NAME "msm-codec"
#define MSM89XX_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
@@ -253,8 +254,6 @@ static struct wcd_mbhc_register
WCD_MBHC_REGISTER("WCD_MBHC_SWCH_LEVEL_REMOVE",
MSM89XX_PMIC_ANALOG_MBHC_ZDET_ELECT_RESULT,
0x10, 4, 0),
- WCD_MBHC_REGISTER("WCD_MBHC_MOISTURE_VREF",
- 0, 0, 0, 0),
WCD_MBHC_REGISTER("WCD_MBHC_PULLDOWN_CTRL",
MSM89XX_PMIC_ANALOG_MICB_2_EN, 0x20, 5, 0),
WCD_MBHC_REGISTER("WCD_MBHC_ANC_DET_EN",
@@ -295,7 +294,7 @@ static int msm8x16_wcd_dt_parse_vreg_info(struct device *dev,
const char *vreg_name, bool ondemand);
static struct msm8x16_wcd_pdata *msm8x16_wcd_populate_dt_pdata(
struct device *dev);
-static int msm8x16_wcd_enable_ext_mb_source(struct snd_soc_codec *codec,
+static int msm8x16_wcd_enable_ext_mb_source(struct wcd_mbhc *mbhc,
bool turn_on);
static void msm8x16_trim_btn_reg(struct snd_soc_codec *codec);
static void msm8x16_wcd_set_micb_v(struct snd_soc_codec *codec);
@@ -335,35 +334,28 @@ static int get_codec_version(struct msm8x16_wcd_priv *msm8x16_wcd)
static int msm_digcdc_clock_control(bool flag)
{
int ret = -EINVAL;
- struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm_asoc_mach_data *pdata = NULL;
pdata = snd_soc_card_get_drvdata(registered_codec->component.card);
if (flag) {
- mutex_lock(&pdata->cdc_mclk_mutex);
- if (atomic_read(&pdata->mclk_enabled) == false) {
- if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
- pdata->digital_cdc_clk.clk_val =
- pdata->mclk_freq;
- ret = afe_set_digital_codec_core_clock(
- AFE_PORT_ID_PRIMARY_MI2S_RX,
- &pdata->digital_cdc_clk);
- } else {
- pdata->digital_cdc_core_clk.enable = 1;
- ret = afe_set_lpass_clock_v2(
- AFE_PORT_ID_PRIMARY_MI2S_RX,
- &pdata->digital_cdc_core_clk);
- }
+ mutex_lock(&pdata->cdc_int_mclk0_mutex);
+ if (atomic_read(&pdata->int_mclk0_enabled) == false) {
+ pdata->digital_cdc_core_clk.enable = 1;
+ ret = afe_set_lpass_clock_v2(
+ AFE_PORT_ID_INT0_MI2S_RX,
+ &pdata->digital_cdc_core_clk);
if (ret < 0) {
- pr_err("failed to enable the MCLK\n");
- goto err;
+ pr_err("failed to enable the INT_MCLK0\n");
+ goto err_mclk;
}
pr_err("enabled digital codec core clk\n");
- atomic_set(&pdata->mclk_enabled, true);
- schedule_delayed_work(&pdata->disable_mclk_work, 50);
+ atomic_set(&pdata->int_mclk0_enabled, true);
+ schedule_delayed_work(&pdata->disable_int_mclk0_work,
+ 50);
}
-err:
- mutex_unlock(&pdata->cdc_mclk_mutex);
+err_mclk:
+ mutex_unlock(&pdata->cdc_int_mclk0_mutex);
return ret;
}
return 0;
@@ -617,11 +609,12 @@ static void msm8x16_wcd_compute_impedance(struct snd_soc_codec *codec, s16 l,
}
static struct firmware_cal *msm8x16_wcd_get_hwdep_fw_cal(
- struct snd_soc_codec *codec,
+ struct wcd_mbhc *mbhc,
enum wcd_cal_type type)
{
struct msm8x16_wcd_priv *msm8x16_wcd;
struct firmware_cal *hwdep_cal;
+ struct snd_soc_codec *codec = mbhc->codec;
if (!codec) {
pr_err("%s: NULL codec pointer\n", __func__);
@@ -1063,10 +1056,11 @@ exit:
pr_err("%s: Impedance detection completed\n", __func__);
}
-static int msm8x16_register_notifier(struct snd_soc_codec *codec,
+static int msm8x16_register_notifier(struct wcd_mbhc *mbhc,
struct notifier_block *nblock,
bool enable)
{
+ struct snd_soc_codec *codec = mbhc->codec;
struct msm8x16_wcd_priv *msm8x16_wcd =
snd_soc_codec_get_drvdata(codec);
@@ -1624,7 +1618,7 @@ out:
static int msm8x16_wcd_codec_enable_clock_block(struct snd_soc_codec *codec,
int enable)
{
- struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm_asoc_mach_data *pdata = NULL;
pdata = snd_soc_card_get_drvdata(codec->component.card);
if (enable) {
@@ -1776,7 +1770,7 @@ static int msm8x16_wcd_loopback_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
- struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm_asoc_mach_data *pdata = NULL;
pdata = snd_soc_card_get_drvdata(codec->component.card);
dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
@@ -1789,7 +1783,7 @@ static int msm8x16_wcd_loopback_mode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
- struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm_asoc_mach_data *pdata = NULL;
pdata = snd_soc_card_get_drvdata(codec->component.card);
dev_err(codec->dev, "%s: ucontrol->value.integer.value[0] = %ld\n",
@@ -3061,7 +3055,7 @@ static int msm8x16_wcd_codec_enable_dig_clk(struct snd_soc_dapm_widget *w,
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
- struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm_asoc_mach_data *pdata = NULL;
pdata = snd_soc_card_get_drvdata(codec->component.card);
@@ -3202,11 +3196,12 @@ static void msm8x16_trim_btn_reg(struct snd_soc_codec *codec)
pr_err("%s: This device is trimmed at ATE\n", __func__);
}
}
-static int msm8x16_wcd_enable_ext_mb_source(struct snd_soc_codec *codec,
+static int msm8x16_wcd_enable_ext_mb_source(struct wcd_mbhc *mbhc,
bool turn_on)
{
int ret = 0;
static int count;
+ struct snd_soc_codec *codec = mbhc->codec;
struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec);
dev_err(codec->dev, "%s turn_on: %d count: %d\n", __func__, turn_on,
@@ -3405,7 +3400,7 @@ static int msm8x16_wcd_codec_enable_dec(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
- struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm_asoc_mach_data *pdata = NULL;
unsigned int decimator;
struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec);
char *dec_name = NULL;
@@ -4328,14 +4323,14 @@ int msm8x16_wcd_mclk_enable(struct snd_soc_codec *codec,
dev_err(codec->dev, "%s: mclk_enable = %u, dapm = %d\n",
__func__, mclk_enable, dapm);
if (mclk_enable) {
- msm8x16_wcd->mclk_enabled = true;
+ msm8x16_wcd->int_mclk0_enabled = true;
msm8x16_wcd_codec_enable_clock_block(codec, 1);
} else {
- if (!msm8x16_wcd->mclk_enabled) {
+ if (!msm8x16_wcd->int_mclk0_enabled) {
dev_err(codec->dev, "Error, MCLK already diabled\n");
return -EINVAL;
}
- msm8x16_wcd->mclk_enabled = false;
+ msm8x16_wcd->int_mclk0_enabled = false;
msm8x16_wcd_codec_enable_clock_block(codec, 0);
}
return 0;
@@ -5178,7 +5173,7 @@ static struct regulator *wcd8x16_wcd_codec_find_regulator(
static int msm8x16_wcd_device_down(struct snd_soc_codec *codec)
{
- struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm_asoc_mach_data *pdata = NULL;
struct msm8x16_wcd_priv *msm8x16_wcd_priv =
snd_soc_codec_get_drvdata(codec);
int i;
@@ -5250,7 +5245,7 @@ static int msm8x16_wcd_device_down(struct snd_soc_codec *codec)
MSM89XX_PMIC_ANALOG_SPKR_DAC_CTL, 0x93);
msm8x16_wcd_bringup(codec);
- atomic_set(&pdata->mclk_enabled, false);
+ atomic_set(&pdata->int_mclk0_enabled, false);
set_bit(BUS_DOWN, &msm8x16_wcd_priv->status_mask);
snd_soc_card_change_online_state(codec->component.card, 0);
return 0;
@@ -5399,7 +5394,7 @@ static void msm8x16_wcd_configure_cap(struct snd_soc_codec *codec,
bool micbias1, bool micbias2)
{
- struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm_asoc_mach_data *pdata = NULL;
pdata = snd_soc_card_get_drvdata(codec->component.card);
@@ -5553,7 +5548,7 @@ static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec)
wcd_mbhc_init(&msm8x16_wcd_priv->mbhc, codec, &mbhc_cb, &intr_ids,
wcd_mbhc_registers, true);
- msm8x16_wcd_priv->mclk_enabled = false;
+ msm8x16_wcd_priv->int_mclk0_enabled = false;
msm8x16_wcd_priv->clock_active = false;
msm8x16_wcd_priv->config_mode_active = false;
@@ -5654,33 +5649,23 @@ static int msm8x16_wcd_disable_static_supplies_to_optimum(
int msm8x16_wcd_suspend(struct snd_soc_codec *codec)
{
- struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm_asoc_mach_data *pdata = NULL;
struct msm8x16_wcd *msm8x16 = codec->control_data;
struct msm8x16_wcd_pdata *msm8x16_pdata = msm8x16->dev->platform_data;
pdata = snd_soc_card_get_drvdata(codec->component.card);
pr_err("%s: mclk cnt = %d, mclk_enabled = %d\n",
- __func__, atomic_read(&pdata->mclk_rsc_ref),
- atomic_read(&pdata->mclk_enabled));
- if (atomic_read(&pdata->mclk_enabled) == true) {
+ __func__, atomic_read(&pdata->int_mclk0_rsc_ref),
+ atomic_read(&pdata->int_mclk0_enabled));
+ if (atomic_read(&pdata->int_mclk0_enabled) == true) {
cancel_delayed_work_sync(
- &pdata->disable_mclk_work);
- mutex_lock(&pdata->cdc_mclk_mutex);
- if (atomic_read(&pdata->mclk_enabled) == true) {
- if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) {
- pdata->digital_cdc_clk.clk_val = 0;
- afe_set_digital_codec_core_clock(
- AFE_PORT_ID_PRIMARY_MI2S_RX,
- &pdata->digital_cdc_clk);
- } else {
- pdata->digital_cdc_core_clk.enable = 0;
- afe_set_lpass_clock_v2(
- AFE_PORT_ID_PRIMARY_MI2S_RX,
- &pdata->digital_cdc_core_clk);
- }
- atomic_set(&pdata->mclk_enabled, false);
- }
- mutex_unlock(&pdata->cdc_mclk_mutex);
+ &pdata->disable_int_mclk0_work);
+ mutex_lock(&pdata->cdc_int_mclk0_mutex);
+ pdata->digital_cdc_core_clk.enable = 0;
+ afe_set_lpass_clock_v2(AFE_PORT_ID_INT0_MI2S_RX,
+ &pdata->digital_cdc_core_clk);
+ atomic_set(&pdata->int_mclk0_enabled, false);
+ mutex_unlock(&pdata->cdc_int_mclk0_mutex);
}
msm8x16_wcd_disable_static_supplies_to_optimum(msm8x16, msm8x16_pdata);
return 0;
@@ -5688,7 +5673,7 @@ int msm8x16_wcd_suspend(struct snd_soc_codec *codec)
int msm8x16_wcd_resume(struct snd_soc_codec *codec)
{
- struct msm8916_asoc_mach_data *pdata = NULL;
+ struct msm_asoc_mach_data *pdata = NULL;
struct msm8x16_wcd *msm8x16 = codec->control_data;
struct msm8x16_wcd_pdata *msm8x16_pdata = msm8x16->dev->platform_data;
diff --git a/sound/soc/codecs/msm8x16/msm8x16-wcd.h b/sound/soc/codecs/msm8x16/msm8x16-wcd.h
index d2e782b07cb2..776090258119 100644
--- a/sound/soc/codecs/msm8x16/msm8x16-wcd.h
+++ b/sound/soc/codecs/msm8x16/msm8x16-wcd.h
@@ -221,31 +221,6 @@ struct wcd_imped_i_ref {
int offset;
};
-struct msm8916_asoc_mach_data {
- int codec_type;
- int ext_pa;
- int us_euro_gpio;
- int spk_ext_pa_gpio;
- int mclk_freq;
- int lb_mode;
- int afe_clk_ver;
- u8 micbias1_cap_mode;
- u8 micbias2_cap_mode;
- atomic_t mclk_rsc_ref;
- atomic_t mclk_enabled;
- atomic_t wsa_mclk_rsc_ref;
- struct mutex cdc_mclk_mutex;
- struct mutex wsa_mclk_mutex;
- struct delayed_work disable_mclk_work;
- struct afe_digital_clk_cfg digital_cdc_clk;
- struct afe_clk_set digital_cdc_core_clk;
- void __iomem *vaddr_gpio_mux_spkr_ctl;
- void __iomem *vaddr_gpio_mux_mic_ctl;
- void __iomem *vaddr_gpio_mux_quin_ctl;
- void __iomem *vaddr_gpio_mux_pcm_ctl;
- struct on_demand_supply wsa_switch_supply;
-};
-
struct msm8x16_wcd_pdata {
int irq;
int irq_base;
@@ -291,7 +266,7 @@ struct msm8x16_wcd_priv {
u32 rx_bias_count;
s32 dmic_1_2_clk_cnt;
u32 mute_mask;
- bool mclk_enabled;
+ bool int_mclk0_enabled;
bool clock_active;
bool config_mode_active;
u16 boost_option;
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 281db1d07f57..393b8b4b8084 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -714,6 +714,16 @@ struct hpf_work {
struct delayed_work dwork;
};
+#define WCD9335_SPK_ANC_EN_DELAY_MS 350
+static int spk_anc_en_delay = WCD9335_SPK_ANC_EN_DELAY_MS;
+module_param(spk_anc_en_delay, int, S_IRUGO | S_IWUSR | S_IWGRP);
+MODULE_PARM_DESC(spk_anc_en_delay, "delay to enable anc in speaker path");
+
+struct spk_anc_work {
+ struct tasha_priv *tasha;
+ struct delayed_work dwork;
+};
+
struct tx_mute_work {
struct tasha_priv *tasha;
u8 decimator;
@@ -836,6 +846,7 @@ struct tasha_priv {
int ear_spkr_gain;
struct hpf_work tx_hpf_work[TASHA_NUM_DECIMATORS];
struct tx_mute_work tx_mute_dwork[TASHA_NUM_DECIMATORS];
+ struct spk_anc_work spk_anc_dwork;
struct mutex codec_mutex;
int hph_l_gain;
int hph_r_gain;
@@ -4278,6 +4289,21 @@ static int tasha_codec_enable_lineout_pa(struct snd_soc_dapm_widget *w,
return ret;
}
+static void tasha_spk_anc_update_callback(struct work_struct *work)
+{
+ struct spk_anc_work *spk_anc_dwork;
+ struct tasha_priv *tasha;
+ struct delayed_work *delayed_work;
+ struct snd_soc_codec *codec;
+
+ delayed_work = to_delayed_work(work);
+ spk_anc_dwork = container_of(delayed_work, struct spk_anc_work, dwork);
+ tasha = spk_anc_dwork->tasha;
+ codec = tasha->codec;
+
+ snd_soc_update_bits(codec, WCD9335_CDC_RX7_RX_PATH_CFG0, 0x10, 0x10);
+}
+
static int tasha_codec_enable_spk_anc(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
@@ -4295,10 +4321,11 @@ static int tasha_codec_enable_spk_anc(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
ret = tasha_codec_enable_anc(w, kcontrol, event);
- snd_soc_update_bits(codec, WCD9335_CDC_RX7_RX_PATH_CFG0,
- 0x10, 0x10);
+ schedule_delayed_work(&tasha->spk_anc_dwork.dwork,
+ msecs_to_jiffies(spk_anc_en_delay));
break;
case SND_SOC_DAPM_POST_PMD:
+ cancel_delayed_work_sync(&tasha->spk_anc_dwork.dwork);
snd_soc_update_bits(codec, WCD9335_CDC_RX7_RX_PATH_CFG0,
0x10, 0x00);
ret = tasha_codec_enable_anc(w, kcontrol, event);
@@ -13687,6 +13714,10 @@ static int tasha_codec_probe(struct snd_soc_codec *codec)
tasha_tx_mute_update_callback);
}
+ tasha->spk_anc_dwork.tasha = tasha;
+ INIT_DELAYED_WORK(&tasha->spk_anc_dwork.dwork,
+ tasha_spk_anc_update_callback);
+
mutex_lock(&tasha->codec_mutex);
snd_soc_dapm_disable_pin(dapm, "ANC LINEOUT1");
snd_soc_dapm_disable_pin(dapm, "ANC LINEOUT2");
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index 6745aec41388..56882be12554 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -546,6 +546,16 @@ struct tx_mute_work {
struct delayed_work dwork;
};
+#define WCD934X_SPK_ANC_EN_DELAY_MS 350
+static int spk_anc_en_delay = WCD934X_SPK_ANC_EN_DELAY_MS;
+module_param(spk_anc_en_delay, int, S_IRUGO | S_IWUSR | S_IWGRP);
+MODULE_PARM_DESC(spk_anc_en_delay, "delay to enable anc in speaker path");
+
+struct spk_anc_work {
+ struct tavil_priv *tavil;
+ struct delayed_work dwork;
+};
+
struct hpf_work {
struct tavil_priv *tavil;
u8 decimator;
@@ -610,6 +620,7 @@ struct tavil_priv {
struct work_struct tavil_add_child_devices_work;
struct hpf_work tx_hpf_work[WCD934X_NUM_DECIMATORS];
struct tx_mute_work tx_mute_dwork[WCD934X_NUM_DECIMATORS];
+ struct spk_anc_work spk_anc_dwork;
unsigned int vi_feed_value;
@@ -1775,6 +1786,21 @@ static int tavil_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
return 0;
}
+static void tavil_spk_anc_update_callback(struct work_struct *work)
+{
+ struct spk_anc_work *spk_anc_dwork;
+ struct tavil_priv *tavil;
+ struct delayed_work *delayed_work;
+ struct snd_soc_codec *codec;
+
+ delayed_work = to_delayed_work(work);
+ spk_anc_dwork = container_of(delayed_work, struct spk_anc_work, dwork);
+ tavil = spk_anc_dwork->tavil;
+ codec = tavil->codec;
+
+ snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_CFG0, 0x10, 0x10);
+}
+
static int tavil_codec_enable_spkr_anc(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol,
int event)
@@ -1792,10 +1818,11 @@ static int tavil_codec_enable_spkr_anc(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
ret = tavil_codec_enable_anc(w, kcontrol, event);
- snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_CFG0,
- 0x10, 0x10);
+ schedule_delayed_work(&tavil->spk_anc_dwork.dwork,
+ msecs_to_jiffies(spk_anc_en_delay));
break;
case SND_SOC_DAPM_POST_PMD:
+ cancel_delayed_work_sync(&tavil->spk_anc_dwork.dwork);
snd_soc_update_bits(codec, WCD934X_CDC_RX7_RX_PATH_CFG0,
0x10, 0x00);
ret = tavil_codec_enable_anc(w, kcontrol, event);
@@ -4182,7 +4209,7 @@ int tavil_micbias_control(struct snd_soc_codec *codec,
post_dapm_on, &tavil->mbhc->wcd_mbhc);
break;
case MICB_DISABLE:
- if (tavil->pullup_ref[micb_index] > 0)
+ if (tavil->micb_ref[micb_index] > 0)
tavil->micb_ref[micb_index]--;
if ((tavil->micb_ref[micb_index] == 0) &&
(tavil->pullup_ref[micb_index] > 0))
@@ -4362,6 +4389,9 @@ static const struct reg_sequence tavil_hph_reset_tbl[] = {
{ WCD934X_HPH_RDAC_LDO_CTL, 0x33 },
{ WCD934X_HPH_RDAC_CHOP_CLK_LP_CTL, 0x00 },
{ WCD934X_HPH_REFBUFF_UHQA_CTL, 0xA8 },
+};
+
+static const struct reg_sequence tavil_hph_reset_tbl_1_0[] = {
{ WCD934X_HPH_REFBUFF_LP_CTL, 0x0A },
{ WCD934X_HPH_L_DAC_CTL, 0x00 },
{ WCD934X_HPH_R_DAC_CTL, 0x00 },
@@ -4383,6 +4413,28 @@ static const struct reg_sequence tavil_hph_reset_tbl[] = {
{ WCD934X_HPH_NEW_INT_PA_RDAC_MISC3, 0x00 },
};
+static const struct reg_sequence tavil_hph_reset_tbl_1_1[] = {
+ { WCD934X_HPH_REFBUFF_LP_CTL, 0x0E },
+ { WCD934X_HPH_L_DAC_CTL, 0x00 },
+ { WCD934X_HPH_R_DAC_CTL, 0x00 },
+ { WCD934X_HPH_NEW_ANA_HPH2, 0x00 },
+ { WCD934X_HPH_NEW_ANA_HPH3, 0x00 },
+ { WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0x40 },
+ { WCD934X_HPH_NEW_INT_RDAC_HD2_CTL, 0x81 },
+ { WCD934X_HPH_NEW_INT_RDAC_VREF_CTL, 0x10 },
+ { WCD934X_HPH_NEW_INT_RDAC_OVERRIDE_CTL, 0x00 },
+ { WCD934X_HPH_NEW_INT_RDAC_MISC1, 0x81 },
+ { WCD934X_HPH_NEW_INT_PA_MISC1, 0x22 },
+ { WCD934X_HPH_NEW_INT_PA_MISC2, 0x00 },
+ { WCD934X_HPH_NEW_INT_PA_RDAC_MISC, 0x00 },
+ { WCD934X_HPH_NEW_INT_HPH_TIMER1, 0xFE },
+ { WCD934X_HPH_NEW_INT_HPH_TIMER2, 0x2 },
+ { WCD934X_HPH_NEW_INT_HPH_TIMER3, 0x4e},
+ { WCD934X_HPH_NEW_INT_HPH_TIMER4, 0x54 },
+ { WCD934X_HPH_NEW_INT_PA_RDAC_MISC2, 0x00 },
+ { WCD934X_HPH_NEW_INT_PA_RDAC_MISC3, 0x00 },
+};
+
static const struct tavil_reg_mask_val tavil_pa_disable[] = {
{ WCD934X_CDC_RX1_RX_PATH_CTL, 0x30, 0x10 }, /* RX1 mute enable */
{ WCD934X_CDC_RX2_RX_PATH_CTL, 0x30, 0x10 }, /* RX2 mute enable */
@@ -4408,6 +4460,7 @@ static const struct tavil_reg_mask_val tavil_ocp_en_seq_1[] = {
/* LO-HIFI */
static const struct tavil_reg_mask_val tavil_pre_pa_en_lohifi[] = {
{ WCD934X_HPH_NEW_INT_HPH_TIMER1, 0x02, 0x00 },
+ { WCD934X_FLYBACK_VNEG_CTRL_4, 0xf0, 0x80 },
{ WCD934X_HPH_NEW_INT_PA_MISC2, 0x20, 0x20 },
{ WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL, 0xf0, 0x40 },
{ WCD934X_HPH_CNP_WG_CTL, 0x80, 0x00 },
@@ -4449,6 +4502,7 @@ static void tavil_codec_hph_reg_recover(struct tavil_priv *tavil,
struct regmap *map, int pa_status)
{
int i;
+ unsigned int reg;
blocking_notifier_call_chain(&tavil->mbhc->notifier,
WCD_EVENT_OCP_OFF,
@@ -4470,6 +4524,12 @@ static void tavil_codec_hph_reg_recover(struct tavil_priv *tavil,
/* Restore to HW defaults */
regmap_multi_reg_write(map, tavil_hph_reset_tbl,
ARRAY_SIZE(tavil_hph_reset_tbl));
+ if (TAVIL_IS_1_1(tavil->wcd9xxx))
+ regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_1,
+ ARRAY_SIZE(tavil_hph_reset_tbl_1_1));
+ if (TAVIL_IS_1_0(tavil->wcd9xxx))
+ regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_0,
+ ARRAY_SIZE(tavil_hph_reset_tbl_1_0));
for (i = 0; i < ARRAY_SIZE(tavil_ocp_en_seq); i++)
regmap_write_bits(map, tavil_ocp_en_seq[i].reg,
@@ -4483,13 +4543,23 @@ pa_en_restore:
__func__, pa_status);
/* Disable PA and other registers before restoring */
- for (i = 0; i < ARRAY_SIZE(tavil_pa_disable); i++)
+ for (i = 0; i < ARRAY_SIZE(tavil_pa_disable); i++) {
+ if (TAVIL_IS_1_1(tavil->wcd9xxx) &&
+ (tavil_pa_disable[i].reg == WCD934X_HPH_CNP_WG_CTL))
+ continue;
regmap_write_bits(map, tavil_pa_disable[i].reg,
tavil_pa_disable[i].mask,
tavil_pa_disable[i].val);
+ }
regmap_multi_reg_write(map, tavil_hph_reset_tbl,
ARRAY_SIZE(tavil_hph_reset_tbl));
+ if (TAVIL_IS_1_1(tavil->wcd9xxx))
+ regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_1,
+ ARRAY_SIZE(tavil_hph_reset_tbl_1_1));
+ if (TAVIL_IS_1_0(tavil->wcd9xxx))
+ regmap_multi_reg_write(map, tavil_hph_reset_tbl_1_0,
+ ARRAY_SIZE(tavil_hph_reset_tbl_1_0));
for (i = 0; i < ARRAY_SIZE(tavil_ocp_en_seq_1); i++)
regmap_write_bits(map, tavil_ocp_en_seq_1[i].reg,
@@ -4497,17 +4567,37 @@ pa_en_restore:
tavil_ocp_en_seq_1[i].val);
if (tavil->hph_mode == CLS_H_LOHIFI) {
- for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en_lohifi); i++)
+ for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en_lohifi); i++) {
+ reg = tavil_pre_pa_en_lohifi[i].reg;
+ if ((TAVIL_IS_1_1(tavil->wcd9xxx)) &&
+ ((reg == WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL) ||
+ (reg == WCD934X_HPH_CNP_WG_CTL) ||
+ (reg == WCD934X_HPH_REFBUFF_LP_CTL)))
+ continue;
regmap_write_bits(map,
tavil_pre_pa_en_lohifi[i].reg,
tavil_pre_pa_en_lohifi[i].mask,
tavil_pre_pa_en_lohifi[i].val);
+ }
} else {
- for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en); i++)
+ for (i = 0; i < ARRAY_SIZE(tavil_pre_pa_en); i++) {
+ reg = tavil_pre_pa_en[i].reg;
+ if ((TAVIL_IS_1_1(tavil->wcd9xxx)) &&
+ ((reg == WCD934X_HPH_NEW_INT_RDAC_GAIN_CTL) ||
+ (reg == WCD934X_HPH_CNP_WG_CTL) ||
+ (reg == WCD934X_HPH_REFBUFF_LP_CTL)))
+ continue;
regmap_write_bits(map, tavil_pre_pa_en[i].reg,
tavil_pre_pa_en[i].mask,
tavil_pre_pa_en[i].val);
+ }
}
+
+ if (TAVIL_IS_1_1(tavil->wcd9xxx)) {
+ regmap_write(map, WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_L, 0x84);
+ regmap_write(map, WCD934X_HPH_NEW_INT_RDAC_HD2_CTL_R, 0x84);
+ }
+
regmap_write_bits(map, WCD934X_ANA_HPH, 0x0C, pa_status & 0x0C);
regmap_write_bits(map, WCD934X_ANA_HPH, 0x30, 0x30);
/* wait for 100usec after HPH DAC is enabled */
@@ -4516,10 +4606,14 @@ pa_en_restore:
/* Sleep for 7msec after PA is enabled */
usleep_range(7000, 7100);
- for (i = 0; i < ARRAY_SIZE(tavil_post_pa_en); i++)
+ for (i = 0; i < ARRAY_SIZE(tavil_post_pa_en); i++) {
+ if ((TAVIL_IS_1_1(tavil->wcd9xxx)) &&
+ (tavil_post_pa_en[i].reg == WCD934X_HPH_CNP_WG_CTL))
+ continue;
regmap_write_bits(map, tavil_post_pa_en[i].reg,
tavil_post_pa_en[i].mask,
tavil_post_pa_en[i].val);
+ }
end:
tavil->mbhc->is_hph_recover = true;
@@ -5049,14 +5143,18 @@ static int tavil_mad_input_put(struct snd_kcontrol *kcontrol,
u32 adc, i, mic_bias_found = 0;
int ret = 0;
char *mad_input;
+ bool is_adc2_input = false;
tavil_mad_input = ucontrol->value.integer.value[0];
if (strnstr(tavil_conn_mad_text[tavil_mad_input], "NOTUSED",
sizeof("NOTUSED"))) {
- dev_err(codec->dev,
+ dev_dbg(codec->dev,
"%s: Unsupported tavil_mad_input = %s\n",
__func__, tavil_conn_mad_text[tavil_mad_input]);
+ /* Make sure the MAD register is updated */
+ snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
+ 0x88, 0x00);
return -EINVAL;
}
@@ -5085,14 +5183,16 @@ static int tavil_mad_input_put(struct snd_kcontrol *kcontrol,
snprintf(mad_amic_input_widget, 6, "%s%u", "AMIC", adc);
mad_input_widget = mad_amic_input_widget;
+ if (adc == 2)
+ is_adc2_input = true;
} else {
/* DMIC type input widget*/
mad_input_widget = tavil_conn_mad_text[tavil_mad_input];
}
dev_dbg(codec->dev,
- "%s: tavil input widget = %s\n", __func__,
- mad_input_widget);
+ "%s: tavil input widget = %s, adc_input = %s\n", __func__,
+ mad_input_widget, is_adc2_input ? "true" : "false");
for (i = 0; i < card->num_of_dapm_routes; i++) {
if (!strcmp(card->of_dapm_routes[i].sink, mad_input_widget)) {
@@ -5137,7 +5237,13 @@ static int tavil_mad_input_put(struct snd_kcontrol *kcontrol,
0x0F, tavil_mad_input);
snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
0x07, mic_bias_found);
-
+ /* for adc2 input, mad should be in micbias mode with BG enabled */
+ if (is_adc2_input)
+ snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
+ 0x88, 0x88);
+ else
+ snd_soc_update_bits(codec, WCD934X_ANA_MAD_SETUP,
+ 0x88, 0x00);
return 0;
}
@@ -8492,21 +8598,6 @@ done:
return rc;
}
-static void tavil_enable_sido_buck(struct snd_soc_codec *codec)
-{
- struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
-
- snd_soc_update_bits(codec, WCD934X_ANA_RCO, 0x80, 0x80);
- usleep_range(100, 110);
- snd_soc_update_bits(codec, WCD934X_ANA_BUCK_CTL, 0x02, 0x02);
- usleep_range(100, 110);
- snd_soc_update_bits(codec, WCD934X_ANA_BUCK_CTL, 0x01, 0x01);
- usleep_range(100, 110);
- snd_soc_update_bits(codec, WCD934X_ANA_BUCK_CTL, 0x04, 0x04);
- usleep_range(100, 110);
- tavil->resmgr->sido_input_src = SIDO_SOURCE_RCO_BG;
-}
-
static void tavil_cdc_vote_svs(struct snd_soc_codec *codec, bool vote)
{
struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
@@ -8609,7 +8700,8 @@ static int tavil_device_down(struct wcd9xxx *wcd9xxx)
for (count = 0; count < NUM_CODEC_DAIS; count++)
priv->dai[count].bus_down_in_recovery = true;
wcd_dsp_ssr_event(priv->wdsp_cntl, WCD_CDC_DOWN_EVENT);
- priv->resmgr->sido_input_src = SIDO_SOURCE_INTERNAL;
+ wcd_resmgr_set_sido_input_src_locked(priv->resmgr,
+ SIDO_SOURCE_INTERNAL);
return 0;
}
@@ -8781,7 +8873,6 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec)
tavil->comp_enabled[i] = 0;
tavil_codec_init_reg(tavil);
- tavil_enable_sido_buck(codec);
pdata = dev_get_platdata(codec->dev->parent);
ret = tavil_handle_pdata(tavil, pdata);
@@ -8837,6 +8928,10 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec)
tavil_tx_mute_update_callback);
}
+ tavil->spk_anc_dwork.tavil = tavil;
+ INIT_DELAYED_WORK(&tavil->spk_anc_dwork.dwork,
+ tavil_spk_anc_update_callback);
+
tavil_mclk2_reg_defaults(tavil);
/* DSD initialization */
@@ -9352,7 +9447,6 @@ err_mem:
static int __tavil_enable_efuse_sensing(struct tavil_priv *tavil)
{
int val, rc;
- struct snd_soc_codec *codec;
__tavil_cdc_mclk_enable(tavil, true);
@@ -9372,14 +9466,6 @@ static int __tavil_enable_efuse_sensing(struct tavil_priv *tavil)
WARN(1, "%s: Efuse sense is not complete val=%x, ret=%d\n",
__func__, val, rc);
- codec = tavil->codec;
- if (!codec) {
- pr_debug("%s: codec is not yet registered\n", __func__);
- goto done;
- }
- tavil_enable_sido_buck(codec);
-
-done:
__tavil_cdc_mclk_enable(tavil, false);
return rc;
diff --git a/sound/soc/codecs/wcd9xxx-resmgr-v2.c b/sound/soc/codecs/wcd9xxx-resmgr-v2.c
index 39ca965e791e..84754b8d09b0 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr-v2.c
+++ b/sound/soc/codecs/wcd9xxx-resmgr-v2.c
@@ -25,6 +25,8 @@
#define WCD93XX_CDC_CLK_RST_CTRL_MCLK_CONTROL 0x0d41
#define WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL 0x0d42
+static void wcd_resmgr_set_sido_input_src(struct wcd9xxx_resmgr_v2 *resmgr,
+ int sido_src);
static const char *wcd_resmgr_clk_type_to_str(enum wcd_clock_type clk_type)
{
if (clk_type == WCD_CLK_OFF)
@@ -262,6 +264,8 @@ static int wcd_resmgr_enable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr)
0x01, 0x01);
wcd_resmgr_codec_reg_update_bits(resmgr,
WCD934X_CODEC_RPM_CLK_GATE, 0x03, 0x00);
+ wcd_resmgr_set_sido_input_src(resmgr,
+ SIDO_SOURCE_RCO_BG);
} else {
wcd_resmgr_codec_reg_update_bits(resmgr,
WCD93XX_CDC_CLK_RST_CTRL_FS_CNT_CONTROL,
@@ -315,6 +319,10 @@ static int wcd_resmgr_disable_clk_mclk(struct wcd9xxx_resmgr_v2 *resmgr)
0x80, 0x00);
}
+ if ((resmgr->codec_type == WCD934X) &&
+ (resmgr->clk_type == WCD_CLK_OFF))
+ wcd_resmgr_set_sido_input_src(resmgr, SIDO_SOURCE_INTERNAL);
+
pr_debug("%s: mclk_users: %d, clk_type: %s\n", __func__,
resmgr->clk_mclk_users,
wcd_resmgr_clk_type_to_str(resmgr->clk_type));
@@ -444,6 +452,9 @@ static int wcd_resmgr_disable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr)
wcd_resmgr_codec_reg_update_bits(resmgr,
WCD9335_ANA_RCO,
0x80, 0x00);
+ wcd_resmgr_codec_reg_update_bits(resmgr,
+ WCD934X_CLK_SYS_MCLK_PRG,
+ 0x01, 0x00);
resmgr->clk_type = WCD_CLK_OFF;
} else if ((resmgr->clk_rco_users == 0) &&
(resmgr->clk_mclk_users)) {
@@ -455,6 +466,11 @@ static int wcd_resmgr_disable_clk_rco(struct wcd9xxx_resmgr_v2 *resmgr)
WCD9335_ANA_RCO,
0x80, 0x00);
}
+
+ if ((resmgr->codec_type == WCD934X) &&
+ (resmgr->clk_type == WCD_CLK_OFF))
+ wcd_resmgr_set_sido_input_src(resmgr, SIDO_SOURCE_INTERNAL);
+
pr_debug("%s: rco clk users: %d, clk_type: %s\n", __func__,
resmgr->clk_rco_users,
wcd_resmgr_clk_type_to_str(resmgr->clk_type));
@@ -493,6 +509,64 @@ int wcd_resmgr_enable_clk_block(struct wcd9xxx_resmgr_v2 *resmgr,
return ret;
}
+static void wcd_resmgr_set_sido_input_src(struct wcd9xxx_resmgr_v2 *resmgr,
+ int sido_src)
+{
+ if (!resmgr)
+ return;
+
+ if (sido_src == resmgr->sido_input_src)
+ return;
+
+ if (sido_src == SIDO_SOURCE_INTERNAL) {
+ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL,
+ 0x04, 0x00);
+ usleep_range(100, 110);
+ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL,
+ 0x03, 0x00);
+ usleep_range(100, 110);
+ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_RCO,
+ 0x80, 0x00);
+ usleep_range(100, 110);
+ resmgr->sido_input_src = SIDO_SOURCE_INTERNAL;
+ pr_debug("%s: sido input src to internal\n", __func__);
+ } else if (sido_src == SIDO_SOURCE_RCO_BG) {
+ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_RCO,
+ 0x80, 0x80);
+ usleep_range(100, 110);
+ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL,
+ 0x02, 0x02);
+ usleep_range(100, 110);
+ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL,
+ 0x01, 0x01);
+ usleep_range(100, 110);
+ wcd_resmgr_codec_reg_update_bits(resmgr, WCD934X_ANA_BUCK_CTL,
+ 0x04, 0x04);
+ usleep_range(100, 110);
+ resmgr->sido_input_src = SIDO_SOURCE_RCO_BG;
+ pr_debug("%s: sido input src to external\n", __func__);
+ }
+}
+
+/*
+ * wcd_resmgr_set_sido_input_src_locked:
+ * Set SIDO input in BG_CLK locked context
+ *
+ * @resmgr: handle to struct wcd9xxx_resmgr_v2
+ * @sido_src: Select the SIDO input source
+ */
+void wcd_resmgr_set_sido_input_src_locked(struct wcd9xxx_resmgr_v2 *resmgr,
+ int sido_src)
+{
+ if (!resmgr)
+ return;
+
+ WCD9XXX_V2_BG_CLK_LOCK(resmgr);
+ wcd_resmgr_set_sido_input_src(resmgr, sido_src);
+ WCD9XXX_V2_BG_CLK_UNLOCK(resmgr);
+}
+EXPORT_SYMBOL(wcd_resmgr_set_sido_input_src_locked);
+
/*
* wcd_resmgr_disable_clk_block: disable MCLK or RCO
* @resmgr: handle to struct wcd9xxx_resmgr_v2
diff --git a/sound/soc/codecs/wcd9xxx-resmgr-v2.h b/sound/soc/codecs/wcd9xxx-resmgr-v2.h
index c1955d31889f..f605a249a620 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr-v2.h
+++ b/sound/soc/codecs/wcd9xxx-resmgr-v2.h
@@ -85,4 +85,6 @@ int wcd_resmgr_disable_clk_block(struct wcd9xxx_resmgr_v2 *resmgr,
enum wcd_clock_type type);
int wcd_resmgr_get_clk_type(struct wcd9xxx_resmgr_v2 *resmgr);
void wcd_resmgr_post_ssr_v2(struct wcd9xxx_resmgr_v2 *resmgr);
+void wcd_resmgr_set_sido_input_src_locked(struct wcd9xxx_resmgr_v2 *resmgr,
+ int sido_src);
#endif
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 64a1fa76604d..9cf69eca0028 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -98,6 +98,70 @@ config SND_SOC_CPE
The configuration includes the cpe lsm driver to enable
listen on codec.
+config SND_SOC_INT_CODEC
+ tristate "SoC Machine driver for MSMFALCON_INT"
+ depends on ARCH_QCOM
+ select SND_SOC_QDSP6V2
+ select SND_SOC_MSM_STUB
+ select SND_SOC_MSM_HOSTLESS_PCM
+ select SND_DYNAMIC_MINORS
+ select MSM_QDSP6_APRV2_GLINK
+ select MSM_QDSP6_SSR
+ select MSM_QDSP6_PDR
+ select MSM_QDSP6_NOTIFIER
+ select MSM_QDSP6V2_CODECS
+ select SND_SOC_MSM_SWR
+ select SND_SOC_MSM8X16_WCD
+ select QTI_PP
+ select DTS_SRS_TM
+ select DOLBY_DAP
+ select DOLBY_DS2
+ select SND_HWDEP
+ select MSM_ULTRASOUND
+ select DTS_EAGLE
+ select SND_SOC_MSMFALCON_COMMON
+ select SND_SOC_COMPRESS
+ help
+ To add support for SoC audio on MSM_INT.
+ This will enable sound soc drivers which
+ interfaces with DSP, also it will enable
+ the machine driver and the corresponding
+ DAI-links
+
+config SND_SOC_EXT_CODEC
+ tristate "SoC Machine driver for MSMFALCON_EXT"
+ depends on ARCH_QCOM
+ select SND_SOC_QDSP6V2
+ select SND_SOC_MSM_STUB
+ select SND_SOC_MSM_HOSTLESS_PCM
+ select SND_DYNAMIC_MINORS
+ select MSM_QDSP6_APRV2_GLINK
+ select MSM_QDSP6_SSR
+ select MSM_QDSP6_PDR
+ select MSM_QDSP6_NOTIFIER
+ select MSM_QDSP6V2_CODECS
+ select SND_SOC_WCD9335
+ select SND_SOC_WCD934X
+ select SND_SOC_WSA881X
+ select MFD_CORE
+ select QTI_PP
+ select DTS_SRS_TM
+ select DOLBY_DAP
+ select DOLBY_DS2
+ select SND_SOC_CPE
+ select SND_SOC_WCD_CPE
+ select SND_HWDEP
+ select MSM_ULTRASOUND
+ select DTS_EAGLE
+ select SND_SOC_MSMFALCON_COMMON
+ select SND_SOC_COMPRESS
+ help
+ To add support for SoC audio on MSM_EXT.
+ This will enable sound soc drivers which
+ interfaces with DSP, also it will enable
+ the machine driver and the corresponding
+ DAI-links
+
config SND_SOC_MSM8996
tristate "SoC Machine driver for MSM8996 boards"
depends on ARCH_MSM8996
@@ -157,4 +221,16 @@ config SND_SOC_MSMCOBALT
the machine driver and the corresponding
DAI-links
+config SND_SOC_FALCON
+ tristate "SoC Machine driver for MSMFALCON boards"
+ depends on ARCH_MSMFALCON
+ select SND_SOC_INT_CODEC
+ select SND_SOC_EXT_CODEC
+ help
+ To add support for SoC audio on MSMFALCON.
+ This will enable sound soc drivers which
+ interfaces with DSP, also it will enable
+ the machine driver and the corresponding
+ DAI-links
+
endmenu
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index 3ad34be41578..799c9ee63d43 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -19,3 +19,18 @@ obj-$(CONFIG_SND_SOC_MSM8996) += snd-soc-msm8996.o
# for MSMCOBALT sound card driver
snd-soc-msmcobalt-objs := msmcobalt.o
obj-$(CONFIG_SND_SOC_MSMCOBALT) += snd-soc-msmcobalt.o
+
+# for MSMFALCON sound card driver
+snd-soc-msmfalcon-common-objs := msm-audio-pinctrl.o msmfalcon-common.o
+obj-$(CONFIG_SND_SOC_MSMFALCON_COMMON) += snd-soc-msmfalcon-common.o
+
+# for MSMFALCON sound card driver
+snd-soc-int-codec-objs := msmfalcon-internal.o
+obj-$(CONFIG_SND_SOC_INT_CODEC) += snd-soc-msmfalcon-common.o
+obj-$(CONFIG_SND_SOC_INT_CODEC) += snd-soc-int-codec.o
+
+# for MSMFALCON sound card driver
+snd-soc-ext-codec-objs := msmfalcon-external.o msmfalcon-ext-dai-links.o
+obj-$(CONFIG_SND_SOC_EXT_CODEC) += snd-soc-msmfalcon-common.o
+obj-$(CONFIG_SND_SOC_EXT_CODEC) += snd-soc-ext-codec.o
+
diff --git a/sound/soc/msm/msm-audio-pinctrl.h b/sound/soc/msm/msm-audio-pinctrl.h
index 0b5395520b1b..73eeaff39bfd 100644
--- a/sound/soc/msm/msm-audio-pinctrl.h
+++ b/sound/soc/msm/msm-audio-pinctrl.h
@@ -1,4 +1,4 @@
- /* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ /* Copyright (c) 2015-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
@@ -14,8 +14,7 @@
#define __MSM_AUDIO_PINCTRL_H
enum pinctrl_client {
- CLIENT_WCD_INT,
- CLIENT_WCD_EXT,
+ CLIENT_WCD,
CLIENT_WSA_BONGO_1,
CLIENT_WSA_BONGO_2,
MAX_PINCTRL_CLIENT,
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index ee9dcacdd5c9..aa036d352f40 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -870,6 +870,38 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
.name = "QUAT_MI2S_RX_HOSTLESS",
.probe = fe_dai_probe,
},
+ {
+ .playback = {
+ .stream_name = "INT0 MI2S_RX Hostless Playback",
+ .aif_name = "INT0_MI2S_DL_HL",
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE),
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 192000,
+ },
+ .ops = &msm_fe_dai_ops,
+ .name = "INT0_MI2S_RX_HOSTLESS",
+ .probe = fe_dai_probe,
+ },
+ {
+ .playback = {
+ .stream_name = "INT4 MI2S_RX Hostless Playback",
+ .aif_name = "INT4_MI2S_DL_HL",
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE),
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 192000,
+ },
+ .ops = &msm_fe_dai_ops,
+ .name = "INT4_MI2S_RX_HOSTLESS",
+ .probe = fe_dai_probe,
+ },
/* TDM Hostless */
{
.capture = {
diff --git a/sound/soc/msm/msmcobalt.c b/sound/soc/msm/msmcobalt.c
index abe944b45395..9c392f3d4ddc 100644
--- a/sound/soc/msm/msmcobalt.c
+++ b/sound/soc/msm/msmcobalt.c
@@ -3253,23 +3253,28 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_ignore_suspend(dapm, "Analog Mic6");
snd_soc_dapm_ignore_suspend(dapm, "MADINPUT");
snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_INPUT");
+ snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_OUT1");
+ snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_OUT2");
snd_soc_dapm_ignore_suspend(dapm, "EAR");
snd_soc_dapm_ignore_suspend(dapm, "LINEOUT1");
snd_soc_dapm_ignore_suspend(dapm, "LINEOUT2");
- snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3");
- snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4");
snd_soc_dapm_ignore_suspend(dapm, "ANC EAR");
snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT");
snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT");
snd_soc_dapm_ignore_suspend(dapm, "HPHL");
snd_soc_dapm_ignore_suspend(dapm, "HPHR");
- snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL");
- snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR");
- snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1");
- snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2");
snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI");
snd_soc_dapm_ignore_suspend(dapm, "VIINPUT");
+ if (!strcmp(dev_name(codec_dai->dev), "tasha_codec")) {
+ snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3");
+ snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2");
+ }
+
snd_soc_dapm_sync(dapm);
snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
diff --git a/sound/soc/msm/msmfalcon-common.c b/sound/soc/msm/msmfalcon-common.c
new file mode 100644
index 000000000000..6c96a0778b52
--- /dev/null
+++ b/sound/soc/msm/msmfalcon-common.c
@@ -0,0 +1,1768 @@
+/* Copyright (c) 2015-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.
+ */
+
+#include <linux/input.h>
+#include <linux/of_gpio.h>
+#include <linux/mfd/msm-cdc-pinctrl.h>
+#include <sound/pcm_params.h>
+#include <sound/q6afe-v2.h>
+#include "qdsp6v2/msm-pcm-routing-v2.h"
+#include "msm-audio-pinctrl.h"
+#include "msmfalcon-common.h"
+#include "msmfalcon-internal.h"
+#include "msmfalcon-external.h"
+#include "../codecs/msm8x16/msm8x16-wcd.h"
+#include "../codecs/wsa881x.h"
+
+#define DRV_NAME "msmfalcon-asoc-snd"
+
+#define DEV_NAME_STR_LEN 32
+#define DEFAULT_MCLK_RATE 9600000
+
+enum {
+ PRIM_MI2S = 0,
+ SEC_MI2S,
+ TERT_MI2S,
+ QUAT_MI2S,
+ MI2S_MAX,
+};
+
+enum {
+ PRIM_AUX_PCM = 0,
+ SEC_AUX_PCM,
+ TERT_AUX_PCM,
+ QUAT_AUX_PCM,
+ AUX_PCM_MAX,
+};
+
+enum {
+ PCM_I2S_SEL_PRIM = 0,
+ PCM_I2S_SEL_SEC,
+ PCM_I2S_SEL_TERT,
+ PCM_I2S_SEL_QUAT,
+ PCM_I2S_SEL_MAX,
+};
+
+struct mi2s_aux_pcm_common_conf {
+ struct mutex lock;
+ void *pcm_i2s_sel_vt_addr;
+};
+
+struct mi2s_conf {
+ struct mutex lock;
+ u32 ref_cnt;
+ u32 msm_is_mi2s_master;
+};
+
+struct auxpcm_conf {
+ struct mutex lock;
+ u32 ref_cnt;
+};
+
+struct dev_config {
+ u32 sample_rate;
+ u32 bit_format;
+ u32 channels;
+};
+
+struct msm_wsa881x_dev_info {
+ struct device_node *of_node;
+ u32 index;
+};
+static struct snd_soc_aux_dev *msm_aux_dev;
+static struct snd_soc_codec_conf *msm_codec_conf;
+
+static bool msm_swap_gnd_mic(struct snd_soc_codec *codec);
+
+static struct wcd_mbhc_config mbhc_cfg = {
+ .read_fw_bin = false,
+ .calibration = NULL,
+ .detect_extn_cable = true,
+ .mono_stero_detection = false,
+ .swap_gnd_mic = NULL,
+ .hs_ext_micbias = false,
+ .key_code[0] = KEY_MEDIA,
+ .key_code[1] = KEY_VOICECOMMAND,
+ .key_code[2] = KEY_VOLUMEUP,
+ .key_code[3] = KEY_VOLUMEDOWN,
+ .key_code[4] = 0,
+ .key_code[5] = 0,
+ .key_code[6] = 0,
+ .key_code[7] = 0,
+ .linein_th = 5000,
+ .moisture_en = false,
+ .mbhc_micbias = 0,
+ .anc_micbias = 0,
+ .enable_anc_mic_detect = false,
+};
+
+static struct dev_config proxy_rx_cfg = {
+ .sample_rate = SAMPLING_RATE_48KHZ,
+ .bit_format = SNDRV_PCM_FORMAT_S16_LE,
+ .channels = 2,
+};
+
+static struct dev_config btsco_cfg = {
+ .sample_rate = SAMPLING_RATE_8KHZ,
+ .bit_format = SNDRV_PCM_FORMAT_S16_LE,
+ .channels = 1,
+};
+
+/* Default configuration of MI2S channels */
+static struct dev_config mi2s_rx_cfg[] = {
+ [PRIM_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+ [SEC_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+ [TERT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+ [QUAT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+};
+
+static struct dev_config mi2s_tx_cfg[] = {
+ [PRIM_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SEC_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [TERT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [QUAT_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+static struct dev_config aux_pcm_rx_cfg[] = {
+ [PRIM_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SEC_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [TERT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [QUAT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+static struct dev_config aux_pcm_tx_cfg[] = {
+ [PRIM_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SEC_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [TERT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [QUAT_AUX_PCM] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+static char const *ch_text[] = {"Two", "Three", "Four", "Five",
+ "Six", "Seven", "Eight"};
+static const char *const auxpcm_rate_text[] = {"KHZ_8", "KHZ_16"};
+static char const *mi2s_rate_text[] = {"KHZ_8", "KHZ_16",
+ "KHZ_32", "KHZ_44P1", "KHZ_48",
+ "KHZ_96", "KHZ_192"};
+static const char *const mi2s_ch_text[] = {"One", "Two", "Three", "Four",
+ "Five", "Six", "Seven",
+ "Eight"};
+
+static SOC_ENUM_SINGLE_EXT_DECL(btsco_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(proxy_rx_chs, ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_aux_pcm_rx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_aux_pcm_rx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_aux_pcm_rx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_aux_pcm_rx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_aux_pcm_tx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_aux_pcm_tx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_aux_pcm_tx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_aux_pcm_tx_sample_rate, auxpcm_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_rx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_rx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_rx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_rx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_tx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_tx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_tx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_tx_sample_rate, mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_rx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(prim_mi2s_tx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_rx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(sec_mi2s_tx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_rx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(tert_mi2s_tx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_rx_chs, mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(quat_mi2s_tx_chs, mi2s_ch_text);
+
+static struct afe_clk_set mi2s_clk[MI2S_MAX] = {
+ {
+ AFE_API_VERSION_I2S_CONFIG,
+ Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT,
+ Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+ },
+ {
+ AFE_API_VERSION_I2S_CONFIG,
+ Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT,
+ Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+ },
+ {
+ AFE_API_VERSION_I2S_CONFIG,
+ Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT,
+ Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+ },
+ {
+ AFE_API_VERSION_I2S_CONFIG,
+ Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT,
+ Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+ }
+};
+
+static struct mi2s_aux_pcm_common_conf mi2s_auxpcm_conf[PCM_I2S_SEL_MAX];
+static struct mi2s_conf mi2s_intf_conf[MI2S_MAX];
+static struct auxpcm_conf auxpcm_intf_conf[AUX_PCM_MAX];
+
+static int proxy_rx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: proxy_rx channels = %d\n",
+ __func__, proxy_rx_cfg.channels);
+ ucontrol->value.integer.value[0] = proxy_rx_cfg.channels - 2;
+
+ return 0;
+}
+
+static int proxy_rx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ proxy_rx_cfg.channels = ucontrol->value.integer.value[0] + 2;
+ pr_debug("%s: proxy_rx channels = %d\n",
+ __func__, proxy_rx_cfg.channels);
+
+ return 1;
+}
+
+static int aux_pcm_get_sample_rate(int value)
+{
+ int sample_rate;
+
+ switch (value) {
+ case 1:
+ sample_rate = SAMPLING_RATE_16KHZ;
+ break;
+ case 0:
+ default:
+ sample_rate = SAMPLING_RATE_8KHZ;
+ break;
+ }
+ return sample_rate;
+}
+
+static int aux_pcm_get_sample_rate_val(int sample_rate)
+{
+ int sample_rate_val;
+
+ switch (sample_rate) {
+ case SAMPLING_RATE_16KHZ:
+ sample_rate_val = 1;
+ break;
+ case SAMPLING_RATE_8KHZ:
+ default:
+ sample_rate_val = 0;
+ break;
+ }
+ return sample_rate_val;
+}
+
+static int aux_pcm_get_port_idx(struct snd_kcontrol *kcontrol)
+{
+ int idx;
+
+ if (strnstr(kcontrol->id.name, "PRIM_AUX_PCM",
+ sizeof("PRIM_AUX_PCM")))
+ idx = PRIM_AUX_PCM;
+ else if (strnstr(kcontrol->id.name, "SEC_AUX_PCM",
+ sizeof("SEC_AUX_PCM")))
+ idx = SEC_AUX_PCM;
+ else if (strnstr(kcontrol->id.name, "TERT_AUX_PCM",
+ sizeof("TERT_AUX_PCM")))
+ idx = TERT_AUX_PCM;
+ else if (strnstr(kcontrol->id.name, "QUAT_AUX_PCM",
+ sizeof("QUAT_AUX_PCM")))
+ idx = QUAT_AUX_PCM;
+ else {
+ pr_err("%s: unsupported port: %s",
+ __func__, kcontrol->id.name);
+ idx = -EINVAL;
+ }
+
+ return idx;
+}
+
+static int btsco_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ btsco_cfg.sample_rate =
+ aux_pcm_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: btsco_sample_rate = %d, item = %d\n", __func__,
+ btsco_cfg.sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int btsco_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.enumerated.item[0] =
+ aux_pcm_get_sample_rate_val(btsco_cfg.sample_rate);
+
+ pr_debug("%s: btsco_sample_rate = %d, item = %d\n", __func__,
+ btsco_cfg.sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int aux_pcm_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = aux_pcm_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ aux_pcm_rx_cfg[idx].sample_rate =
+ aux_pcm_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+ idx, aux_pcm_rx_cfg[idx].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int aux_pcm_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = aux_pcm_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ ucontrol->value.enumerated.item[0] =
+ aux_pcm_get_sample_rate_val(aux_pcm_rx_cfg[idx].sample_rate);
+
+ pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+ idx, aux_pcm_rx_cfg[idx].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int aux_pcm_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = aux_pcm_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ aux_pcm_tx_cfg[idx].sample_rate =
+ aux_pcm_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+ idx, aux_pcm_tx_cfg[idx].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int aux_pcm_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = aux_pcm_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ ucontrol->value.enumerated.item[0] =
+ aux_pcm_get_sample_rate_val(aux_pcm_tx_cfg[idx].sample_rate);
+
+ pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+ idx, aux_pcm_tx_cfg[idx].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int mi2s_get_port_idx(struct snd_kcontrol *kcontrol)
+{
+ int idx;
+
+ if (strnstr(kcontrol->id.name, "PRIM_MI2S_RX",
+ sizeof("PRIM_MI2S_RX")))
+ idx = PRIM_MI2S;
+ else if (strnstr(kcontrol->id.name, "SEC_MI2S_RX",
+ sizeof("SEC_MI2S_RX")))
+ idx = SEC_MI2S;
+ else if (strnstr(kcontrol->id.name, "TERT_MI2S_RX",
+ sizeof("TERT_MI2S_RX")))
+ idx = TERT_MI2S;
+ else if (strnstr(kcontrol->id.name, "QUAT_MI2S_RX",
+ sizeof("QUAT_MI2S_RX")))
+ idx = QUAT_MI2S;
+ else if (strnstr(kcontrol->id.name, "PRIM_MI2S_TX",
+ sizeof("PRIM_MI2S_TX")))
+ idx = PRIM_MI2S;
+ else if (strnstr(kcontrol->id.name, "SEC_MI2S_TX",
+ sizeof("SEC_MI2S_TX")))
+ idx = SEC_MI2S;
+ else if (strnstr(kcontrol->id.name, "TERT_MI2S_TX",
+ sizeof("TERT_MI2S_TX")))
+ idx = TERT_MI2S;
+ else if (strnstr(kcontrol->id.name, "QUAT_MI2S_TX",
+ sizeof("QUAT_MI2S_TX")))
+ idx = QUAT_MI2S;
+ else {
+ pr_err("%s: unsupported channel: %s",
+ __func__, kcontrol->id.name);
+ idx = -EINVAL;
+ }
+
+ return idx;
+}
+
+static int mi2s_get_sample_rate_val(int sample_rate)
+{
+ int sample_rate_val;
+
+ switch (sample_rate) {
+ case SAMPLING_RATE_8KHZ:
+ sample_rate_val = 0;
+ break;
+ case SAMPLING_RATE_16KHZ:
+ sample_rate_val = 1;
+ break;
+ case SAMPLING_RATE_32KHZ:
+ sample_rate_val = 2;
+ break;
+ case SAMPLING_RATE_44P1KHZ:
+ sample_rate_val = 3;
+ break;
+ case SAMPLING_RATE_48KHZ:
+ sample_rate_val = 4;
+ break;
+ case SAMPLING_RATE_96KHZ:
+ sample_rate_val = 5;
+ break;
+ case SAMPLING_RATE_192KHZ:
+ sample_rate_val = 6;
+ break;
+ default:
+ sample_rate_val = 4;
+ break;
+ }
+ return sample_rate_val;
+}
+
+static int mi2s_get_sample_rate(int value)
+{
+ int sample_rate;
+
+ switch (value) {
+ case 0:
+ sample_rate = SAMPLING_RATE_8KHZ;
+ break;
+ case 1:
+ sample_rate = SAMPLING_RATE_16KHZ;
+ break;
+ case 2:
+ sample_rate = SAMPLING_RATE_32KHZ;
+ break;
+ case 3:
+ sample_rate = SAMPLING_RATE_44P1KHZ;
+ break;
+ case 4:
+ sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ case 5:
+ sample_rate = SAMPLING_RATE_96KHZ;
+ break;
+ case 6:
+ sample_rate = SAMPLING_RATE_192KHZ;
+ break;
+ default:
+ sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ }
+ return sample_rate;
+}
+
+static int mi2s_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = mi2s_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ mi2s_rx_cfg[idx].sample_rate =
+ mi2s_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+ idx, mi2s_rx_cfg[idx].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int mi2s_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = mi2s_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ ucontrol->value.enumerated.item[0] =
+ mi2s_get_sample_rate_val(mi2s_rx_cfg[idx].sample_rate);
+
+ pr_debug("%s: idx[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+ idx, mi2s_rx_cfg[idx].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int mi2s_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = mi2s_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ mi2s_tx_cfg[idx].sample_rate =
+ mi2s_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+ idx, mi2s_tx_cfg[idx].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int mi2s_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = mi2s_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ ucontrol->value.enumerated.item[0] =
+ mi2s_get_sample_rate_val(mi2s_tx_cfg[idx].sample_rate);
+
+ pr_debug("%s: idx[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+ idx, mi2s_tx_cfg[idx].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int msm_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = mi2s_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ pr_debug("%s: msm_mi2s_[%d]_rx_ch = %d\n", __func__,
+ idx, mi2s_rx_cfg[idx].channels);
+ ucontrol->value.enumerated.item[0] = mi2s_rx_cfg[idx].channels - 1;
+
+ return 0;
+}
+
+static int msm_mi2s_rx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = mi2s_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ mi2s_rx_cfg[idx].channels = ucontrol->value.enumerated.item[0] + 1;
+ pr_debug("%s: msm_mi2s_[%d]_rx_ch = %d\n", __func__,
+ idx, mi2s_rx_cfg[idx].channels);
+
+ return 1;
+}
+
+static int msm_mi2s_tx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = mi2s_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ pr_debug("%s: msm_mi2s_[%d]_tx_ch = %d\n", __func__,
+ idx, mi2s_tx_cfg[idx].channels);
+ ucontrol->value.enumerated.item[0] = mi2s_tx_cfg[idx].channels - 1;
+
+ return 0;
+}
+
+static int msm_mi2s_tx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = mi2s_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ mi2s_tx_cfg[idx].channels = ucontrol->value.enumerated.item[0] + 1;
+ pr_debug("%s: msm_mi2s_[%d]_tx_ch = %d\n", __func__,
+ idx, mi2s_tx_cfg[idx].channels);
+
+ return 1;
+}
+
+const struct snd_kcontrol_new msm_common_snd_controls[] = {
+ SOC_ENUM_EXT("PROXY_RX Channels", proxy_rx_chs,
+ proxy_rx_ch_get, proxy_rx_ch_put),
+ SOC_ENUM_EXT("BTSCO SampleRate", btsco_sample_rate,
+ btsco_sample_rate_get,
+ btsco_sample_rate_put),
+ SOC_ENUM_EXT("PRIM_AUX_PCM_RX SampleRate", prim_aux_pcm_rx_sample_rate,
+ aux_pcm_rx_sample_rate_get,
+ aux_pcm_rx_sample_rate_put),
+ SOC_ENUM_EXT("SEC_AUX_PCM_RX SampleRate", sec_aux_pcm_rx_sample_rate,
+ aux_pcm_rx_sample_rate_get,
+ aux_pcm_rx_sample_rate_put),
+ SOC_ENUM_EXT("TERT_AUX_PCM_RX SampleRate", tert_aux_pcm_rx_sample_rate,
+ aux_pcm_rx_sample_rate_get,
+ aux_pcm_rx_sample_rate_put),
+ SOC_ENUM_EXT("QUAT_AUX_PCM_RX SampleRate", quat_aux_pcm_rx_sample_rate,
+ aux_pcm_rx_sample_rate_get,
+ aux_pcm_rx_sample_rate_put),
+ SOC_ENUM_EXT("PRIM_AUX_PCM_TX SampleRate", prim_aux_pcm_tx_sample_rate,
+ aux_pcm_tx_sample_rate_get,
+ aux_pcm_tx_sample_rate_put),
+ SOC_ENUM_EXT("SEC_AUX_PCM_TX SampleRate", sec_aux_pcm_tx_sample_rate,
+ aux_pcm_tx_sample_rate_get,
+ aux_pcm_tx_sample_rate_put),
+ SOC_ENUM_EXT("TERT_AUX_PCM_TX SampleRate", tert_aux_pcm_tx_sample_rate,
+ aux_pcm_tx_sample_rate_get,
+ aux_pcm_tx_sample_rate_put),
+ SOC_ENUM_EXT("QUAT_AUX_PCM_TX SampleRate", quat_aux_pcm_tx_sample_rate,
+ aux_pcm_tx_sample_rate_get,
+ aux_pcm_tx_sample_rate_put),
+ SOC_ENUM_EXT("PRIM_MI2S_RX SampleRate", prim_mi2s_rx_sample_rate,
+ mi2s_rx_sample_rate_get,
+ mi2s_rx_sample_rate_put),
+ SOC_ENUM_EXT("SEC_MI2S_RX SampleRate", sec_mi2s_rx_sample_rate,
+ mi2s_rx_sample_rate_get,
+ mi2s_rx_sample_rate_put),
+ SOC_ENUM_EXT("TERT_MI2S_RX SampleRate", tert_mi2s_rx_sample_rate,
+ mi2s_rx_sample_rate_get,
+ mi2s_rx_sample_rate_put),
+ SOC_ENUM_EXT("QUAT_MI2S_RX SampleRate", quat_mi2s_rx_sample_rate,
+ mi2s_rx_sample_rate_get,
+ mi2s_rx_sample_rate_put),
+ SOC_ENUM_EXT("PRIM_MI2S_TX SampleRate", prim_mi2s_tx_sample_rate,
+ mi2s_tx_sample_rate_get,
+ mi2s_tx_sample_rate_put),
+ SOC_ENUM_EXT("SEC_MI2S_TX SampleRate", sec_mi2s_tx_sample_rate,
+ mi2s_tx_sample_rate_get,
+ mi2s_tx_sample_rate_put),
+ SOC_ENUM_EXT("TERT_MI2S_TX SampleRate", tert_mi2s_tx_sample_rate,
+ mi2s_tx_sample_rate_get,
+ mi2s_tx_sample_rate_put),
+ SOC_ENUM_EXT("QUAT_MI2S_TX SampleRate", quat_mi2s_tx_sample_rate,
+ mi2s_tx_sample_rate_get,
+ mi2s_tx_sample_rate_put),
+ SOC_ENUM_EXT("PRIM_MI2S_RX Channels", prim_mi2s_rx_chs,
+ msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
+ SOC_ENUM_EXT("PRIM_MI2S_TX Channels", prim_mi2s_tx_chs,
+ msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
+ SOC_ENUM_EXT("SEC_MI2S_RX Channels", sec_mi2s_rx_chs,
+ msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
+ SOC_ENUM_EXT("SEC_MI2S_TX Channels", sec_mi2s_tx_chs,
+ msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
+ SOC_ENUM_EXT("TERT_MI2S_RX Channels", tert_mi2s_rx_chs,
+ msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
+ SOC_ENUM_EXT("TERT_MI2S_TX Channels", tert_mi2s_tx_chs,
+ msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
+ SOC_ENUM_EXT("QUAT_MI2S_RX Channels", quat_mi2s_rx_chs,
+ msm_mi2s_rx_ch_get, msm_mi2s_rx_ch_put),
+ SOC_ENUM_EXT("QUAT_MI2S_TX Channels", quat_mi2s_tx_chs,
+ msm_mi2s_tx_ch_get, msm_mi2s_tx_ch_put),
+};
+
+/**
+ * msm_common_be_hw_params_fixup - updates settings of ALSA BE hw params.
+ *
+ * @rtd: runtime dailink instance
+ * @params: HW params of associated backend dailink.
+ *
+ * Returns 0.
+ */
+int msm_common_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ 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);
+ int rc = 0;
+
+ pr_debug("%s: format = %d, rate = %d\n",
+ __func__, params_format(params), params_rate(params));
+
+ switch (dai_link->be_id) {
+ case MSM_BACKEND_DAI_INT_BT_SCO_RX:
+ case MSM_BACKEND_DAI_INT_BT_SCO_TX:
+ channels->min = channels->max = btsco_cfg.channels;
+ rate->min = rate->max = 1;
+ break;
+
+ case MSM_BACKEND_DAI_AFE_PCM_RX:
+ channels->min = channels->max = proxy_rx_cfg.channels;
+ rate->min = rate->max = SAMPLING_RATE_48KHZ;
+ break;
+
+ case MSM_BACKEND_DAI_AUXPCM_RX:
+ rate->min = rate->max =
+ aux_pcm_rx_cfg[PRIM_AUX_PCM].sample_rate;
+ channels->min = channels->max =
+ aux_pcm_rx_cfg[PRIM_AUX_PCM].channels;
+ break;
+
+ case MSM_BACKEND_DAI_AUXPCM_TX:
+ rate->min = rate->max =
+ aux_pcm_tx_cfg[PRIM_AUX_PCM].sample_rate;
+ channels->min = channels->max =
+ aux_pcm_tx_cfg[PRIM_AUX_PCM].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SEC_AUXPCM_RX:
+ rate->min = rate->max =
+ aux_pcm_rx_cfg[SEC_AUX_PCM].sample_rate;
+ channels->min = channels->max =
+ aux_pcm_rx_cfg[SEC_AUX_PCM].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SEC_AUXPCM_TX:
+ rate->min = rate->max =
+ aux_pcm_tx_cfg[SEC_AUX_PCM].sample_rate;
+ channels->min = channels->max =
+ aux_pcm_tx_cfg[SEC_AUX_PCM].channels;
+ break;
+
+ case MSM_BACKEND_DAI_TERT_AUXPCM_RX:
+ rate->min = rate->max =
+ aux_pcm_rx_cfg[TERT_AUX_PCM].sample_rate;
+ channels->min = channels->max =
+ aux_pcm_rx_cfg[TERT_AUX_PCM].channels;
+ break;
+
+ case MSM_BACKEND_DAI_TERT_AUXPCM_TX:
+ rate->min = rate->max =
+ aux_pcm_tx_cfg[TERT_AUX_PCM].sample_rate;
+ channels->min = channels->max =
+ aux_pcm_tx_cfg[TERT_AUX_PCM].channels;
+ break;
+
+ case MSM_BACKEND_DAI_QUAT_AUXPCM_RX:
+ rate->min = rate->max =
+ aux_pcm_rx_cfg[QUAT_AUX_PCM].sample_rate;
+ channels->min = channels->max =
+ aux_pcm_rx_cfg[QUAT_AUX_PCM].channels;
+ break;
+
+ case MSM_BACKEND_DAI_QUAT_AUXPCM_TX:
+ rate->min = rate->max =
+ aux_pcm_tx_cfg[QUAT_AUX_PCM].sample_rate;
+ channels->min = channels->max =
+ aux_pcm_tx_cfg[QUAT_AUX_PCM].channels;
+ break;
+
+ case MSM_BACKEND_DAI_PRI_MI2S_RX:
+ rate->min = rate->max = mi2s_rx_cfg[PRIM_MI2S].sample_rate;
+ channels->min = channels->max =
+ mi2s_rx_cfg[PRIM_MI2S].channels;
+ break;
+
+ case MSM_BACKEND_DAI_PRI_MI2S_TX:
+ rate->min = rate->max = mi2s_tx_cfg[PRIM_MI2S].sample_rate;
+ channels->min = channels->max =
+ mi2s_tx_cfg[PRIM_MI2S].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SECONDARY_MI2S_RX:
+ rate->min = rate->max = mi2s_rx_cfg[SEC_MI2S].sample_rate;
+ channels->min = channels->max =
+ mi2s_rx_cfg[SEC_MI2S].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SECONDARY_MI2S_TX:
+ rate->min = rate->max = mi2s_tx_cfg[SEC_MI2S].sample_rate;
+ channels->min = channels->max =
+ mi2s_tx_cfg[SEC_MI2S].channels;
+ break;
+
+ case MSM_BACKEND_DAI_TERTIARY_MI2S_RX:
+ rate->min = rate->max = mi2s_rx_cfg[TERT_MI2S].sample_rate;
+ channels->min = channels->max =
+ mi2s_rx_cfg[TERT_MI2S].channels;
+ break;
+
+ case MSM_BACKEND_DAI_TERTIARY_MI2S_TX:
+ rate->min = rate->max = mi2s_tx_cfg[TERT_MI2S].sample_rate;
+ channels->min = channels->max =
+ mi2s_tx_cfg[TERT_MI2S].channels;
+ break;
+
+ case MSM_BACKEND_DAI_QUATERNARY_MI2S_RX:
+ rate->min = rate->max = mi2s_rx_cfg[QUAT_MI2S].sample_rate;
+ channels->min = channels->max =
+ mi2s_rx_cfg[QUAT_MI2S].channels;
+ break;
+
+ case MSM_BACKEND_DAI_QUATERNARY_MI2S_TX:
+ rate->min = rate->max = mi2s_tx_cfg[QUAT_MI2S].sample_rate;
+ channels->min = channels->max =
+ mi2s_tx_cfg[QUAT_MI2S].channels;
+ break;
+
+ default:
+ rate->min = rate->max = SAMPLING_RATE_48KHZ;
+ break;
+ }
+ return rc;
+}
+EXPORT_SYMBOL(msm_common_be_hw_params_fixup);
+
+/**
+ * msm_aux_pcm_snd_startup - startup ops of auxpcm.
+ *
+ * @substream: PCM stream pointer of associated backend dailink
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int msm_aux_pcm_snd_startup(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int index = cpu_dai->id - 1;
+ return ret = 0;
+
+ dev_dbg(rtd->card->dev,
+ "%s: substream = %s stream = %d, dai name %s, dai ID %d\n",
+ __func__, substream->name, substream->stream,
+ cpu_dai->name, cpu_dai->id);
+
+ if (index < PRIM_AUX_PCM || index > QUAT_AUX_PCM) {
+ ret = -EINVAL;
+ dev_err(rtd->card->dev,
+ "%s: CPU DAI id (%d) out of range\n",
+ __func__, cpu_dai->id);
+ goto done;
+ }
+
+ mutex_lock(&auxpcm_intf_conf[index].lock);
+ if (++auxpcm_intf_conf[index].ref_cnt == 1) {
+ if (mi2s_auxpcm_conf[index].pcm_i2s_sel_vt_addr != NULL) {
+ mutex_lock(&mi2s_auxpcm_conf[index].lock);
+ iowrite32(1,
+ mi2s_auxpcm_conf[index].pcm_i2s_sel_vt_addr);
+ mutex_unlock(&mi2s_auxpcm_conf[index].lock);
+ } else {
+ dev_err(rtd->card->dev,
+ "%s lpaif_tert_muxsel_virt_addr is NULL\n",
+ __func__);
+ ret = -EINVAL;
+ }
+ }
+ if (IS_ERR_VALUE(ret))
+ auxpcm_intf_conf[index].ref_cnt--;
+
+ mutex_unlock(&auxpcm_intf_conf[index].lock);
+
+done:
+ return ret;
+}
+EXPORT_SYMBOL(msm_aux_pcm_snd_startup);
+
+/**
+ * msm_aux_pcm_snd_shutdown - shutdown ops of auxpcm.
+ *
+ * @substream: PCM stream pointer of associated backend dailink
+ */
+void msm_aux_pcm_snd_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ int index = rtd->cpu_dai->id - 1;
+
+ dev_dbg(rtd->card->dev,
+ "%s: substream = %s stream = %d, dai name %s, dai ID %d\n",
+ __func__,
+ substream->name, substream->stream,
+ rtd->cpu_dai->name, rtd->cpu_dai->id);
+
+ if (index < PRIM_AUX_PCM || index > QUAT_AUX_PCM) {
+ dev_err(rtd->card->dev,
+ "%s: CPU DAI id (%d) out of range\n",
+ __func__, rtd->cpu_dai->id);
+ return;
+ }
+
+ mutex_lock(&auxpcm_intf_conf[index].lock);
+ if (--auxpcm_intf_conf[index].ref_cnt == 0) {
+ if (mi2s_auxpcm_conf[index].pcm_i2s_sel_vt_addr != NULL) {
+ mutex_lock(&mi2s_auxpcm_conf[index].lock);
+ iowrite32(0,
+ mi2s_auxpcm_conf[index].pcm_i2s_sel_vt_addr);
+ mutex_unlock(&mi2s_auxpcm_conf[index].lock);
+ } else {
+ dev_err(rtd->card->dev,
+ "%s lpaif_tert_muxsel_virt_addr is NULL\n",
+ __func__);
+ auxpcm_intf_conf[index].ref_cnt++;
+ }
+ }
+ mutex_unlock(&auxpcm_intf_conf[index].lock);
+}
+EXPORT_SYMBOL(msm_aux_pcm_snd_shutdown);
+
+static int msm_get_port_id(int be_id)
+{
+ int afe_port_id;
+
+ switch (be_id) {
+ case MSM_BACKEND_DAI_PRI_MI2S_RX:
+ afe_port_id = AFE_PORT_ID_PRIMARY_MI2S_RX;
+ break;
+ case MSM_BACKEND_DAI_PRI_MI2S_TX:
+ afe_port_id = AFE_PORT_ID_PRIMARY_MI2S_TX;
+ break;
+ case MSM_BACKEND_DAI_SECONDARY_MI2S_RX:
+ afe_port_id = AFE_PORT_ID_SECONDARY_MI2S_RX;
+ break;
+ case MSM_BACKEND_DAI_SECONDARY_MI2S_TX:
+ afe_port_id = AFE_PORT_ID_SECONDARY_MI2S_TX;
+ break;
+ case MSM_BACKEND_DAI_TERTIARY_MI2S_RX:
+ afe_port_id = AFE_PORT_ID_TERTIARY_MI2S_RX;
+ break;
+ case MSM_BACKEND_DAI_TERTIARY_MI2S_TX:
+ afe_port_id = AFE_PORT_ID_TERTIARY_MI2S_TX;
+ break;
+ case MSM_BACKEND_DAI_QUATERNARY_MI2S_RX:
+ afe_port_id = AFE_PORT_ID_QUATERNARY_MI2S_RX;
+ break;
+ case MSM_BACKEND_DAI_QUATERNARY_MI2S_TX:
+ afe_port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX;
+ break;
+ default:
+ pr_err("%s: Invalid be_id: %d\n", __func__, be_id);
+ afe_port_id = -EINVAL;
+ }
+
+ return afe_port_id;
+}
+
+static u32 get_mi2s_bits_per_sample(u32 bit_format)
+{
+ u32 bit_per_sample;
+
+ switch (bit_format) {
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ case SNDRV_PCM_FORMAT_S24_LE:
+ bit_per_sample = 32;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
+ bit_per_sample = 16;
+ break;
+ }
+
+ return bit_per_sample;
+}
+
+static void update_mi2s_clk_val(int dai_id, int stream)
+{
+ u32 bit_per_sample;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ bit_per_sample =
+ get_mi2s_bits_per_sample(mi2s_rx_cfg[dai_id].bit_format);
+ mi2s_clk[dai_id].clk_freq_in_hz =
+ mi2s_rx_cfg[dai_id].sample_rate * 2 * bit_per_sample;
+ } else {
+ bit_per_sample =
+ get_mi2s_bits_per_sample(mi2s_tx_cfg[dai_id].bit_format);
+ mi2s_clk[dai_id].clk_freq_in_hz =
+ mi2s_tx_cfg[dai_id].sample_rate * 2 * bit_per_sample;
+ }
+
+ if (!mi2s_intf_conf[dai_id].msm_is_mi2s_master)
+ mi2s_clk[dai_id].clk_freq_in_hz = 0;
+}
+
+static int msm_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable)
+{
+ int ret = 0;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int port_id = 0;
+ int index = cpu_dai->id;
+
+ port_id = msm_get_port_id(rtd->dai_link->be_id);
+ if (IS_ERR_VALUE(port_id)) {
+ dev_err(rtd->card->dev, "%s: Invalid port_id\n", __func__);
+ ret = port_id;
+ goto done;
+ }
+
+ if (enable) {
+ update_mi2s_clk_val(index, substream->stream);
+ dev_dbg(rtd->card->dev, "%s: clock rate %ul\n", __func__,
+ mi2s_clk[index].clk_freq_in_hz);
+ }
+
+ mi2s_clk[index].enable = enable;
+ ret = afe_set_lpass_clock_v2(port_id,
+ &mi2s_clk[index]);
+ if (ret < 0) {
+ dev_err(rtd->card->dev,
+ "%s: afe lpass clock failed for port 0x%x , err:%d\n",
+ __func__, port_id, ret);
+ goto done;
+ }
+
+done:
+ return ret;
+}
+
+/**
+ * msm_mi2s_snd_startup - startup ops of mi2s.
+ *
+ * @substream: PCM stream pointer of associated backend dailink
+ *
+ * Returns 0 on success or -EINVAL on error.
+ */
+int msm_mi2s_snd_startup(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int index = cpu_dai->id;
+ unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS;
+
+ dev_dbg(rtd->card->dev,
+ "%s: substream = %s stream = %d, dai name %s, dai ID %d\n",
+ __func__, substream->name, substream->stream,
+ cpu_dai->name, cpu_dai->id);
+
+ if (index < PRIM_MI2S || index > QUAT_MI2S) {
+ ret = -EINVAL;
+ dev_err(rtd->card->dev,
+ "%s: CPU DAI id (%d) out of range\n",
+ __func__, cpu_dai->id);
+ goto done;
+ }
+ /*
+ * Muxtex protection in case the same MI2S
+ * interface using for both TX and RX so
+ * that the same clock won't be enable twice.
+ */
+ mutex_lock(&mi2s_intf_conf[index].lock);
+ if (++mi2s_intf_conf[index].ref_cnt == 1) {
+ ret = msm_mi2s_set_sclk(substream, true);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(rtd->card->dev,
+ "%s: afe lpass clock failed to enable MI2S clock, err:%d\n",
+ __func__, ret);
+ goto clean_up;
+ }
+ if (mi2s_auxpcm_conf[index].pcm_i2s_sel_vt_addr != NULL) {
+ mutex_lock(&mi2s_auxpcm_conf[index].lock);
+ iowrite32(0,
+ mi2s_auxpcm_conf[index].pcm_i2s_sel_vt_addr);
+ mutex_unlock(&mi2s_auxpcm_conf[index].lock);
+ } else {
+ dev_err(rtd->card->dev,
+ "%s lpaif_muxsel_virt_addr is NULL for dai %d\n",
+ __func__, index);
+ ret = -EINVAL;
+ goto clk_off;
+ }
+ /* Check if msm needs to provide the clock to the interface */
+ if (!mi2s_intf_conf[index].msm_is_mi2s_master)
+ fmt = SND_SOC_DAIFMT_CBM_CFM;
+ ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
+ if (IS_ERR_VALUE(ret)) {
+ dev_err(rtd->card->dev,
+ "%s: set fmt cpu dai failed for MI2S (%d), err:%d\n",
+ __func__, index, ret);
+ goto clk_off;
+ }
+ }
+clk_off:
+ if (IS_ERR_VALUE(ret))
+ msm_mi2s_set_sclk(substream, false);
+clean_up:
+ if (IS_ERR_VALUE(ret))
+ mi2s_intf_conf[index].ref_cnt--;
+ mutex_unlock(&mi2s_intf_conf[index].lock);
+done:
+ return ret;
+}
+EXPORT_SYMBOL(msm_mi2s_snd_startup);
+
+/**
+ * msm_mi2s_snd_shutdown - shutdown ops of mi2s.
+ *
+ * @substream: PCM stream pointer of associated backend dailink
+ */
+void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
+{
+ int ret;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ int index = rtd->cpu_dai->id;
+
+ pr_debug("%s(): substream = %s stream = %d\n", __func__,
+ substream->name, substream->stream);
+ if (index < PRIM_MI2S || index > QUAT_MI2S) {
+ pr_err("%s:invalid MI2S DAI(%d)\n", __func__, index);
+ return;
+ }
+
+ mutex_lock(&mi2s_intf_conf[index].lock);
+ if (--mi2s_intf_conf[index].ref_cnt == 0) {
+ ret = msm_mi2s_set_sclk(substream, false);
+ if (ret < 0) {
+ pr_err("%s:clock disable failed for MI2S (%d); ret=%d\n",
+ __func__, index, ret);
+ mi2s_intf_conf[index].ref_cnt++;
+ }
+ }
+ mutex_unlock(&mi2s_intf_conf[index].lock);
+}
+EXPORT_SYMBOL(msm_mi2s_snd_shutdown);
+
+/* Validate whether US EU switch is present or not */
+static int msm_prepare_us_euro(struct snd_soc_card *card)
+{
+ struct msm_asoc_mach_data *pdata =
+ snd_soc_card_get_drvdata(card);
+ int ret = 0;
+
+ if (pdata->us_euro_gpio >= 0) {
+ dev_dbg(card->dev, "%s: us_euro gpio request %d", __func__,
+ pdata->us_euro_gpio);
+ ret = gpio_request(pdata->us_euro_gpio, "TASHA_CODEC_US_EURO");
+ if (ret) {
+ dev_err(card->dev,
+ "%s: Failed to request codec US/EURO gpio %d error %d\n",
+ __func__, pdata->us_euro_gpio, ret);
+ }
+ }
+
+ return ret;
+}
+
+static bool msm_swap_gnd_mic(struct snd_soc_codec *codec)
+{
+ struct snd_soc_card *card = codec->component.card;
+ struct msm_asoc_mach_data *pdata =
+ snd_soc_card_get_drvdata(card);
+ int value = 0;
+
+ if (pdata->us_euro_gpio_p) {
+ value = msm_cdc_pinctrl_get_state(pdata->us_euro_gpio_p);
+ if (value)
+ msm_cdc_pinctrl_select_sleep_state(
+ pdata->us_euro_gpio_p);
+ else
+ msm_cdc_pinctrl_select_active_state(
+ pdata->us_euro_gpio_p);
+ } else if (pdata->us_euro_gpio >= 0) {
+ value = gpio_get_value_cansleep(pdata->us_euro_gpio);
+ gpio_set_value_cansleep(pdata->us_euro_gpio, !value);
+ }
+ pr_debug("%s: swap select switch %d to %d\n", __func__, value, !value);
+ return true;
+}
+
+static int msm_populate_dai_link_component_of_node(
+ struct snd_soc_card *card)
+{
+ int i, index, ret = 0;
+ struct device *cdev = card->dev;
+ struct snd_soc_dai_link *dai_link = card->dai_link;
+ struct device_node *phandle;
+
+ if (!cdev) {
+ pr_err("%s: Sound card device memory NULL\n", __func__);
+ return -ENODEV;
+ }
+
+ for (i = 0; i < card->num_links; i++) {
+ if (dai_link[i].platform_of_node && dai_link[i].cpu_of_node)
+ continue;
+
+ /* populate platform_of_node for snd card dai links */
+ if (dai_link[i].platform_name &&
+ !dai_link[i].platform_of_node) {
+ index = of_property_match_string(cdev->of_node,
+ "asoc-platform-names",
+ dai_link[i].platform_name);
+ if (index < 0) {
+ pr_err("%s: No match found for platform name: %s\n",
+ __func__, dai_link[i].platform_name);
+ ret = index;
+ goto cpu_dai;
+ }
+ phandle = of_parse_phandle(cdev->of_node,
+ "asoc-platform",
+ index);
+ if (!phandle) {
+ pr_err("%s: retrieving phandle for platform %s, index %d failed\n",
+ __func__, dai_link[i].platform_name,
+ index);
+ ret = -ENODEV;
+ goto err;
+ }
+ dai_link[i].platform_of_node = phandle;
+ dai_link[i].platform_name = NULL;
+ }
+cpu_dai:
+ /* populate cpu_of_node for snd card dai links */
+ if (dai_link[i].cpu_dai_name && !dai_link[i].cpu_of_node) {
+ index = of_property_match_string(cdev->of_node,
+ "asoc-cpu-names",
+ dai_link[i].cpu_dai_name);
+ if (index < 0)
+ goto codec_dai;
+ phandle = of_parse_phandle(cdev->of_node, "asoc-cpu",
+ index);
+ if (!phandle) {
+ pr_err("%s: retrieving phandle for cpu dai %s failed\n",
+ __func__, dai_link[i].cpu_dai_name);
+ ret = -ENODEV;
+ goto err;
+ }
+ dai_link[i].cpu_of_node = phandle;
+ dai_link[i].cpu_dai_name = NULL;
+ }
+codec_dai:
+ /* populate codec_of_node for snd card dai links */
+ if (dai_link[i].codec_name && !dai_link[i].codec_of_node) {
+ index = of_property_match_string(cdev->of_node,
+ "asoc-codec-names",
+ dai_link[i].codec_name);
+ if (index < 0)
+ continue;
+ phandle = of_parse_phandle(cdev->of_node, "asoc-codec",
+ index);
+ if (!phandle) {
+ pr_err("%s: retrieving phandle for codec dai %s failed\n",
+ __func__, dai_link[i].codec_name);
+ ret = -ENODEV;
+ goto err;
+ }
+ dai_link[i].codec_of_node = phandle;
+ dai_link[i].codec_name = NULL;
+ }
+ }
+err:
+ return ret;
+}
+
+static int msm_wsa881x_init(struct snd_soc_component *component)
+{
+ u8 spkleft_ports[WSA881X_MAX_SWR_PORTS] = {100, 101, 102, 106};
+ u8 spkright_ports[WSA881X_MAX_SWR_PORTS] = {103, 104, 105, 107};
+ unsigned int ch_rate[WSA881X_MAX_SWR_PORTS] = {2400, 600, 300, 1200};
+ unsigned int ch_mask[WSA881X_MAX_SWR_PORTS] = {0x1, 0xF, 0x3, 0x3};
+ struct snd_soc_codec *codec = snd_soc_component_to_codec(component);
+ struct msm_asoc_mach_data *pdata;
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_codec_get_dapm(codec);
+
+ if (!codec) {
+ pr_err("%s codec is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ if (!strcmp(component->name_prefix, "SpkrLeft")) {
+ dev_dbg(codec->dev, "%s: setting left ch map to codec %s\n",
+ __func__, codec->component.name);
+ wsa881x_set_channel_map(codec, &spkleft_ports[0],
+ WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+ &ch_rate[0]);
+ if (dapm->component) {
+ snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft IN");
+ snd_soc_dapm_ignore_suspend(dapm, "SpkrLeft SPKR");
+ }
+ } else if (!strcmp(component->name_prefix, "SpkrRight")) {
+ dev_dbg(codec->dev, "%s: setting right ch map to codec %s\n",
+ __func__, codec->component.name);
+ wsa881x_set_channel_map(codec, &spkright_ports[0],
+ WSA881X_MAX_SWR_PORTS, &ch_mask[0],
+ &ch_rate[0]);
+ if (dapm->component) {
+ snd_soc_dapm_ignore_suspend(dapm, "SpkrRight IN");
+ snd_soc_dapm_ignore_suspend(dapm, "SpkrRight SPKR");
+ }
+ } else {
+ dev_err(codec->dev, "%s: wrong codec name %s\n", __func__,
+ codec->component.name);
+ return -EINVAL;
+ }
+
+
+ pdata = snd_soc_card_get_drvdata(component->card);
+ if (pdata && pdata->codec_root)
+ wsa881x_codec_info_create_codec_entry(pdata->codec_root,
+ codec);
+ return 0;
+}
+
+
+static int msm_init_wsa_dev(struct platform_device *pdev,
+ struct snd_soc_card *card)
+{
+ struct device_node *wsa_of_node;
+ u32 wsa_max_devs;
+ u32 wsa_dev_cnt;
+ char *dev_name_str = NULL;
+ struct msm_wsa881x_dev_info *wsa881x_dev_info;
+ const char *wsa_auxdev_name_prefix[1];
+ int found = 0;
+ int i;
+ int ret;
+
+ /* Get maximum WSA device count for this platform */
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "qcom,wsa-max-devs", &wsa_max_devs);
+ if (ret) {
+ dev_dbg(&pdev->dev,
+ "%s: wsa-max-devs property missing in DT %s, ret = %d\n",
+ __func__, pdev->dev.of_node->full_name, ret);
+ goto err_dt;
+ }
+ if (wsa_max_devs == 0) {
+ dev_warn(&pdev->dev,
+ "%s: Max WSA devices is 0 for this target?\n",
+ __func__);
+ goto err_dt;
+ }
+
+ /* Get count of WSA device phandles for this platform */
+ wsa_dev_cnt = of_count_phandle_with_args(pdev->dev.of_node,
+ "qcom,wsa-devs", NULL);
+ if (wsa_dev_cnt == -ENOENT) {
+ dev_warn(&pdev->dev, "%s: No wsa device defined in DT.\n",
+ __func__);
+ goto err_dt;
+ } else if (wsa_dev_cnt <= 0) {
+ dev_err(&pdev->dev,
+ "%s: Error reading wsa device from DT. wsa_dev_cnt = %d\n",
+ __func__, wsa_dev_cnt);
+ ret = -EINVAL;
+ goto err_dt;
+ }
+
+ /*
+ * Expect total phandles count to be NOT less than maximum possible
+ * WSA count. However, if it is less, then assign same value to
+ * max count as well.
+ */
+ if (wsa_dev_cnt < wsa_max_devs) {
+ dev_dbg(&pdev->dev,
+ "%s: wsa_max_devs = %d cannot exceed wsa_dev_cnt = %d\n",
+ __func__, wsa_max_devs, wsa_dev_cnt);
+ wsa_max_devs = wsa_dev_cnt;
+ }
+
+ /* Make sure prefix string passed for each WSA device */
+ ret = of_property_count_strings(pdev->dev.of_node,
+ "qcom,wsa-aux-dev-prefix");
+ if (ret != wsa_dev_cnt) {
+ dev_err(&pdev->dev,
+ "%s: expecting %d wsa prefix. Defined only %d in DT\n",
+ __func__, wsa_dev_cnt, ret);
+ ret = -EINVAL;
+ goto err_dt;
+ }
+
+ /*
+ * Alloc mem to store phandle and index info of WSA device, if already
+ * registered with ALSA core
+ */
+ wsa881x_dev_info = devm_kcalloc(&pdev->dev, wsa_max_devs,
+ sizeof(struct msm_wsa881x_dev_info),
+ GFP_KERNEL);
+ if (!wsa881x_dev_info) {
+ ret = -ENOMEM;
+ goto err_mem;
+ }
+
+ /*
+ * search and check whether all WSA devices are already
+ * registered with ALSA core or not. If found a node, store
+ * the node and the index in a local array of struct for later
+ * use.
+ */
+ for (i = 0; i < wsa_dev_cnt; i++) {
+ wsa_of_node = of_parse_phandle(pdev->dev.of_node,
+ "qcom,wsa-devs", i);
+ if (unlikely(!wsa_of_node)) {
+ /* we should not be here */
+ dev_err(&pdev->dev,
+ "%s: wsa dev node is not present\n",
+ __func__);
+ ret = -EINVAL;
+ goto err_dev_node;
+ }
+ if (soc_find_component(wsa_of_node, NULL)) {
+ /* WSA device registered with ALSA core */
+ wsa881x_dev_info[found].of_node = wsa_of_node;
+ wsa881x_dev_info[found].index = i;
+ found++;
+ if (found == wsa_max_devs)
+ break;
+ }
+ }
+
+ if (found < wsa_max_devs) {
+ dev_dbg(&pdev->dev,
+ "%s: failed to find %d components. Found only %d\n",
+ __func__, wsa_max_devs, found);
+ return -EPROBE_DEFER;
+ }
+ dev_info(&pdev->dev,
+ "%s: found %d wsa881x devices registered with ALSA core\n",
+ __func__, found);
+
+ card->num_aux_devs = wsa_max_devs;
+ card->num_configs = wsa_max_devs;
+
+ /* Alloc array of AUX devs struct */
+ msm_aux_dev = devm_kcalloc(&pdev->dev, card->num_aux_devs,
+ sizeof(struct snd_soc_aux_dev),
+ GFP_KERNEL);
+ if (!msm_aux_dev) {
+ ret = -ENOMEM;
+ goto err_auxdev_mem;
+ }
+
+ /* Alloc array of codec conf struct */
+ msm_codec_conf = devm_kcalloc(&pdev->dev, card->num_aux_devs,
+ sizeof(struct snd_soc_codec_conf),
+ GFP_KERNEL);
+ if (!msm_codec_conf) {
+ ret = -ENOMEM;
+ goto err_codec_conf;
+ }
+
+ for (i = 0; i < card->num_aux_devs; i++) {
+ dev_name_str = devm_kzalloc(&pdev->dev, DEV_NAME_STR_LEN,
+ GFP_KERNEL);
+ if (!dev_name_str) {
+ ret = -ENOMEM;
+ goto err_dev_str;
+ }
+
+ ret = of_property_read_string_index(pdev->dev.of_node,
+ "qcom,wsa-aux-dev-prefix",
+ wsa881x_dev_info[i].index,
+ wsa_auxdev_name_prefix);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s: failed to read wsa aux dev prefix, ret = %d\n",
+ __func__, ret);
+ ret = -EINVAL;
+ goto err_dt_prop;
+ }
+
+ snprintf(dev_name_str, strlen("wsa881x.%d"), "wsa881x.%d", i);
+ msm_aux_dev[i].name = dev_name_str;
+ msm_aux_dev[i].codec_name = NULL;
+ msm_aux_dev[i].codec_of_node =
+ wsa881x_dev_info[i].of_node;
+ msm_aux_dev[i].init = msm_wsa881x_init;
+ msm_codec_conf[i].dev_name = NULL;
+ msm_codec_conf[i].name_prefix = wsa_auxdev_name_prefix[0];
+ msm_codec_conf[i].of_node = wsa881x_dev_info[i].of_node;
+ }
+ card->codec_conf = msm_codec_conf;
+ card->aux_dev = msm_aux_dev;
+
+ return 0;
+
+err_dt_prop:
+ devm_kfree(&pdev->dev, dev_name_str);
+err_dev_str:
+ devm_kfree(&pdev->dev, msm_codec_conf);
+err_codec_conf:
+ devm_kfree(&pdev->dev, msm_aux_dev);
+err_auxdev_mem:
+err_dev_node:
+ devm_kfree(&pdev->dev, wsa881x_dev_info);
+err_mem:
+err_dt:
+ return ret;
+}
+
+static void msm_free_auxdev_mem(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ int i;
+
+ if (card->num_aux_devs > 0) {
+ for (i = 0; i < card->num_aux_devs; i++) {
+ kfree(msm_aux_dev[i].codec_name);
+ kfree(msm_codec_conf[i].dev_name);
+ kfree(msm_codec_conf[i].name_prefix);
+ }
+ }
+}
+
+static void i2s_auxpcm_init(struct platform_device *pdev)
+{
+ struct resource *muxsel;
+ int count;
+ u32 mi2s_master_slave[MI2S_MAX];
+ int ret;
+ char *str[PCM_I2S_SEL_MAX] = {
+ "lpaif_pri_mode_muxsel",
+ "lpaif_sec_mode_muxsel",
+ "lpaif_tert_mode_muxsel",
+ "lpaif_quat_mode_muxsel"
+ };
+
+ for (count = 0; count < MI2S_MAX; count++) {
+ mutex_init(&mi2s_intf_conf[count].lock);
+ mi2s_intf_conf[count].ref_cnt = 0;
+ }
+
+ for (count = 0; count < AUX_PCM_MAX; count++) {
+ mutex_init(&auxpcm_intf_conf[count].lock);
+ auxpcm_intf_conf[count].ref_cnt = 0;
+ }
+
+ for (count = 0; count < PCM_I2S_SEL_MAX; count++) {
+ mutex_init(&mi2s_auxpcm_conf[count].lock);
+ mi2s_auxpcm_conf[count].pcm_i2s_sel_vt_addr = NULL;
+ }
+
+ for (count = 0; count < PCM_I2S_SEL_MAX; count++) {
+ muxsel = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ str[count]);
+ if (muxsel) {
+ mi2s_auxpcm_conf[count].pcm_i2s_sel_vt_addr
+ = ioremap(muxsel->start, resource_size(muxsel));
+ }
+ }
+
+ ret = of_property_read_u32_array(pdev->dev.of_node,
+ "qcom,msm-mi2s-master",
+ mi2s_master_slave, MI2S_MAX);
+ if (ret) {
+ dev_dbg(&pdev->dev, "%s: no qcom,msm-mi2s-master in DT node\n",
+ __func__);
+ } else {
+ for (count = 0; count < MI2S_MAX; count++) {
+ mi2s_intf_conf[count].msm_is_mi2s_master =
+ mi2s_master_slave[count];
+ }
+ }
+}
+
+static void i2s_auxpcm_deinit(void)
+{
+ int count;
+
+ for (count = 0; count < PCM_I2S_SEL_MAX; count++)
+ if (mi2s_auxpcm_conf[count].pcm_i2s_sel_vt_addr !=
+ NULL)
+ iounmap(
+ mi2s_auxpcm_conf[count].pcm_i2s_sel_vt_addr);
+}
+
+static const struct of_device_id msmfalcon_asoc_machine_of_match[] = {
+ { .compatible = "qcom,msmfalcon-asoc-snd",
+ .data = "internal_codec"},
+ { .compatible = "qcom,msmfalcon-asoc-snd-tasha",
+ .data = "tasha_codec"},
+ { .compatible = "qcom,msmfalcon-asoc-snd-tavil",
+ .data = "tavil_codec"},
+ {},
+};
+
+static int msm_asoc_machine_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = NULL;
+ struct msm_asoc_mach_data *pdata = NULL;
+ const char *mclk = "qcom,msm-mclk-freq";
+ int ret = -EINVAL, id;
+ const struct of_device_id *match;
+
+ pdata = devm_kzalloc(&pdev->dev,
+ sizeof(struct msm_asoc_mach_data),
+ GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ match = of_match_node(msmfalcon_asoc_machine_of_match,
+ pdev->dev.of_node);
+ if (!match)
+ goto err;
+
+ ret = of_property_read_u32(pdev->dev.of_node, mclk, &id);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s: missing %s in dt node\n", __func__, mclk);
+ id = DEFAULT_MCLK_RATE;
+ }
+ pdata->mclk_freq = id;
+
+ if (!strcmp(match->data, "tasha_codec") ||
+ !strcmp(match->data, "tavil_codec")) {
+ ret = msm_ext_cdc_init(pdev, pdata, &card, &mbhc_cfg);
+ if (ret)
+ goto err;
+ } else if (!strcmp(match->data, "internal_codec")) {
+ pdata->int_codec = 1;
+ ret = msm_int_cdc_init(pdev, pdata, &card, &mbhc_cfg);
+ if (ret)
+ goto err;
+ } else {
+ dev_err(&pdev->dev,
+ "%s: Not a matching DT sound node\n", __func__);
+ goto err;
+ }
+ if (!card)
+ goto err;
+
+ /*reading the gpio configurations from dtsi file*/
+ ret = msm_gpioset_initialize(CLIENT_WCD, &pdev->dev);
+ if (ret < 0) {
+ dev_err(&pdev->dev,
+ "%s: error reading dtsi files%d\n", __func__, ret);
+ goto err;
+ }
+
+ /*
+ * Parse US-Euro gpio info from DT. Report no error if us-euro
+ * entry is not found in DT file as some targets do not support
+ * US-Euro detection
+ */
+ pdata->us_euro_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,us-euro-gpios", 0);
+ if (!gpio_is_valid(pdata->us_euro_gpio))
+ pdata->us_euro_gpio_p = of_parse_phandle(pdev->dev.of_node,
+ "qcom,us-euro-gpios", 0);
+ if (!gpio_is_valid(pdata->us_euro_gpio) && (!pdata->us_euro_gpio_p)) {
+ dev_dbg(&pdev->dev, "property %s not detected in node %s",
+ "qcom,us-euro-gpios", pdev->dev.of_node->full_name);
+ } else {
+ dev_dbg(&pdev->dev, "%s detected",
+ "qcom,us-euro-gpios");
+ mbhc_cfg.swap_gnd_mic = msm_swap_gnd_mic;
+ }
+
+ ret = msm_prepare_us_euro(card);
+ if (ret)
+ dev_dbg(&pdev->dev, "msm_prepare_us_euro failed (%d)\n",
+ ret);
+
+ i2s_auxpcm_init(pdev);
+
+ ret = snd_soc_of_parse_audio_routing(card, "qcom,audio-routing");
+ if (ret)
+ goto err;
+
+ ret = msm_populate_dai_link_component_of_node(card);
+ if (ret) {
+ ret = -EPROBE_DEFER;
+ goto err;
+ }
+ ret = msm_init_wsa_dev(pdev, card);
+ if (ret)
+ goto err;
+
+
+ ret = devm_snd_soc_register_card(&pdev->dev, card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ goto err;
+ }
+ return 0;
+err:
+ if (pdata->us_euro_gpio > 0) {
+ dev_dbg(&pdev->dev, "%s free us_euro gpio %d\n",
+ __func__, pdata->us_euro_gpio);
+ pdata->us_euro_gpio = 0;
+ }
+ if (pdata->hph_en1_gpio > 0) {
+ dev_dbg(&pdev->dev, "%s free hph_en1_gpio %d\n",
+ __func__, pdata->hph_en1_gpio);
+ gpio_free(pdata->hph_en1_gpio);
+ pdata->hph_en1_gpio = 0;
+ }
+ if (pdata->hph_en0_gpio > 0) {
+ dev_dbg(&pdev->dev, "%s free hph_en0_gpio %d\n",
+ __func__, pdata->hph_en0_gpio);
+ gpio_free(pdata->hph_en0_gpio);
+ pdata->hph_en0_gpio = 0;
+ }
+ devm_kfree(&pdev->dev, pdata);
+ return ret;
+}
+
+static int msm_asoc_machine_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+
+ if (pdata->int_codec)
+ mutex_destroy(&pdata->cdc_int_mclk0_mutex);
+ msm_free_auxdev_mem(pdev);
+
+ gpio_free(pdata->us_euro_gpio);
+ gpio_free(pdata->hph_en1_gpio);
+ gpio_free(pdata->hph_en0_gpio);
+ i2s_auxpcm_deinit();
+ snd_soc_unregister_card(card);
+ return 0;
+}
+
+static struct platform_driver msmfalcon_asoc_machine_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = msmfalcon_asoc_machine_of_match,
+ },
+ .probe = msm_asoc_machine_probe,
+ .remove = msm_asoc_machine_remove,
+};
+module_platform_driver(msmfalcon_asoc_machine_driver);
+
+MODULE_DESCRIPTION("ALSA SoC msm");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, msmfalcon_asoc_machine_of_match);
diff --git a/sound/soc/msm/msmfalcon-common.h b/sound/soc/msm/msmfalcon-common.h
new file mode 100644
index 000000000000..ff8232d6fcbb
--- /dev/null
+++ b/sound/soc/msm/msmfalcon-common.h
@@ -0,0 +1,69 @@
+/* Copyright (c) 2015-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 __MSM_COMMON
+#define __MSM_COMMON
+
+#include <sound/soc.h>
+#include <sound/q6afe-v2.h>
+#include "../codecs/wcd-mbhc-v2.h"
+
+#define SAMPLING_RATE_8KHZ 8000
+#define SAMPLING_RATE_11P025KHZ 11025
+#define SAMPLING_RATE_16KHZ 16000
+#define SAMPLING_RATE_22P05KHZ 22050
+#define SAMPLING_RATE_32KHZ 32000
+#define SAMPLING_RATE_44P1KHZ 44100
+#define SAMPLING_RATE_48KHZ 48000
+#define SAMPLING_RATE_88P2KHZ 88200
+#define SAMPLING_RATE_96KHZ 96000
+#define SAMPLING_RATE_176P4KHZ 176400
+#define SAMPLING_RATE_192KHZ 192000
+#define SAMPLING_RATE_352P8KHZ 352800
+#define SAMPLING_RATE_384KHZ 384000
+
+extern const struct snd_kcontrol_new msm_common_snd_controls[];
+struct msmfalcon_codec {
+ void* (*get_afe_config_fn)(struct snd_soc_codec *codec,
+ enum afe_config_type config_type);
+};
+
+struct msm_asoc_mach_data {
+ int us_euro_gpio; /* used by gpio driver API */
+ int hph_en1_gpio;
+ int hph_en0_gpio;
+ struct device_node *us_euro_gpio_p; /* used by pinctrl API */
+ struct device_node *hph_en1_gpio_p; /* used by pinctrl API */
+ struct device_node *hph_en0_gpio_p; /* used by pinctrl API */
+ struct snd_soc_codec *codec;
+ struct msmfalcon_codec msmfalcon_codec_fn;
+ struct snd_info_entry *codec_root;
+ int spk_ext_pa_gpio;
+ int mclk_freq;
+ int lb_mode;
+ u8 micbias1_cap_mode;
+ u8 micbias2_cap_mode;
+ atomic_t int_mclk0_rsc_ref;
+ atomic_t int_mclk0_enabled;
+ struct mutex cdc_int_mclk0_mutex;
+ struct delayed_work disable_int_mclk0_work;
+ struct afe_clk_set digital_cdc_core_clk;
+ bool int_codec;
+};
+
+int msm_common_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params);
+int msm_aux_pcm_snd_startup(struct snd_pcm_substream *substream);
+void msm_aux_pcm_snd_shutdown(struct snd_pcm_substream *substream);
+int msm_mi2s_snd_startup(struct snd_pcm_substream *substream);
+void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream);
+#endif
diff --git a/sound/soc/msm/msmfalcon-ext-dai-links.c b/sound/soc/msm/msmfalcon-ext-dai-links.c
new file mode 100644
index 000000000000..4dca7908c108
--- /dev/null
+++ b/sound/soc/msm/msmfalcon-ext-dai-links.c
@@ -0,0 +1,1527 @@
+/* Copyright (c) 2015-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.
+ */
+
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/of.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include "qdsp6v2/msm-pcm-routing-v2.h"
+#include "../codecs/wcd9335.h"
+#include "msmfalcon-common.h"
+#include "msmfalcon-external.h"
+
+#define DEV_NAME_STR_LEN 32
+#define __CHIPSET__ "MSMFALCON "
+#define MSM_DAILINK_NAME(name) (__CHIPSET__#name)
+
+static struct snd_soc_card snd_soc_card_msm_card;
+
+static struct snd_soc_ops msm_ext_slimbus_be_ops = {
+ .hw_params = msm_snd_hw_params,
+};
+
+static struct snd_soc_ops msm_ext_cpe_ops = {
+ .hw_params = msm_snd_cpe_hw_params,
+};
+
+static struct snd_soc_ops msm_ext_slimbus_2_be_ops = {
+ .hw_params = msm_ext_slimbus_2_hw_params,
+};
+
+static struct snd_soc_ops msm_mi2s_be_ops = {
+ .startup = msm_mi2s_snd_startup,
+ .shutdown = msm_mi2s_snd_shutdown,
+};
+
+static struct snd_soc_ops msm_aux_pcm_be_ops = {
+ .startup = msm_aux_pcm_snd_startup,
+ .shutdown = msm_aux_pcm_snd_shutdown,
+};
+
+static struct snd_soc_dai_link msm_ext_tasha_fe_dai[] = {
+ /* tasha_vifeedback for speaker protection */
+ {
+ .name = LPASS_BE_SLIMBUS_4_TX,
+ .stream_name = "Slimbus4 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16393",
+ .platform_name = "msm-pcm-hostless",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_vifeedback",
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ },
+ /* Ultrasound RX DAI Link */
+ {
+ .name = "SLIMBUS_2 Hostless Playback",
+ .stream_name = "SLIMBUS_2 Hostless Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16388",
+ .platform_name = "msm-pcm-hostless",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_rx2",
+ .ignore_suspend = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ops = &msm_ext_slimbus_2_be_ops,
+ },
+ /* Ultrasound TX DAI Link */
+ {
+ .name = "SLIMBUS_2 Hostless Capture",
+ .stream_name = "SLIMBUS_2 Hostless Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16389",
+ .platform_name = "msm-pcm-hostless",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_tx2",
+ .ignore_suspend = 1,
+ .dpcm_capture = 1,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ops = &msm_ext_slimbus_2_be_ops,
+ },
+ /* CPE LSM direct dai-link */
+ {
+ .name = "CPE Listen service",
+ .stream_name = "CPE Listen Audio Service",
+ .cpu_dai_name = "msm-dai-slim",
+ .platform_name = "msm-cpe-lsm",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .dpcm_capture = 1,
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "tasha_mad1",
+ .codec_name = "tasha_codec",
+ .ops = &msm_ext_cpe_ops,
+ },
+ {
+ .name = "SLIMBUS_6 Hostless Playback",
+ .stream_name = "SLIMBUS_6 Hostless",
+ .cpu_dai_name = "SLIMBUS6_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_playback = 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,
+ /* this dailink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ /* CPE LSM EC PP direct dai-link */
+ {
+ .name = "CPE Listen service ECPP",
+ .stream_name = "CPE Listen Audio Service ECPP",
+ .cpu_dai_name = "CPE_LSM_NOHOST",
+ .platform_name = "msm-cpe-lsm.3",
+ .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 = "tasha_cpe",
+ .codec_name = "tasha_codec",
+ },
+};
+
+static struct snd_soc_dai_link msm_ext_tavil_fe_dai[] = {
+ {
+ .name = LPASS_BE_SLIMBUS_4_TX,
+ .stream_name = "Slimbus4 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16393",
+ .platform_name = "msm-pcm-hostless",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_vifeedback",
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ },
+ /* Ultrasound RX DAI Link */
+ {
+ .name = "SLIMBUS_2 Hostless Playback",
+ .stream_name = "SLIMBUS_2 Hostless Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16388",
+ .platform_name = "msm-pcm-hostless",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_rx2",
+ .ignore_suspend = 1,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ops = &msm_ext_slimbus_2_be_ops,
+ },
+ /* Ultrasound TX DAI Link */
+ {
+ .name = "SLIMBUS_2 Hostless Capture",
+ .stream_name = "SLIMBUS_2 Hostless Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16389",
+ .platform_name = "msm-pcm-hostless",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_tx2",
+ .ignore_suspend = 1,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ops = &msm_ext_slimbus_2_be_ops,
+ },
+};
+
+static struct snd_soc_dai_link msm_ext_tasha_be_dai[] = {
+ /* Backend DAI Links */
+ {
+ .name = LPASS_BE_SLIMBUS_0_RX,
+ .stream_name = "Slimbus Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16384",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_mix_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ .init = &msm_audrx_init,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ .ops = &msm_ext_slimbus_be_ops,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_0_TX,
+ .stream_name = "Slimbus Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16385",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_tx1",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ .ops = &msm_ext_slimbus_be_ops,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_1_RX,
+ .stream_name = "Slimbus1 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16386",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_mix_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_1_TX,
+ .stream_name = "Slimbus1 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16387",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_tx3",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_3_RX,
+ .stream_name = "Slimbus3 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16390",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_mix_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_3_TX,
+ .stream_name = "Slimbus3 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16391",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_tx1",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_4_RX,
+ .stream_name = "Slimbus4 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16392",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_mix_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_5_RX,
+ .stream_name = "Slimbus5 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16394",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_rx3",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_5_RX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ /* MAD BE */
+ {
+ .name = LPASS_BE_SLIMBUS_5_TX,
+ .stream_name = "Slimbus5 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16395",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_mad1",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_6_RX,
+ .stream_name = "Slimbus6 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16396",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tasha_codec",
+ .codec_dai_name = "tasha_rx4",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_6_RX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+};
+
+static struct snd_soc_dai_link msm_ext_tavil_be_dai[] = {
+ {
+ .name = LPASS_BE_SLIMBUS_0_RX,
+ .stream_name = "Slimbus Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16384",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ .init = &msm_audrx_init,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ .ops = &msm_ext_slimbus_be_ops,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_0_TX,
+ .stream_name = "Slimbus Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16385",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_tx1",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ .ops = &msm_ext_slimbus_be_ops,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_1_RX,
+ .stream_name = "Slimbus1 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16386",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_1_TX,
+ .stream_name = "Slimbus1 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16387",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_tx3",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_2_RX,
+ .stream_name = "Slimbus2 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16388",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_rx2",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_2_RX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_3_RX,
+ .stream_name = "Slimbus3 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16390",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_3_TX,
+ .stream_name = "Slimbus3 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16391",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_tx1",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_4_RX,
+ .stream_name = "Slimbus4 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16392",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_5_RX,
+ .stream_name = "Slimbus5 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16394",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_rx3",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_5_RX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ /* MAD BE */
+ {
+ .name = LPASS_BE_SLIMBUS_5_TX,
+ .stream_name = "Slimbus5 Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.16395",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_mad1",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SLIMBUS_6_RX,
+ .stream_name = "Slimbus6 Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.16396",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "tavil_codec",
+ .codec_dai_name = "tavil_rx4",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_6_RX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ops = &msm_ext_slimbus_be_ops,
+ /* dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+};
+
+static struct snd_soc_dai_link msm_ext_common_fe_dai[] = {
+ /* FrontEnd DAI Links */
+ {/* hw:x,0 */
+ .name = MSM_DAILINK_NAME(Media1),
+ .stream_name = "MultiMedia1",
+ .cpu_dai_name = "MultiMedia1",
+ .platform_name = "msm-pcm-dsp.0",
+ .dynamic = 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,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
+ },
+ {/* hw:x,1 */
+ .name = MSM_DAILINK_NAME(Media2),
+ .stream_name = "MultiMedia2",
+ .cpu_dai_name = "MultiMedia2",
+ .platform_name = "msm-pcm-dsp.0",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .ignore_suspend = 1,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+ },
+ {/* hw:x,2 */
+ .name = "VoiceMMode1",
+ .stream_name = "VoiceMMode1",
+ .cpu_dai_name = "VoiceMMode1",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .dpcm_capture = 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",
+ .be_id = MSM_FRONTEND_DAI_VOICEMMODE1,
+ },
+ {/* hw:x,3 */
+ .name = "MSM VoIP",
+ .stream_name = "VoIP",
+ .cpu_dai_name = "VoIP",
+ .platform_name = "msm-voip-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",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_VOIP,
+ },
+ {/* hw:x,4 */
+ .name = MSM_DAILINK_NAME(ULL),
+ .stream_name = "ULL",
+ .cpu_dai_name = "MultiMedia3",
+ .platform_name = "msm-pcm-dsp.2",
+ .dynamic = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
+ },
+ /* Hostless PCM purpose */
+ {/* hw:x,5 */
+ .name = "SLIMBUS_0 Hostless",
+ .stream_name = "SLIMBUS_0 Hostless",
+ .cpu_dai_name = "SLIMBUS0_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_capture = 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,
+ /* This dai link has MI2S support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {/* hw:x,6 */
+ .name = "MSM AFE-PCM RX",
+ .stream_name = "AFE-PROXY RX",
+ .cpu_dai_name = "msm-dai-q6-dev.241",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .platform_name = "msm-pcm-afe",
+ .ignore_suspend = 1,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ },
+ {/* hw:x,7 */
+ .name = "MSM AFE-PCM TX",
+ .stream_name = "AFE-PROXY TX",
+ .cpu_dai_name = "msm-dai-q6-dev.240",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .platform_name = "msm-pcm-afe",
+ .ignore_suspend = 1,
+ },
+ {/* hw:x,8 */
+ .name = MSM_DAILINK_NAME(Compress1),
+ .stream_name = "Compress1",
+ .cpu_dai_name = "MultiMedia4",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+ },
+ {/* hw:x,9*/
+ .name = "AUXPCM Hostless",
+ .stream_name = "AUXPCM Hostless",
+ .cpu_dai_name = "AUXPCM_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_capture = 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,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {/* hw:x,10 */
+ .name = "SLIMBUS_1 Hostless",
+ .stream_name = "SLIMBUS_1 Hostless",
+ .cpu_dai_name = "SLIMBUS1_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_capture = 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, /* dai link has playback support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {/* hw:x,11 */
+ .name = "SLIMBUS_3 Hostless",
+ .stream_name = "SLIMBUS_3 Hostless",
+ .cpu_dai_name = "SLIMBUS3_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_capture = 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, /* dai link has playback support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {/* hw:x,12 */
+ .name = "SLIMBUS_4 Hostless",
+ .stream_name = "SLIMBUS_4 Hostless",
+ .cpu_dai_name = "SLIMBUS4_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_capture = 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, /* dai link has playback support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {/* hw:x,13 */
+ .name = MSM_DAILINK_NAME(LowLatency),
+ .stream_name = "MultiMedia5",
+ .cpu_dai_name = "MultiMedia5",
+ .platform_name = "msm-pcm-dsp.1",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .ignore_suspend = 1,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
+ },
+ /* LSM FE */
+ {/* hw:x,14 */
+ .name = "Listen 1 Audio Service",
+ .stream_name = "Listen 1 Audio Service",
+ .cpu_dai_name = "LSM1",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM1,
+ },
+ {/* hw:x,15 */
+ .name = MSM_DAILINK_NAME(Compress2),
+ .stream_name = "Compress2",
+ .cpu_dai_name = "MultiMedia7",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .ignore_suspend = 1,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+ },
+ {/* hw:x,16 */
+ .name = MSM_DAILINK_NAME(Compress3),
+ .stream_name = "Compress3",
+ .cpu_dai_name = "MultiMedia10",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA10,
+ },
+ {/* hw:x,17 */
+ .name = MSM_DAILINK_NAME(ULL_NOIRQ),
+ .stream_name = "MM_NOIRQ",
+ .cpu_dai_name = "MultiMedia8",
+ .platform_name = "msm-pcm-dsp-noirq",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+ },
+ {/* hw:x,18 */
+ .name = "HDMI_RX_HOSTLESS",
+ .stream_name = "HDMI_RX_HOSTLESS",
+ .cpu_dai_name = "HDMI_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",
+ },
+ {/* hw:x,19 */
+ .name = "VoiceMMode2",
+ .stream_name = "VoiceMMode2",
+ .cpu_dai_name = "VoiceMMode2",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .dpcm_capture = 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",
+ .be_id = MSM_FRONTEND_DAI_VOICEMMODE2,
+ },
+ {/* hw:x,20 */
+ .name = "Listen 2 Audio Service",
+ .stream_name = "Listen 2 Audio Service",
+ .cpu_dai_name = "LSM2",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM2,
+ },
+ {/* hw:x,21 */
+ .name = "Listen 3 Audio Service",
+ .stream_name = "Listen 3 Audio Service",
+ .cpu_dai_name = "LSM3",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM3,
+ },
+ {/* hw:x,22 */
+ .name = "Listen 4 Audio Service",
+ .stream_name = "Listen 4 Audio Service",
+ .cpu_dai_name = "LSM4",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM4,
+ },
+ {/* hw:x,23 */
+ .name = "Listen 5 Audio Service",
+ .stream_name = "Listen 5 Audio Service",
+ .cpu_dai_name = "LSM5",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM5,
+ },
+ {/* hw:x,24 */
+ .name = "Listen 6 Audio Service",
+ .stream_name = "Listen 6 Audio Service",
+ .cpu_dai_name = "LSM6",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM6
+ },
+ {/* hw:x,25 */
+ .name = "Listen 7 Audio Service",
+ .stream_name = "Listen 7 Audio Service",
+ .cpu_dai_name = "LSM7",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM7,
+ },
+ {/* hw:x,26 */
+ .name = "Listen 8 Audio Service",
+ .stream_name = "Listen 8 Audio Service",
+ .cpu_dai_name = "LSM8",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM8,
+ },
+ {/* hw:x,27 */
+ .name = MSM_DAILINK_NAME(Media9),
+ .stream_name = "MultiMedia9",
+ .cpu_dai_name = "MultiMedia9",
+ .platform_name = "msm-pcm-dsp.0",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA9,
+ },
+ {/* hw:x,28 */
+ .name = MSM_DAILINK_NAME(Compress4),
+ .stream_name = "Compress4",
+ .cpu_dai_name = "MultiMedia11",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA11,
+ },
+ {/* hw:x,29 */
+ .name = MSM_DAILINK_NAME(Compress5),
+ .stream_name = "Compress5",
+ .cpu_dai_name = "MultiMedia12",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA12,
+ },
+ {/* hw:x,30 */
+ .name = MSM_DAILINK_NAME(Compress6),
+ .stream_name = "Compress6",
+ .cpu_dai_name = "MultiMedia13",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA13,
+ },
+ {/* hw:x,31 */
+ .name = MSM_DAILINK_NAME(Compress7),
+ .stream_name = "Compress7",
+ .cpu_dai_name = "MultiMedia14",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA14,
+ },
+ {/* hw:x,32 */
+ .name = MSM_DAILINK_NAME(Compress8),
+ .stream_name = "Compress8",
+ .cpu_dai_name = "MultiMedia15",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA15,
+ },
+ {/* hw:x,33 */
+ .name = MSM_DAILINK_NAME(Compress9),
+ .stream_name = "Compress9",
+ .cpu_dai_name = "MultiMedia16",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA16,
+ },
+ {/* hw:x,34 */
+ .name = "SLIMBUS_8 Hostless",
+ .stream_name = "SLIMBUS8_HOSTLESS Capture",
+ .cpu_dai_name = "SLIMBUS8_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_ext_common_be_dai[] = {
+ {
+ .name = LPASS_BE_AFE_PCM_RX,
+ .stream_name = "AFE Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.224",
+ .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_AFE_PCM_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_AFE_PCM_TX,
+ .stream_name = "AFE Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.225",
+ .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_PCM_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Record Uplink BACK END DAI Link */
+ {
+ .name = LPASS_BE_INCALL_RECORD_TX,
+ .stream_name = "Voice Uplink Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.32772",
+ .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_INCALL_RECORD_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Record Downlink BACK END DAI Link */
+ {
+ .name = LPASS_BE_INCALL_RECORD_RX,
+ .stream_name = "Voice Downlink Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.32771",
+ .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_INCALL_RECORD_RX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Music BACK END DAI Link */
+ {
+ .name = LPASS_BE_VOICE_PLAYBACK_TX,
+ .stream_name = "Voice Farend Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.32773",
+ .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_VOICE_PLAYBACK_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Music 2 BACK END DAI Link */
+ {
+ .name = LPASS_BE_VOICE2_PLAYBACK_TX,
+ .stream_name = "Voice2 Farend Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.32770",
+ .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_VOICE2_PLAYBACK_TX,
+ .be_hw_params_fixup = msm_ext_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+};
+
+static struct snd_soc_dai_link msm_mi2s_be_dai_links[] = {
+ {
+ .name = LPASS_BE_PRI_MI2S_RX,
+ .stream_name = "Primary MI2S Playback",
+ .cpu_dai_name = "msm-dai-q6-mi2s.0",
+ .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_MI2S_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = LPASS_BE_PRI_MI2S_TX,
+ .stream_name = "Primary MI2S Capture",
+ .cpu_dai_name = "msm-dai-q6-mi2s.0",
+ .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_MI2S_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SEC_MI2S_RX,
+ .stream_name = "Secondary MI2S Playback",
+ .cpu_dai_name = "msm-dai-q6-mi2s.1",
+ .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_SECONDARY_MI2S_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = LPASS_BE_SEC_MI2S_TX,
+ .stream_name = "Secondary MI2S Capture",
+ .cpu_dai_name = "msm-dai-q6-mi2s.1",
+ .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_SECONDARY_MI2S_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_TERT_MI2S_RX,
+ .stream_name = "Tertiary MI2S Playback",
+ .cpu_dai_name = "msm-dai-q6-mi2s.2",
+ .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_TERTIARY_MI2S_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = LPASS_BE_TERT_MI2S_TX,
+ .stream_name = "Tertiary MI2S Capture",
+ .cpu_dai_name = "msm-dai-q6-mi2s.2",
+ .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_TERTIARY_MI2S_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_QUAT_MI2S_RX,
+ .stream_name = "Quaternary MI2S Playback",
+ .cpu_dai_name = "msm-dai-q6-mi2s.3",
+ .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_QUATERNARY_MI2S_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = LPASS_BE_QUAT_MI2S_TX,
+ .stream_name = "Quaternary MI2S Capture",
+ .cpu_dai_name = "msm-dai-q6-mi2s.3",
+ .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_QUATERNARY_MI2S_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ },
+};
+
+static struct snd_soc_dai_link msm_auxpcm_be_dai_links[] = {
+ /* Primary AUX PCM Backend DAI Links */
+ {
+ .name = LPASS_BE_AUXPCM_RX,
+ .stream_name = "AUX PCM Playback",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.1",
+ .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_AUXPCM_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ {
+ .name = LPASS_BE_AUXPCM_TX,
+ .stream_name = "AUX PCM Capture",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.1",
+ .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_AUXPCM_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ /* Secondary AUX PCM Backend DAI Links */
+ {
+ .name = LPASS_BE_SEC_AUXPCM_RX,
+ .stream_name = "Sec AUX PCM Playback",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.2",
+ .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_SEC_AUXPCM_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ {
+ .name = LPASS_BE_SEC_AUXPCM_TX,
+ .stream_name = "Sec AUX PCM Capture",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.2",
+ .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_SEC_AUXPCM_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ /* Tertiary AUX PCM Backend DAI Links */
+ {
+ .name = LPASS_BE_TERT_AUXPCM_RX,
+ .stream_name = "Tert AUX PCM Playback",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.3",
+ .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_TERT_AUXPCM_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ {
+ .name = LPASS_BE_TERT_AUXPCM_TX,
+ .stream_name = "Tert AUX PCM Capture",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.3",
+ .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_TERT_AUXPCM_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ /* Quaternary AUX PCM Backend DAI Links */
+ {
+ .name = LPASS_BE_QUAT_AUXPCM_RX,
+ .stream_name = "Quat AUX PCM Playback",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.4",
+ .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_QUAT_AUXPCM_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ {
+ .name = LPASS_BE_QUAT_AUXPCM_TX,
+ .stream_name = "Quat AUX PCM Capture",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.4",
+ .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_QUAT_AUXPCM_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+};
+
+static struct snd_soc_dai_link msm_ext_tasha_dai_links[
+ARRAY_SIZE(msm_ext_common_fe_dai) +
+ARRAY_SIZE(msm_ext_tasha_fe_dai) +
+ARRAY_SIZE(msm_ext_common_be_dai) +
+ARRAY_SIZE(msm_ext_tasha_be_dai) +
+ARRAY_SIZE(msm_mi2s_be_dai_links) +
+ARRAY_SIZE(msm_auxpcm_be_dai_links)];
+
+static struct snd_soc_dai_link msm_ext_tavil_dai_links[
+ARRAY_SIZE(msm_ext_common_fe_dai) +
+ARRAY_SIZE(msm_ext_tavil_fe_dai) +
+ARRAY_SIZE(msm_ext_common_be_dai) +
+ARRAY_SIZE(msm_ext_tavil_be_dai) +
+ARRAY_SIZE(msm_mi2s_be_dai_links) +
+ARRAY_SIZE(msm_auxpcm_be_dai_links)];
+
+/**
+ * populate_snd_card_dailinks - prepares dailink array and initializes card.
+ *
+ * @dev: device handle
+ *
+ * Returns card on success or NULL on failure.
+ */
+struct snd_soc_card *populate_snd_card_dailinks(struct device *dev)
+{
+ struct snd_soc_card *card = &snd_soc_card_msm_card;
+ struct snd_soc_dai_link *msm_ext_dai_links = NULL;
+ int ret, len1, len2, len3, len4;
+ enum codec_variant codec_ver = 0;
+
+ card->dev = dev;
+ ret = snd_soc_of_parse_card_name(card, "qcom,model");
+ if (ret) {
+ dev_err(dev, "%s: parse card name failed, err:%d\n",
+ __func__, ret);
+ return NULL;
+ }
+
+ if (strnstr(card->name, "tasha", strlen(card->name))) {
+ codec_ver = tasha_codec_ver();
+ if (codec_ver == WCD9326)
+ card->name = "msmfalcon-tashalite-snd-card";
+
+ len1 = ARRAY_SIZE(msm_ext_common_fe_dai);
+ len2 = len1 + ARRAY_SIZE(msm_ext_tasha_fe_dai);
+ len3 = len2 + ARRAY_SIZE(msm_ext_common_be_dai);
+ memcpy(msm_ext_tasha_dai_links, msm_ext_common_fe_dai,
+ sizeof(msm_ext_common_fe_dai));
+ memcpy(msm_ext_tasha_dai_links + len1,
+ msm_ext_tasha_fe_dai, sizeof(msm_ext_tasha_fe_dai));
+ memcpy(msm_ext_tasha_dai_links + len2,
+ msm_ext_common_be_dai, sizeof(msm_ext_common_be_dai));
+ memcpy(msm_ext_tasha_dai_links + len3,
+ msm_ext_tasha_be_dai, sizeof(msm_ext_tasha_be_dai));
+ len4 = len3 + ARRAY_SIZE(msm_ext_tasha_be_dai);
+ if (of_property_read_bool(dev->of_node,
+ "qcom,mi2s-audio-intf")) {
+ memcpy(msm_ext_tasha_dai_links + len4,
+ msm_mi2s_be_dai_links,
+ sizeof(msm_mi2s_be_dai_links));
+ len4 += ARRAY_SIZE(msm_mi2s_be_dai_links);
+ }
+ if (of_property_read_bool(dev->of_node,
+ "qcom,auxpcm-audio-intf")) {
+ memcpy(msm_ext_tasha_dai_links + len4,
+ msm_auxpcm_be_dai_links,
+ sizeof(msm_auxpcm_be_dai_links));
+ len4 += ARRAY_SIZE(msm_auxpcm_be_dai_links);
+ }
+ msm_ext_dai_links = msm_ext_tasha_dai_links;
+ } else if (strnstr(card->name, "tavil", strlen(card->name))) {
+ len1 = ARRAY_SIZE(msm_ext_common_fe_dai);
+ len2 = len1 + ARRAY_SIZE(msm_ext_tavil_fe_dai);
+ len3 = len2 + ARRAY_SIZE(msm_ext_common_be_dai);
+ memcpy(msm_ext_tavil_dai_links, msm_ext_common_fe_dai,
+ sizeof(msm_ext_common_fe_dai));
+ memcpy(msm_ext_tavil_dai_links + len1,
+ msm_ext_tavil_fe_dai, sizeof(msm_ext_tavil_fe_dai));
+ memcpy(msm_ext_tavil_dai_links + len2,
+ msm_ext_common_be_dai, sizeof(msm_ext_common_be_dai));
+ memcpy(msm_ext_tavil_dai_links + len3,
+ msm_ext_tavil_be_dai, sizeof(msm_ext_tavil_be_dai));
+ len4 = len3 + ARRAY_SIZE(msm_ext_tavil_be_dai);
+ if (of_property_read_bool(dev->of_node,
+ "qcom,mi2s-audio-intf")) {
+ memcpy(msm_ext_tavil_dai_links + len4,
+ msm_mi2s_be_dai_links,
+ sizeof(msm_mi2s_be_dai_links));
+ len4 += ARRAY_SIZE(msm_mi2s_be_dai_links);
+ }
+ if (of_property_read_bool(dev->of_node,
+ "qcom,auxpcm-audio-intf")) {
+ memcpy(msm_ext_tavil_dai_links + len4,
+ msm_auxpcm_be_dai_links,
+ sizeof(msm_auxpcm_be_dai_links));
+ len4 += ARRAY_SIZE(msm_auxpcm_be_dai_links);
+ }
+ msm_ext_dai_links = msm_ext_tavil_dai_links;
+ } else {
+ dev_err(dev, "%s: failing as no matching card name\n",
+ __func__);
+ return NULL;
+ }
+ card->dai_link = msm_ext_dai_links;
+ card->num_links = len4;
+ card->dev = dev;
+
+ return card;
+}
+EXPORT_SYMBOL(populate_snd_card_dailinks);
diff --git a/sound/soc/msm/msmfalcon-external.c b/sound/soc/msm/msmfalcon-external.c
new file mode 100644
index 000000000000..046c63bb73cf
--- /dev/null
+++ b/sound/soc/msm/msmfalcon-external.c
@@ -0,0 +1,1700 @@
+/* Copyright (c) 2015-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.
+ */
+
+#include <linux/delay.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <sound/soc.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/q6core.h>
+#include <linux/qdsp6v2/audio_notifier.h>
+#include "qdsp6v2/msm-pcm-routing-v2.h"
+#include "msm-audio-pinctrl.h"
+#include "msmfalcon-common.h"
+#include "msmfalcon-external.h"
+#include "../codecs/wcd9335.h"
+#include "../codecs/wcd934x/wcd934x.h"
+#include "../codecs/wcd934x/wcd934x-mbhc.h"
+
+#define MSMFALCON_SPK_ON 1
+#define MSMFALCON_SPK_OFF 0
+
+#define WCD9XXX_MBHC_DEF_BUTTONS 8
+#define WCD9XXX_MBHC_DEF_RLOADS 5
+#define CODEC_EXT_CLK_RATE 9600000
+#define ADSP_STATE_READY_TIMEOUT_MS 3000
+
+#define WSA8810_NAME_1 "wsa881x.20170211"
+#define WSA8810_NAME_2 "wsa881x.20170212"
+
+static int msm_ext_spk_control = 1;
+static struct wcd_mbhc_config *wcd_mbhc_cfg_ptr;
+
+struct msm_asoc_wcd93xx_codec {
+ void* (*get_afe_config_fn)(struct snd_soc_codec *codec,
+ enum afe_config_type config_type);
+ void (*mbhc_hs_detect_exit)(struct snd_soc_codec *codec);
+};
+
+static struct msm_asoc_wcd93xx_codec msm_codec_fn;
+static struct platform_device *spdev;
+
+static bool is_initial_boot;
+
+static void *def_ext_mbhc_cal(void);
+
+enum {
+ SLIM_RX_0 = 0,
+ SLIM_RX_1,
+ SLIM_RX_2,
+ SLIM_RX_3,
+ SLIM_RX_4,
+ SLIM_RX_5,
+ SLIM_RX_6,
+ SLIM_RX_7,
+ SLIM_RX_MAX,
+};
+
+enum {
+ SLIM_TX_0 = 0,
+ SLIM_TX_1,
+ SLIM_TX_2,
+ SLIM_TX_3,
+ SLIM_TX_4,
+ SLIM_TX_5,
+ SLIM_TX_6,
+ SLIM_TX_7,
+ SLIM_TX_8,
+ SLIM_TX_MAX,
+};
+
+struct dev_config {
+ u32 sample_rate;
+ u32 bit_format;
+ u32 channels;
+};
+
+/* Default configuration of slimbus channels */
+static struct dev_config slim_rx_cfg[] = {
+ [SLIM_RX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_RX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_RX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_RX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_RX_4] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_RX_5] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_RX_6] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_RX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+};
+
+static struct dev_config slim_tx_cfg[] = {
+ [SLIM_TX_0] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_1] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_2] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_3] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_4] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_5] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_6] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_7] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [SLIM_TX_8] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+};
+
+static int msm_vi_feed_tx_ch = 2;
+static const char *const slim_rx_ch_text[] = {"One", "Two"};
+static const char *const slim_tx_ch_text[] = {"One", "Two", "Three", "Four",
+ "Five", "Six", "Seven",
+ "Eight"};
+static const char *const vi_feed_ch_text[] = {"One", "Two"};
+static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE",
+ "S32_LE"};
+static char const *slim_sample_rate_text[] = {"KHZ_8", "KHZ_16",
+ "KHZ_32", "KHZ_44P1", "KHZ_48",
+ "KHZ_88P2", "KHZ_96", "KHZ_176P4",
+ "KHZ_192", "KHZ_352P8", "KHZ_384"};
+static const char *const spk_function_text[] = {"Off", "On"};
+
+static SOC_ENUM_SINGLE_EXT_DECL(spk_func_en, spk_function_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_chs, slim_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_chs, slim_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_chs, slim_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_1_tx_chs, slim_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_chs, slim_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_chs, slim_rx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(vi_feed_tx_chs, vi_feed_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_0_rx_sample_rate, slim_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_2_rx_sample_rate, slim_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_0_tx_sample_rate, slim_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_5_rx_sample_rate, slim_sample_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(slim_6_rx_sample_rate, slim_sample_rate_text);
+
+static int slim_get_sample_rate_val(int sample_rate)
+{
+ int sample_rate_val = 0;
+
+ switch (sample_rate) {
+ case SAMPLING_RATE_8KHZ:
+ sample_rate_val = 0;
+ break;
+ case SAMPLING_RATE_16KHZ:
+ sample_rate_val = 1;
+ break;
+ case SAMPLING_RATE_32KHZ:
+ sample_rate_val = 2;
+ break;
+ case SAMPLING_RATE_44P1KHZ:
+ sample_rate_val = 3;
+ break;
+ case SAMPLING_RATE_48KHZ:
+ sample_rate_val = 4;
+ break;
+ case SAMPLING_RATE_88P2KHZ:
+ sample_rate_val = 5;
+ break;
+ case SAMPLING_RATE_96KHZ:
+ sample_rate_val = 6;
+ break;
+ case SAMPLING_RATE_176P4KHZ:
+ sample_rate_val = 7;
+ break;
+ case SAMPLING_RATE_192KHZ:
+ sample_rate_val = 8;
+ break;
+ case SAMPLING_RATE_352P8KHZ:
+ sample_rate_val = 9;
+ break;
+ case SAMPLING_RATE_384KHZ:
+ sample_rate_val = 10;
+ break;
+ default:
+ sample_rate_val = 4;
+ break;
+ }
+ return sample_rate_val;
+}
+
+static int slim_get_sample_rate(int value)
+{
+ int sample_rate = 0;
+
+ switch (value) {
+ case 0:
+ sample_rate = SAMPLING_RATE_8KHZ;
+ break;
+ case 1:
+ sample_rate = SAMPLING_RATE_16KHZ;
+ break;
+ case 2:
+ sample_rate = SAMPLING_RATE_32KHZ;
+ break;
+ case 3:
+ sample_rate = SAMPLING_RATE_44P1KHZ;
+ break;
+ case 4:
+ sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ case 5:
+ sample_rate = SAMPLING_RATE_88P2KHZ;
+ break;
+ case 6:
+ sample_rate = SAMPLING_RATE_96KHZ;
+ break;
+ case 7:
+ sample_rate = SAMPLING_RATE_176P4KHZ;
+ break;
+ case 8:
+ sample_rate = SAMPLING_RATE_192KHZ;
+ break;
+ case 9:
+ sample_rate = SAMPLING_RATE_352P8KHZ;
+ break;
+ case 10:
+ sample_rate = SAMPLING_RATE_384KHZ;
+ break;
+ default:
+ sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ }
+ return sample_rate;
+}
+
+static int slim_get_bit_format_val(int bit_format)
+{
+ int val = 0;
+
+ switch (bit_format) {
+ case SNDRV_PCM_FORMAT_S32_LE:
+ val = 3;
+ break;
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ val = 2;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ val = 1;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
+ val = 0;
+ break;
+ }
+ return val;
+}
+
+static int slim_get_bit_format(int val)
+{
+ int bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
+
+ switch (val) {
+ case 0:
+ bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
+ break;
+ case 1:
+ bit_fmt = SNDRV_PCM_FORMAT_S24_LE;
+ break;
+ case 2:
+ bit_fmt = SNDRV_PCM_FORMAT_S24_3LE;
+ break;
+ case 3:
+ bit_fmt = SNDRV_PCM_FORMAT_S32_LE;
+ break;
+ default:
+ bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
+ break;
+ }
+ return bit_fmt;
+}
+
+static int slim_get_port_idx(struct snd_kcontrol *kcontrol)
+{
+ int port_id = 0;
+
+ if (strnstr(kcontrol->id.name, "SLIM_0_RX", sizeof("SLIM_0_RX")))
+ port_id = SLIM_RX_0;
+ else if (strnstr(kcontrol->id.name, "SLIM_2_RX", sizeof("SLIM_2_RX")))
+ port_id = SLIM_RX_2;
+ else if (strnstr(kcontrol->id.name, "SLIM_5_RX", sizeof("SLIM_5_RX")))
+ port_id = SLIM_RX_5;
+ else if (strnstr(kcontrol->id.name, "SLIM_6_RX", sizeof("SLIM_6_RX")))
+ port_id = SLIM_RX_6;
+ else if (strnstr(kcontrol->id.name, "SLIM_0_TX", sizeof("SLIM_0_TX")))
+ port_id = SLIM_TX_0;
+ else if (strnstr(kcontrol->id.name, "SLIM_1_TX", sizeof("SLIM_1_TX")))
+ port_id = SLIM_TX_1;
+ else {
+ pr_err("%s: unsupported channel: %s",
+ __func__, kcontrol->id.name);
+ return -EINVAL;
+ }
+
+ return port_id;
+}
+
+static int slim_rx_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ ucontrol->value.enumerated.item[0] =
+ slim_get_sample_rate_val(slim_rx_cfg[ch_num].sample_rate);
+
+ pr_debug("%s: slim[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+ ch_num, slim_rx_cfg[ch_num].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_rx_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ slim_rx_cfg[ch_num].sample_rate =
+ slim_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: slim[%d]_rx_sample_rate = %d, item = %d\n", __func__,
+ ch_num, slim_rx_cfg[ch_num].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_tx_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ ucontrol->value.enumerated.item[0] =
+ slim_get_sample_rate_val(slim_tx_cfg[ch_num].sample_rate);
+
+ pr_debug("%s: slim[%d]_tx_sample_rate = %d, item = %d\n", __func__,
+ ch_num, slim_tx_cfg[ch_num].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_tx_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int sample_rate = 0;
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ sample_rate = slim_get_sample_rate(ucontrol->value.enumerated.item[0]);
+ if (sample_rate == SAMPLING_RATE_44P1KHZ) {
+ pr_err("%s: Unsupported sample rate %d: for Tx path\n",
+ __func__, sample_rate);
+ return -EINVAL;
+ }
+ slim_tx_cfg[ch_num].sample_rate = sample_rate;
+
+ pr_debug("%s: slim[%d]_tx_sample_rate = %d, value = %d\n", __func__,
+ ch_num, slim_tx_cfg[ch_num].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_rx_bit_format_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ ucontrol->value.enumerated.item[0] =
+ slim_get_bit_format_val(slim_rx_cfg[ch_num].bit_format);
+
+ pr_debug("%s: slim[%d]_rx_bit_format = %d, ucontrol value = %d\n",
+ __func__, ch_num, slim_rx_cfg[ch_num].bit_format,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_rx_bit_format_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ slim_rx_cfg[ch_num].bit_format =
+ slim_get_bit_format(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: slim[%d]_rx_bit_format = %d, ucontrol value = %d\n",
+ __func__, ch_num, slim_rx_cfg[ch_num].bit_format,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_tx_bit_format_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ ucontrol->value.enumerated.item[0] =
+ slim_get_bit_format_val(slim_tx_cfg[ch_num].bit_format);
+
+ pr_debug("%s: slim[%d]_tx_bit_format = %d, ucontrol value = %d\n",
+ __func__, ch_num, slim_tx_cfg[ch_num].bit_format,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int slim_tx_bit_format_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ slim_tx_cfg[ch_num].bit_format =
+ slim_get_bit_format(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: slim[%d]_tx_bit_format = %d, ucontrol value = %d\n",
+ __func__, ch_num, slim_tx_cfg[ch_num].bit_format,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int msm_slim_rx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ pr_debug("%s: msm_slim_[%d]_rx_ch = %d\n", __func__,
+ ch_num, slim_rx_cfg[ch_num].channels);
+ ucontrol->value.enumerated.item[0] = slim_rx_cfg[ch_num].channels - 1;
+
+ return 0;
+}
+
+static int msm_slim_rx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ slim_rx_cfg[ch_num].channels = ucontrol->value.enumerated.item[0] + 1;
+ pr_debug("%s: msm_slim_[%d]_rx_ch = %d\n", __func__,
+ ch_num, slim_rx_cfg[ch_num].channels);
+
+ return 1;
+}
+
+static int msm_slim_tx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ pr_debug("%s: msm_slim_[%d]_tx_ch = %d\n", __func__,
+ ch_num, slim_tx_cfg[ch_num].channels);
+ ucontrol->value.enumerated.item[0] = slim_tx_cfg[ch_num].channels - 1;
+
+ return 0;
+}
+
+static int msm_slim_tx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = slim_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ slim_tx_cfg[ch_num].channels = ucontrol->value.enumerated.item[0] + 1;
+ pr_debug("%s: msm_slim_[%d]_tx_ch = %d\n", __func__,
+ ch_num, slim_tx_cfg[ch_num].channels);
+
+ return 1;
+}
+
+static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = msm_vi_feed_tx_ch - 1;
+ pr_debug("%s: msm_vi_feed_tx_ch = %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ msm_vi_feed_tx_ch = ucontrol->value.integer.value[0] + 1;
+
+ pr_debug("%s: msm_vi_feed_tx_ch = %d\n", __func__, msm_vi_feed_tx_ch);
+ return 1;
+}
+
+static void *def_ext_mbhc_cal(void)
+{
+ void *tavil_wcd_cal;
+ struct wcd_mbhc_btn_detect_cfg *btn_cfg;
+ u16 *btn_high;
+
+ tavil_wcd_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
+ WCD9XXX_MBHC_DEF_RLOADS), GFP_KERNEL);
+ if (!tavil_wcd_cal)
+ return NULL;
+
+#define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(tavil_wcd_cal)->X) = (Y))
+ S(v_hs_max, 1600);
+#undef S
+#define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(tavil_wcd_cal)->X) = (Y))
+ S(num_btn, WCD_MBHC_DEF_BUTTONS);
+#undef S
+
+ btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(tavil_wcd_cal);
+ btn_high = ((void *)&btn_cfg->_v_btn_low) +
+ (sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
+
+ btn_high[0] = 75;
+ btn_high[1] = 150;
+ btn_high[2] = 237;
+ btn_high[3] = 500;
+ btn_high[4] = 500;
+ btn_high[5] = 500;
+ btn_high[6] = 500;
+ btn_high[7] = 500;
+
+ return tavil_wcd_cal;
+}
+
+static inline int param_is_mask(int p)
+{
+ return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
+ (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
+}
+
+static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
+{
+ return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
+}
+
+
+static void msm_ext_control(struct snd_soc_codec *codec)
+{
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_codec_get_dapm(codec);
+
+ pr_debug("%s: msm_ext_spk_control = %d", __func__, msm_ext_spk_control);
+ if (msm_ext_spk_control == MSMFALCON_SPK_ON) {
+ snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp");
+ snd_soc_dapm_enable_pin(dapm, "Lineout_3 amp");
+ } else {
+ snd_soc_dapm_disable_pin(dapm, "Lineout_1 amp");
+ snd_soc_dapm_disable_pin(dapm, "Lineout_3 amp");
+ }
+ snd_soc_dapm_sync(dapm);
+}
+
+static int msm_ext_get_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: msm_ext_spk_control = %d\n",
+ __func__, msm_ext_spk_control);
+ ucontrol->value.integer.value[0] = msm_ext_spk_control;
+ return 0;
+}
+
+static int msm_ext_set_spk(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ pr_debug("%s()\n", __func__);
+ if (msm_ext_spk_control == ucontrol->value.integer.value[0])
+ return 0;
+
+ msm_ext_spk_control = ucontrol->value.integer.value[0];
+ msm_ext_control(codec);
+ return 1;
+}
+
+
+int msm_ext_enable_codec_mclk(struct snd_soc_codec *codec, int enable,
+ bool dapm)
+{
+ int ret;
+
+ pr_debug("%s: enable = %d\n", __func__, enable);
+
+ if (!strcmp(dev_name(codec->dev), "tasha_codec"))
+ ret = tasha_cdc_mclk_enable(codec, enable, dapm);
+ else if (!strcmp(dev_name(codec->dev), "tavil_codec"))
+ ret = tavil_cdc_mclk_enable(codec, enable);
+ else {
+ dev_err(codec->dev, "%s: unknown codec to enable ext clk\n",
+ __func__);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static const struct snd_kcontrol_new msm_snd_controls[] = {
+ SOC_ENUM_EXT("Speaker Function", spk_func_en, msm_ext_get_spk,
+ msm_ext_set_spk),
+ SOC_ENUM_EXT("SLIM_0_RX Channels", slim_0_rx_chs,
+ msm_slim_rx_ch_get, msm_slim_rx_ch_put),
+ SOC_ENUM_EXT("SLIM_2_RX Channels", slim_2_rx_chs,
+ msm_slim_rx_ch_get, msm_slim_rx_ch_put),
+ SOC_ENUM_EXT("SLIM_0_TX Channels", slim_0_tx_chs,
+ msm_slim_tx_ch_get, msm_slim_tx_ch_put),
+ SOC_ENUM_EXT("SLIM_1_TX Channels", slim_1_tx_chs,
+ msm_slim_tx_ch_get, msm_slim_tx_ch_put),
+ SOC_ENUM_EXT("SLIM_5_RX Channels", slim_5_rx_chs,
+ msm_slim_rx_ch_get, msm_slim_rx_ch_put),
+ SOC_ENUM_EXT("SLIM_6_RX Channels", slim_6_rx_chs,
+ msm_slim_rx_ch_get, msm_slim_rx_ch_put),
+ SOC_ENUM_EXT("VI_FEED_TX Channels", vi_feed_tx_chs,
+ msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
+ SOC_ENUM_EXT("SLIM_0_RX Format", slim_0_rx_format,
+ slim_rx_bit_format_get, slim_rx_bit_format_put),
+ SOC_ENUM_EXT("SLIM_5_RX Format", slim_5_rx_format,
+ slim_rx_bit_format_get, slim_rx_bit_format_put),
+ SOC_ENUM_EXT("SLIM_6_RX Format", slim_6_rx_format,
+ slim_rx_bit_format_get, slim_rx_bit_format_put),
+ SOC_ENUM_EXT("SLIM_0_TX Format", slim_0_tx_format,
+ slim_tx_bit_format_get, slim_tx_bit_format_put),
+ SOC_ENUM_EXT("SLIM_0_RX SampleRate", slim_0_rx_sample_rate,
+ slim_rx_sample_rate_get, slim_rx_sample_rate_put),
+ SOC_ENUM_EXT("SLIM_2_RX SampleRate", slim_2_rx_sample_rate,
+ slim_rx_sample_rate_get, slim_rx_sample_rate_put),
+ SOC_ENUM_EXT("SLIM_0_TX SampleRate", slim_0_tx_sample_rate,
+ slim_tx_sample_rate_get, slim_tx_sample_rate_put),
+ SOC_ENUM_EXT("SLIM_5_RX SampleRate", slim_5_rx_sample_rate,
+ slim_rx_sample_rate_get, slim_rx_sample_rate_put),
+ SOC_ENUM_EXT("SLIM_6_RX SampleRate", slim_6_rx_sample_rate,
+ slim_rx_sample_rate_get, slim_rx_sample_rate_put),
+};
+
+static int msm_slim_get_ch_from_beid(int32_t be_id)
+{
+ int ch_id = 0;
+
+ switch (be_id) {
+ case MSM_BACKEND_DAI_SLIMBUS_0_RX:
+ ch_id = SLIM_RX_0;
+ break;
+ case MSM_BACKEND_DAI_SLIMBUS_1_RX:
+ ch_id = SLIM_RX_1;
+ break;
+ case MSM_BACKEND_DAI_SLIMBUS_2_RX:
+ ch_id = SLIM_RX_2;
+ break;
+ case MSM_BACKEND_DAI_SLIMBUS_3_RX:
+ ch_id = SLIM_RX_3;
+ break;
+ case MSM_BACKEND_DAI_SLIMBUS_4_RX:
+ ch_id = SLIM_RX_4;
+ break;
+ case MSM_BACKEND_DAI_SLIMBUS_6_RX:
+ ch_id = SLIM_RX_6;
+ break;
+ case MSM_BACKEND_DAI_SLIMBUS_0_TX:
+ ch_id = SLIM_TX_0;
+ break;
+ case MSM_BACKEND_DAI_SLIMBUS_3_TX:
+ ch_id = SLIM_TX_3;
+ break;
+ default:
+ ch_id = SLIM_RX_0;
+ break;
+ }
+
+ return ch_id;
+}
+
+static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit)
+{
+ if (bit >= SNDRV_MASK_MAX)
+ return;
+ if (param_is_mask(n)) {
+ struct snd_mask *m = param_to_mask(p, n);
+
+ m->bits[0] = 0;
+ m->bits[1] = 0;
+ m->bits[bit >> 5] |= (1 << (bit & 31));
+ }
+}
+
+/**
+ * msm_ext_be_hw_params_fixup - updates settings of ALSA BE hw params.
+ *
+ * @rtd: runtime dailink instance
+ * @params: HW params of associated backend dailink.
+ *
+ * Returns 0 on success or rc on failure.
+ */
+int msm_ext_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ 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);
+ int rc = 0;
+ int idx;
+ void *config = NULL;
+ struct snd_soc_codec *codec = rtd->codec;
+
+ pr_debug("%s: format = %d, rate = %d\n",
+ __func__, params_format(params), params_rate(params));
+
+ switch (dai_link->be_id) {
+ case MSM_BACKEND_DAI_SLIMBUS_0_RX:
+ case MSM_BACKEND_DAI_SLIMBUS_1_RX:
+ case MSM_BACKEND_DAI_SLIMBUS_2_RX:
+ case MSM_BACKEND_DAI_SLIMBUS_3_RX:
+ case MSM_BACKEND_DAI_SLIMBUS_4_RX:
+ case MSM_BACKEND_DAI_SLIMBUS_6_RX:
+ idx = msm_slim_get_ch_from_beid(dai_link->be_id);
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ slim_rx_cfg[idx].bit_format);
+ rate->min = rate->max = slim_rx_cfg[idx].sample_rate;
+ channels->min = channels->max = slim_rx_cfg[idx].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_0_TX:
+ case MSM_BACKEND_DAI_SLIMBUS_3_TX:
+ idx = msm_slim_get_ch_from_beid(dai_link->be_id);
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ slim_tx_cfg[idx].bit_format);
+ rate->min = rate->max = slim_tx_cfg[idx].sample_rate;
+ channels->min = channels->max = slim_tx_cfg[idx].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_1_TX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ slim_tx_cfg[1].bit_format);
+ rate->min = rate->max = slim_tx_cfg[1].sample_rate;
+ channels->min = channels->max = slim_tx_cfg[1].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_4_TX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ SNDRV_PCM_FORMAT_S32_LE);
+ rate->min = rate->max = SAMPLING_RATE_8KHZ;
+ channels->min = channels->max = msm_vi_feed_tx_ch;
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_5_RX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ slim_rx_cfg[5].bit_format);
+ rate->min = rate->max = slim_rx_cfg[5].sample_rate;
+ channels->min = channels->max = slim_rx_cfg[5].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_5_TX:
+ rate->min = rate->max = SAMPLING_RATE_16KHZ;
+ channels->min = channels->max = 1;
+
+ config = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_SLIMBUS_SLAVE_PORT_CONFIG);
+ if (config) {
+ rc = afe_set_config(AFE_SLIMBUS_SLAVE_PORT_CONFIG,
+ config, SLIMBUS_5_TX);
+ if (rc)
+ pr_err("%s: Failed to set slimbus slave port config %d\n",
+ __func__, rc);
+ }
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_7_RX:
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ slim_rx_cfg[SLIM_RX_7].bit_format);
+ rate->min = rate->max = slim_rx_cfg[SLIM_RX_7].sample_rate;
+ channels->min = channels->max =
+ slim_rx_cfg[SLIM_RX_7].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_7_TX:
+ rate->min = rate->max = slim_tx_cfg[SLIM_TX_7].sample_rate;
+ channels->min = channels->max =
+ slim_tx_cfg[SLIM_TX_7].channels;
+ break;
+
+ case MSM_BACKEND_DAI_SLIMBUS_8_TX:
+ rate->min = rate->max = slim_tx_cfg[SLIM_TX_8].sample_rate;
+ channels->min = channels->max =
+ slim_tx_cfg[SLIM_TX_8].channels;
+ break;
+
+ default:
+ rate->min = rate->max = SAMPLING_RATE_48KHZ;
+ break;
+ }
+ return rc;
+}
+EXPORT_SYMBOL(msm_ext_be_hw_params_fixup);
+
+/**
+ * msm_snd_hw_params - hw params ops of backend dailink.
+ *
+ * @substream: PCM stream of associated backend dailink.
+ * @params: HW params of associated backend dailink.
+ *
+ * Returns 0 on success or ret on failure.
+ */
+int msm_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 *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+
+ int ret = 0;
+ u32 rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+ u32 rx_ch_cnt = 0, tx_ch_cnt = 0;
+ u32 user_set_tx_ch = 0;
+ u32 rx_ch_count;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map, err:%d\n",
+ __func__, ret);
+ goto err_ch_map;
+ }
+ if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_5_RX) {
+ pr_debug("%s: rx_5_ch=%d\n", __func__,
+ slim_rx_cfg[5].channels);
+ rx_ch_count = slim_rx_cfg[5].channels;
+ } else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_2_RX) {
+ pr_debug("%s: rx_2_ch=%d\n", __func__,
+ slim_rx_cfg[2].channels);
+ rx_ch_count = slim_rx_cfg[2].channels;
+ } else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_6_RX) {
+ pr_debug("%s: rx_6_ch=%d\n", __func__,
+ slim_rx_cfg[6].channels);
+ rx_ch_count = slim_rx_cfg[6].channels;
+ } else {
+ pr_debug("%s: rx_0_ch=%d\n", __func__,
+ slim_rx_cfg[0].channels);
+ rx_ch_count = slim_rx_cfg[0].channels;
+ }
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+ rx_ch_count, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to set cpu chan map, err:%d\n",
+ __func__, ret);
+ goto err_ch_map;
+ }
+ } else {
+ pr_debug("%s: %s_tx_dai_id_%d_ch=%d\n", __func__,
+ codec_dai->name, codec_dai->id, user_set_tx_ch);
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map\n, err:%d\n",
+ __func__, ret);
+ goto err_ch_map;
+ }
+ /* For <codec>_tx1 case */
+ if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_0_TX)
+ user_set_tx_ch = slim_tx_cfg[0].channels;
+ /* For <codec>_tx3 case */
+ else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_1_TX)
+ user_set_tx_ch = slim_tx_cfg[1].channels;
+ else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_4_TX)
+ user_set_tx_ch = msm_vi_feed_tx_ch;
+ else
+ user_set_tx_ch = tx_ch_cnt;
+
+ pr_debug("%s: msm_slim_0_tx_ch(%d) user_set_tx_ch(%d) tx_ch_cnt(%d), be_id (%d)\n",
+ __func__, slim_tx_cfg[0].channels, user_set_tx_ch,
+ tx_ch_cnt, dai_link->be_id);
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai,
+ user_set_tx_ch, tx_ch, 0, 0);
+ if (ret < 0)
+ pr_err("%s: failed to set cpu chan map, err:%d\n",
+ __func__, ret);
+ }
+
+err_ch_map:
+ return ret;
+}
+EXPORT_SYMBOL(msm_snd_hw_params);
+
+/**
+ * msm_ext_slimbus_2_hw_params - hw params ops of slimbus_2 BE.
+ *
+ * @substream: PCM stream of associated backend dailink.
+ * @params: HW params of associated backend dailink.
+ *
+ * Returns 0 on success or ret on failure.
+ */
+int msm_ext_slimbus_2_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 *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret = 0;
+ unsigned int rx_ch[SLIM_MAX_RX_PORTS], tx_ch[SLIM_MAX_TX_PORTS];
+ unsigned int rx_ch_cnt = 0, tx_ch_cnt = 0;
+ unsigned int num_tx_ch = 0;
+ unsigned int num_rx_ch = 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ num_rx_ch = params_channels(params);
+ pr_debug("%s: %s rx_dai_id = %d num_ch = %d\n", __func__,
+ codec_dai->name, codec_dai->id, num_rx_ch);
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 0, 0,
+ num_rx_ch, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to set cpu chan map, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+ } else {
+ num_tx_ch = params_channels(params);
+ pr_debug("%s: %s tx_dai_id = %d num_ch = %d\n", __func__,
+ codec_dai->name, codec_dai->id, num_tx_ch);
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, &rx_ch_cnt, rx_ch);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+ ret = snd_soc_dai_set_channel_map(cpu_dai,
+ num_tx_ch, tx_ch, 0, 0);
+ if (ret < 0) {
+ pr_err("%s: failed to set cpu chan map, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+ }
+end:
+ return ret;
+}
+EXPORT_SYMBOL(msm_ext_slimbus_2_hw_params);
+
+/**
+ * msm_snd_cpe_hw_params - hw params ops of CPE backend.
+ *
+ * @substream: PCM stream of associated backend dailink.
+ * @params: HW params of associated backend dailink.
+ *
+ * Returns 0 on success or ret on failure.
+ */
+int msm_snd_cpe_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 *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ int ret = 0;
+ u32 tx_ch[SLIM_MAX_TX_PORTS];
+ u32 tx_ch_cnt = 0;
+
+ if (substream->stream != SNDRV_PCM_STREAM_CAPTURE) {
+ pr_err("%s: Invalid stream type %d\n",
+ __func__, substream->stream);
+ ret = -EINVAL;
+ goto end;
+ }
+
+ pr_debug("%s: %s_tx_dai_id_%d\n", __func__,
+ codec_dai->name, codec_dai->id);
+ ret = snd_soc_dai_get_channel_map(codec_dai,
+ &tx_ch_cnt, tx_ch, NULL, NULL);
+ if (ret < 0) {
+ pr_err("%s: failed to get codec chan map\n, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+
+ pr_debug("%s: tx_ch_cnt(%d) be_id %d\n",
+ __func__, tx_ch_cnt, dai_link->be_id);
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai,
+ tx_ch_cnt, tx_ch, 0, 0);
+ if (ret < 0) {
+ pr_err("%s: failed to set cpu chan map, err:%d\n",
+ __func__, ret);
+ goto end;
+ }
+end:
+ return ret;
+}
+EXPORT_SYMBOL(msm_snd_cpe_hw_params);
+
+static int msm_afe_set_config(struct snd_soc_codec *codec)
+{
+ int rc;
+ void *config_data;
+
+ pr_debug("%s: enter\n", __func__);
+
+ if (!msm_codec_fn.get_afe_config_fn) {
+ dev_err(codec->dev, "%s: codec get afe config not init'ed\n",
+ __func__);
+ return -EINVAL;
+ }
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_CDC_REGISTERS_CONFIG);
+ if (config_data) {
+ rc = afe_set_config(AFE_CDC_REGISTERS_CONFIG, config_data, 0);
+ if (rc) {
+ pr_err("%s: Failed to set codec registers config %d\n",
+ __func__, rc);
+ return rc;
+ }
+ }
+
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_CDC_REGISTER_PAGE_CONFIG);
+ if (config_data) {
+ rc = afe_set_config(AFE_CDC_REGISTER_PAGE_CONFIG, config_data,
+ 0);
+ if (rc)
+ pr_err("%s: Failed to set cdc register page config\n",
+ __func__);
+ }
+
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_SLIMBUS_SLAVE_CONFIG);
+ if (config_data) {
+ rc = afe_set_config(AFE_SLIMBUS_SLAVE_CONFIG, config_data, 0);
+ if (rc) {
+ pr_err("%s: Failed to set slimbus slave config %d\n",
+ __func__, rc);
+ return rc;
+ }
+ }
+
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_AANC_VERSION);
+ if (config_data) {
+ rc = afe_set_config(AFE_AANC_VERSION, config_data, 0);
+ if (rc) {
+ pr_err("%s: Failed to set AANC version %d\n",
+ __func__, rc);
+ return rc;
+ }
+ }
+
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_CDC_CLIP_REGISTERS_CONFIG);
+ if (config_data) {
+ rc = afe_set_config(AFE_CDC_CLIP_REGISTERS_CONFIG,
+ config_data, 0);
+ if (rc) {
+ pr_err("%s: Failed to set clip registers %d\n",
+ __func__, rc);
+ return rc;
+ }
+ }
+
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_CLIP_BANK_SEL);
+ if (config_data) {
+ rc = afe_set_config(AFE_CLIP_BANK_SEL,
+ config_data, 0);
+ if (rc) {
+ pr_err("%s: Failed to set AFE bank selection %d\n",
+ __func__, rc);
+ return rc;
+ }
+ }
+
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_CDC_REGISTER_PAGE_CONFIG);
+ if (config_data) {
+ rc = afe_set_config(AFE_CDC_REGISTER_PAGE_CONFIG, config_data,
+ 0);
+ if (rc)
+ pr_err("%s: Failed to set cdc register page config\n",
+ __func__);
+ }
+
+ return 0;
+}
+
+static void msm_afe_clear_config(void)
+{
+ afe_clear_config(AFE_CDC_REGISTERS_CONFIG);
+ afe_clear_config(AFE_SLIMBUS_SLAVE_CONFIG);
+}
+
+static int msm_adsp_power_up_config(struct snd_soc_codec *codec)
+{
+ int ret = 0;
+ unsigned long timeout;
+ int adsp_ready = 0;
+
+ timeout = jiffies +
+ msecs_to_jiffies(ADSP_STATE_READY_TIMEOUT_MS);
+
+ do {
+ if (q6core_is_adsp_ready()) {
+ pr_debug("%s: ADSP Audio is ready\n", __func__);
+ adsp_ready = 1;
+ break;
+ }
+ /*
+ * ADSP will be coming up after subsystem restart and
+ * it might not be fully up when the control reaches
+ * here. So, wait for 50msec before checking ADSP state
+ */
+ msleep(50);
+ } while (time_after(timeout, jiffies));
+
+ if (!adsp_ready) {
+ pr_err("%s: timed out waiting for ADSP Audio\n", __func__);
+ ret = -ETIMEDOUT;
+ goto err_fail;
+ }
+
+ ret = msm_afe_set_config(codec);
+ if (ret)
+ pr_err("%s: Failed to set AFE config. err %d\n",
+ __func__, ret);
+
+ return 0;
+
+err_fail:
+ return ret;
+}
+
+static int msmfalcon_notifier_service_cb(struct notifier_block *this,
+ unsigned long opcode, void *ptr)
+{
+ int ret;
+ struct snd_soc_card *card = NULL;
+ const char *be_dl_name = LPASS_BE_SLIMBUS_0_RX;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_codec *codec;
+
+ pr_debug("%s: Service opcode 0x%lx\n", __func__, opcode);
+
+ switch (opcode) {
+ case AUDIO_NOTIFIER_SERVICE_DOWN:
+ /*
+ * Use flag to ignore initial boot notifications
+ * On initial boot msm_adsp_power_up_config is
+ * called on init. There is no need to clear
+ * and set the config again on initial boot.
+ */
+ if (is_initial_boot)
+ break;
+ msm_afe_clear_config();
+ break;
+ case AUDIO_NOTIFIER_SERVICE_UP:
+ if (is_initial_boot) {
+ is_initial_boot = false;
+ break;
+ }
+ if (!spdev)
+ return -EINVAL;
+
+ card = platform_get_drvdata(spdev);
+ rtd = snd_soc_get_pcm_runtime(card, be_dl_name);
+ if (!rtd) {
+ dev_err(card->dev,
+ "%s: snd_soc_get_pcm_runtime for %s failed!\n",
+ __func__, be_dl_name);
+ ret = -EINVAL;
+ goto done;
+ }
+ codec = rtd->codec;
+
+ ret = msm_adsp_power_up_config(codec);
+ if (ret < 0) {
+ dev_err(card->dev,
+ "%s: msm_adsp_power_up_config failed ret = %d!\n",
+ __func__, ret);
+ goto done;
+ }
+ break;
+ default:
+ break;
+ }
+done:
+ return NOTIFY_OK;
+}
+
+static struct notifier_block service_nb = {
+ .notifier_call = msmfalcon_notifier_service_cb,
+ .priority = -INT_MAX,
+};
+
+static int msm_config_hph_en0_gpio(struct snd_soc_codec *codec, bool high)
+{
+ struct snd_soc_card *card = codec->component.card;
+ struct msm_asoc_mach_data *pdata;
+ int val;
+
+ if (!card)
+ return 0;
+
+ pdata = snd_soc_card_get_drvdata(card);
+ if (!pdata || !gpio_is_valid(pdata->hph_en0_gpio))
+ return 0;
+
+ val = gpio_get_value_cansleep(pdata->hph_en0_gpio);
+ if ((!!val) == high)
+ return 0;
+
+ gpio_direction_output(pdata->hph_en0_gpio, (int)high);
+
+ return 1;
+}
+
+static int msm_snd_enable_codec_ext_tx_clk(struct snd_soc_codec *codec,
+ int enable, bool dapm)
+{
+ int ret = 0;
+
+ if (!strcmp(dev_name(codec->dev), "tasha_codec"))
+ ret = tasha_cdc_mclk_tx_enable(codec, enable, dapm);
+ else {
+ dev_err(codec->dev, "%s: unknown codec to enable ext clk\n",
+ __func__);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+static int msm_ext_mclk_tx_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ pr_debug("%s: event = %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ return msm_snd_enable_codec_ext_tx_clk(codec, 1, true);
+ case SND_SOC_DAPM_POST_PMD:
+ return msm_snd_enable_codec_ext_tx_clk(codec, 0, true);
+ }
+ return 0;
+}
+
+static int msm_ext_mclk_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ pr_debug("%s: event = %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ return msm_ext_enable_codec_mclk(codec, 1, true);
+ case SND_SOC_DAPM_POST_PMD:
+ return msm_ext_enable_codec_mclk(codec, 0, true);
+ }
+ return 0;
+}
+
+static int msm_ext_prepare_hifi(struct msm_asoc_mach_data *pdata)
+{
+ int ret = 0;
+
+ if (gpio_is_valid(pdata->hph_en1_gpio)) {
+ pr_debug("%s: hph_en1_gpio request %d\n", __func__,
+ pdata->hph_en1_gpio);
+ ret = gpio_request(pdata->hph_en1_gpio, "hph_en1_gpio");
+ if (ret) {
+ pr_err("%s: hph_en1_gpio request failed, ret:%d\n",
+ __func__, ret);
+ goto err;
+ }
+ }
+ if (gpio_is_valid(pdata->hph_en0_gpio)) {
+ pr_debug("%s: hph_en0_gpio request %d\n", __func__,
+ pdata->hph_en0_gpio);
+ ret = gpio_request(pdata->hph_en0_gpio, "hph_en0_gpio");
+ if (ret)
+ pr_err("%s: hph_en0_gpio request failed, ret:%d\n",
+ __func__, ret);
+ }
+
+err:
+ return ret;
+}
+
+static const struct snd_soc_dapm_widget msm_dapm_widgets[] = {
+
+ SND_SOC_DAPM_SUPPLY_S("MCLK", -1, SND_SOC_NOPM, 0, 0,
+ msm_ext_mclk_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("MCLK TX", -1, SND_SOC_NOPM, 0, 0,
+ msm_ext_mclk_tx_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SPK("Lineout_1 amp", NULL),
+ SND_SOC_DAPM_SPK("Lineout_3 amp", NULL),
+ SND_SOC_DAPM_SPK("Lineout_2 amp", NULL),
+ SND_SOC_DAPM_SPK("Lineout_4 amp", NULL),
+ SND_SOC_DAPM_MIC("Handset Mic", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Secondary Mic", NULL),
+ SND_SOC_DAPM_MIC("ANCRight Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("ANCLeft Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Analog Mic4", NULL),
+ SND_SOC_DAPM_MIC("Analog Mic6", NULL),
+ SND_SOC_DAPM_MIC("Analog Mic7", NULL),
+ SND_SOC_DAPM_MIC("Analog Mic8", NULL),
+
+ SND_SOC_DAPM_MIC("Digital Mic0", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic1", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic2", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic3", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic4", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic5", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic6", NULL),
+};
+
+static struct snd_soc_dapm_route wcd_audio_paths_tasha[] = {
+ {"MIC BIAS1", NULL, "MCLK TX"},
+ {"MIC BIAS2", NULL, "MCLK TX"},
+ {"MIC BIAS3", NULL, "MCLK TX"},
+ {"MIC BIAS4", NULL, "MCLK TX"},
+};
+
+static struct snd_soc_dapm_route wcd_audio_paths[] = {
+ {"MIC BIAS1", NULL, "MCLK"},
+ {"MIC BIAS2", NULL, "MCLK"},
+ {"MIC BIAS3", NULL, "MCLK"},
+ {"MIC BIAS4", NULL, "MCLK"},
+};
+
+/**
+ * msm_audrx_init - Audio init function of sound card instantiate.
+ *
+ * @rtd: runtime dailink instance
+ *
+ * Returns 0 on success or ret on failure.
+ */
+int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
+{
+ int ret;
+ void *config_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_codec_get_dapm(codec);
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_pcm_runtime *rtd_aux = rtd->card->rtd_aux;
+ struct snd_card *card;
+ struct snd_info_entry *entry;
+ struct msm_asoc_mach_data *pdata =
+ snd_soc_card_get_drvdata(rtd->card);
+
+ /* Codec SLIMBUS configuration
+ * RX1, RX2, RX3, RX4, RX5, RX6, RX7, RX8, RX9, RX10, RX11, RX12, RX13
+ * TX1, TX2, TX3, TX4, TX5, TX6, TX7, TX8, TX9, TX10, TX11, TX12, TX13
+ * TX14, TX15, TX16
+ */
+ unsigned int rx_ch[TASHA_RX_MAX] = {144, 145, 146, 147, 148, 149, 150,
+ 151, 152, 153, 154, 155, 156};
+ unsigned int tx_ch[TASHA_TX_MAX] = {128, 129, 130, 131, 132, 133,
+ 134, 135, 136, 137, 138, 139,
+ 140, 141, 142, 143};
+
+ pr_debug("%s: dev_name%s\n", __func__, dev_name(cpu_dai->dev));
+
+ rtd->pmdown_time = 0;
+
+ ret = snd_soc_add_codec_controls(codec, msm_snd_controls,
+ ARRAY_SIZE(msm_snd_controls));
+ if (ret < 0) {
+ pr_err("%s: add_codec_controls failed: %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ snd_soc_dapm_new_controls(dapm, msm_dapm_widgets,
+ ARRAY_SIZE(msm_dapm_widgets));
+
+ if (!strcmp(dev_name(codec_dai->dev), "tasha_codec"))
+ snd_soc_dapm_add_routes(dapm, wcd_audio_paths_tasha,
+ ARRAY_SIZE(wcd_audio_paths_tasha));
+ else
+ snd_soc_dapm_add_routes(dapm, wcd_audio_paths,
+ ARRAY_SIZE(wcd_audio_paths));
+
+ snd_soc_dapm_enable_pin(dapm, "Lineout_1 amp");
+ snd_soc_dapm_enable_pin(dapm, "Lineout_3 amp");
+ snd_soc_dapm_enable_pin(dapm, "Lineout_2 amp");
+ snd_soc_dapm_enable_pin(dapm, "Lineout_4 amp");
+
+ snd_soc_dapm_ignore_suspend(dapm, "MADINPUT");
+ snd_soc_dapm_ignore_suspend(dapm, "MAD_CPE_INPUT");
+ snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "Secondary Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "Lineout_1 amp");
+ snd_soc_dapm_ignore_suspend(dapm, "Lineout_3 amp");
+ snd_soc_dapm_ignore_suspend(dapm, "Lineout_2 amp");
+ snd_soc_dapm_ignore_suspend(dapm, "Lineout_4 amp");
+ snd_soc_dapm_ignore_suspend(dapm, "ANCRight Headset Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "ANCLeft Headset Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic0");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic3");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic4");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic5");
+ snd_soc_dapm_ignore_suspend(dapm, "Analog Mic4");
+ snd_soc_dapm_ignore_suspend(dapm, "Analog Mic6");
+ snd_soc_dapm_ignore_suspend(dapm, "Analog Mic7");
+ snd_soc_dapm_ignore_suspend(dapm, "Analog Mic8");
+
+ snd_soc_dapm_ignore_suspend(dapm, "EAR");
+ snd_soc_dapm_ignore_suspend(dapm, "LINEOUT1");
+ snd_soc_dapm_ignore_suspend(dapm, "LINEOUT2");
+ snd_soc_dapm_ignore_suspend(dapm, "LINEOUT3");
+ snd_soc_dapm_ignore_suspend(dapm, "LINEOUT4");
+ snd_soc_dapm_ignore_suspend(dapm, "AMIC1");
+ snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
+ snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
+ snd_soc_dapm_ignore_suspend(dapm, "AMIC4");
+ snd_soc_dapm_ignore_suspend(dapm, "AMIC5");
+ snd_soc_dapm_ignore_suspend(dapm, "AMIC6");
+ snd_soc_dapm_ignore_suspend(dapm, "DMIC0");
+ snd_soc_dapm_ignore_suspend(dapm, "DMIC1");
+ snd_soc_dapm_ignore_suspend(dapm, "DMIC2");
+ snd_soc_dapm_ignore_suspend(dapm, "DMIC3");
+ snd_soc_dapm_ignore_suspend(dapm, "DMIC4");
+ snd_soc_dapm_ignore_suspend(dapm, "DMIC5");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC EAR");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC HEADPHONE");
+ snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT");
+ snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT");
+ snd_soc_dapm_ignore_suspend(dapm, "HPHL");
+ snd_soc_dapm_ignore_suspend(dapm, "HPHR");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC HPHL");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC HPHR");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT1");
+ snd_soc_dapm_ignore_suspend(dapm, "ANC LINEOUT2");
+ snd_soc_dapm_ignore_suspend(dapm, "AIF4 VI");
+ snd_soc_dapm_ignore_suspend(dapm, "VIINPUT");
+
+ snd_soc_dapm_sync(dapm);
+ snd_soc_dai_set_channel_map(codec_dai, ARRAY_SIZE(tx_ch),
+ tx_ch, ARRAY_SIZE(rx_ch), rx_ch);
+
+ if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
+ msm_codec_fn.get_afe_config_fn = tavil_get_afe_config;
+ } else {
+ msm_codec_fn.get_afe_config_fn = tasha_get_afe_config;
+ msm_codec_fn.mbhc_hs_detect_exit = tasha_mbhc_hs_detect_exit;
+ }
+
+ ret = msm_adsp_power_up_config(codec);
+ if (ret) {
+ pr_err("%s: Failed to set AFE config %d\n", __func__, ret);
+ goto err_afe_cfg;
+ }
+
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_AANC_VERSION);
+ if (config_data) {
+ ret = afe_set_config(AFE_AANC_VERSION, config_data, 0);
+ if (ret) {
+ pr_err("%s: Failed to set aanc version %d\n",
+ __func__, ret);
+ goto err_afe_cfg;
+ }
+ }
+
+ if (!strcmp(dev_name(codec_dai->dev), "tasha_codec")) {
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_CDC_CLIP_REGISTERS_CONFIG);
+ if (config_data) {
+ ret = afe_set_config(AFE_CDC_CLIP_REGISTERS_CONFIG,
+ config_data, 0);
+ if (ret) {
+ pr_err("%s: Failed to set clip registers %d\n",
+ __func__, ret);
+ goto err_afe_cfg;
+ }
+ }
+ config_data = msm_codec_fn.get_afe_config_fn(codec,
+ AFE_CLIP_BANK_SEL);
+ if (config_data) {
+ ret = afe_set_config(AFE_CLIP_BANK_SEL, config_data, 0);
+ if (ret) {
+ pr_err("%s: Failed to set AFE bank selection %d\n",
+ __func__, ret);
+ goto err_afe_cfg;
+ }
+ }
+ }
+
+ /*
+ * Send speaker configuration only for WSA8810.
+ * Defalut configuration is for WSA8815.
+ */
+ if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
+ if (rtd_aux && rtd_aux->component)
+ if (!strcmp(rtd_aux->component->name, WSA8810_NAME_1) ||
+ !strcmp(rtd_aux->component->name, WSA8810_NAME_2)) {
+ tavil_set_spkr_mode(rtd->codec, SPKR_MODE_1);
+ tavil_set_spkr_gain_offset(rtd->codec,
+ RX_GAIN_OFFSET_M1P5_DB);
+ }
+ card = rtd->card->snd_card;
+ entry = snd_register_module_info(card->module, "codecs",
+ card->proc_root);
+ if (!entry) {
+ pr_debug("%s: Cannot create codecs module entry\n",
+ __func__);
+ pdata->codec_root = NULL;
+ goto done;
+ }
+ pdata->codec_root = entry;
+ tavil_codec_info_create_codec_entry(pdata->codec_root, codec);
+ } else {
+ if (rtd_aux && rtd_aux->component)
+ if (!strcmp(rtd_aux->component->name, WSA8810_NAME_1) ||
+ !strcmp(rtd_aux->component->name, WSA8810_NAME_2)) {
+ tasha_set_spkr_mode(rtd->codec, SPKR_MODE_1);
+ tasha_set_spkr_gain_offset(rtd->codec,
+ RX_GAIN_OFFSET_M1P5_DB);
+ }
+ card = rtd->card->snd_card;
+ entry = snd_register_module_info(card->module, "codecs",
+ card->proc_root);
+ if (!entry) {
+ pr_debug("%s: Cannot create codecs module entry\n",
+ __func__);
+ ret = 0;
+ goto err_snd_module;
+ }
+ pdata->codec_root = entry;
+ tasha_codec_info_create_codec_entry(pdata->codec_root, codec);
+ tasha_mbhc_zdet_gpio_ctrl(msm_config_hph_en0_gpio, rtd->codec);
+ }
+
+ wcd_mbhc_cfg_ptr->calibration = def_ext_mbhc_cal();
+ if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
+ if (wcd_mbhc_cfg_ptr->calibration) {
+ pdata->codec = codec;
+ ret = tavil_mbhc_hs_detect(codec, wcd_mbhc_cfg_ptr);
+ if (ret < 0)
+ pr_err("%s: Failed to intialise mbhc %d\n",
+ __func__, ret);
+ } else {
+ pr_err("%s: wcd_mbhc_cfg calibration is NULL\n",
+ __func__);
+ ret = -ENOMEM;
+ goto err_mbhc_cal;
+ }
+ } else {
+ if (wcd_mbhc_cfg_ptr->calibration) {
+ pdata->codec = codec;
+ ret = tasha_mbhc_hs_detect(codec, wcd_mbhc_cfg_ptr);
+ if (ret < 0)
+ pr_err("%s: Failed to intialise mbhc %d\n",
+ __func__, ret);
+ } else {
+ pr_err("%s: wcd_mbhc_cfg calibration is NULL\n",
+ __func__);
+ ret = -ENOMEM;
+ goto err_mbhc_cal;
+ }
+
+ }
+done:
+ return 0;
+
+err_snd_module:
+err_afe_cfg:
+err_mbhc_cal:
+ return ret;
+}
+EXPORT_SYMBOL(msm_audrx_init);
+
+/**
+ * msm_ext_cdc_init - external codec machine specific init.
+ *
+ * @pdev: platform device handle
+ * @pdata: private data of machine driver
+ * @card: sound card pointer reference
+ * @mbhc_cfg: MBHC config reference
+ *
+ * Returns 0 on success or ret on failure.
+ */
+int msm_ext_cdc_init(struct platform_device *pdev,
+ struct msm_asoc_mach_data *pdata,
+ struct snd_soc_card **card,
+ struct wcd_mbhc_config *wcd_mbhc_cfg_ptr1)
+{
+ int ret = 0;
+
+ wcd_mbhc_cfg_ptr = wcd_mbhc_cfg_ptr1;
+ pdev->id = 0;
+ wcd_mbhc_cfg_ptr->moisture_en = true;
+ wcd_mbhc_cfg_ptr->mbhc_micbias = MIC_BIAS_2;
+ wcd_mbhc_cfg_ptr->anc_micbias = MIC_BIAS_2;
+ wcd_mbhc_cfg_ptr->enable_anc_mic_detect = false;
+
+ *card = populate_snd_card_dailinks(&pdev->dev);
+ if (!(*card)) {
+ dev_err(&pdev->dev, "%s: Card uninitialized\n", __func__);
+ ret = -EPROBE_DEFER;
+ goto err;
+ }
+ (*card)->dev = &pdev->dev;
+ spdev = pdev;
+ platform_set_drvdata(pdev, *card);
+ snd_soc_card_set_drvdata(*card, pdata);
+ is_initial_boot = true;
+ ret = audio_notifier_register("msmfalcon", AUDIO_NOTIFIER_ADSP_DOMAIN,
+ &service_nb);
+ if (ret < 0) {
+ pr_err("%s: Audio notifier register failed ret = %d\n",
+ __func__, ret);
+ goto err;
+ }
+ pdata->hph_en1_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,hph-en1-gpio", 0);
+ if (!gpio_is_valid(pdata->hph_en1_gpio))
+ pdata->hph_en1_gpio_p = of_parse_phandle(pdev->dev.of_node,
+ "qcom,hph-en1-gpio", 0);
+ if (!gpio_is_valid(pdata->hph_en1_gpio) && (!pdata->hph_en1_gpio_p)) {
+ dev_dbg(&pdev->dev, "property %s not detected in node %s",
+ "qcom,hph-en1-gpio", pdev->dev.of_node->full_name);
+ }
+
+ pdata->hph_en0_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,hph-en0-gpio", 0);
+ if (!gpio_is_valid(pdata->hph_en0_gpio))
+ pdata->hph_en0_gpio_p = of_parse_phandle(pdev->dev.of_node,
+ "qcom,hph-en0-gpio", 0);
+ if (!gpio_is_valid(pdata->hph_en0_gpio) && (!pdata->hph_en0_gpio_p)) {
+ dev_dbg(&pdev->dev, "property %s not detected in node %s",
+ "qcom,hph-en0-gpio", pdev->dev.of_node->full_name);
+ }
+
+ ret = msm_ext_prepare_hifi(pdata);
+ if (ret) {
+ dev_dbg(&pdev->dev, "msm_ext_prepare_hifi failed (%d)\n",
+ ret);
+ ret = 0;
+ }
+err:
+ return ret;
+}
+EXPORT_SYMBOL(msm_ext_cdc_init);
diff --git a/sound/soc/msm/msmfalcon-external.h b/sound/soc/msm/msmfalcon-external.h
new file mode 100644
index 000000000000..24aa7ea53a09
--- /dev/null
+++ b/sound/soc/msm/msmfalcon-external.h
@@ -0,0 +1,44 @@
+/* Copyright (c) 2015-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 __MSMFALCON_EXTERNAL
+#define __MSMFALCON_EXTERNAL
+
+int msm_snd_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params);
+int msm_ext_slimbus_2_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params);
+int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params);
+int msm_proxy_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params);
+int msm_proxy_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params);
+int msm_audrx_init(struct snd_soc_pcm_runtime *rtd);
+int msm_snd_cpe_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params);
+struct snd_soc_card *populate_snd_card_dailinks(struct device *dev);
+int msm_ext_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params);
+#ifdef CONFIG_SND_SOC_EXT_CODEC
+int msm_ext_cdc_init(struct platform_device *, struct msm_asoc_mach_data *,
+ struct snd_soc_card **, struct wcd_mbhc_config *);
+#else
+inline int msm_ext_cdc_init(struct platform_device *pdev,
+ struct msm_asoc_mach_data *pdata,
+ struct snd_soc_card **card,
+ struct wcd_mbhc_config *wcd_mbhc_cfg_ptr1)
+{
+ return 0;
+}
+#endif
+#endif
diff --git a/sound/soc/msm/msmfalcon-internal.c b/sound/soc/msm/msmfalcon-internal.c
new file mode 100644
index 000000000000..3a8b88cdfb64
--- /dev/null
+++ b/sound/soc/msm/msmfalcon-internal.c
@@ -0,0 +1,2453 @@
+/* Copyright (c) 2015-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.
+ */
+
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <sound/pcm_params.h>
+#include "qdsp6v2/msm-pcm-routing-v2.h"
+#include "msm-audio-pinctrl.h"
+#include "msmfalcon-common.h"
+#include "../codecs/msm8x16/msm8x16-wcd.h"
+
+#define __CHIPSET__ "MSMFALCON "
+#define MSM_DAILINK_NAME(name) (__CHIPSET__#name)
+
+#define DEFAULT_MCLK_RATE 9600000
+#define NATIVE_MCLK_RATE 11289600
+
+#define WCD_MBHC_DEF_RLOADS 5
+
+enum {
+ INT0_MI2S = 0,
+ INT1_MI2S,
+ INT2_MI2S,
+ INT3_MI2S,
+ INT4_MI2S,
+ INT5_MI2S,
+ INT6_MI2S,
+ INT_MI2S_MAX,
+};
+
+static struct afe_clk_set int_mi2s_clk[INT_MI2S_MAX] = {
+ {
+ AFE_API_VERSION_I2S_CONFIG,
+ Q6AFE_LPASS_CLK_ID_INT0_MI2S_IBIT,
+ Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+ },
+ {
+ AFE_API_VERSION_I2S_CONFIG,
+ Q6AFE_LPASS_CLK_ID_INT1_MI2S_IBIT,
+ Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+ },
+ {
+ AFE_API_VERSION_I2S_CONFIG,
+ Q6AFE_LPASS_CLK_ID_INT2_MI2S_IBIT,
+ Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+ },
+ {
+ AFE_API_VERSION_I2S_CONFIG,
+ Q6AFE_LPASS_CLK_ID_INT3_MI2S_IBIT,
+ Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+ },
+ {
+ AFE_API_VERSION_I2S_CONFIG,
+ Q6AFE_LPASS_CLK_ID_INT4_MI2S_IBIT,
+ Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+ },
+ {
+ AFE_API_VERSION_I2S_CONFIG,
+ Q6AFE_LPASS_CLK_ID_INT5_MI2S_IBIT,
+ Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+ },
+ {
+ AFE_API_VERSION_I2S_CONFIG,
+ Q6AFE_LPASS_CLK_ID_INT6_MI2S_IBIT,
+ Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ,
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO,
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT,
+ 0,
+ },
+};
+
+struct dev_config {
+ u32 sample_rate;
+ u32 bit_format;
+ u32 channels;
+};
+
+/* Default configuration of MI2S channels */
+static struct dev_config int_mi2s_cfg[] = {
+ [INT0_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+ [INT1_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [INT2_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [INT3_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [INT4_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1},
+ [INT5_MI2S] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+ [INT6_MI2S] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 2},
+};
+
+static char const *int_mi2s_rate_text[] = {"KHZ_8", "KHZ_16",
+ "KHZ_32", "KHZ_44P1", "KHZ_48",
+ "KHZ_96", "KHZ_192"};
+static const char *const int_mi2s_ch_text[] = {"One", "Two"};
+static const char *const int_mi2s_tx_ch_text[] = {"One", "Two",
+ "Three", "Four"};
+static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"};
+static const char *const loopback_mclk_text[] = {"DISABLE", "ENABLE"};
+
+static SOC_ENUM_SINGLE_EXT_DECL(int0_mi2s_rx_sample_rate, int_mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(int0_mi2s_rx_chs, int_mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(int0_mi2s_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(int2_mi2s_tx_sample_rate, int_mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(int2_mi2s_tx_chs, int_mi2s_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(int2_mi2s_tx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(int3_mi2s_tx_sample_rate, int_mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(int3_mi2s_tx_chs, int_mi2s_tx_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(int3_mi2s_tx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(int4_mi2s_rx_sample_rate, int_mi2s_rate_text);
+static SOC_ENUM_SINGLE_EXT_DECL(int4_mi2s_rx_chs, int_mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(int4_mi2s_rx_format, bit_format_text);
+static SOC_ENUM_SINGLE_EXT_DECL(int5_mi2s_tx_chs, int_mi2s_ch_text);
+static SOC_ENUM_SINGLE_EXT_DECL(loopback_mclk_en, loopback_mclk_text);
+
+static int msm_dmic_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event);
+static int msm_int_enable_dig_cdc_clk(struct snd_soc_codec *codec, int enable,
+ bool dapm);
+static int msm_int_mclk0_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event);
+static int msm_int_mi2s_snd_startup(struct snd_pcm_substream *substream);
+static void msm_int_mi2s_snd_shutdown(struct snd_pcm_substream *substream);
+
+static struct wcd_mbhc_config *mbhc_cfg_ptr;
+
+static int int_mi2s_get_bit_format_val(int bit_format)
+{
+ int val = 0;
+
+ switch (bit_format) {
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ val = 2;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ val = 1;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
+ val = 0;
+ break;
+ }
+ return val;
+}
+
+static int int_mi2s_get_bit_format(int val)
+{
+ int bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
+
+ switch (val) {
+ case 0:
+ bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
+ break;
+ case 1:
+ bit_fmt = SNDRV_PCM_FORMAT_S24_LE;
+ break;
+ case 2:
+ bit_fmt = SNDRV_PCM_FORMAT_S24_3LE;
+ break;
+ default:
+ bit_fmt = SNDRV_PCM_FORMAT_S16_LE;
+ break;
+ }
+ return bit_fmt;
+}
+
+static int int_mi2s_get_port_idx(struct snd_kcontrol *kcontrol)
+{
+ int port_id = 0;
+
+ if (strnstr(kcontrol->id.name, "INT0_MI2S", sizeof("INT0_MI2S")))
+ port_id = INT0_MI2S;
+ else if (strnstr(kcontrol->id.name, "INT2_MI2S", sizeof("INT2_MI2S")))
+ port_id = INT2_MI2S;
+ else if (strnstr(kcontrol->id.name, "INT3_MI2S", sizeof("INT3_MI2S")))
+ port_id = INT3_MI2S;
+ else if (strnstr(kcontrol->id.name, "INT4_MI2S", sizeof("INT4_MI2S")))
+ port_id = INT4_MI2S;
+ else {
+ pr_err("%s: unsupported channel: %s",
+ __func__, kcontrol->id.name);
+ return -EINVAL;
+ }
+
+ return port_id;
+}
+
+static int int_mi2s_bit_format_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = int_mi2s_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ ucontrol->value.enumerated.item[0] =
+ int_mi2s_get_bit_format_val(int_mi2s_cfg[ch_num].bit_format);
+
+ pr_debug("%s: int_mi2s[%d]_bit_format = %d, ucontrol value = %d\n",
+ __func__, ch_num, int_mi2s_cfg[ch_num].bit_format,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int int_mi2s_bit_format_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ch_num = int_mi2s_get_port_idx(kcontrol);
+
+ if (ch_num < 0)
+ return ch_num;
+
+ int_mi2s_cfg[ch_num].bit_format =
+ int_mi2s_get_bit_format(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: int_mi2s[%d]_rx_bit_format = %d, ucontrol value = %d\n",
+ __func__, ch_num, int_mi2s_cfg[ch_num].bit_format,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static inline int param_is_mask(int p)
+{
+ return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
+ (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
+}
+
+static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p,
+ int n)
+{
+ return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
+}
+
+static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned bit)
+{
+ if (bit >= SNDRV_MASK_MAX)
+ return;
+ if (param_is_mask(n)) {
+ struct snd_mask *m = param_to_mask(p, n);
+
+ m->bits[0] = 0;
+ m->bits[1] = 0;
+ m->bits[bit >> 5] |= (1 << (bit & 31));
+ }
+}
+
+static int int_mi2s_get_sample_rate_val(int sample_rate)
+{
+ int sample_rate_val;
+
+ switch (sample_rate) {
+ case SAMPLING_RATE_8KHZ:
+ sample_rate_val = 0;
+ break;
+ case SAMPLING_RATE_16KHZ:
+ sample_rate_val = 1;
+ break;
+ case SAMPLING_RATE_32KHZ:
+ sample_rate_val = 2;
+ break;
+ case SAMPLING_RATE_44P1KHZ:
+ sample_rate_val = 3;
+ break;
+ case SAMPLING_RATE_48KHZ:
+ sample_rate_val = 4;
+ break;
+ case SAMPLING_RATE_96KHZ:
+ sample_rate_val = 5;
+ break;
+ case SAMPLING_RATE_192KHZ:
+ sample_rate_val = 6;
+ break;
+ default:
+ sample_rate_val = 4;
+ break;
+ }
+ return sample_rate_val;
+}
+
+static int int_mi2s_get_sample_rate(int value)
+{
+ int sample_rate;
+
+ switch (value) {
+ case 0:
+ sample_rate = SAMPLING_RATE_8KHZ;
+ break;
+ case 1:
+ sample_rate = SAMPLING_RATE_16KHZ;
+ break;
+ case 2:
+ sample_rate = SAMPLING_RATE_32KHZ;
+ break;
+ case 3:
+ sample_rate = SAMPLING_RATE_44P1KHZ;
+ break;
+ case 4:
+ sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ case 5:
+ sample_rate = SAMPLING_RATE_96KHZ;
+ break;
+ case 6:
+ sample_rate = SAMPLING_RATE_192KHZ;
+ break;
+ default:
+ sample_rate = SAMPLING_RATE_48KHZ;
+ break;
+ }
+ return sample_rate;
+}
+
+static int int_mi2s_sample_rate_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = int_mi2s_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ int_mi2s_cfg[idx].sample_rate =
+ int_mi2s_get_sample_rate(ucontrol->value.enumerated.item[0]);
+
+ pr_debug("%s: idx[%d]_sample_rate = %d, item = %d\n", __func__,
+ idx, int_mi2s_cfg[idx].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int int_mi2s_sample_rate_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = int_mi2s_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ ucontrol->value.enumerated.item[0] =
+ int_mi2s_get_sample_rate_val(int_mi2s_cfg[idx].sample_rate);
+
+ pr_debug("%s: idx[%d]_sample_rate = %d, item = %d\n", __func__,
+ idx, int_mi2s_cfg[idx].sample_rate,
+ ucontrol->value.enumerated.item[0]);
+
+ return 0;
+}
+
+static int int_mi2s_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = int_mi2s_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ pr_debug("%s: int_mi2s_[%d]_rx_ch = %d\n", __func__,
+ idx, int_mi2s_cfg[idx].channels);
+ ucontrol->value.enumerated.item[0] = int_mi2s_cfg[idx].channels - 1;
+
+ return 0;
+}
+
+static int int_mi2s_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int idx = int_mi2s_get_port_idx(kcontrol);
+
+ if (idx < 0)
+ return idx;
+
+ int_mi2s_cfg[idx].channels = ucontrol->value.enumerated.item[0] + 1;
+ pr_debug("%s: int_mi2s_[%d]_ch = %d\n", __func__,
+ idx, int_mi2s_cfg[idx].channels);
+
+ return 1;
+}
+
+static const struct snd_soc_dapm_widget msm_int_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY_S("INT_MCLK0", -1, SND_SOC_NOPM, 0, 0,
+ msm_int_mclk0_event, SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIC("Handset Mic", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Secondary Mic", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic1", msm_dmic_event),
+ SND_SOC_DAPM_MIC("Digital Mic2", msm_dmic_event),
+ SND_SOC_DAPM_MIC("Digital Mic3", msm_dmic_event),
+ SND_SOC_DAPM_MIC("Digital Mic4", msm_dmic_event),
+};
+
+static int msm_config_hph_compander_gpio(bool enable)
+{
+ int ret = 0;
+
+ pr_debug("%s: %s HPH Compander\n", __func__,
+ enable ? "Enable" : "Disable");
+
+ if (enable) {
+ ret = msm_gpioset_activate(CLIENT_WCD, "comp_gpio");
+ if (ret) {
+ pr_err("%s: gpio set cannot be activated %s\n",
+ __func__, "comp_gpio");
+ goto done;
+ }
+ } else {
+ ret = msm_gpioset_suspend(CLIENT_WCD, "comp_gpio");
+ if (ret) {
+ pr_err("%s: gpio set cannot be de-activated %s\n",
+ __func__, "comp_gpio");
+ goto done;
+ }
+ }
+
+done:
+ return ret;
+}
+
+static int is_ext_spk_gpio_support(struct platform_device *pdev,
+ struct msm_asoc_mach_data *pdata)
+{
+ const char *spk_ext_pa = "qcom,msm-spk-ext-pa";
+
+ pr_debug("%s:Enter\n", __func__);
+
+ pdata->spk_ext_pa_gpio = of_get_named_gpio(pdev->dev.of_node,
+ spk_ext_pa, 0);
+
+ if (pdata->spk_ext_pa_gpio < 0) {
+ dev_dbg(&pdev->dev,
+ "%s: missing %s in dt node\n", __func__, spk_ext_pa);
+ } else {
+ if (!gpio_is_valid(pdata->spk_ext_pa_gpio)) {
+ pr_err("%s: Invalid external speaker gpio: %d",
+ __func__, pdata->spk_ext_pa_gpio);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
+static int enable_spk_ext_pa(struct snd_soc_codec *codec, int enable)
+{
+ struct snd_soc_card *card = codec->component.card;
+ struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+ int ret;
+
+ if (!gpio_is_valid(pdata->spk_ext_pa_gpio)) {
+ pr_err("%s: Invalid gpio: %d\n", __func__,
+ pdata->spk_ext_pa_gpio);
+ return false;
+ }
+
+ pr_debug("%s: %s external speaker PA\n", __func__,
+ enable ? "Enable" : "Disable");
+
+ if (enable) {
+ ret = msm_gpioset_activate(CLIENT_WCD, "ext_spk_gpio");
+ if (ret) {
+ pr_err("%s: gpio set cannot be de-activated %s\n",
+ __func__, "ext_spk_gpio");
+ return ret;
+ }
+ gpio_set_value_cansleep(pdata->spk_ext_pa_gpio, enable);
+ } else {
+ gpio_set_value_cansleep(pdata->spk_ext_pa_gpio, enable);
+ ret = msm_gpioset_suspend(CLIENT_WCD, "ext_spk_gpio");
+ if (ret) {
+ pr_err("%s: gpio set cannot be de-activated %s\n",
+ __func__, "ext_spk_gpio");
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int int_mi2s_get_idx_from_beid(int32_t be_id)
+{
+ int idx = 0;
+
+ switch (be_id) {
+ case MSM_BACKEND_DAI_INT0_MI2S_RX:
+ idx = INT0_MI2S;
+ break;
+ case MSM_BACKEND_DAI_INT2_MI2S_TX:
+ idx = INT2_MI2S;
+ break;
+ case MSM_BACKEND_DAI_INT3_MI2S_TX:
+ idx = INT3_MI2S;
+ break;
+ case MSM_BACKEND_DAI_INT4_MI2S_RX:
+ idx = INT4_MI2S;
+ break;
+ case MSM_BACKEND_DAI_INT5_MI2S_TX:
+ idx = INT5_MI2S;
+ break;
+ default:
+ idx = INT0_MI2S;
+ break;
+ }
+
+ return idx;
+}
+
+static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ 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);
+
+ pr_debug("%s()\n", __func__);
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = 2;
+
+ return 0;
+}
+
+int int_mi2s_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ 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);
+ int idx;
+
+ pr_debug("%s: format = %d, rate = %d\n",
+ __func__, params_format(params), params_rate(params));
+
+ switch (dai_link->be_id) {
+ case MSM_BACKEND_DAI_INT0_MI2S_RX:
+ case MSM_BACKEND_DAI_INT2_MI2S_TX:
+ case MSM_BACKEND_DAI_INT3_MI2S_TX:
+ case MSM_BACKEND_DAI_INT4_MI2S_RX:
+ case MSM_BACKEND_DAI_INT5_MI2S_TX:
+ idx = int_mi2s_get_idx_from_beid(dai_link->be_id);
+ rate->min = rate->max = int_mi2s_cfg[idx].sample_rate;
+ channels->min = channels->max =
+ int_mi2s_cfg[idx].channels;
+ param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
+ int_mi2s_cfg[idx].bit_format);
+ break;
+ default:
+ rate->min = rate->max = SAMPLING_RATE_48KHZ;
+ break;
+ }
+ return 0;
+}
+
+static int msm_vi_feed_tx_ch_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] =
+ (int_mi2s_cfg[INT5_MI2S].channels/2 - 1);
+ pr_debug("%s: msm_vi_feed_tx_ch = %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int_mi2s_cfg[INT5_MI2S].channels =
+ roundup_pow_of_two(ucontrol->value.integer.value[0] + 2);
+
+ pr_debug("%s: msm_vi_feed_tx_ch = %d\n",
+ __func__, int_mi2s_cfg[INT5_MI2S].channels);
+ return 1;
+}
+
+static int msm_int_enable_dig_cdc_clk(struct snd_soc_codec *codec,
+ int enable, bool dapm)
+{
+ int ret = 0;
+ struct msm_asoc_mach_data *pdata = NULL;
+ int clk_freq_in_hz;
+ bool int_mclk0_freq_chg = false;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ pr_debug("%s: enable %d mclk ref counter %d\n",
+ __func__, enable,
+ atomic_read(&pdata->int_mclk0_rsc_ref));
+ if (enable) {
+ if (int_mi2s_cfg[INT0_MI2S].sample_rate ==
+ SAMPLING_RATE_44P1KHZ)
+ clk_freq_in_hz = NATIVE_MCLK_RATE;
+ else
+ clk_freq_in_hz = pdata->mclk_freq;
+
+ if (pdata->digital_cdc_core_clk.clk_freq_in_hz
+ != clk_freq_in_hz)
+ int_mclk0_freq_chg = true;
+ if (!atomic_read(&pdata->int_mclk0_rsc_ref) ||
+ int_mclk0_freq_chg) {
+ cancel_delayed_work_sync(
+ &pdata->disable_int_mclk0_work);
+ mutex_lock(&pdata->cdc_int_mclk0_mutex);
+ if (atomic_read(&pdata->int_mclk0_enabled) == false ||
+ int_mclk0_freq_chg) {
+ pdata->digital_cdc_core_clk.clk_freq_in_hz =
+ clk_freq_in_hz;
+ pdata->digital_cdc_core_clk.enable = 1;
+ ret = afe_set_lpass_clock_v2(
+ AFE_PORT_ID_INT0_MI2S_RX,
+ &pdata->digital_cdc_core_clk);
+ if (ret < 0) {
+ pr_err("%s: failed to enable CCLK\n",
+ __func__);
+ mutex_unlock(
+ &pdata->cdc_int_mclk0_mutex);
+ return ret;
+ }
+ pr_debug("enabled digital codec core clk\n");
+ atomic_set(&pdata->int_mclk0_enabled, true);
+ }
+ mutex_unlock(&pdata->cdc_int_mclk0_mutex);
+ }
+ atomic_inc(&pdata->int_mclk0_rsc_ref);
+ } else {
+ cancel_delayed_work_sync(&pdata->disable_int_mclk0_work);
+ mutex_lock(&pdata->cdc_int_mclk0_mutex);
+ if (atomic_read(&pdata->int_mclk0_enabled) == true) {
+ pdata->digital_cdc_core_clk.enable = 0;
+ ret = afe_set_lpass_clock_v2(
+ AFE_PORT_ID_INT0_MI2S_RX,
+ &pdata->digital_cdc_core_clk);
+ if (ret < 0)
+ pr_err("%s: failed to disable CCLK\n",
+ __func__);
+ atomic_set(&pdata->int_mclk0_enabled, false);
+ }
+ mutex_unlock(&pdata->cdc_int_mclk0_mutex);
+ }
+ return ret;
+}
+
+static int loopback_mclk_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s\n", __func__);
+ return 0;
+}
+
+static int loopback_mclk_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ret = -EINVAL;
+ struct msm_asoc_mach_data *pdata = NULL;
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ pr_debug("%s: mclk_rsc_ref %d enable %ld\n",
+ __func__, atomic_read(&pdata->int_mclk0_rsc_ref),
+ ucontrol->value.integer.value[0]);
+ switch (ucontrol->value.integer.value[0]) {
+ case 1:
+ ret = msm_gpioset_activate(CLIENT_WCD, "int_pdm");
+ if (ret) {
+ pr_err("%s: failed to enable the pri gpios: %d\n",
+ __func__, ret);
+ break;
+ }
+ mutex_lock(&pdata->cdc_int_mclk0_mutex);
+ if ((!atomic_read(&pdata->int_mclk0_rsc_ref)) &&
+ (!atomic_read(&pdata->int_mclk0_enabled))) {
+ pdata->digital_cdc_core_clk.enable = 1;
+ ret = afe_set_lpass_clock_v2(
+ AFE_PORT_ID_INT0_MI2S_RX,
+ &pdata->digital_cdc_core_clk);
+ if (ret < 0) {
+ pr_err("%s: failed to enable the MCLK: %d\n",
+ __func__, ret);
+ mutex_unlock(&pdata->cdc_int_mclk0_mutex);
+ ret = msm_gpioset_suspend(CLIENT_WCD,
+ "int_pdm");
+ if (ret)
+ pr_err("%s: failed to disable the pri gpios: %d\n",
+ __func__, ret);
+ break;
+ }
+ atomic_set(&pdata->int_mclk0_enabled, true);
+ }
+ mutex_unlock(&pdata->cdc_int_mclk0_mutex);
+ atomic_inc(&pdata->int_mclk0_rsc_ref);
+ msm8x16_wcd_mclk_enable(codec, 1, true);
+ break;
+ case 0:
+ if (atomic_read(&pdata->int_mclk0_rsc_ref) <= 0)
+ break;
+ msm8x16_wcd_mclk_enable(codec, 0, true);
+ mutex_lock(&pdata->cdc_int_mclk0_mutex);
+ if ((!atomic_dec_return(&pdata->int_mclk0_rsc_ref)) &&
+ (atomic_read(&pdata->int_mclk0_enabled))) {
+ pdata->digital_cdc_core_clk.enable = 0;
+ ret = afe_set_lpass_clock_v2(
+ AFE_PORT_ID_INT0_MI2S_RX,
+ &pdata->digital_cdc_core_clk);
+ if (ret < 0) {
+ pr_err("%s: failed to disable the CCLK: %d\n",
+ __func__, ret);
+ mutex_unlock(&pdata->cdc_int_mclk0_mutex);
+ break;
+ }
+ atomic_set(&pdata->int_mclk0_enabled, false);
+ }
+ mutex_unlock(&pdata->cdc_int_mclk0_mutex);
+ ret = msm_gpioset_suspend(CLIENT_WCD, "int_pdm");
+ if (ret)
+ pr_err("%s: failed to disable the pri gpios: %d\n",
+ __func__, ret);
+ break;
+ default:
+ pr_err("%s: Unexpected input value\n", __func__);
+ break;
+ }
+ return ret;
+}
+
+static const struct snd_kcontrol_new msm_snd_controls[] = {
+ SOC_ENUM_EXT("INT0_MI2S_RX Format", int0_mi2s_rx_format,
+ int_mi2s_bit_format_get, int_mi2s_bit_format_put),
+ SOC_ENUM_EXT("INT2_MI2S_TX Format", int2_mi2s_tx_format,
+ int_mi2s_bit_format_get, int_mi2s_bit_format_put),
+ SOC_ENUM_EXT("INT3_MI2S_TX Format", int3_mi2s_tx_format,
+ int_mi2s_bit_format_get, int_mi2s_bit_format_put),
+ SOC_ENUM_EXT("INT0_MI2S_RX SampleRate", int0_mi2s_rx_sample_rate,
+ int_mi2s_sample_rate_get,
+ int_mi2s_sample_rate_put),
+ SOC_ENUM_EXT("INT2_MI2S_TX SampleRate", int2_mi2s_tx_sample_rate,
+ int_mi2s_sample_rate_get,
+ int_mi2s_sample_rate_put),
+ SOC_ENUM_EXT("INT3_MI2S_TX SampleRate", int3_mi2s_tx_sample_rate,
+ int_mi2s_sample_rate_get,
+ int_mi2s_sample_rate_put),
+ SOC_ENUM_EXT("INT0_MI2S_RX SampleRate", int0_mi2s_rx_sample_rate,
+ int_mi2s_sample_rate_get,
+ int_mi2s_sample_rate_put),
+ SOC_ENUM_EXT("INT2_MI2S_TX SampleRate", int2_mi2s_tx_sample_rate,
+ int_mi2s_sample_rate_get,
+ int_mi2s_sample_rate_put),
+ SOC_ENUM_EXT("INT3_MI2S_TX SampleRate", int3_mi2s_tx_sample_rate,
+ int_mi2s_sample_rate_get,
+ int_mi2s_sample_rate_put),
+ SOC_ENUM_EXT("INT0_MI2S_RX Channels", int0_mi2s_rx_chs,
+ int_mi2s_ch_get, int_mi2s_ch_put),
+ SOC_ENUM_EXT("INT2_MI2S_TX Channels", int2_mi2s_tx_chs,
+ int_mi2s_ch_get, int_mi2s_ch_put),
+ SOC_ENUM_EXT("INT3_MI2S_TX Channels", int3_mi2s_tx_chs,
+ int_mi2s_ch_get, int_mi2s_ch_put),
+ SOC_ENUM_EXT("Loopback MCLK", loopback_mclk_en,
+ loopback_mclk_get, loopback_mclk_put),
+};
+
+static const struct snd_kcontrol_new msm_swr_controls[] = {
+ SOC_ENUM_EXT("INT4_MI2S_RX Format", int4_mi2s_rx_format,
+ int_mi2s_bit_format_get, int_mi2s_bit_format_put),
+ SOC_ENUM_EXT("INT4_MI2S_RX SampleRate", int4_mi2s_rx_sample_rate,
+ int_mi2s_sample_rate_get,
+ int_mi2s_sample_rate_put),
+ SOC_ENUM_EXT("INT4_MI2S_RX SampleRate", int4_mi2s_rx_sample_rate,
+ int_mi2s_sample_rate_get,
+ int_mi2s_sample_rate_put),
+ SOC_ENUM_EXT("INT4_MI2S_RX Channels", int4_mi2s_rx_chs,
+ int_mi2s_ch_get, int_mi2s_ch_put),
+ SOC_ENUM_EXT("VI_FEED_TX Channels", int5_mi2s_tx_chs,
+ msm_vi_feed_tx_ch_get, msm_vi_feed_tx_ch_put),
+};
+
+static int msm_dmic_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct msm_asoc_mach_data *pdata = NULL;
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ int ret = 0;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ pr_debug("%s: event = %d\n", __func__, event);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ ret = msm_gpioset_activate(CLIENT_WCD, "dmic_gpio");
+ if (ret < 0) {
+ pr_err("%s: gpio set cannot be activated %sd",
+ __func__, "dmic_gpio");
+ return ret;
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ ret = msm_gpioset_suspend(CLIENT_WCD, "dmic_gpio");
+ if (ret < 0) {
+ pr_err("%s: gpio set cannot be de-activated %sd",
+ __func__, "dmic_gpio");
+ return ret;
+ }
+ break;
+ default:
+ pr_err("%s: invalid DAPM event %d\n", __func__, event);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int msm_int_mclk0_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct msm_asoc_mach_data *pdata = NULL;
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+ int ret = 0;
+
+ pdata = snd_soc_card_get_drvdata(codec->component.card);
+ pr_debug("%s: event = %d\n", __func__, event);
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMD:
+ pr_debug("%s: mclk_res_ref = %d\n",
+ __func__, atomic_read(&pdata->int_mclk0_rsc_ref));
+ ret = msm_gpioset_suspend(CLIENT_WCD, "int_pdm");
+ if (ret < 0) {
+ pr_err("%s: gpio set cannot be de-activated %sd",
+ __func__, "int_pdm");
+ return ret;
+ }
+ if (atomic_read(&pdata->int_mclk0_rsc_ref) == 0) {
+ pr_debug("%s: disabling MCLK\n", __func__);
+ /* disable the codec mclk config*/
+ msm8x16_wcd_mclk_enable(codec, 0, true);
+ msm_int_enable_dig_cdc_clk(codec, 0, true);
+ }
+ break;
+ default:
+ pr_err("%s: invalid DAPM event %d\n", __func__, event);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int int_mi2s_get_port_id(int be_id)
+{
+ int afe_port_id;
+
+ switch (be_id) {
+ case MSM_BACKEND_DAI_INT0_MI2S_RX:
+ afe_port_id = AFE_PORT_ID_INT0_MI2S_RX;
+ break;
+ case MSM_BACKEND_DAI_INT2_MI2S_TX:
+ afe_port_id = AFE_PORT_ID_INT2_MI2S_TX;
+ break;
+ case MSM_BACKEND_DAI_INT3_MI2S_TX:
+ afe_port_id = AFE_PORT_ID_INT3_MI2S_TX;
+ break;
+ case MSM_BACKEND_DAI_INT4_MI2S_RX:
+ afe_port_id = AFE_PORT_ID_INT4_MI2S_RX;
+ break;
+ case MSM_BACKEND_DAI_INT5_MI2S_TX:
+ afe_port_id = AFE_PORT_ID_INT5_MI2S_TX;
+ break;
+ default:
+ pr_err("%s: Invalid be_id: %d\n", __func__, be_id);
+ afe_port_id = -EINVAL;
+ }
+
+ return afe_port_id;
+}
+
+static int int_mi2s_get_index(int port_id)
+{
+ int index;
+
+ switch (port_id) {
+ case AFE_PORT_ID_INT0_MI2S_RX:
+ index = INT0_MI2S;
+ break;
+ case AFE_PORT_ID_INT2_MI2S_TX:
+ index = INT2_MI2S;
+ break;
+ case AFE_PORT_ID_INT3_MI2S_TX:
+ index = INT3_MI2S;
+ break;
+ case AFE_PORT_ID_INT4_MI2S_RX:
+ index = INT4_MI2S;
+ break;
+ case AFE_PORT_ID_INT5_MI2S_TX:
+ index = INT5_MI2S;
+ break;
+ default:
+ pr_err("%s: Invalid port_id: %d\n", __func__, port_id);
+ index = -EINVAL;
+ }
+
+ return index;
+}
+
+static u32 get_int_mi2s_bits_per_sample(u32 bit_format)
+{
+ u32 bit_per_sample;
+
+ switch (bit_format) {
+ case SNDRV_PCM_FORMAT_S24_3LE:
+ case SNDRV_PCM_FORMAT_S24_LE:
+ bit_per_sample = 32;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ default:
+ bit_per_sample = 16;
+ break;
+ }
+
+ return bit_per_sample;
+}
+
+static void update_int_mi2s_clk_val(int idx, int stream)
+{
+ u32 bit_per_sample;
+
+ bit_per_sample =
+ get_int_mi2s_bits_per_sample(int_mi2s_cfg[idx].bit_format);
+ int_mi2s_clk[idx].clk_freq_in_hz =
+ (int_mi2s_cfg[idx].sample_rate * int_mi2s_cfg[idx].channels
+ * bit_per_sample);
+}
+
+static int int_mi2s_set_sclk(struct snd_pcm_substream *substream, bool enable)
+{
+ int ret = 0;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ int port_id = 0;
+ int index;
+
+ port_id = int_mi2s_get_port_id(rtd->dai_link->be_id);
+ if (IS_ERR_VALUE(port_id)) {
+ dev_err(rtd->card->dev, "%s: Invalid port_id\n", __func__);
+ ret = port_id;
+ goto done;
+ }
+ index = int_mi2s_get_index(port_id);
+ if (index < 0) {
+ dev_err(rtd->card->dev, "%s: Invalid port_id\n", __func__);
+ ret = port_id;
+ goto done;
+ }
+ if (enable) {
+ update_int_mi2s_clk_val(index, substream->stream);
+ dev_dbg(rtd->card->dev, "%s: clock rate %ul\n", __func__,
+ int_mi2s_clk[index].clk_freq_in_hz);
+ }
+
+ int_mi2s_clk[index].enable = enable;
+ ret = afe_set_lpass_clock_v2(port_id,
+ &int_mi2s_clk[index]);
+ if (ret < 0) {
+ dev_err(rtd->card->dev,
+ "%s: afe lpass clock failed for port 0x%x , err:%d\n",
+ __func__, port_id, ret);
+ goto done;
+ }
+
+done:
+ return ret;
+}
+
+static int msm_swr_mi2s_snd_startup(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;
+
+ pr_debug("%s(): substream = %s stream = %d\n", __func__,
+ substream->name, substream->stream);
+
+ ret = int_mi2s_set_sclk(substream, true);
+ if (ret < 0) {
+ pr_err("%s: failed to enable sclk %d\n",
+ __func__, ret);
+ return ret;
+ }
+ /* Enable the codec mclk config */
+ ret = msm_gpioset_activate(CLIENT_WCD, "swr_pin");
+ if (ret < 0) {
+ pr_err("%s: gpio set cannot be activated %sd",
+ __func__, "swr_pin");
+ return ret;
+ }
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ pr_err("%s: set fmt cpu dai failed; ret=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static void msm_swr_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
+{
+ int ret;
+
+ pr_debug("%s(): substream = %s stream = %d\n", __func__,
+ substream->name, substream->stream);
+
+ ret = int_mi2s_set_sclk(substream, false);
+ if (ret < 0)
+ pr_err("%s:clock disable failed; ret=%d\n", __func__,
+ ret);
+}
+
+static int msm_int_mi2s_snd_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_codec *codec = rtd->codec;
+ int ret = 0;
+
+ pr_debug("%s(): substream = %s stream = %d\n", __func__,
+ substream->name, substream->stream);
+
+ ret = int_mi2s_set_sclk(substream, true);
+ if (ret < 0) {
+ pr_err("%s: failed to enable sclk %d\n",
+ __func__, ret);
+ return ret;
+ }
+ ret = msm_int_enable_dig_cdc_clk(codec, 1, true);
+ if (ret < 0) {
+ pr_err("failed to enable mclk\n");
+ return ret;
+ }
+ /* Enable the codec mclk config */
+ ret = msm_gpioset_activate(CLIENT_WCD, "int_pdm");
+ if (ret < 0) {
+ pr_err("%s: gpio set cannot be activated %s\n",
+ __func__, "int_pdm");
+ return ret;
+ }
+ msm8x16_wcd_mclk_enable(codec, 1, true);
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBS_CFS);
+ if (ret < 0)
+ pr_err("%s: set fmt cpu dai failed; ret=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static void msm_int_mi2s_snd_shutdown(struct snd_pcm_substream *substream)
+{
+ int ret;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+
+ pr_debug("%s(): substream = %s stream = %d\n", __func__,
+ substream->name, substream->stream);
+
+ ret = int_mi2s_set_sclk(substream, false);
+ if (ret < 0)
+ pr_err("%s:clock disable failed; ret=%d\n", __func__,
+ ret);
+ if (atomic_read(&pdata->int_mclk0_rsc_ref) > 0) {
+ atomic_dec(&pdata->int_mclk0_rsc_ref);
+ pr_debug("%s: decrementing mclk_res_ref %d\n",
+ __func__,
+ atomic_read(&pdata->int_mclk0_rsc_ref));
+ }
+}
+
+static void *def_msm_int_wcd_mbhc_cal(void)
+{
+ void *msm_int_wcd_cal;
+ struct wcd_mbhc_btn_detect_cfg *btn_cfg;
+ u16 *btn_low, *btn_high;
+
+ msm_int_wcd_cal = kzalloc(WCD_MBHC_CAL_SIZE(WCD_MBHC_DEF_BUTTONS,
+ WCD_MBHC_DEF_RLOADS), GFP_KERNEL);
+ if (!msm_int_wcd_cal)
+ return NULL;
+
+#define S(X, Y) ((WCD_MBHC_CAL_PLUG_TYPE_PTR(msm_int_wcd_cal)->X) = (Y))
+ S(v_hs_max, 1500);
+#undef S
+#define S(X, Y) ((WCD_MBHC_CAL_BTN_DET_PTR(msm_int_wcd_cal)->X) = (Y))
+ S(num_btn, WCD_MBHC_DEF_BUTTONS);
+#undef S
+
+
+ btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(msm_int_wcd_cal);
+ btn_low = btn_cfg->_v_btn_low;
+ btn_high = ((void *)&btn_cfg->_v_btn_low) +
+ (sizeof(btn_cfg->_v_btn_low[0]) * btn_cfg->num_btn);
+
+ /*
+ * In SW we are maintaining two sets of threshold register
+ * one for current source and another for Micbias.
+ * all btn_low corresponds to threshold for current source
+ * all bt_high corresponds to threshold for Micbias
+ * Below thresholds are based on following resistances
+ * 0-70 == Button 0
+ * 110-180 == Button 1
+ * 210-290 == Button 2
+ * 360-680 == Button 3
+ */
+ btn_low[0] = 75;
+ btn_high[0] = 75;
+ btn_low[1] = 150;
+ btn_high[1] = 150;
+ btn_low[2] = 225;
+ btn_high[2] = 225;
+ btn_low[3] = 450;
+ btn_high[3] = 450;
+ btn_low[4] = 500;
+ btn_high[4] = 500;
+
+ return msm_int_wcd_cal;
+}
+
+static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_codec_get_dapm(codec);
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret = -ENOMEM;
+
+ pr_debug("%s(),dev_name%s\n", __func__, dev_name(cpu_dai->dev));
+
+ snd_soc_add_codec_controls(codec, msm_snd_controls,
+ ARRAY_SIZE(msm_snd_controls));
+
+ snd_soc_add_codec_controls(codec, msm_common_snd_controls,
+ ARRAY_SIZE(msm_snd_controls));
+
+ snd_soc_dapm_new_controls(dapm, msm_int_dapm_widgets,
+ ARRAY_SIZE(msm_int_dapm_widgets));
+
+ snd_soc_dapm_ignore_suspend(dapm, "Handset Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "Headset Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "Secondary Mic");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic1");
+ snd_soc_dapm_ignore_suspend(dapm, "Digital Mic2");
+
+ snd_soc_dapm_ignore_suspend(dapm, "EAR");
+ snd_soc_dapm_ignore_suspend(dapm, "HEADPHONE");
+ snd_soc_dapm_ignore_suspend(dapm, "SPK_OUT");
+ snd_soc_dapm_ignore_suspend(dapm, "AMIC1");
+ snd_soc_dapm_ignore_suspend(dapm, "AMIC2");
+ snd_soc_dapm_ignore_suspend(dapm, "AMIC3");
+ snd_soc_dapm_ignore_suspend(dapm, "DMIC1");
+ snd_soc_dapm_ignore_suspend(dapm, "DMIC2");
+ snd_soc_dapm_ignore_suspend(dapm, "DMIC3");
+ snd_soc_dapm_ignore_suspend(dapm, "DMIC4");
+
+ snd_soc_dapm_sync(dapm);
+
+ msm8x16_wcd_spk_ext_pa_cb(enable_spk_ext_pa, codec);
+ msm8x16_wcd_hph_comp_cb(msm_config_hph_compander_gpio, codec);
+
+ mbhc_cfg_ptr->calibration = def_msm_int_wcd_mbhc_cal();
+ if (mbhc_cfg_ptr->calibration) {
+ ret = msm8x16_wcd_hs_detect(codec, mbhc_cfg_ptr);
+ if (ret) {
+ pr_err("%s: msm8x16_wcd_hs_detect failed\n", __func__);
+ kfree(mbhc_cfg_ptr->calibration);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int msm_swr_audrx_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_codec_get_dapm(codec);
+
+ snd_soc_add_codec_controls(codec, msm_swr_controls,
+ ARRAY_SIZE(msm_swr_controls));
+
+ snd_soc_dapm_ignore_suspend(dapm, "AIF1_SWR Playback");
+ snd_soc_dapm_ignore_suspend(dapm, "VIfeed_SWR");
+ snd_soc_dapm_ignore_suspend(dapm, "SPK1 OUT");
+ snd_soc_dapm_ignore_suspend(dapm, "SPK2 OUT");
+ snd_soc_dapm_ignore_suspend(dapm, "AIF1_SWR VI");
+ snd_soc_dapm_ignore_suspend(dapm, "VIINPUT_SWR");
+
+ snd_soc_dapm_sync(dapm);
+
+ return 0;
+}
+
+static struct snd_soc_ops msm_mi2s_be_ops = {
+ .startup = msm_mi2s_snd_startup,
+ .shutdown = msm_mi2s_snd_shutdown,
+};
+
+static struct snd_soc_ops msm_aux_pcm_be_ops = {
+ .startup = msm_aux_pcm_snd_startup,
+ .shutdown = msm_aux_pcm_snd_shutdown,
+};
+
+static struct snd_soc_ops msm_int_mi2s_be_ops = {
+ .startup = msm_int_mi2s_snd_startup,
+ .shutdown = msm_int_mi2s_snd_shutdown,
+};
+
+static struct snd_soc_ops msm_swr_mi2s_be_ops = {
+ .startup = msm_swr_mi2s_snd_startup,
+ .shutdown = msm_swr_mi2s_snd_shutdown,
+};
+
+/* Digital audio interface glue - connects codec <---> CPU */
+static struct snd_soc_dai_link msm_int_dai[] = {
+ /* FrontEnd DAI Links */
+ {/* hw:x,0 */
+ .name = MSM_DAILINK_NAME(Media1),
+ .stream_name = "MultiMedia1",
+ .cpu_dai_name = "MultiMedia1",
+ .platform_name = "msm-pcm-dsp.0",
+ .dynamic = 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,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
+ },
+ {/* hw:x,1 */
+ .name = MSM_DAILINK_NAME(Media2),
+ .stream_name = "MultiMedia2",
+ .cpu_dai_name = "MultiMedia2",
+ .platform_name = "msm-pcm-dsp.0",
+ .dynamic = 1,
+ .dpcm_playback = 1,
+ .dpcm_capture = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .ignore_suspend = 1,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+ },
+ {/* hw:x,2 */
+ .name = "VoiceMMode1",
+ .stream_name = "VoiceMMode1",
+ .cpu_dai_name = "VoiceMMode1",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .dpcm_capture = 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",
+ .be_id = MSM_FRONTEND_DAI_VOICEMMODE1,
+ },
+ {/* hw:x,3 */
+ .name = "MSM VoIP",
+ .stream_name = "VoIP",
+ .cpu_dai_name = "VoIP",
+ .platform_name = "msm-voip-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",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_VOIP,
+ },
+ {/* hw:x,4 */
+ .name = MSM_DAILINK_NAME(ULL),
+ .stream_name = "ULL",
+ .cpu_dai_name = "MultiMedia3",
+ .platform_name = "msm-pcm-dsp.2",
+ .dynamic = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
+ },
+ /* Hostless PCM purpose */
+ {/* hw:x,5 */
+ .name = "INT4 MI2S_RX Hostless",
+ .stream_name = "INT4 MI2S_RX Hostless",
+ .cpu_dai_name = "INT4_MI2S_RX_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,
+ /* this dailink has playback support */
+ .ignore_pmdown_time = 1,
+ /* This dainlink has MI2S support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {/* hw:x,6 */
+ .name = "MSM AFE-PCM RX",
+ .stream_name = "AFE-PROXY RX",
+ .cpu_dai_name = "msm-dai-q6-dev.241",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .platform_name = "msm-pcm-afe",
+ .ignore_suspend = 1,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ },
+ {/* hw:x,7 */
+ .name = "MSM AFE-PCM TX",
+ .stream_name = "AFE-PROXY TX",
+ .cpu_dai_name = "msm-dai-q6-dev.240",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .platform_name = "msm-pcm-afe",
+ .ignore_suspend = 1,
+ },
+ {/* hw:x,8 */
+ .name = MSM_DAILINK_NAME(Compress1),
+ .stream_name = "Compress1",
+ .cpu_dai_name = "MultiMedia4",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+ },
+ {/* hw:x,9*/
+ .name = "AUXPCM Hostless",
+ .stream_name = "AUXPCM Hostless",
+ .cpu_dai_name = "AUXPCM_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_capture = 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,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {/* hw:x,10 */
+ .name = "SLIMBUS_1 Hostless",
+ .stream_name = "SLIMBUS_1 Hostless",
+ .cpu_dai_name = "SLIMBUS1_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_capture = 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, /* dai link has playback support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {/* hw:x,11 */
+ .name = "SLIMBUS_3 Hostless",
+ .stream_name = "SLIMBUS_3 Hostless",
+ .cpu_dai_name = "SLIMBUS3_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_capture = 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, /* dai link has playback support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {/* hw:x,12 */
+ .name = "SLIMBUS_4 Hostless",
+ .stream_name = "SLIMBUS_4 Hostless",
+ .cpu_dai_name = "SLIMBUS4_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dpcm_capture = 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, /* dai link has playback support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {/* hw:x,13 */
+ .name = MSM_DAILINK_NAME(LowLatency),
+ .stream_name = "MultiMedia5",
+ .cpu_dai_name = "MultiMedia5",
+ .platform_name = "msm-pcm-dsp.1",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .ignore_suspend = 1,
+ /* this dai link has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
+ },
+ /* LSM FE */
+ {/* hw:x,14 */
+ .name = "Listen 1 Audio Service",
+ .stream_name = "Listen 1 Audio Service",
+ .cpu_dai_name = "LSM1",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM1,
+ },
+ {/* hw:x,15 */
+ .name = MSM_DAILINK_NAME(Compress2),
+ .stream_name = "Compress2",
+ .cpu_dai_name = "MultiMedia7",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .ignore_suspend = 1,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+ },
+ {/* hw:x,16 */
+ .name = MSM_DAILINK_NAME(Compress3),
+ .stream_name = "Compress3",
+ .cpu_dai_name = "MultiMedia10",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA10,
+ },
+ {/* hw:x,17 */
+ .name = MSM_DAILINK_NAME(ULL_NOIRQ),
+ .stream_name = "MM_NOIRQ",
+ .cpu_dai_name = "MultiMedia8",
+ .platform_name = "msm-pcm-dsp-noirq",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+ },
+ {/* hw:x,18 */
+ .name = "HDMI_RX_HOSTLESS",
+ .stream_name = "HDMI_RX_HOSTLESS",
+ .cpu_dai_name = "HDMI_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",
+ },
+ {/* hw:x,19 */
+ .name = "VoiceMMode2",
+ .stream_name = "VoiceMMode2",
+ .cpu_dai_name = "VoiceMMode2",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .dpcm_capture = 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",
+ .be_id = MSM_FRONTEND_DAI_VOICEMMODE2,
+ },
+ {/* hw:x,20 */
+ .name = "Listen 2 Audio Service",
+ .stream_name = "Listen 2 Audio Service",
+ .cpu_dai_name = "LSM2",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM2,
+ },
+ {/* hw:x,21 */
+ .name = "Listen 3 Audio Service",
+ .stream_name = "Listen 3 Audio Service",
+ .cpu_dai_name = "LSM3",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM3,
+ },
+ {/* hw:x,22 */
+ .name = "Listen 4 Audio Service",
+ .stream_name = "Listen 4 Audio Service",
+ .cpu_dai_name = "LSM4",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM4,
+ },
+ {/* hw:x,23 */
+ .name = "Listen 5 Audio Service",
+ .stream_name = "Listen 5 Audio Service",
+ .cpu_dai_name = "LSM5",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM5,
+ },
+ {/* hw:x,24 */
+ .name = "Listen 6 Audio Service",
+ .stream_name = "Listen 6 Audio Service",
+ .cpu_dai_name = "LSM6",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM6
+ },
+ {/* hw:x,25 */
+ .name = "Listen 7 Audio Service",
+ .stream_name = "Listen 7 Audio Service",
+ .cpu_dai_name = "LSM7",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM7,
+ },
+ {/* hw:x,26 */
+ .name = "Listen 8 Audio Service",
+ .stream_name = "Listen 8 Audio Service",
+ .cpu_dai_name = "LSM8",
+ .platform_name = "msm-lsm-client",
+ .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",
+ .be_id = MSM_FRONTEND_DAI_LSM8,
+ },
+ {/* hw:x,27 */
+ .name = MSM_DAILINK_NAME(Media9),
+ .stream_name = "MultiMedia9",
+ .cpu_dai_name = "MultiMedia9",
+ .platform_name = "msm-pcm-dsp.0",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA9,
+ },
+ {/* hw:x,28 */
+ .name = MSM_DAILINK_NAME(Compress4),
+ .stream_name = "Compress4",
+ .cpu_dai_name = "MultiMedia11",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA11,
+ },
+ {/* hw:x,29 */
+ .name = MSM_DAILINK_NAME(Compress5),
+ .stream_name = "Compress5",
+ .cpu_dai_name = "MultiMedia12",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA12,
+ },
+ {/* hw:x,30 */
+ .name = MSM_DAILINK_NAME(Compress6),
+ .stream_name = "Compress6",
+ .cpu_dai_name = "MultiMedia13",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA13,
+ },
+ {/* hw:x,31 */
+ .name = MSM_DAILINK_NAME(Compress7),
+ .stream_name = "Compress7",
+ .cpu_dai_name = "MultiMedia14",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA14,
+ },
+ {/* hw:x,32 */
+ .name = MSM_DAILINK_NAME(Compress8),
+ .stream_name = "Compress8",
+ .cpu_dai_name = "MultiMedia15",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA15,
+ },
+ {/* hw:x,33 */
+ .name = MSM_DAILINK_NAME(Compress9),
+ .stream_name = "Compress9",
+ .cpu_dai_name = "MultiMedia16",
+ .platform_name = "msm-compress-dsp",
+ .dynamic = 1,
+ .dpcm_capture = 1,
+ .dpcm_playback = 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,
+ /* this dai link has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA16,
+ },
+ {/* hw:x,34 */
+ .name = "SLIMBUS_8 Hostless",
+ .stream_name = "SLIMBUS8_HOSTLESS Capture",
+ .cpu_dai_name = "SLIMBUS8_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",
+ },
+ {/* hw:x,35 */
+ .name = LPASS_BE_INT5_MI2S_TX,
+ .stream_name = "INT5_mi2s Capture",
+ .cpu_dai_name = "msm-dai-q6-mi2s.12",
+ .platform_name = "msm-pcm-hostless",
+ .codec_name = "msm_swr_codec",
+ .codec_dai_name = "msm_swr_vifeedback",
+ .be_id = MSM_BACKEND_DAI_INT5_MI2S_TX,
+ .be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
+ .ops = &msm_swr_mi2s_be_ops,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ .dpcm_capture = 1,
+ .ignore_pmdown_time = 1,
+ },
+ {/* hw:x,36 */
+ .name = "Primary MI2S_RX Hostless",
+ .stream_name = "Primary MI2S_RX Hostless",
+ .cpu_dai_name = "PRI_MI2S_RX_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,
+ /* this dailink has playback support */
+ .ignore_pmdown_time = 1,
+ /* This dainlink has MI2S support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {/* hw:x,37 */
+ .name = "Secondary MI2S_RX Hostless",
+ .stream_name = "Secondary MI2S_RX Hostless",
+ .cpu_dai_name = "SEC_MI2S_RX_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,
+ /* this dailink has playback support */
+ .ignore_pmdown_time = 1,
+ /* This dainlink has MI2S support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {/* hw:x,38 */
+ .name = "Tertiary MI2S_RX Hostless",
+ .stream_name = "Tertiary MI2S_RX Hostless",
+ .cpu_dai_name = "TERT_MI2S_RX_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,
+ /* this dailink has playback support */
+ .ignore_pmdown_time = 1,
+ /* This dainlink has MI2S support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {/* hw:x,39 */
+ .name = "INT0 MI2S_RX Hostless",
+ .stream_name = "INT0 MI2S_RX Hostless",
+ .cpu_dai_name = "INT0_MI2S_RX_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,
+ /* this dailink has playback support */
+ .ignore_pmdown_time = 1,
+ /* This dainlink has MI2S support */
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ /* Backend I2S DAI Links */
+ {
+ .name = LPASS_BE_INT0_MI2S_RX,
+ .stream_name = "INT0 MI2S Playback",
+ .cpu_dai_name = "msm-dai-q6-mi2s.7",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "cajon_codec",
+ .codec_dai_name = "msm8x16_wcd_i2s_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
+ ASYNC_DPCM_SND_SOC_HW_PARAMS,
+ .be_id = MSM_BACKEND_DAI_INT0_MI2S_RX,
+ .init = &msm_audrx_init,
+ .be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
+ .ops = &msm_int_mi2s_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_INT4_MI2S_RX,
+ .stream_name = "INT4 MI2S Playback",
+ .cpu_dai_name = "msm-dai-q6-mi2s.11",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm_swr_codec",
+ .codec_dai_name = "msm_swr_i2s_rx1",
+ .no_pcm = 1,
+ .dpcm_playback = 1,
+ .be_id = MSM_BACKEND_DAI_INT4_MI2S_RX,
+ .init = &msm_swr_audrx_init,
+ .be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
+ .ops = &msm_swr_mi2s_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_INT2_MI2S_TX,
+ .stream_name = "INT2 MI2S Capture",
+ .cpu_dai_name = "msm-dai-q6-mi2s.9",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "cajon_codec",
+ .codec_dai_name = "msm8x16_wcd_i2s_tx2",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
+ ASYNC_DPCM_SND_SOC_HW_PARAMS,
+ .be_id = MSM_BACKEND_DAI_INT2_MI2S_TX,
+ .be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
+ .ops = &msm_int_mi2s_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_INT3_MI2S_TX,
+ .stream_name = "INT3 MI2S Capture",
+ .cpu_dai_name = "msm-dai-q6-mi2s.10",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "cajon_codec",
+ .codec_dai_name = "msm8x16_wcd_i2s_tx1",
+ .no_pcm = 1,
+ .dpcm_capture = 1,
+ .async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
+ ASYNC_DPCM_SND_SOC_HW_PARAMS,
+ .be_id = MSM_BACKEND_DAI_INT3_MI2S_TX,
+ .be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
+ .ops = &msm_int_mi2s_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_AFE_PCM_RX,
+ .stream_name = "AFE Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.224",
+ .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_AFE_PCM_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_AFE_PCM_TX,
+ .stream_name = "AFE Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.225",
+ .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_PCM_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Record Uplink BACK END DAI Link */
+ {
+ .name = LPASS_BE_INCALL_RECORD_TX,
+ .stream_name = "Voice Uplink Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.32772",
+ .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_INCALL_RECORD_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Record Downlink BACK END DAI Link */
+ {
+ .name = LPASS_BE_INCALL_RECORD_RX,
+ .stream_name = "Voice Downlink Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.32771",
+ .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_INCALL_RECORD_RX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Music BACK END DAI Link */
+ {
+ .name = LPASS_BE_VOICE_PLAYBACK_TX,
+ .stream_name = "Voice Farend Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.32773",
+ .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_VOICE_PLAYBACK_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+ /* Incall Music 2 BACK END DAI Link */
+ {
+ .name = LPASS_BE_VOICE2_PLAYBACK_TX,
+ .stream_name = "Voice2 Farend Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.32770",
+ .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_VOICE2_PLAYBACK_TX,
+ .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ },
+};
+
+static struct snd_soc_dai_link msm_mi2s_be_dai_links[] = {
+ {
+ .name = LPASS_BE_PRI_MI2S_RX,
+ .stream_name = "Primary MI2S Playback",
+ .cpu_dai_name = "msm-dai-q6-mi2s.0",
+ .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_MI2S_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = LPASS_BE_PRI_MI2S_TX,
+ .stream_name = "Primary MI2S Capture",
+ .cpu_dai_name = "msm-dai-q6-mi2s.0",
+ .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_MI2S_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_SEC_MI2S_RX,
+ .stream_name = "Secondary MI2S Playback",
+ .cpu_dai_name = "msm-dai-q6-mi2s.1",
+ .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_SECONDARY_MI2S_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = LPASS_BE_SEC_MI2S_TX,
+ .stream_name = "Secondary MI2S Capture",
+ .cpu_dai_name = "msm-dai-q6-mi2s.1",
+ .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_SECONDARY_MI2S_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_TERT_MI2S_RX,
+ .stream_name = "Tertiary MI2S Playback",
+ .cpu_dai_name = "msm-dai-q6-mi2s.2",
+ .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_TERTIARY_MI2S_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = LPASS_BE_TERT_MI2S_TX,
+ .stream_name = "Tertiary MI2S Capture",
+ .cpu_dai_name = "msm-dai-q6-mi2s.2",
+ .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_TERTIARY_MI2S_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ },
+ {
+ .name = LPASS_BE_QUAT_MI2S_RX,
+ .stream_name = "Quaternary MI2S Playback",
+ .cpu_dai_name = "msm-dai-q6-mi2s.3",
+ .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_QUATERNARY_MI2S_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = LPASS_BE_QUAT_MI2S_TX,
+ .stream_name = "Quaternary MI2S Capture",
+ .cpu_dai_name = "msm-dai-q6-mi2s.3",
+ .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_QUATERNARY_MI2S_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ops = &msm_mi2s_be_ops,
+ .ignore_suspend = 1,
+ },
+};
+
+static struct snd_soc_dai_link msm_auxpcm_be_dai_links[] = {
+ /* Primary AUX PCM Backend DAI Links */
+ {
+ .name = LPASS_BE_AUXPCM_RX,
+ .stream_name = "AUX PCM Playback",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.1",
+ .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_AUXPCM_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ {
+ .name = LPASS_BE_AUXPCM_TX,
+ .stream_name = "AUX PCM Capture",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.1",
+ .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_AUXPCM_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ /* Secondary AUX PCM Backend DAI Links */
+ {
+ .name = LPASS_BE_SEC_AUXPCM_RX,
+ .stream_name = "Sec AUX PCM Playback",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.2",
+ .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_SEC_AUXPCM_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ {
+ .name = LPASS_BE_SEC_AUXPCM_TX,
+ .stream_name = "Sec AUX PCM Capture",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.2",
+ .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_SEC_AUXPCM_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ /* Tertiary AUX PCM Backend DAI Links */
+ {
+ .name = LPASS_BE_TERT_AUXPCM_RX,
+ .stream_name = "Tert AUX PCM Playback",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.3",
+ .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_TERT_AUXPCM_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ {
+ .name = LPASS_BE_TERT_AUXPCM_TX,
+ .stream_name = "Tert AUX PCM Capture",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.3",
+ .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_TERT_AUXPCM_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ /* Quaternary AUX PCM Backend DAI Links */
+ {
+ .name = LPASS_BE_QUAT_AUXPCM_RX,
+ .stream_name = "Quat AUX PCM Playback",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.4",
+ .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_QUAT_AUXPCM_RX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+ {
+ .name = LPASS_BE_QUAT_AUXPCM_TX,
+ .stream_name = "Quat AUX PCM Capture",
+ .cpu_dai_name = "msm-dai-q6-auxpcm.4",
+ .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_QUAT_AUXPCM_TX,
+ .be_hw_params_fixup = msm_common_be_hw_params_fixup,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .ops = &msm_aux_pcm_be_ops,
+ },
+};
+
+static struct snd_soc_dai_link msm_int_dai_links[
+ARRAY_SIZE(msm_int_dai) +
+ARRAY_SIZE(msm_mi2s_be_dai_links) +
+ARRAY_SIZE(msm_auxpcm_be_dai_links)];
+
+static struct snd_soc_card msmfalcon_card = {
+ /* snd_soc_card_msmfalcon */
+ .name = "msmfalcon-snd-card",
+ .dai_link = msm_int_dai,
+ .num_links = ARRAY_SIZE(msm_int_dai),
+};
+
+static void msm_disable_int_mclk0(struct work_struct *work)
+{
+ struct msm_asoc_mach_data *pdata = NULL;
+ struct delayed_work *dwork;
+ int ret = 0;
+
+ dwork = to_delayed_work(work);
+ pdata = container_of(dwork, struct msm_asoc_mach_data,
+ disable_int_mclk0_work);
+ mutex_lock(&pdata->cdc_int_mclk0_mutex);
+ pr_debug("%s: mclk_enabled %d mclk_rsc_ref %d\n", __func__,
+ atomic_read(&pdata->int_mclk0_enabled),
+ atomic_read(&pdata->int_mclk0_rsc_ref));
+
+ if (atomic_read(&pdata->int_mclk0_enabled) == true
+ && atomic_read(&pdata->int_mclk0_rsc_ref) == 0) {
+ pr_debug("Disable the mclk\n");
+ pdata->digital_cdc_core_clk.enable = 0;
+ ret = afe_set_lpass_clock_v2(
+ AFE_PORT_ID_INT0_MI2S_RX,
+ &pdata->digital_cdc_core_clk);
+ if (ret < 0)
+ pr_err("%s failed to disable the CCLK\n", __func__);
+ atomic_set(&pdata->int_mclk0_enabled, false);
+ }
+ mutex_unlock(&pdata->cdc_int_mclk0_mutex);
+}
+
+static void msm_int_dt_parse_cap_info(struct platform_device *pdev,
+ struct msm_asoc_mach_data *pdata)
+{
+ const char *ext1_cap = "qcom,msm-micbias1-ext-cap";
+ const char *ext2_cap = "qcom,msm-micbias2-ext-cap";
+
+ pdata->micbias1_cap_mode =
+ (of_property_read_bool(pdev->dev.of_node, ext1_cap) ?
+ MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
+
+ pdata->micbias2_cap_mode =
+ (of_property_read_bool(pdev->dev.of_node, ext2_cap) ?
+ MICBIAS_EXT_BYP_CAP : MICBIAS_NO_EXT_BYP_CAP);
+}
+
+static struct snd_soc_card *msm_int_populate_sndcard_dailinks(
+ struct device *dev)
+{
+ struct snd_soc_card *card = &msmfalcon_card;
+ struct snd_soc_dai_link *dailink;
+ int len1;
+
+ card->name = dev_name(dev);
+ len1 = ARRAY_SIZE(msm_int_dai);
+ memcpy(msm_int_dai_links, msm_int_dai, sizeof(msm_int_dai));
+ dailink = msm_int_dai_links;
+ if (of_property_read_bool(dev->of_node,
+ "qcom,mi2s-audio-intf")) {
+ memcpy(dailink + len1,
+ msm_mi2s_be_dai_links,
+ sizeof(msm_mi2s_be_dai_links));
+ len1 += ARRAY_SIZE(msm_mi2s_be_dai_links);
+ }
+ if (of_property_read_bool(dev->of_node,
+ "qcom,auxpcm-audio-intf")) {
+ memcpy(dailink + len1,
+ msm_auxpcm_be_dai_links,
+ sizeof(msm_auxpcm_be_dai_links));
+ len1 += ARRAY_SIZE(msm_auxpcm_be_dai_links);
+ }
+ card->dai_link = dailink;
+ card->num_links = len1;
+ return card;
+}
+
+static int msm_internal_init(struct platform_device *pdev,
+ struct msm_asoc_mach_data *pdata,
+ struct snd_soc_card *card)
+{
+ const char *type = NULL;
+ const char *hs_micbias_type = "qcom,msm-hs-micbias-type";
+ int ret;
+
+ ret = is_ext_spk_gpio_support(pdev, pdata);
+ if (ret < 0)
+ dev_dbg(&pdev->dev,
+ "%s: doesn't support external speaker pa\n",
+ __func__);
+
+ ret = of_property_read_string(pdev->dev.of_node,
+ hs_micbias_type, &type);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: missing %s in dt node\n",
+ __func__, hs_micbias_type);
+ goto err;
+ }
+ if (!strcmp(type, "external")) {
+ dev_dbg(&pdev->dev, "Headset is using external micbias\n");
+ mbhc_cfg_ptr->hs_ext_micbias = true;
+ } else {
+ dev_dbg(&pdev->dev, "Headset is using internal micbias\n");
+ mbhc_cfg_ptr->hs_ext_micbias = false;
+ }
+
+ /* initialize the int_mclk0 */
+ pdata->digital_cdc_core_clk.clk_set_minor_version =
+ AFE_API_VERSION_I2S_CONFIG;
+ pdata->digital_cdc_core_clk.clk_id =
+ Q6AFE_LPASS_CLK_ID_INT_MCLK_0;
+ pdata->digital_cdc_core_clk.clk_freq_in_hz =
+ pdata->mclk_freq;
+ pdata->digital_cdc_core_clk.clk_attri =
+ Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO;
+ pdata->digital_cdc_core_clk.clk_root =
+ Q6AFE_LPASS_CLK_ROOT_DEFAULT;
+ pdata->digital_cdc_core_clk.enable = 1;
+
+ /* Initialize loopback mode to false */
+ pdata->lb_mode = false;
+
+ msm_int_dt_parse_cap_info(pdev, pdata);
+
+ card->dev = &pdev->dev;
+ platform_set_drvdata(pdev, card);
+ snd_soc_card_set_drvdata(card, pdata);
+ ret = snd_soc_of_parse_card_name(card, "qcom,model");
+ if (ret)
+ goto err;
+ /* initialize timer */
+ INIT_DELAYED_WORK(&pdata->disable_int_mclk0_work,
+ msm_disable_int_mclk0);
+ mutex_init(&pdata->cdc_int_mclk0_mutex);
+ atomic_set(&pdata->int_mclk0_rsc_ref, 0);
+ atomic_set(&pdata->int_mclk0_enabled, false);
+
+ dev_info(&pdev->dev, "%s: default codec configured\n", __func__);
+
+ return 0;
+err:
+ return ret;
+}
+
+/**
+ * msm_int_cdc_init - internal codec machine specific init.
+ *
+ * @pdev: platform device handle
+ * @pdata: private data of machine driver
+ * @card: sound card pointer reference
+ * @mbhc_cfg: MBHC config reference
+ *
+ * Returns 0.
+ */
+int msm_int_cdc_init(struct platform_device *pdev,
+ struct msm_asoc_mach_data *pdata,
+ struct snd_soc_card **card,
+ struct wcd_mbhc_config *mbhc_cfg)
+{
+ mbhc_cfg_ptr = mbhc_cfg;
+
+ *card = msm_int_populate_sndcard_dailinks(&pdev->dev);
+ msm_internal_init(pdev, pdata, *card);
+ return 0;
+}
+EXPORT_SYMBOL(msm_int_cdc_init);
diff --git a/sound/soc/msm/msmfalcon-internal.h b/sound/soc/msm/msmfalcon-internal.h
new file mode 100644
index 000000000000..e5e3e7c66246
--- /dev/null
+++ b/sound/soc/msm/msmfalcon-internal.h
@@ -0,0 +1,32 @@
+/* Copyright (c) 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 __MSMFALCON_INTERNAL
+#define __MSMFALCON_INTERNAL
+
+#include <sound/soc.h>
+
+#ifdef CONFIG_SND_SOC_INT_CODEC
+int msm_int_cdc_init(struct platform_device *pdev,
+ struct msm_asoc_mach_data *pdata,
+ struct snd_soc_card **card,
+ struct wcd_mbhc_config *mbhc_cfg);
+#else
+int msm_int_cdc_init(struct platform_device *pdev,
+ struct msm_asoc_mach_data *pdata,
+ struct snd_soc_card **card,
+ struct wcd_mbhc_config *mbhc_cfg)
+{
+ return 0;
+}
+#endif
+#endif
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index 770bd12eb501..a2cd6c6f98db 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -2779,10 +2779,10 @@ static int msm_compr_app_type_cfg_put(struct snd_kcontrol *kcontrol,
acdb_dev_id = ucontrol->value.integer.value[1];
if (0 != ucontrol->value.integer.value[2])
sample_rate = ucontrol->value.integer.value[2];
- pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d\n",
- __func__, app_type, acdb_dev_id, sample_rate);
+ pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n",
+ __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_RX);
msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type,
- acdb_dev_id, sample_rate);
+ acdb_dev_id, sample_rate, SESSION_TYPE_RX);
return 0;
}
@@ -2804,8 +2804,8 @@ static int msm_compr_app_type_cfg_get(struct snd_kcontrol *kcontrol,
goto done;
}
- ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, &app_type,
- &acdb_dev_id, &sample_rate);
+ ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_RX,
+ &app_type, &acdb_dev_id, &sample_rate);
if (ret < 0) {
pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
__func__, ret);
@@ -2815,8 +2815,9 @@ static int msm_compr_app_type_cfg_get(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[0] = app_type;
ucontrol->value.integer.value[1] = acdb_dev_id;
ucontrol->value.integer.value[2] = sample_rate;
- pr_debug("%s: fedai_id %llu, app_type %d, acdb_dev_id %d, sample_rate %d\n",
- __func__, fe_id, app_type, acdb_dev_id, sample_rate);
+ pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
+ __func__, fe_id, SESSION_TYPE_RX,
+ app_type, acdb_dev_id, sample_rate);
done:
return ret;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 7eb4a10b83c7..718f7017342b 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -3481,12 +3481,32 @@ static int msm_mi2s_get_port_id(u32 mi2s_id, int stream, u16 *port_id)
case MSM_QUIN_MI2S:
*port_id = AFE_PORT_ID_QUINARY_MI2S_RX;
break;
- break;
+ case MSM_INT0_MI2S:
+ *port_id = AFE_PORT_ID_INT0_MI2S_RX;
+ break;
+ case MSM_INT1_MI2S:
+ *port_id = AFE_PORT_ID_INT1_MI2S_RX;
+ break;
+ case MSM_INT2_MI2S:
+ *port_id = AFE_PORT_ID_INT2_MI2S_RX;
+ break;
+ case MSM_INT3_MI2S:
+ *port_id = AFE_PORT_ID_INT3_MI2S_RX;
+ break;
+ case MSM_INT4_MI2S:
+ *port_id = AFE_PORT_ID_INT4_MI2S_RX;
+ break;
+ case MSM_INT5_MI2S:
+ *port_id = AFE_PORT_ID_INT5_MI2S_RX;
+ break;
+ case MSM_INT6_MI2S:
+ *port_id = AFE_PORT_ID_INT6_MI2S_RX;
+ break;
default:
pr_err("%s: playback err id 0x%x\n",
__func__, mi2s_id);
ret = -1;
- break;
+ break;
}
break;
case SNDRV_PCM_STREAM_CAPTURE:
@@ -3509,10 +3529,31 @@ static int msm_mi2s_get_port_id(u32 mi2s_id, int stream, u16 *port_id)
case MSM_SENARY_MI2S:
*port_id = AFE_PORT_ID_SENARY_MI2S_TX;
break;
+ case MSM_INT0_MI2S:
+ *port_id = AFE_PORT_ID_INT0_MI2S_TX;
+ break;
+ case MSM_INT1_MI2S:
+ *port_id = AFE_PORT_ID_INT1_MI2S_TX;
+ break;
+ case MSM_INT2_MI2S:
+ *port_id = AFE_PORT_ID_INT2_MI2S_TX;
+ break;
+ case MSM_INT3_MI2S:
+ *port_id = AFE_PORT_ID_INT3_MI2S_TX;
+ break;
+ case MSM_INT4_MI2S:
+ *port_id = AFE_PORT_ID_INT4_MI2S_TX;
+ break;
+ case MSM_INT5_MI2S:
+ *port_id = AFE_PORT_ID_INT5_MI2S_TX;
+ break;
+ case MSM_INT6_MI2S:
+ *port_id = AFE_PORT_ID_INT6_MI2S_TX;
+ break;
default:
pr_err("%s: capture err id 0x%x\n", __func__, mi2s_id);
ret = -1;
- break;
+ break;
}
break;
default:
@@ -3968,6 +4009,188 @@ static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai[] = {
.probe = msm_dai_q6_dai_mi2s_probe,
.remove = msm_dai_q6_dai_mi2s_remove,
},
+ {
+ .playback = {
+ .stream_name = "INT0 MI2S Playback",
+ .aif_name = "INT0_MI2S_RX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_44100,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "INT0 MI2S Capture",
+ .aif_name = "INT0_MI2S_TX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_dai_q6_mi2s_ops,
+ .id = MSM_INT0_MI2S,
+ .probe = msm_dai_q6_dai_mi2s_probe,
+ .remove = msm_dai_q6_dai_mi2s_remove,
+ },
+ {
+ .playback = {
+ .stream_name = "INT1 MI2S Playback",
+ .aif_name = "INT1_MI2S_RX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "INT1 MI2S Capture",
+ .aif_name = "INT1_MI2S_TX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_dai_q6_mi2s_ops,
+ .id = MSM_INT1_MI2S,
+ .probe = msm_dai_q6_dai_mi2s_probe,
+ .remove = msm_dai_q6_dai_mi2s_remove,
+ },
+ {
+ .playback = {
+ .stream_name = "INT2 MI2S Playback",
+ .aif_name = "INT2_MI2S_RX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "INT2 MI2S Capture",
+ .aif_name = "INT2_MI2S_TX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_dai_q6_mi2s_ops,
+ .id = MSM_INT2_MI2S,
+ .probe = msm_dai_q6_dai_mi2s_probe,
+ .remove = msm_dai_q6_dai_mi2s_remove,
+ },
+ {
+ .playback = {
+ .stream_name = "INT3 MI2S Playback",
+ .aif_name = "INT3_MI2S_RX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "INT3 MI2S Capture",
+ .aif_name = "INT3_MI2S_TX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_dai_q6_mi2s_ops,
+ .id = MSM_INT3_MI2S,
+ .probe = msm_dai_q6_dai_mi2s_probe,
+ .remove = msm_dai_q6_dai_mi2s_remove,
+ },
+ {
+ .playback = {
+ .stream_name = "INT4 MI2S Playback",
+ .aif_name = "INT4_MI2S_RX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "INT4 MI2S Capture",
+ .aif_name = "INT4_MI2S_TX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_dai_q6_mi2s_ops,
+ .id = MSM_INT4_MI2S,
+ .probe = msm_dai_q6_dai_mi2s_probe,
+ .remove = msm_dai_q6_dai_mi2s_remove,
+ },
+ {
+ .playback = {
+ .stream_name = "INT5 MI2S Playback",
+ .aif_name = "INT5_MI2S_RX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "INT5 MI2S Capture",
+ .aif_name = "INT5_MI2S_TX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_dai_q6_mi2s_ops,
+ .id = MSM_INT5_MI2S,
+ .probe = msm_dai_q6_dai_mi2s_probe,
+ .remove = msm_dai_q6_dai_mi2s_remove,
+ },
+ {
+ .playback = {
+ .stream_name = "INT6 MI2S Playback",
+ .aif_name = "INT6_MI2S_RX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S24_3LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .capture = {
+ .stream_name = "INT6 MI2S Capture",
+ .aif_name = "INT6_MI2S_TX",
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_dai_q6_mi2s_ops,
+ .id = MSM_INT6_MI2S,
+ .probe = msm_dai_q6_dai_mi2s_probe,
+ .remove = msm_dai_q6_dai_mi2s_remove,
+ },
};
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c
index ff7cf5812c0c..82458275b892 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-loopback-v2.c
@@ -516,7 +516,7 @@ exit:
return rc;
}
-static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd)
+static int msm_pcm_add_volume_controls(struct snd_soc_pcm_runtime *rtd)
{
struct snd_pcm *pcm = rtd->pcm->streams[0].pcm;
struct snd_pcm_volume *volume_info;
@@ -537,6 +537,192 @@ static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd)
return 0;
}
+static int msm_pcm_playback_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int app_type;
+ int acdb_dev_id;
+ int sample_rate = 48000;
+
+ 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;
+ }
+
+ app_type = ucontrol->value.integer.value[0];
+ acdb_dev_id = ucontrol->value.integer.value[1];
+ if (ucontrol->value.integer.value[2] != 0)
+ sample_rate = ucontrol->value.integer.value[2];
+ pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n",
+ __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_RX);
+ msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type,
+ acdb_dev_id, sample_rate, SESSION_TYPE_RX);
+
+ return 0;
+}
+
+static int msm_pcm_playback_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int ret = 0;
+ int app_type;
+ int acdb_dev_id;
+ int sample_rate;
+
+ 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;
+ }
+
+ ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_RX,
+ &app_type, &acdb_dev_id, &sample_rate);
+ if (ret < 0) {
+ pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
+ __func__, ret);
+ goto done;
+ }
+
+ ucontrol->value.integer.value[0] = app_type;
+ ucontrol->value.integer.value[1] = acdb_dev_id;
+ ucontrol->value.integer.value[2] = sample_rate;
+ pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
+ __func__, fe_id, SESSION_TYPE_RX,
+ app_type, acdb_dev_id, sample_rate);
+done:
+ return ret;
+}
+
+static int msm_pcm_capture_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int app_type;
+ int acdb_dev_id;
+ int sample_rate = 48000;
+
+ 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;
+ }
+
+ app_type = ucontrol->value.integer.value[0];
+ acdb_dev_id = ucontrol->value.integer.value[1];
+ if (ucontrol->value.integer.value[2] != 0)
+ sample_rate = ucontrol->value.integer.value[2];
+ pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n",
+ __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_TX);
+ msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type,
+ acdb_dev_id, sample_rate, SESSION_TYPE_TX);
+
+ return 0;
+}
+
+static int msm_pcm_capture_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int ret = 0;
+ int app_type;
+ int acdb_dev_id;
+ int sample_rate;
+
+ 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;
+ }
+
+ ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_TX,
+ &app_type, &acdb_dev_id, &sample_rate);
+ if (ret < 0) {
+ pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
+ __func__, ret);
+ goto done;
+ }
+
+ ucontrol->value.integer.value[0] = app_type;
+ ucontrol->value.integer.value[1] = acdb_dev_id;
+ ucontrol->value.integer.value[2] = sample_rate;
+ pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
+ __func__, fe_id, SESSION_TYPE_TX,
+ app_type, acdb_dev_id, sample_rate);
+done:
+ return ret;
+}
+
+static int msm_pcm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_pcm *pcm = rtd->pcm->streams[0].pcm;
+ struct snd_pcm_usr *app_type_info;
+ struct snd_kcontrol *kctl;
+ const char *playback_mixer_ctl_name = "Audio Stream";
+ const char *capture_mixer_ctl_name = "Audio Stream Capture";
+ const char *deviceNo = "NN";
+ const char *suffix = "App Type Cfg";
+ int ctl_len, ret = 0;
+
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+ ctl_len = strlen(playback_mixer_ctl_name) + 1 +
+ strlen(deviceNo) + 1 + strlen(suffix) + 1;
+ pr_debug("%s: Playback app type cntrl add\n", __func__);
+ ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ NULL, 1, ctl_len, rtd->dai_link->be_id,
+ &app_type_info);
+ if (ret < 0)
+ return ret;
+ kctl = app_type_info->kctl;
+ snprintf(kctl->id.name, ctl_len, "%s %d %s",
+ playback_mixer_ctl_name, rtd->pcm->device, suffix);
+ kctl->put = msm_pcm_playback_app_type_cfg_ctl_put;
+ kctl->get = msm_pcm_playback_app_type_cfg_ctl_get;
+ }
+
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+ ctl_len = strlen(capture_mixer_ctl_name) + 1 +
+ strlen(deviceNo) + 1 + strlen(suffix) + 1;
+ pr_debug("%s: Capture app type cntrl add\n", __func__);
+ ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ NULL, 1, ctl_len, rtd->dai_link->be_id,
+ &app_type_info);
+ if (ret < 0)
+ return ret;
+ kctl = app_type_info->kctl;
+ snprintf(kctl->id.name, ctl_len, "%s %d %s",
+ capture_mixer_ctl_name, rtd->pcm->device, suffix);
+ kctl->put = msm_pcm_capture_app_type_cfg_ctl_put;
+ kctl->get = msm_pcm_capture_app_type_cfg_ctl_get;
+ }
+
+ return 0;
+}
+
+static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd)
+{
+ int ret = 0;
+
+ pr_debug("%s\n", __func__);
+ ret = msm_pcm_add_volume_controls(rtd);
+ if (ret)
+ pr_err("%s: pcm add volume controls failed:%d\n",
+ __func__, ret);
+ ret = msm_pcm_add_app_type_controls(rtd);
+ if (ret)
+ pr_err("%s: pcm add app type controls failed:%d\n",
+ __func__, ret);
+ return ret;
+}
+
static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index c5baf0e63732..920e7324f14a 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -1178,7 +1178,7 @@ static int msm_pcm_add_chmap_controls(struct snd_soc_pcm_runtime *rtd)
return 0;
}
-static int msm_pcm_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
+static int msm_pcm_playback_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
u64 fe_id = kcontrol->private_value;
@@ -1197,15 +1197,15 @@ static int msm_pcm_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
acdb_dev_id = ucontrol->value.integer.value[1];
if (0 != ucontrol->value.integer.value[2])
sample_rate = ucontrol->value.integer.value[2];
- pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d\n",
- __func__, app_type, acdb_dev_id, sample_rate);
+ pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n",
+ __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_RX);
msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type,
- acdb_dev_id, sample_rate);
+ acdb_dev_id, sample_rate, SESSION_TYPE_RX);
return 0;
}
-static int msm_pcm_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
+static int msm_pcm_playback_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
u64 fe_id = kcontrol->private_value;
@@ -1222,8 +1222,8 @@ static int msm_pcm_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
goto done;
}
- ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, &app_type,
- &acdb_dev_id, &sample_rate);
+ ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_RX,
+ &app_type, &acdb_dev_id, &sample_rate);
if (ret < 0) {
pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
__func__, ret);
@@ -1233,8 +1233,71 @@ static int msm_pcm_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[0] = app_type;
ucontrol->value.integer.value[1] = acdb_dev_id;
ucontrol->value.integer.value[2] = sample_rate;
- pr_debug("%s: fedai_id %llu, app_type %d, acdb_dev_id %d, sample_rate %d\n",
- __func__, fe_id, app_type, acdb_dev_id, sample_rate);
+ pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
+ __func__, fe_id, SESSION_TYPE_RX,
+ app_type, acdb_dev_id, sample_rate);
+done:
+ return ret;
+}
+
+static int msm_pcm_capture_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int app_type;
+ int acdb_dev_id;
+ int sample_rate = 48000;
+
+ 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;
+ }
+
+ app_type = ucontrol->value.integer.value[0];
+ acdb_dev_id = ucontrol->value.integer.value[1];
+ if (ucontrol->value.integer.value[2] != 0)
+ sample_rate = ucontrol->value.integer.value[2];
+ pr_debug("%s: app_type- %d acdb_dev_id- %d sample_rate- %d session_type- %d\n",
+ __func__, app_type, acdb_dev_id, sample_rate, SESSION_TYPE_TX);
+ msm_pcm_routing_reg_stream_app_type_cfg(fe_id, app_type,
+ acdb_dev_id, sample_rate, SESSION_TYPE_TX);
+
+ return 0;
+}
+
+static int msm_pcm_capture_app_type_cfg_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int ret = 0;
+ int app_type;
+ int acdb_dev_id;
+ int sample_rate;
+
+ 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;
+ }
+
+ ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, SESSION_TYPE_TX,
+ &app_type, &acdb_dev_id, &sample_rate);
+ if (ret < 0) {
+ pr_err("%s: msm_pcm_routing_get_stream_app_type_cfg failed returned %d\n",
+ __func__, ret);
+ goto done;
+ }
+
+ ucontrol->value.integer.value[0] = app_type;
+ ucontrol->value.integer.value[1] = acdb_dev_id;
+ ucontrol->value.integer.value[2] = sample_rate;
+ pr_debug("%s: fedai_id %llu, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
+ __func__, fe_id, SESSION_TYPE_TX,
+ app_type, acdb_dev_id, sample_rate);
done:
return ret;
}
@@ -1244,27 +1307,49 @@ static int msm_pcm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd)
struct snd_pcm *pcm = rtd->pcm;
struct snd_pcm_usr *app_type_info;
struct snd_kcontrol *kctl;
- const char *mixer_ctl_name = "Audio Stream";
+ const char *playback_mixer_ctl_name = "Audio Stream";
+ const char *capture_mixer_ctl_name = "Audio Stream Capture";
const char *deviceNo = "NN";
const char *suffix = "App Type Cfg";
int ctl_len, ret = 0;
- ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 +
- strlen(suffix) + 1;
- pr_debug("%s, App type cntrl add\n", __func__);
- ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- NULL, 1, ctl_len, rtd->dai_link->be_id,
- &app_type_info);
- if (ret < 0) {
- pr_err("%s, app type cntrl add failed:%d\n", __func__, ret);
- return ret;
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+ ctl_len = strlen(playback_mixer_ctl_name) + 1 +
+ strlen(deviceNo) + 1 + strlen(suffix) + 1;
+ pr_debug("%s: Playback app type cntrl add\n", __func__);
+ ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ NULL, 1, ctl_len, rtd->dai_link->be_id,
+ &app_type_info);
+ if (ret < 0) {
+ pr_err("%s: playback app type cntrl add failed: %d\n",
+ __func__, ret);
+ return ret;
+ }
+ kctl = app_type_info->kctl;
+ snprintf(kctl->id.name, ctl_len, "%s %d %s",
+ playback_mixer_ctl_name, rtd->pcm->device, suffix);
+ kctl->put = msm_pcm_playback_app_type_cfg_ctl_put;
+ kctl->get = msm_pcm_playback_app_type_cfg_ctl_get;
+ }
+
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+ ctl_len = strlen(capture_mixer_ctl_name) + 1 +
+ strlen(deviceNo) + 1 + strlen(suffix) + 1;
+ pr_debug("%s: Capture app type cntrl add\n", __func__);
+ ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ NULL, 1, ctl_len, rtd->dai_link->be_id,
+ &app_type_info);
+ if (ret < 0) {
+ pr_err("%s: capture app type cntrl add failed: %d\n",
+ __func__, ret);
+ return ret;
+ }
+ kctl = app_type_info->kctl;
+ snprintf(kctl->id.name, ctl_len, "%s %d %s",
+ capture_mixer_ctl_name, rtd->pcm->device, suffix);
+ kctl->put = msm_pcm_capture_app_type_cfg_ctl_put;
+ kctl->get = msm_pcm_capture_app_type_cfg_ctl_get;
}
- kctl = app_type_info->kctl;
- snprintf(kctl->id.name, ctl_len, "%s %d %s", mixer_ctl_name,
- rtd->pcm->device, suffix);
- kctl = app_type_info->kctl;
- kctl->put = msm_pcm_app_type_cfg_ctl_put;
- kctl->get = msm_pcm_app_type_cfg_ctl_get;
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 13d4ba27d990..9681330be33b 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -466,6 +466,34 @@ struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
LPASS_BE_QUAT_AUXPCM_RX},
{ AFE_PORT_ID_QUATERNARY_PCM_TX, 0, 0, {0}, 0, 0, 0, 0, 0,
LPASS_BE_QUAT_AUXPCM_TX},
+ { AFE_PORT_ID_INT0_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT0_MI2S_RX},
+ { AFE_PORT_ID_INT0_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT0_MI2S_TX},
+ { AFE_PORT_ID_INT1_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT1_MI2S_RX},
+ { AFE_PORT_ID_INT1_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT1_MI2S_TX},
+ { AFE_PORT_ID_INT2_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT2_MI2S_RX},
+ { AFE_PORT_ID_INT2_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT2_MI2S_TX},
+ { AFE_PORT_ID_INT3_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT3_MI2S_RX},
+ { AFE_PORT_ID_INT3_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT3_MI2S_TX},
+ { AFE_PORT_ID_INT4_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT4_MI2S_RX},
+ { AFE_PORT_ID_INT4_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT4_MI2S_TX},
+ { AFE_PORT_ID_INT5_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT5_MI2S_RX},
+ { AFE_PORT_ID_INT5_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT5_MI2S_TX},
+ { AFE_PORT_ID_INT6_MI2S_RX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT6_MI2S_RX},
+ { AFE_PORT_ID_INT6_MI2S_TX, 0, 0, {0}, 0, 0, 0, 0, 0,
+ LPASS_BE_INT6_MI2S_TX},
};
/* Track ASM playback & capture sessions of DAI */
@@ -525,7 +553,7 @@ static unsigned long session_copp_map[MSM_FRONTEND_DAI_MM_SIZE][2]
[MSM_BACKEND_DAI_MAX];
static struct msm_pcm_routing_app_type_data app_type_cfg[MAX_APP_TYPES];
static struct msm_pcm_stream_app_type_cfg
- fe_dai_app_type_cfg[MSM_FRONTEND_DAI_MM_SIZE];
+ fe_dai_app_type_cfg[MSM_FRONTEND_DAI_MM_SIZE][2];
/* The caller of this should aqcuire routing lock */
void msm_pcm_routing_get_bedai_info(int be_idx,
@@ -569,34 +597,43 @@ static int msm_pcm_routing_get_app_type_idx(int app_type)
}
void msm_pcm_routing_reg_stream_app_type_cfg(int fedai_id, int app_type,
- int acdb_dev_id, int sample_rate)
+ int acdb_dev_id, int sample_rate, int session_type)
{
- pr_debug("%s: fedai_id %d, app_type %d, sample_rate %d\n",
- __func__, fedai_id, app_type, sample_rate);
+ pr_debug("%s: fedai_id %d, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
+ __func__, fedai_id, session_type, app_type,
+ acdb_dev_id, sample_rate);
if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
pr_err("%s: Invalid machine driver ID %d\n",
__func__, fedai_id);
return;
}
- fe_dai_app_type_cfg[fedai_id].app_type = app_type;
- fe_dai_app_type_cfg[fedai_id].acdb_dev_id = acdb_dev_id;
- fe_dai_app_type_cfg[fedai_id].sample_rate = sample_rate;
+ if (session_type != SESSION_TYPE_RX &&
+ session_type != SESSION_TYPE_TX) {
+ pr_err("%s: Invalid session type %d\n",
+ __func__, session_type);
+ return;
+ }
+ fe_dai_app_type_cfg[fedai_id][session_type].app_type = app_type;
+ fe_dai_app_type_cfg[fedai_id][session_type].acdb_dev_id = acdb_dev_id;
+ fe_dai_app_type_cfg[fedai_id][session_type].sample_rate = sample_rate;
}
/**
* msm_pcm_routing_get_stream_app_type_cfg
*
- * Receives fedai_id and populates app_type, acdb_dev_id, &
+ * Receives fedai_id, session_type and populates app_type, acdb_dev_id, &
* sample rate. Returns 0 on success. On failure returns
* -EINVAL and does not alter passed values.
*
* fedai_id - Passed value, front end ID for which app type config is wanted
+ * session_type - Passed value, session type for which app type config
+ * is wanted
* app_type - Returned value, app type used by app type config
* acdb_dev_id - Returned value, ACDB device ID used by app type config
* sample_rate - Returned value, sample rate used by app type config
*/
-int msm_pcm_routing_get_stream_app_type_cfg(int fedai_id, int *app_type,
- int *acdb_dev_id, int *sample_rate)
+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 ret = 0;
@@ -617,13 +654,20 @@ int msm_pcm_routing_get_stream_app_type_cfg(int fedai_id, int *app_type,
__func__, fedai_id);
ret = -EINVAL;
goto done;
+ } else if (session_type != SESSION_TYPE_RX &&
+ session_type != SESSION_TYPE_TX) {
+ pr_err("%s: Invalid session type %d\n",
+ __func__, session_type);
+ ret = -EINVAL;
+ goto done;
}
- *app_type = fe_dai_app_type_cfg[fedai_id].app_type;
- *acdb_dev_id = fe_dai_app_type_cfg[fedai_id].acdb_dev_id;
- *sample_rate = fe_dai_app_type_cfg[fedai_id].sample_rate;
+ *app_type = fe_dai_app_type_cfg[fedai_id][session_type].app_type;
+ *acdb_dev_id = fe_dai_app_type_cfg[fedai_id][session_type].acdb_dev_id;
+ *sample_rate = fe_dai_app_type_cfg[fedai_id][session_type].sample_rate;
- pr_debug("%s: fedai_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
- __func__, fedai_id, *app_type, *acdb_dev_id, *sample_rate);
+ pr_debug("%s: fedai_id %d, session_type %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
+ __func__, fedai_id, session_type,
+ *app_type, *acdb_dev_id, *sample_rate);
done:
return ret;
}
@@ -680,7 +724,8 @@ static struct cal_block_data *msm_routing_find_topology(int path,
return msm_routing_find_topology_by_path(path);
}
-static int msm_routing_get_adm_topology(int path, int fedai_id)
+static int msm_routing_get_adm_topology(int path, int fedai_id,
+ int session_type)
{
int topology = NULL_COPP_TOPOLOGY;
struct cal_block_data *cal_block = NULL;
@@ -693,11 +738,10 @@ static int msm_routing_get_adm_topology(int path, int fedai_id)
mutex_lock(&cal_data->lock);
- if (path == RX_DEVICE) {
- app_type = fe_dai_app_type_cfg[fedai_id].app_type;
- acdb_dev_id = fe_dai_app_type_cfg[fedai_id].acdb_dev_id;
- sample_rate = fe_dai_app_type_cfg[fedai_id].sample_rate;
- }
+ app_type = fe_dai_app_type_cfg[fedai_id][session_type].app_type;
+ acdb_dev_id = fe_dai_app_type_cfg[fedai_id][session_type].acdb_dev_id;
+ sample_rate = fe_dai_app_type_cfg[fedai_id][session_type].sample_rate;
+
cal_block = msm_routing_find_topology(path, app_type,
acdb_dev_id, sample_rate);
if (cal_block == NULL)
@@ -753,9 +797,12 @@ static void msm_pcm_routing_build_matrix(int fedai_id, int sess_type,
if (num_copps) {
payload.num_copps = num_copps;
payload.session_id = fe_dai_map[fedai_id][sess_type].strm_id;
- payload.app_type = fe_dai_app_type_cfg[fedai_id].app_type;
- payload.acdb_dev_id = fe_dai_app_type_cfg[fedai_id].acdb_dev_id;
- payload.sample_rate = fe_dai_app_type_cfg[fedai_id].sample_rate;
+ payload.app_type =
+ fe_dai_app_type_cfg[fedai_id][sess_type].app_type;
+ payload.acdb_dev_id =
+ fe_dai_app_type_cfg[fedai_id][sess_type].acdb_dev_id;
+ payload.sample_rate =
+ fe_dai_app_type_cfg[fedai_id][sess_type].sample_rate;
adm_matrix_map(path_type, payload, perf_mode);
msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode);
}
@@ -863,22 +910,23 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode,
bit_width = msm_routing_get_bit_width(
msm_bedais[i].format);
- app_type = (stream_type == SNDRV_PCM_STREAM_PLAYBACK) ?
- fe_dai_app_type_cfg[fe_id].app_type : 0;
+ app_type =
+ fe_dai_app_type_cfg[fe_id][session_type].app_type;
if (app_type) {
app_type_idx =
msm_pcm_routing_get_app_type_idx(
app_type);
sample_rate =
- fe_dai_app_type_cfg[fe_id].sample_rate;
+ fe_dai_app_type_cfg[fe_id][session_type].sample_rate;
bit_width =
app_type_cfg[app_type_idx].bit_width;
} else {
sample_rate = msm_bedais[i].sample_rate;
}
- acdb_dev_id = fe_dai_app_type_cfg[fe_id].acdb_dev_id;
+ acdb_dev_id =
+ fe_dai_app_type_cfg[fe_id][session_type].acdb_dev_id;
topology = msm_routing_get_adm_topology(path_type,
- fe_id);
+ fe_id, session_type);
if (compr_passthr_mode == COMPRESSED_PASSTHROUGH_DSD)
topology = COMPRESS_PASSTHROUGH_NONE_TOPOLOGY;
pr_err("%s: Before adm open topology %d\n", __func__,
@@ -928,8 +976,10 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode,
if (num_copps) {
payload.num_copps = num_copps;
payload.session_id = fe_dai_map[fe_id][session_type].strm_id;
- payload.app_type = fe_dai_app_type_cfg[fe_id].app_type;
- payload.acdb_dev_id = fe_dai_app_type_cfg[fe_id].acdb_dev_id;
+ payload.app_type =
+ fe_dai_app_type_cfg[fe_id][session_type].app_type;
+ payload.acdb_dev_id =
+ fe_dai_app_type_cfg[fe_id][session_type].acdb_dev_id;
adm_matrix_map(path_type, payload, perf_mode);
msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode);
}
@@ -1026,21 +1076,23 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
bits_per_sample = msm_routing_get_bit_width(
msm_bedais[i].format);
- app_type = (stream_type == SNDRV_PCM_STREAM_PLAYBACK) ?
- fe_dai_app_type_cfg[fedai_id].app_type : 0;
+ app_type =
+ fe_dai_app_type_cfg[fedai_id][session_type].app_type;
if (app_type) {
app_type_idx =
msm_pcm_routing_get_app_type_idx(app_type);
sample_rate =
- fe_dai_app_type_cfg[fedai_id].sample_rate;
+ fe_dai_app_type_cfg[fedai_id][session_type].
+ sample_rate;
bits_per_sample =
app_type_cfg[app_type_idx].bit_width;
} else
sample_rate = msm_bedais[i].sample_rate;
- acdb_dev_id = fe_dai_app_type_cfg[fedai_id].acdb_dev_id;
+ acdb_dev_id =
+ fe_dai_app_type_cfg[fedai_id][session_type].acdb_dev_id;
topology = msm_routing_get_adm_topology(path_type,
- fedai_id);
+ fedai_id, session_type);
copp_idx = adm_open(msm_bedais[i].port_id, path_type,
sample_rate, channels, topology,
perf_mode, bits_per_sample,
@@ -1085,9 +1137,12 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode,
if (num_copps) {
payload.num_copps = num_copps;
payload.session_id = fe_dai_map[fedai_id][session_type].strm_id;
- payload.app_type = fe_dai_app_type_cfg[fedai_id].app_type;
- payload.acdb_dev_id = fe_dai_app_type_cfg[fedai_id].acdb_dev_id;
- payload.sample_rate = fe_dai_app_type_cfg[fedai_id].sample_rate;
+ payload.app_type =
+ fe_dai_app_type_cfg[fedai_id][session_type].app_type;
+ payload.acdb_dev_id =
+ fe_dai_app_type_cfg[fedai_id][session_type].acdb_dev_id;
+ payload.sample_rate =
+ fe_dai_app_type_cfg[fedai_id][session_type].sample_rate;
adm_matrix_map(path_type, payload, perf_mode);
msm_pcm_routng_cfg_matrix_map_pp(payload, path_type, perf_mode);
}
@@ -1255,20 +1310,23 @@ static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
bits_per_sample = msm_routing_get_bit_width(
msm_bedais[reg].format);
- app_type = (session_type == SESSION_TYPE_RX) ?
- fe_dai_app_type_cfg[val].app_type : 0;
+ app_type =
+ fe_dai_app_type_cfg[val][session_type].app_type;
if (app_type) {
app_type_idx =
msm_pcm_routing_get_app_type_idx(app_type);
sample_rate =
- fe_dai_app_type_cfg[val].sample_rate;
+ fe_dai_app_type_cfg[val][session_type].
+ sample_rate;
bits_per_sample =
app_type_cfg[app_type_idx].bit_width;
} else
sample_rate = msm_bedais[reg].sample_rate;
- topology = msm_routing_get_adm_topology(path_type, val);
- acdb_dev_id = fe_dai_app_type_cfg[val].acdb_dev_id;
+ topology = msm_routing_get_adm_topology(path_type, val,
+ session_type);
+ acdb_dev_id =
+ fe_dai_app_type_cfg[val][session_type].acdb_dev_id;
copp_idx = adm_open(msm_bedais[reg].port_id, path_type,
sample_rate, channels, topology,
fdai->perf_mode, bits_per_sample,
@@ -2919,6 +2977,108 @@ static const struct snd_kcontrol_new primary_mi2s_rx_mixer_controls[] = {
msm_routing_put_audio_mixer),
};
+static const struct snd_kcontrol_new int0_mi2s_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+};
+
+static const struct snd_kcontrol_new int4_mi2s_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+};
+
static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -4358,6 +4518,12 @@ static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -4451,6 +4617,12 @@ static const struct snd_kcontrol_new mmul2_mixer_controls[] = {
SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -4526,6 +4698,12 @@ static const struct snd_kcontrol_new mmul3_mixer_controls[] = {
SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0,
MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -4604,6 +4782,12 @@ static const struct snd_kcontrol_new mmul4_mixer_controls[] = {
SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -4646,6 +4830,12 @@ static const struct snd_kcontrol_new mmul5_mixer_controls[] = {
SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_TERT_TDM_TX_0,
MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -4703,6 +4893,12 @@ static const struct snd_kcontrol_new mmul6_mixer_controls[] = {
SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -4760,6 +4956,12 @@ static const struct snd_kcontrol_new mmul8_mixer_controls[] = {
SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT2_MI2S_TX", MSM_BACKEND_DAI_INT2_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -5113,6 +5315,42 @@ static const struct snd_kcontrol_new pri_mi2s_rx_voice_mixer_controls[] = {
msm_routing_put_voice_mixer),
};
+static const struct snd_kcontrol_new int0_mi2s_rx_voice_mixer_controls[] = {
+ SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_VOICEMMODE1, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("VoiceMMode2", MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_FRONTEND_DAI_VOICEMMODE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+};
+
+static const struct snd_kcontrol_new int4_mi2s_rx_voice_mixer_controls[] = {
+ SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("QCHAT", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("VoiceMMode1", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_VOICEMMODE1, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("VoiceMMode2", MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_FRONTEND_DAI_VOICEMMODE2, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+};
+
static const struct snd_kcontrol_new tert_mi2s_rx_voice_mixer_controls[] = {
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
@@ -5777,6 +6015,9 @@ static const struct snd_kcontrol_new tx_voicemmode1_mixer_controls[] = {
SOC_SINGLE_EXT("TERT_MI2S_TX_MMode1",
MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_VOICEMMODE1,
1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("INT3_MI2S_TX_MMode1",
+ MSM_BACKEND_DAI_INT3_MI2S_TX, MSM_FRONTEND_DAI_VOICEMMODE1,
+ 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("SLIM_7_TX_MMode1",
MSM_BACKEND_DAI_SLIMBUS_7_TX, MSM_FRONTEND_DAI_VOICEMMODE1, 1,
0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
@@ -5822,6 +6063,9 @@ static const struct snd_kcontrol_new tx_voicemmode2_mixer_controls[] = {
SOC_SINGLE_EXT("TERT_MI2S_TX_MMode2",
MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_VOICEMMODE2,
1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("INT3_MI2S_TX_MMode2",
+ MSM_BACKEND_DAI_INT3_MI2S_TX, MSM_FRONTEND_DAI_VOICEMMODE2,
+ 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("SLIM_7_TX_MMode2",
MSM_BACKEND_DAI_SLIMBUS_7_TX, MSM_FRONTEND_DAI_VOICEMMODE2, 1,
0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
@@ -5867,6 +6111,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("INT3_MI2S_TX_Voip", MSM_BACKEND_DAI_INT3_MI2S_TX,
+ MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("SLIM_7_TX_Voip", MSM_BACKEND_DAI_SLIMBUS_7_TX,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -5900,6 +6147,9 @@ static const struct snd_kcontrol_new tx_voice_stub_mixer_controls[] = {
SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("INT3_MI2S_TX", MSM_BACKEND_DAI_INT3_MI2S_TX,
+ MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
@@ -6056,6 +6306,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("INT3_MI2S_TX_QCHAT", MSM_BACKEND_DAI_INT3_MI2S_TX,
+ MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("SLIM_7_TX_QCHAT", MSM_BACKEND_DAI_SLIMBUS_7_TX,
MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -7877,6 +8130,12 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
SND_SOC_DAPM_AIF_IN("HDMI_DL_HL", "HDMI_HOSTLESS Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_I2S_DL_HL", "SEC_I2S_RX_HOSTLESS Playback",
0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("INT0_MI2S_DL_HL",
+ "INT0 MI2S_RX Hostless Playback",
+ 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("INT4_MI2S_DL_HL",
+ "INT4 MI2S_RX Hostless Playback",
+ 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRI_MI2S_DL_HL",
"Primary MI2S_RX Hostless Playback",
0, 0, 0, 0),
@@ -8150,6 +8409,10 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("PRI_MI2S_RX", "Primary MI2S Playback",
0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("INT0_MI2S_RX", "INT0 MI2S Playback",
+ 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("INT4_MI2S_RX", "INT4 MI2S Playback",
+ 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("QUIN_MI2S_RX", "Quinary MI2S Playback",
0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0),
@@ -8160,6 +8423,10 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("TERT_MI2S_TX", "Tertiary MI2S Capture",
0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("INT2_MI2S_TX", "INT2 MI2S Capture",
+ 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("INT3_MI2S_TX", "INT3 MI2S Capture",
+ 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX", "Secondary MI2S Capture",
0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
@@ -8444,6 +8711,12 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
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)),
+ SND_SOC_DAPM_MIXER("INT0_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+ int0_mi2s_rx_mixer_controls,
+ ARRAY_SIZE(int0_mi2s_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("INT4_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+ int4_mi2s_rx_mixer_controls,
+ ARRAY_SIZE(int4_mi2s_rx_mixer_controls)),
SND_SOC_DAPM_MIXER("QUIN_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
quinary_mi2s_rx_mixer_controls,
ARRAY_SIZE(quinary_mi2s_rx_mixer_controls)),
@@ -8581,6 +8854,14 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
SND_SOC_NOPM, 0, 0,
pri_mi2s_rx_voice_mixer_controls,
ARRAY_SIZE(pri_mi2s_rx_voice_mixer_controls)),
+ SND_SOC_DAPM_MIXER("INT0_MI2S_RX_Voice Mixer",
+ SND_SOC_NOPM, 0, 0,
+ int0_mi2s_rx_voice_mixer_controls,
+ ARRAY_SIZE(int0_mi2s_rx_voice_mixer_controls)),
+ SND_SOC_DAPM_MIXER("INT4_MI2S_RX_Voice Mixer",
+ SND_SOC_NOPM, 0, 0,
+ int4_mi2s_rx_voice_mixer_controls,
+ ARRAY_SIZE(int4_mi2s_rx_voice_mixer_controls)),
SND_SOC_DAPM_MIXER("TERT_MI2S_RX_Voice Mixer",
SND_SOC_NOPM, 0, 0,
tert_mi2s_rx_voice_mixer_controls,
@@ -9082,6 +9363,42 @@ static const struct snd_soc_dapm_route intercon[] = {
{"PRI_MI2S_RX Audio Mixer", "MultiMedia16", "MM_DL16"},
{"PRI_MI2S_RX", NULL, "PRI_MI2S_RX Audio Mixer"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia10", "MM_DL10"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia11", "MM_DL11"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia12", "MM_DL12"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia13", "MM_DL13"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia14", "MM_DL14"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia15", "MM_DL15"},
+ {"INT0_MI2S_RX Audio Mixer", "MultiMedia16", "MM_DL16"},
+ {"INT0_MI2S_RX", NULL, "INT0_MI2S_RX Audio Mixer"},
+
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia10", "MM_DL10"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia11", "MM_DL11"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia12", "MM_DL12"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia13", "MM_DL13"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia14", "MM_DL14"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia15", "MM_DL15"},
+ {"INT4_MI2S_RX Audio Mixer", "MultiMedia16", "MM_DL16"},
+ {"INT4_MI2S_RX", NULL, "INT4_MI2S_RX Audio Mixer"},
+
+ {"QUIN_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
+ {"QUIN_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"QUIN_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"QUIN_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"QUIN_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
@@ -9363,6 +9680,10 @@ static const struct snd_soc_dapm_route intercon[] = {
{"MultiMedia2 Mixer", "QUIN_MI2S_TX", "QUIN_MI2S_TX"},
{"MultiMedia1 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
{"MultiMedia2 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
+ {"MultiMedia1 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"},
+ {"MultiMedia2 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"},
+ {"MultiMedia1 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"},
+ {"MultiMedia2 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"},
{"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"MultiMedia3 Mixer", "AUX_PCM_TX", "AUX_PCM_TX"},
@@ -9384,6 +9705,12 @@ static const struct snd_soc_dapm_route intercon[] = {
{"MultiMedia6 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
{"MultiMedia3 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
{"MultiMedia5 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
+ {"MultiMedia6 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"},
+ {"MultiMedia3 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"},
+ {"MultiMedia5 Mixer", "INT2_MI2S_TX", "INT2_MI2S_TX"},
+ {"MultiMedia6 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"},
+ {"MultiMedia3 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"},
+ {"MultiMedia5 Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"},
{"MultiMedia6 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
{"MultiMedia6 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"MultiMedia6 Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
@@ -9821,6 +10148,20 @@ static const struct snd_soc_dapm_route intercon[] = {
{"PRI_MI2S_RX_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"},
{"PRI_MI2S_RX", NULL, "PRI_MI2S_RX_Voice Mixer"},
+ {"INT0_MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
+ {"INT0_MI2S_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
+ {"INT0_MI2S_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+ {"INT0_MI2S_RX_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"},
+ {"INT0_MI2S_RX_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"},
+ {"INT0_MI2S_RX", NULL, "INT0_MI2S_RX_Voice Mixer"},
+
+ {"INT4_MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
+ {"INT4_MI2S_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
+ {"INT4_MI2S_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+ {"INT4_MI2S_RX_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"},
+ {"INT4_MI2S_RX_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"},
+ {"INT4_MI2S_RX", NULL, "INT4_MI2S_RX_Voice Mixer"},
+
{"TERT_MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"TERT_MI2S_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"TERT_MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
@@ -9992,6 +10333,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"VoiceMMode1_Tx Mixer", "PRI_MI2S_TX_MMode1", "PRI_MI2S_TX"},
{"VoiceMMode1_Tx Mixer", "MI2S_TX_MMode1", "MI2S_TX"},
{"VoiceMMode1_Tx Mixer", "TERT_MI2S_TX_MMode1", "TERT_MI2S_TX"},
+ {"VoiceMMode1_Tx Mixer", "INT3_MI2S_TX_MMode1", "INT3_MI2S_TX"},
{"VoiceMMode1_Tx Mixer", "SLIM_0_TX_MMode1", "SLIMBUS_0_TX"},
{"VoiceMMode1_Tx Mixer", "SLIM_7_TX_MMode1", "SLIMBUS_7_TX"},
{"VoiceMMode1_Tx Mixer", "SLIM_8_TX_MMode1", "SLIMBUS_8_TX"},
@@ -10008,6 +10350,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"VoiceMMode2_Tx Mixer", "PRI_MI2S_TX_MMode2", "PRI_MI2S_TX"},
{"VoiceMMode2_Tx Mixer", "MI2S_TX_MMode2", "MI2S_TX"},
{"VoiceMMode2_Tx Mixer", "TERT_MI2S_TX_MMode2", "TERT_MI2S_TX"},
+ {"VoiceMMode2_Tx Mixer", "INT3_MI2S_TX_MMode2", "INT3_MI2S_TX"},
{"VoiceMMode2_Tx Mixer", "SLIM_0_TX_MMode2", "SLIMBUS_0_TX"},
{"VoiceMMode2_Tx Mixer", "SLIM_7_TX_MMode2", "SLIMBUS_7_TX"},
{"VoiceMMode2_Tx Mixer", "SLIM_8_TX_MMode2", "SLIMBUS_8_TX"},
@@ -10023,6 +10366,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
{"Voip_Tx Mixer", "MI2S_TX_Voip", "MI2S_TX"},
{"Voip_Tx Mixer", "TERT_MI2S_TX_Voip", "TERT_MI2S_TX"},
+ {"Voip_Tx Mixer", "INT3_MI2S_TX_Voip", "INT3_MI2S_TX"},
{"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"},
{"Voip_Tx Mixer", "SLIM_7_TX_Voip", "SLIMBUS_7_TX"},
{"Voip_Tx Mixer", "SLIM_8_TX_Voip", "SLIMBUS_8_TX"},
@@ -10132,6 +10476,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", "INT3_MI2S_TX_QCHAT", "INT3_MI2S_TX"},
{"QCHAT_Tx Mixer", "USB_AUDIO_TX_QCHAT", "USB_AUDIO_TX"},
{"QCHAT_UL", NULL, "QCHAT_Tx Mixer"},
@@ -10149,6 +10494,10 @@ static const struct snd_soc_dapm_route intercon[] = {
{"MI2S_UL_HL", NULL, "MI2S_TX"},
{"PCM_RX_DL_HL", "Switch", "SLIM0_DL_HL"},
{"PCM_RX", NULL, "PCM_RX_DL_HL"},
+ {"INT0_MI2S_RX_DL_HL", "Switch", "INT0_MI2S_DL_HL"},
+ {"INT0_MI2S_RX", NULL, "INT0_MI2S_RX_DL_HL"},
+ {"INT4_MI2S_RX_DL_HL", "Switch", "INT4_MI2S_DL_HL"},
+ {"INT4_MI2S_RX", NULL, "INT4_MI2S_RX_DL_HL"},
{"PRI_MI2S_RX_DL_HL", "Switch", "PRI_MI2S_DL_HL"},
{"PRI_MI2S_RX", NULL, "PRI_MI2S_RX_DL_HL"},
{"SEC_MI2S_RX_DL_HL", "Switch", "SEC_MI2S_DL_HL"},
@@ -10384,6 +10733,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Voice Stub Tx Mixer", "MI2S_TX", "MI2S_TX"},
{"Voice Stub Tx Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
{"Voice Stub Tx Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
+ {"Voice Stub Tx Mixer", "INT3_MI2S_TX", "INT3_MI2S_TX"},
{"Voice Stub Tx Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
{"Voice Stub Tx Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"Voice Stub Tx Mixer", "SLIM_3_TX", "SLIMBUS_3_TX"},
@@ -10561,6 +10911,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"BE_OUT", NULL, "SEC_MI2S_RX"},
{"BE_OUT", NULL, "SEC_MI2S_RX_SD1"},
{"BE_OUT", NULL, "PRI_MI2S_RX"},
+ {"BE_OUT", NULL, "INT0_MI2S_RX"},
+ {"BE_OUT", NULL, "INT4_MI2S_RX"},
{"BE_OUT", NULL, "INT_BT_SCO_RX"},
{"BE_OUT", NULL, "INT_BT_A2DP_RX"},
{"BE_OUT", NULL, "INT_FM_RX"},
@@ -10593,6 +10945,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"QUIN_MI2S_TX", NULL, "BE_IN"},
{"PRI_MI2S_TX", NULL, "BE_IN"},
{"TERT_MI2S_TX", NULL, "BE_IN"},
+ {"INT2_MI2S_TX", NULL, "BE_IN"},
+ {"INT3_MI2S_TX", NULL, "BE_IN"},
{"SEC_MI2S_TX", NULL, "BE_IN"},
{"SENARY_MI2S_TX", NULL, "BE_IN" },
{"SLIMBUS_0_TX", NULL, "BE_IN" },
@@ -10726,7 +11080,6 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
int i, path_type, session_type, topology;
struct msm_pcm_routing_bdai_data *bedai;
u32 channels, sample_rate;
- bool playback, capture;
uint16_t bits_per_sample = 16, voc_path_type;
struct msm_pcm_routing_fdai_data *fdai;
u32 session_id;
@@ -10762,8 +11115,6 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
* is started.
*/
bedai->active = 1;
- playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
- capture = substream->stream == SNDRV_PCM_STREAM_CAPTURE;
for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
fdai = &fe_dai_map[i][session_type];
@@ -10785,13 +11136,14 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
bits_per_sample = msm_routing_get_bit_width(
bedai->format);
- app_type = playback ?
- fe_dai_app_type_cfg[i].app_type : 0;
+ app_type =
+ fe_dai_app_type_cfg[i][session_type].app_type;
if (app_type) {
app_type_idx =
msm_pcm_routing_get_app_type_idx(app_type);
sample_rate =
- fe_dai_app_type_cfg[i].sample_rate;
+ fe_dai_app_type_cfg[i][session_type].
+ sample_rate;
bits_per_sample =
app_type_cfg[app_type_idx].bit_width;
} else
@@ -10804,8 +11156,10 @@ static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
channels = bedai->channel;
else
channels = bedai->adm_override_ch;
- acdb_dev_id = fe_dai_app_type_cfg[i].acdb_dev_id;
- topology = msm_routing_get_adm_topology(path_type, i);
+ acdb_dev_id =
+ fe_dai_app_type_cfg[i][session_type].acdb_dev_id;
+ topology = msm_routing_get_adm_topology(path_type, i,
+ session_type);
copp_idx = adm_open(bedai->port_id, path_type,
sample_rate, channels, topology,
fdai->perf_mode, bits_per_sample,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 8e3086849d92..8a62e900ff28 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -143,6 +143,21 @@
#define LPASS_BE_USB_AUDIO_RX "USB_AUDIO_RX"
#define LPASS_BE_USB_AUDIO_TX "USB_AUDIO_TX"
+
+#define LPASS_BE_INT0_MI2S_RX "INT0_MI2S_RX"
+#define LPASS_BE_INT0_MI2S_TX "INT0_MI2S_TX"
+#define LPASS_BE_INT1_MI2S_RX "INT1_MI2S_RX"
+#define LPASS_BE_INT1_MI2S_TX "INT1_MI2S_TX"
+#define LPASS_BE_INT2_MI2S_RX "INT2_MI2S_RX"
+#define LPASS_BE_INT2_MI2S_TX "INT2_MI2S_TX"
+#define LPASS_BE_INT3_MI2S_RX "INT3_MI2S_RX"
+#define LPASS_BE_INT3_MI2S_TX "INT3_MI2S_TX"
+#define LPASS_BE_INT4_MI2S_RX "INT4_MI2S_RX"
+#define LPASS_BE_INT4_MI2S_TX "INT4_MI2S_TX"
+#define LPASS_BE_INT5_MI2S_RX "INT5_MI2S_RX"
+#define LPASS_BE_INT5_MI2S_TX "INT5_MI2S_TX"
+#define LPASS_BE_INT6_MI2S_RX "INT6_MI2S_RX"
+#define LPASS_BE_INT6_MI2S_TX "INT6_MI2S_TX"
/* For multimedia front-ends, asm session is allocated dynamically.
* Hence, asm session/multimedia front-end mapping has to be maintained.
* Due to this reason, additional multimedia front-end must be placed before
@@ -321,6 +336,20 @@ enum {
MSM_BACKEND_DAI_TERT_AUXPCM_TX,
MSM_BACKEND_DAI_QUAT_AUXPCM_RX,
MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
+ MSM_BACKEND_DAI_INT0_MI2S_RX,
+ MSM_BACKEND_DAI_INT0_MI2S_TX,
+ MSM_BACKEND_DAI_INT1_MI2S_RX,
+ MSM_BACKEND_DAI_INT1_MI2S_TX,
+ MSM_BACKEND_DAI_INT2_MI2S_RX,
+ MSM_BACKEND_DAI_INT2_MI2S_TX,
+ MSM_BACKEND_DAI_INT3_MI2S_RX,
+ MSM_BACKEND_DAI_INT3_MI2S_TX,
+ MSM_BACKEND_DAI_INT4_MI2S_RX,
+ MSM_BACKEND_DAI_INT4_MI2S_TX,
+ MSM_BACKEND_DAI_INT5_MI2S_RX,
+ MSM_BACKEND_DAI_INT5_MI2S_TX,
+ MSM_BACKEND_DAI_INT6_MI2S_RX,
+ MSM_BACKEND_DAI_INT6_MI2S_TX,
MSM_BACKEND_DAI_MAX,
};
@@ -432,7 +461,7 @@ void msm_pcm_routing_acquire_lock(void);
void msm_pcm_routing_release_lock(void);
void msm_pcm_routing_reg_stream_app_type_cfg(int fedai_id, int app_type,
- int acdb_dev_id, int sample_rate);
-int msm_pcm_routing_get_stream_app_type_cfg(int fedai_id, int *app_type,
- int *acdb_dev_id, int *sample_rate);
+ 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);
#endif /*_MSM_PCM_H*/
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 78546fef7b3b..c75f7214db1a 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -483,6 +483,13 @@ int afe_get_port_type(u16 port_id)
case AFE_PORT_ID_QUATERNARY_TDM_RX_6:
case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
case AFE_PORT_ID_USB_RX:
+ case AFE_PORT_ID_INT0_MI2S_RX:
+ case AFE_PORT_ID_INT1_MI2S_RX:
+ case AFE_PORT_ID_INT2_MI2S_RX:
+ case AFE_PORT_ID_INT3_MI2S_RX:
+ case AFE_PORT_ID_INT4_MI2S_RX:
+ case AFE_PORT_ID_INT5_MI2S_RX:
+ case AFE_PORT_ID_INT6_MI2S_RX:
ret = MSM_AFE_PORT_TYPE_RX;
break;
@@ -547,6 +554,13 @@ int afe_get_port_type(u16 port_id)
case AFE_PORT_ID_QUATERNARY_TDM_TX_6:
case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
case AFE_PORT_ID_USB_TX:
+ case AFE_PORT_ID_INT0_MI2S_TX:
+ case AFE_PORT_ID_INT1_MI2S_TX:
+ case AFE_PORT_ID_INT2_MI2S_TX:
+ case AFE_PORT_ID_INT3_MI2S_TX:
+ case AFE_PORT_ID_INT4_MI2S_TX:
+ case AFE_PORT_ID_INT5_MI2S_TX:
+ case AFE_PORT_ID_INT6_MI2S_TX:
ret = MSM_AFE_PORT_TYPE_TX;
break;
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 0ea94cb52bfb..2874a334dfdd 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1658,8 +1658,10 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
ac->apr = NULL;
atomic_set(&ac->time_flag, 0);
atomic_set(&ac->cmd_state, 0);
+ atomic_set(&ac->mem_state, 0);
wake_up(&ac->time_wait);
wake_up(&ac->cmd_wait);
+ wake_up(&ac->mem_wait);
mutex_unlock(&ac->cmd_lock);
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index 99f5f0e1a5a5..84e1178dc354 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -233,6 +233,34 @@ int q6audio_get_port_index(u16 port_id)
return IDX_AFE_PORT_ID_USB_RX;
case AFE_PORT_ID_USB_TX:
return IDX_AFE_PORT_ID_USB_TX;
+ case AFE_PORT_ID_INT0_MI2S_RX:
+ return IDX_AFE_PORT_ID_INT0_MI2S_RX;
+ case AFE_PORT_ID_INT0_MI2S_TX:
+ return IDX_AFE_PORT_ID_INT0_MI2S_TX;
+ case AFE_PORT_ID_INT1_MI2S_RX:
+ return IDX_AFE_PORT_ID_INT1_MI2S_RX;
+ case AFE_PORT_ID_INT1_MI2S_TX:
+ return IDX_AFE_PORT_ID_INT1_MI2S_TX;
+ case AFE_PORT_ID_INT2_MI2S_RX:
+ return IDX_AFE_PORT_ID_INT2_MI2S_RX;
+ case AFE_PORT_ID_INT2_MI2S_TX:
+ return IDX_AFE_PORT_ID_INT2_MI2S_TX;
+ case AFE_PORT_ID_INT3_MI2S_RX:
+ return IDX_AFE_PORT_ID_INT3_MI2S_RX;
+ case AFE_PORT_ID_INT3_MI2S_TX:
+ return IDX_AFE_PORT_ID_INT3_MI2S_TX;
+ case AFE_PORT_ID_INT4_MI2S_RX:
+ return IDX_AFE_PORT_ID_INT4_MI2S_RX;
+ case AFE_PORT_ID_INT4_MI2S_TX:
+ return IDX_AFE_PORT_ID_INT4_MI2S_TX;
+ case AFE_PORT_ID_INT5_MI2S_RX:
+ return IDX_AFE_PORT_ID_INT5_MI2S_RX;
+ case AFE_PORT_ID_INT5_MI2S_TX:
+ return IDX_AFE_PORT_ID_INT5_MI2S_TX;
+ case AFE_PORT_ID_INT6_MI2S_RX:
+ return IDX_AFE_PORT_ID_INT6_MI2S_RX;
+ case AFE_PORT_ID_INT6_MI2S_TX:
+ return IDX_AFE_PORT_ID_INT6_MI2S_TX;
default: return -EINVAL;
}
}
@@ -452,6 +480,34 @@ int q6audio_get_port_id(u16 port_id)
return AFE_PORT_ID_USB_RX;
case AFE_PORT_ID_USB_TX:
return AFE_PORT_ID_USB_TX;
+ case AFE_PORT_ID_INT0_MI2S_RX:
+ return AFE_PORT_ID_INT0_MI2S_RX;
+ case AFE_PORT_ID_INT0_MI2S_TX:
+ return AFE_PORT_ID_INT0_MI2S_TX;
+ case AFE_PORT_ID_INT1_MI2S_RX:
+ return AFE_PORT_ID_INT1_MI2S_RX;
+ case AFE_PORT_ID_INT1_MI2S_TX:
+ return AFE_PORT_ID_INT1_MI2S_TX;
+ case AFE_PORT_ID_INT2_MI2S_RX:
+ return AFE_PORT_ID_INT2_MI2S_RX;
+ case AFE_PORT_ID_INT2_MI2S_TX:
+ return AFE_PORT_ID_INT2_MI2S_TX;
+ case AFE_PORT_ID_INT3_MI2S_RX:
+ return AFE_PORT_ID_INT3_MI2S_RX;
+ case AFE_PORT_ID_INT3_MI2S_TX:
+ return AFE_PORT_ID_INT3_MI2S_TX;
+ case AFE_PORT_ID_INT4_MI2S_RX:
+ return AFE_PORT_ID_INT4_MI2S_RX;
+ case AFE_PORT_ID_INT4_MI2S_TX:
+ return AFE_PORT_ID_INT4_MI2S_TX;
+ case AFE_PORT_ID_INT5_MI2S_RX:
+ return AFE_PORT_ID_INT5_MI2S_RX;
+ case AFE_PORT_ID_INT5_MI2S_TX:
+ return AFE_PORT_ID_INT5_MI2S_TX;
+ case AFE_PORT_ID_INT6_MI2S_RX:
+ return AFE_PORT_ID_INT6_MI2S_RX;
+ case AFE_PORT_ID_INT6_MI2S_TX:
+ return AFE_PORT_ID_INT6_MI2S_TX;
default:
pr_warn("%s: Invalid port_id %d\n", __func__, port_id);
return -EINVAL;
@@ -572,6 +628,20 @@ int q6audio_is_digital_pcm_interface(u16 port_id)
case AFE_PORT_ID_QUATERNARY_TDM_RX_7:
case AFE_PORT_ID_QUATERNARY_TDM_TX_7:
case AFE_PORT_ID_SENARY_MI2S_TX:
+ case AFE_PORT_ID_INT0_MI2S_RX:
+ case AFE_PORT_ID_INT0_MI2S_TX:
+ case AFE_PORT_ID_INT1_MI2S_RX:
+ case AFE_PORT_ID_INT1_MI2S_TX:
+ case AFE_PORT_ID_INT2_MI2S_RX:
+ case AFE_PORT_ID_INT2_MI2S_TX:
+ case AFE_PORT_ID_INT3_MI2S_RX:
+ case AFE_PORT_ID_INT3_MI2S_TX:
+ case AFE_PORT_ID_INT4_MI2S_RX:
+ case AFE_PORT_ID_INT4_MI2S_TX:
+ case AFE_PORT_ID_INT5_MI2S_RX:
+ case AFE_PORT_ID_INT5_MI2S_TX:
+ case AFE_PORT_ID_INT6_MI2S_RX:
+ case AFE_PORT_ID_INT6_MI2S_TX:
break;
default:
ret = -EINVAL;
@@ -710,6 +780,20 @@ int q6audio_validate_port(u16 port_id)
case AFE_PORT_ID_SENARY_MI2S_TX:
case AFE_PORT_ID_USB_RX:
case AFE_PORT_ID_USB_TX:
+ case AFE_PORT_ID_INT0_MI2S_RX:
+ case AFE_PORT_ID_INT0_MI2S_TX:
+ case AFE_PORT_ID_INT1_MI2S_RX:
+ case AFE_PORT_ID_INT1_MI2S_TX:
+ case AFE_PORT_ID_INT2_MI2S_RX:
+ case AFE_PORT_ID_INT2_MI2S_TX:
+ case AFE_PORT_ID_INT3_MI2S_RX:
+ case AFE_PORT_ID_INT3_MI2S_TX:
+ case AFE_PORT_ID_INT4_MI2S_RX:
+ case AFE_PORT_ID_INT4_MI2S_TX:
+ case AFE_PORT_ID_INT5_MI2S_RX:
+ case AFE_PORT_ID_INT5_MI2S_TX:
+ case AFE_PORT_ID_INT6_MI2S_RX:
+ case AFE_PORT_ID_INT6_MI2S_TX:
{
ret = 0;
break;
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index c8f45b4efa21..f4ceb5f5c678 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -852,8 +852,8 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
}
}
- printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name,
- cpu_dai->name);
+ dev_dbg(rtd->card->dev, "compress asoc: %s <-> %s mapping ok\n",
+ codec_dai->name, cpu_dai->name);
return ret;
compr_err:
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 4ef20ba02cb4..13649f96b370 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -3017,7 +3017,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
pcm->private_free = platform->driver->pcm_free;
out:
- dev_info(rtd->card->dev, "%s <-> %s mapping ok\n",
+ dev_dbg(rtd->card->dev, "%s <-> %s mapping ok\n",
(rtd->num_codecs > 1) ? "multicodec" : rtd->codec_dai->name,
cpu_dai->name);
return ret;
diff --git a/sound/usb/usb_audio_qmi_svc.c b/sound/usb/usb_audio_qmi_svc.c
index 9f7d4e2cb532..22468eee62db 100644
--- a/sound/usb/usb_audio_qmi_svc.c
+++ b/sound/usb/usb_audio_qmi_svc.c
@@ -68,6 +68,9 @@ struct intf_info {
size_t xfer_buf_size;
phys_addr_t xfer_buf_pa;
u8 *xfer_buf;
+ u8 pcm_card_num;
+ u8 pcm_dev_num;
+ u8 direction;
bool in_use;
};
@@ -115,6 +118,7 @@ struct uaudio_qmi_svc {
struct qmi_handle *uaudio_svc_hdl;
void *curr_conn;
struct work_struct recv_msg_work;
+ struct work_struct qmi_disconnect_work;
struct workqueue_struct *uaudio_wq;
ktime_t t_request_recvd;
ktime_t t_resp_sent;
@@ -385,7 +389,7 @@ static void uaudio_iommu_unmap(enum mem_type mtype, unsigned long va,
static int prepare_qmi_response(struct snd_usb_substream *subs,
struct qmi_uaudio_stream_resp_msg_v01 *resp, u32 xfer_buf_len,
- int card_num)
+ int card_num, int pcm_dev_num)
{
int ret = -ENODEV;
struct usb_interface *iface;
@@ -411,6 +415,14 @@ static int prepare_qmi_response(struct snd_usb_substream *subs,
goto err;
}
+ if (uadev[card_num].info &&
+ uadev[card_num].info[subs->interface].in_use) {
+ pr_err("%s interface# %d already in use card# %d\n", __func__,
+ subs->interface, card_num);
+ ret = -EBUSY;
+ goto err;
+ }
+
alts = &iface->altsetting[subs->altset_idx];
altsd = get_iface_desc(alts);
protocol = altsd->bInterfaceProtocol;
@@ -627,12 +639,6 @@ skip_sync:
kref_get(&uadev[card_num].kref);
}
- if (uadev[card_num].info[subs->interface].in_use) {
- pr_err("%s interface# %d already in use card# %d\n", __func__,
- subs->interface, card_num);
- goto unmap_xfer_buf;
- }
-
uadev[card_num].card_num = card_num;
/* cache intf specific info to use it for unmap and free xfer buf */
@@ -644,6 +650,9 @@ skip_sync:
uadev[card_num].info[subs->interface].xfer_buf_pa = xfer_buf_pa;
uadev[card_num].info[subs->interface].xfer_buf_size = len;
uadev[card_num].info[subs->interface].xfer_buf = xfer_buf;
+ uadev[card_num].info[subs->interface].pcm_card_num = card_num;
+ uadev[card_num].info[subs->interface].pcm_dev_num = pcm_dev_num;
+ uadev[card_num].info[subs->interface].direction = subs->direction;
uadev[card_num].info[subs->interface].in_use = true;
set_bit(card_num, &uaudio_qdev->card_slot);
@@ -665,9 +674,71 @@ err:
return ret;
}
-void uaudio_disconnect_cb(struct snd_usb_audio *chip)
+static void uaudio_dev_intf_cleanup(struct usb_device *udev,
+ struct intf_info *info)
+{
+ uaudio_iommu_unmap(MEM_XFER_RING, info->data_xfer_ring_va,
+ info->data_xfer_ring_size);
+ info->data_xfer_ring_va = 0;
+ info->data_xfer_ring_size = 0;
+
+ uaudio_iommu_unmap(MEM_XFER_RING, info->sync_xfer_ring_va,
+ info->sync_xfer_ring_size);
+ info->sync_xfer_ring_va = 0;
+ info->sync_xfer_ring_size = 0;
+
+ uaudio_iommu_unmap(MEM_XFER_BUF, info->xfer_buf_va,
+ info->xfer_buf_size);
+ info->xfer_buf_va = 0;
+
+ usb_free_coherent(udev, info->xfer_buf_size,
+ info->xfer_buf, info->xfer_buf_pa);
+ info->xfer_buf_size = 0;
+ info->xfer_buf = NULL;
+ info->xfer_buf_pa = 0;
+
+ info->in_use = false;
+}
+
+static void uaudio_dev_cleanup(struct uaudio_dev *dev)
{
- int ret, if_idx;
+ int if_idx;
+
+ /* free xfer buffer and unmap xfer ring and buf per interface */
+ for (if_idx = 0; if_idx < dev->num_intf; if_idx++) {
+ if (!dev->info[if_idx].in_use)
+ continue;
+ uaudio_dev_intf_cleanup(dev->udev, &dev->info[if_idx]);
+ pr_debug("%s: release resources: intf# %d card# %d\n", __func__,
+ if_idx, dev->card_num);
+ }
+
+ /* iommu_unmap dcba iova for a usb device */
+ uaudio_iommu_unmap(MEM_DCBA, dev->dcba_iova, dev->dcba_size);
+
+ dev->dcba_iova = 0;
+ dev->dcba_size = 0;
+ dev->num_intf = 0;
+
+ /* free interface info */
+ kfree(dev->info);
+ dev->info = NULL;
+
+ clear_bit(dev->card_num, &uaudio_qdev->card_slot);
+
+ /* all audio devices are disconnected */
+ if (!uaudio_qdev->card_slot) {
+ uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE);
+ usb_sec_event_ring_cleanup(dev->udev, uaudio_qdev->intr_num);
+ pr_debug("%s: all audio devices disconnected\n", __func__);
+ }
+
+ dev->udev = NULL;
+}
+
+static void uaudio_disconnect_cb(struct snd_usb_audio *chip)
+{
+ int ret;
struct uaudio_dev *dev;
int card_num = chip->card_num;
struct uaudio_qmi_svc *svc = uaudio_svc;
@@ -713,57 +784,7 @@ void uaudio_disconnect_cb(struct snd_usb_audio *chip)
mutex_lock(&chip->dev_lock);
}
- /* free xfer buffer and unmap xfer ring and buf per interface */
- for (if_idx = 0; if_idx < dev->num_intf; if_idx++) {
- if (!dev->info[if_idx].in_use)
- continue;
- usb_free_coherent(dev->udev,
- dev->info[if_idx].xfer_buf_size,
- dev->info[if_idx].xfer_buf,
- dev->info[if_idx].xfer_buf_pa);
-
- uaudio_iommu_unmap(MEM_XFER_RING,
- dev->info[if_idx].data_xfer_ring_va,
- dev->info[if_idx].data_xfer_ring_size);
- dev->info[if_idx].data_xfer_ring_va = 0;
- dev->info[if_idx].data_xfer_ring_size = 0;
-
- uaudio_iommu_unmap(MEM_XFER_RING,
- dev->info[if_idx].sync_xfer_ring_va,
- dev->info[if_idx].sync_xfer_ring_size);
- dev->info[if_idx].sync_xfer_ring_va = 0;
- dev->info[if_idx].sync_xfer_ring_size = 0;
-
- uaudio_iommu_unmap(MEM_XFER_BUF,
- dev->info[if_idx].xfer_buf_va,
- dev->info[if_idx].xfer_buf_size);
- dev->info[if_idx].xfer_buf_va = 0;
- dev->info[if_idx].xfer_buf_size = 0;
- pr_debug("%s: release resources: intf# %d card# %d\n", __func__,
- if_idx, card_num);
- }
-
- /* iommu_unmap dcba iova for a usb device */
- uaudio_iommu_unmap(MEM_DCBA, dev->dcba_iova, dev->dcba_size);
-
- dev->dcba_iova = 0;
- dev->dcba_size = 0;
- dev->num_intf = 0;
-
- /* free interface info */
- kfree(dev->info);
- dev->info = NULL;
-
- clear_bit(card_num, &uaudio_qdev->card_slot);
-
- /* all audio devices are disconnected */
- if (!uaudio_qdev->card_slot) {
- uaudio_iommu_unmap(MEM_EVENT_RING, IOVA_BASE, PAGE_SIZE);
- usb_sec_event_ring_cleanup(dev->udev, uaudio_qdev->intr_num);
- pr_debug("%s: all audio devices disconnected\n", __func__);
- }
-
- dev->udev = NULL;
+ uaudio_dev_cleanup(dev);
done:
mutex_unlock(&chip->dev_lock);
}
@@ -789,7 +810,7 @@ static void uaudio_dev_release(struct kref *kref)
}
/* maps audio format received over QMI to asound.h based pcm format */
-int map_pcm_format(unsigned int fmt_received)
+static int map_pcm_format(unsigned int fmt_received)
{
switch (fmt_received) {
case USB_QMI_PCM_FORMAT_S8:
@@ -903,7 +924,7 @@ static int handle_uaudio_stream_req(void *req_h, void *req)
if (!ret && req_msg->enable)
ret = prepare_qmi_response(subs, &resp, req_msg->xfer_buff_size,
- pcm_card_num);
+ pcm_card_num, pcm_dev_num);
mutex_unlock(&chip->dev_lock);
@@ -912,31 +933,7 @@ response:
if (intf_num >= 0) {
mutex_lock(&chip->dev_lock);
info = &uadev[pcm_card_num].info[intf_num];
- uaudio_iommu_unmap(MEM_XFER_RING,
- info->data_xfer_ring_va,
- info->data_xfer_ring_size);
- info->data_xfer_ring_va = 0;
- info->data_xfer_ring_size = 0;
-
- uaudio_iommu_unmap(MEM_XFER_RING,
- info->sync_xfer_ring_va,
- info->sync_xfer_ring_size);
- info->sync_xfer_ring_va = 0;
- info->sync_xfer_ring_size = 0;
-
- uaudio_iommu_unmap(MEM_XFER_BUF,
- info->xfer_buf_va,
- info->xfer_buf_size);
- info->xfer_buf_va = 0;
-
- usb_free_coherent(uadev[pcm_card_num].udev,
- info->xfer_buf_size,
- info->xfer_buf,
- info->xfer_buf_pa);
- info->xfer_buf_size = 0;
- info->xfer_buf = NULL;
- info->xfer_buf_pa = 0;
- info->in_use = false;
+ uaudio_dev_intf_cleanup(uadev[pcm_card_num].udev, info);
pr_debug("%s:release resources: intf# %d card# %d\n",
__func__, intf_num, pcm_card_num);
mutex_unlock(&chip->dev_lock);
@@ -980,6 +977,43 @@ static int uaudio_qmi_svc_connect_cb(struct qmi_handle *handle,
return 0;
}
+static void uaudio_qmi_disconnect_work(struct work_struct *w)
+{
+ struct intf_info *info;
+ int idx, if_idx;
+ struct snd_usb_substream *subs;
+ struct snd_usb_audio *chip = NULL;
+
+ /* find all active intf for set alt 0 and cleanup usb audio dev */
+ for (idx = 0; idx < SNDRV_CARDS; idx++) {
+ if (!atomic_read(&uadev[idx].in_use))
+ continue;
+
+ for (if_idx = 0; if_idx < uadev[idx].num_intf; if_idx++) {
+ if (!uadev[idx].info || !uadev[idx].info[if_idx].in_use)
+ continue;
+ info = &uadev[idx].info[if_idx];
+ subs = find_snd_usb_substream(info->pcm_card_num,
+ info->pcm_dev_num,
+ info->direction,
+ &chip,
+ uaudio_disconnect_cb);
+ if (!subs || !chip || atomic_read(&chip->shutdown)) {
+ pr_debug("%s:no subs for c#%u, dev#%u dir%u\n",
+ __func__, info->pcm_card_num,
+ info->pcm_dev_num,
+ info->direction);
+ continue;
+ }
+ snd_usb_enable_audio_stream(subs, 0);
+ }
+ atomic_set(&uadev[idx].in_use, 0);
+ mutex_lock(&chip->dev_lock);
+ uaudio_dev_cleanup(&uadev[idx]);
+ mutex_unlock(&chip->dev_lock);
+ }
+}
+
static int uaudio_qmi_svc_disconnect_cb(struct qmi_handle *handle,
void *conn_h)
{
@@ -991,6 +1025,8 @@ static int uaudio_qmi_svc_disconnect_cb(struct qmi_handle *handle,
}
svc->curr_conn = NULL;
+ queue_work(svc->uaudio_wq, &svc->qmi_disconnect_work);
+
return 0;
}
@@ -1195,6 +1231,7 @@ static int uaudio_qmi_svc_init(void)
}
INIT_WORK(&svc->recv_msg_work, uaudio_qmi_svc_recv_msg);
+ INIT_WORK(&svc->qmi_disconnect_work, uaudio_qmi_disconnect_work);
uaudio_svc = svc;
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 39c38cb45b00..eeb21eb43898 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -57,6 +57,7 @@ include/asm-generic/bitops/const_hweight.h
include/asm-generic/bitops/fls64.h
include/asm-generic/bitops/__fls.h
include/asm-generic/bitops/fls.h
+include/linux/coresight-pmu.h
include/linux/perf_event.h
include/linux/list.h
include/linux/hash.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 0d19d5447d6c..34846e71fdbd 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -77,6 +77,9 @@ include config/utilities.mak
# Define NO_AUXTRACE if you do not want AUX area tracing support
#
# Define NO_LIBBPF if you do not want BPF support
+#
+# Define NO_CSTRACE if you do not want CoreSight trace decoding support
+#
# As per kernel Makefile, avoid funny character set dependencies
unexport LC_ALL
diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build
index d22e3d07de3d..71de3fc40502 100644
--- a/tools/perf/arch/arm/util/Build
+++ b/tools/perf/arch/arm/util/Build
@@ -2,3 +2,5 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
+
+libperf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs-etm.o
diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c
new file mode 100644
index 000000000000..95c38b683159
--- /dev/null
+++ b/tools/perf/arch/arm/util/auxtrace.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdbool.h>
+#include <linux/coresight-pmu.h>
+
+#include "../../util/auxtrace.h"
+#include "../../util/evlist.h"
+#include "../../util/pmu.h"
+#include "cs-etm.h"
+
+struct auxtrace_record
+*auxtrace_record__init(struct perf_evlist *evlist, int *err)
+{
+ struct perf_pmu *cs_etm_pmu;
+ struct perf_evsel *evsel;
+ bool found_etm = false;
+
+ cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME);
+
+ if (evlist) {
+ evlist__for_each(evlist, evsel) {
+ if (cs_etm_pmu &&
+ evsel->attr.type == cs_etm_pmu->type)
+ found_etm = true;
+ }
+ }
+
+ if (found_etm)
+ return cs_etm_record_init(err);
+
+ /*
+ * Clear 'err' even if we haven't found a cs_etm event - that way perf
+ * record can still be used even if tracers aren't present. The NULL
+ * return value will take care of telling the infrastructure HW tracing
+ * isn't available.
+ */
+ *err = 0;
+ return NULL;
+}
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
new file mode 100644
index 000000000000..13a2188dc5dc
--- /dev/null
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -0,0 +1,563 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <api/fs/fs.h>
+#include <linux/bitops.h>
+#include <linux/coresight-pmu.h>
+#include <linux/kernel.h>
+#include <linux/log2.h>
+#include <linux/types.h>
+
+#include "cs-etm.h"
+#include "../../perf.h"
+#include "../../util/auxtrace.h"
+#include "../../util/cpumap.h"
+#include "../../util/evlist.h"
+#include "../../util/pmu.h"
+#include "../../util/thread_map.h"
+#include "../../util/cs-etm.h"
+
+#include <stdlib.h>
+
+struct cs_etm_recording {
+ struct auxtrace_record itr;
+ struct perf_pmu *cs_etm_pmu;
+ struct perf_evlist *evlist;
+ bool snapshot_mode;
+ size_t snapshot_size;
+};
+
+static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu);
+
+static int cs_etm_parse_snapshot_options(struct auxtrace_record *itr,
+ struct record_opts *opts,
+ const char *str)
+{
+ struct cs_etm_recording *ptr =
+ container_of(itr, struct cs_etm_recording, itr);
+ unsigned long long snapshot_size = 0;
+ char *endptr;
+
+ if (str) {
+ snapshot_size = strtoull(str, &endptr, 0);
+ if (*endptr || snapshot_size > SIZE_MAX)
+ return -1;
+ }
+
+ opts->auxtrace_snapshot_mode = true;
+ opts->auxtrace_snapshot_size = snapshot_size;
+ ptr->snapshot_size = snapshot_size;
+
+ return 0;
+}
+
+static int cs_etm_recording_options(struct auxtrace_record *itr,
+ struct perf_evlist *evlist,
+ struct record_opts *opts)
+{
+ struct cs_etm_recording *ptr =
+ container_of(itr, struct cs_etm_recording, itr);
+ struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
+ struct perf_evsel *evsel, *cs_etm_evsel = NULL;
+ const struct cpu_map *cpus = evlist->cpus;
+ bool privileged = (geteuid() == 0 || perf_event_paranoid() < 0);
+
+ ptr->evlist = evlist;
+ ptr->snapshot_mode = opts->auxtrace_snapshot_mode;
+
+ evlist__for_each(evlist, evsel) {
+ if (evsel->attr.type == cs_etm_pmu->type) {
+ if (cs_etm_evsel) {
+ pr_err("There may be only one %s event\n",
+ CORESIGHT_ETM_PMU_NAME);
+ return -EINVAL;
+ }
+ evsel->attr.freq = 0;
+ evsel->attr.sample_period = 1;
+ cs_etm_evsel = evsel;
+ opts->full_auxtrace = true;
+ }
+ }
+
+ /* no need to continue if at least one event of interest was found */
+ if (!cs_etm_evsel)
+ return 0;
+
+ if (opts->use_clockid) {
+ pr_err("Cannot use clockid (-k option) with %s\n",
+ CORESIGHT_ETM_PMU_NAME);
+ return -EINVAL;
+ }
+
+ /* we are in snapshot mode */
+ if (opts->auxtrace_snapshot_mode) {
+ /*
+ * No size were given to '-S' or '-m,', so go with
+ * the default
+ */
+ if (!opts->auxtrace_snapshot_size &&
+ !opts->auxtrace_mmap_pages) {
+ if (privileged) {
+ opts->auxtrace_mmap_pages = MiB(4) / page_size;
+ } else {
+ opts->auxtrace_mmap_pages =
+ KiB(128) / page_size;
+ if (opts->mmap_pages == UINT_MAX)
+ opts->mmap_pages = KiB(256) / page_size;
+ }
+ } else if (!opts->auxtrace_mmap_pages && !privileged &&
+ opts->mmap_pages == UINT_MAX) {
+ opts->mmap_pages = KiB(256) / page_size;
+ }
+
+ /*
+ * '-m,xyz' was specified but no snapshot size, so make the
+ * snapshot size as big as the auxtrace mmap area.
+ */
+ if (!opts->auxtrace_snapshot_size) {
+ opts->auxtrace_snapshot_size =
+ opts->auxtrace_mmap_pages * (size_t)page_size;
+ }
+
+ /*
+ * -Sxyz was specified but no auxtrace mmap area, so make the
+ * auxtrace mmap area big enough to fit the requested snapshot
+ * size.
+ */
+ if (!opts->auxtrace_mmap_pages) {
+ size_t sz = opts->auxtrace_snapshot_size;
+
+ sz = round_up(sz, page_size) / page_size;
+ opts->auxtrace_mmap_pages = roundup_pow_of_two(sz);
+ }
+
+ /* Snapshost size can't be bigger than the auxtrace area */
+ if (opts->auxtrace_snapshot_size >
+ opts->auxtrace_mmap_pages * (size_t)page_size) {
+ pr_err("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n",
+ opts->auxtrace_snapshot_size,
+ opts->auxtrace_mmap_pages * (size_t)page_size);
+ return -EINVAL;
+ }
+
+ /* Something went wrong somewhere - this shouldn't happen */
+ if (!opts->auxtrace_snapshot_size ||
+ !opts->auxtrace_mmap_pages) {
+ pr_err("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n");
+ return -EINVAL;
+ }
+ }
+
+ /* We are in full trace mode but '-m,xyz' wasn't specified */
+ if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) {
+ if (privileged) {
+ opts->auxtrace_mmap_pages = MiB(4) / page_size;
+ } else {
+ opts->auxtrace_mmap_pages = KiB(128) / page_size;
+ if (opts->mmap_pages == UINT_MAX)
+ opts->mmap_pages = KiB(256) / page_size;
+ }
+
+ }
+
+ /* Validate auxtrace_mmap_pages provided by user */
+ if (opts->auxtrace_mmap_pages) {
+ unsigned int max_page = (KiB(128) / page_size);
+ size_t sz = opts->auxtrace_mmap_pages * (size_t)page_size;
+
+ if (!privileged &&
+ opts->auxtrace_mmap_pages > max_page) {
+ opts->auxtrace_mmap_pages = max_page;
+ pr_err("auxtrace too big, truncating to %d\n",
+ max_page);
+ }
+
+ if (!is_power_of_2(sz)) {
+ pr_err("Invalid mmap size for %s: must be a power of 2\n",
+ CORESIGHT_ETM_PMU_NAME);
+ return -EINVAL;
+ }
+ }
+
+ if (opts->auxtrace_snapshot_mode)
+ pr_debug2("%s snapshot size: %zu\n", CORESIGHT_ETM_PMU_NAME,
+ opts->auxtrace_snapshot_size);
+
+ if (cs_etm_evsel) {
+ /*
+ * To obtain the auxtrace buffer file descriptor, the auxtrace
+ * event must come first.
+ */
+ perf_evlist__to_front(evlist, cs_etm_evsel);
+ /*
+ * In the case of per-cpu mmaps, we need the CPU on the
+ * AUX event.
+ */
+ if (!cpu_map__empty(cpus))
+ perf_evsel__set_sample_bit(cs_etm_evsel, CPU);
+ }
+
+ /* Add dummy event to keep tracking */
+ if (opts->full_auxtrace) {
+ struct perf_evsel *tracking_evsel;
+ int err;
+
+ err = parse_events(evlist, "dummy:u", NULL);
+ if (err)
+ return err;
+
+ tracking_evsel = perf_evlist__last(evlist);
+ perf_evlist__set_tracking_event(evlist, tracking_evsel);
+
+ tracking_evsel->attr.freq = 0;
+ tracking_evsel->attr.sample_period = 1;
+
+ /* In per-cpu case, always need the time of mmap events etc */
+ if (!cpu_map__empty(cpus))
+ perf_evsel__set_sample_bit(tracking_evsel, TIME);
+ }
+
+ return 0;
+}
+
+static u64 cs_etm_get_config(struct auxtrace_record *itr)
+{
+ u64 config = 0;
+ struct cs_etm_recording *ptr =
+ container_of(itr, struct cs_etm_recording, itr);
+ struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
+ struct perf_evlist *evlist = ptr->evlist;
+ struct perf_evsel *evsel;
+
+ evlist__for_each(evlist, evsel) {
+ if (evsel->attr.type == cs_etm_pmu->type) {
+ /*
+ * Variable perf_event_attr::config is assigned to
+ * ETMv3/PTM. The bit fields have been made to match
+ * the ETMv3.5 ETRMCR register specification. See the
+ * PMU_FORMAT_ATTR() declarations in
+ * drivers/hwtracing/coresight/coresight-perf.c for
+ * details.
+ */
+ config = evsel->attr.config;
+ break;
+ }
+ }
+
+ return config;
+}
+
+static size_t
+cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
+ struct perf_evlist *evlist __maybe_unused)
+{
+ int i;
+ int etmv3 = 0, etmv4 = 0;
+ const struct cpu_map *cpus = evlist->cpus;
+
+ /* cpu map is not empty, we have specific CPUs to work with */
+ if (!cpu_map__empty(cpus)) {
+ for (i = 0; i < cpu_map__nr(cpus); i++) {
+ if (cs_etm_is_etmv4(itr, cpus->map[i]))
+ etmv4++;
+ else
+ etmv3++;
+ }
+ } else {
+ /* get configuration for all CPUs in the system */
+ for (i = 0; i < cpu__max_cpu(); i++) {
+ if (cs_etm_is_etmv4(itr, i))
+ etmv4++;
+ else
+ etmv3++;
+ }
+ }
+
+ return (CS_ETM_HEADER_SIZE +
+ (etmv4 * CS_ETMV4_PRIV_SIZE) +
+ (etmv3 * CS_ETMV3_PRIV_SIZE));
+}
+
+static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX] = {
+ [CS_ETM_ETMCCER] = "mgmt/etmccer",
+ [CS_ETM_ETMIDR] = "mgmt/etmidr",
+};
+
+static const char *metadata_etmv4_ro[CS_ETMV4_PRIV_MAX] = {
+ [CS_ETMV4_TRCIDR0] = "trcidr/trcidr0",
+ [CS_ETMV4_TRCIDR1] = "trcidr/trcidr1",
+ [CS_ETMV4_TRCIDR2] = "trcidr/trcidr2",
+ [CS_ETMV4_TRCIDR8] = "trcidr/trcidr8",
+ [CS_ETMV4_TRCAUTHSTATUS] = "mgmt/trcauthstatus",
+};
+
+static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu)
+{
+ bool ret = false;
+ char path[PATH_MAX];
+ int scan;
+ unsigned int val;
+ struct cs_etm_recording *ptr =
+ container_of(itr, struct cs_etm_recording, itr);
+ struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
+
+ /* Take any of the RO files for ETMv4 and see if it present */
+ snprintf(path, PATH_MAX, "cpu%d/%s",
+ cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
+ scan = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
+
+ /* The file was read successfully, we have a winner */
+ if (scan == 1)
+ ret = true;
+
+ return ret;
+}
+
+static int cs_etm_get_ro(struct perf_pmu *pmu, int cpu, const char *path)
+{
+ char pmu_path[PATH_MAX];
+ int scan;
+ unsigned int val = 0;
+
+ /* Get RO metadata from sysfs */
+ snprintf(pmu_path, PATH_MAX, "cpu%d/%s", cpu, path);
+
+ scan = perf_pmu__scan_file(pmu, pmu_path, "%x", &val);
+ if (scan != 1)
+ pr_err("%s: error reading: %s\n", __func__, pmu_path);
+
+ return val;
+}
+
+static void cs_etm_get_metadata(int cpu, u32 *offset,
+ struct auxtrace_record *itr,
+ struct auxtrace_info_event *info)
+{
+ u32 increment;
+ u64 magic;
+ struct cs_etm_recording *ptr =
+ container_of(itr, struct cs_etm_recording, itr);
+ struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
+
+ /* first see what kind of tracer this cpu is affined to */
+ if (cs_etm_is_etmv4(itr, cpu)) {
+ magic = __perf_cs_etmv4_magic;
+ /* Get trace configuration register */
+ info->priv[*offset + CS_ETMV4_TRCCONFIGR] =
+ cs_etm_get_config(itr);
+ /* Get traceID from the framework */
+ info->priv[*offset + CS_ETMV4_TRCTRACEIDR] =
+ coresight_get_trace_id(cpu);
+ /* Get read-only information from sysFS */
+ info->priv[*offset + CS_ETMV4_TRCIDR0] =
+ cs_etm_get_ro(cs_etm_pmu, cpu,
+ metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
+ info->priv[*offset + CS_ETMV4_TRCIDR1] =
+ cs_etm_get_ro(cs_etm_pmu, cpu,
+ metadata_etmv4_ro[CS_ETMV4_TRCIDR1]);
+ info->priv[*offset + CS_ETMV4_TRCIDR2] =
+ cs_etm_get_ro(cs_etm_pmu, cpu,
+ metadata_etmv4_ro[CS_ETMV4_TRCIDR2]);
+ info->priv[*offset + CS_ETMV4_TRCIDR8] =
+ cs_etm_get_ro(cs_etm_pmu, cpu,
+ metadata_etmv4_ro[CS_ETMV4_TRCIDR8]);
+ info->priv[*offset + CS_ETMV4_TRCAUTHSTATUS] =
+ cs_etm_get_ro(cs_etm_pmu, cpu,
+ metadata_etmv4_ro
+ [CS_ETMV4_TRCAUTHSTATUS]);
+
+ /* How much space was used */
+ increment = CS_ETMV4_PRIV_MAX;
+ } else {
+ magic = __perf_cs_etmv3_magic;
+ /* Get configuration register */
+ info->priv[*offset + CS_ETM_ETMCR] = cs_etm_get_config(itr);
+ /* Get traceID from the framework */
+ info->priv[*offset + CS_ETM_ETMTRACEIDR] =
+ coresight_get_trace_id(cpu);
+ /* Get read-only information from sysFS */
+ info->priv[*offset + CS_ETM_ETMCCER] =
+ cs_etm_get_ro(cs_etm_pmu, cpu,
+ metadata_etmv3_ro[CS_ETM_ETMCCER]);
+ info->priv[*offset + CS_ETM_ETMIDR] =
+ cs_etm_get_ro(cs_etm_pmu, cpu,
+ metadata_etmv3_ro[CS_ETM_ETMIDR]);
+
+ /* How much space was used */
+ increment = CS_ETM_PRIV_MAX;
+ }
+
+ /* Build generic header portion */
+ info->priv[*offset + CS_ETM_MAGIC] = magic;
+ info->priv[*offset + CS_ETM_CPU] = cpu;
+ /* Where the next CPU entry should start from */
+ *offset += increment;
+}
+
+static int cs_etm_info_fill(struct auxtrace_record *itr,
+ struct perf_session *session,
+ struct auxtrace_info_event *info,
+ size_t priv_size)
+{
+ int i;
+ u32 offset;
+ u64 nr_cpu, type;
+ const struct cpu_map *cpus = session->evlist->cpus;
+ struct cs_etm_recording *ptr =
+ container_of(itr, struct cs_etm_recording, itr);
+ struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
+
+ if (priv_size != cs_etm_info_priv_size(itr, session->evlist))
+ return -EINVAL;
+
+ if (!session->evlist->nr_mmaps)
+ return -EINVAL;
+
+ /* If the cpu_map is empty all CPUs are involved */
+ nr_cpu = cpu_map__empty(cpus) ? cpu__max_cpu() : cpu_map__nr(cpus);
+ /* Get PMU type as dynamically assigned by the core */
+ type = cs_etm_pmu->type;
+
+ /* First fill out the session header */
+ info->type = PERF_AUXTRACE_CS_ETM;
+ info->priv[CS_HEADER_VERSION_0] = 0;
+ info->priv[CS_PMU_TYPE_CPUS] = type << 32;
+ info->priv[CS_PMU_TYPE_CPUS] |= nr_cpu;
+ info->priv[CS_ETM_SNAPSHOT] = ptr->snapshot_mode;
+
+ offset = CS_ETM_SNAPSHOT + 1;
+
+ /* cpu map is not empty, we have specific CPUs to work with */
+ if (!cpu_map__empty(cpus)) {
+ for (i = 0; i < cpu_map__nr(cpus) && offset < priv_size; i++)
+ cs_etm_get_metadata(cpus->map[i], &offset, itr, info);
+ } else {
+ /* get configuration for all CPUs in the system */
+ for (i = 0; i < cpu__max_cpu(); i++)
+ cs_etm_get_metadata(i, &offset, itr, info);
+ }
+
+ return 0;
+}
+
+static int cs_etm_find_snapshot(struct auxtrace_record *itr __maybe_unused,
+ int idx, struct auxtrace_mmap *mm,
+ unsigned char *data __maybe_unused,
+ u64 *head, u64 *old)
+{
+ pr_debug3("%s: mmap index %d old head %zu new head %zu size %zu\n",
+ __func__, idx, (size_t)*old, (size_t)*head, mm->len);
+
+ *old = *head;
+ *head += mm->len;
+
+ return 0;
+}
+
+static int cs_etm_snapshot_start(struct auxtrace_record *itr)
+{
+ struct cs_etm_recording *ptr =
+ container_of(itr, struct cs_etm_recording, itr);
+ struct perf_evsel *evsel;
+
+ evlist__for_each(ptr->evlist, evsel) {
+ if (evsel->attr.type == ptr->cs_etm_pmu->type)
+ return perf_evsel__disable(evsel);
+ }
+ return -EINVAL;
+}
+
+static int cs_etm_snapshot_finish(struct auxtrace_record *itr)
+{
+ struct cs_etm_recording *ptr =
+ container_of(itr, struct cs_etm_recording, itr);
+ struct perf_evsel *evsel;
+
+ evlist__for_each(ptr->evlist, evsel) {
+ int nthreads = thread_map__nr(evsel->threads);
+ int ncpus = cpu_map__nr(evsel->cpus);
+
+ if (evsel->attr.type == ptr->cs_etm_pmu->type) {
+ return perf_evsel__enable(evsel, ncpus, nthreads);
+ }
+ }
+ return -EINVAL;
+}
+
+static u64 cs_etm_reference(struct auxtrace_record *itr __maybe_unused)
+{
+ return (((u64) rand() << 0) & 0x00000000FFFFFFFFull) |
+ (((u64) rand() << 32) & 0xFFFFFFFF00000000ull);
+}
+
+static void cs_etm_recording_free(struct auxtrace_record *itr)
+{
+ struct cs_etm_recording *ptr =
+ container_of(itr, struct cs_etm_recording, itr);
+ free(ptr);
+}
+
+static int cs_etm_read_finish(struct auxtrace_record *itr, int idx)
+{
+ struct cs_etm_recording *ptr =
+ container_of(itr, struct cs_etm_recording, itr);
+ struct perf_evsel *evsel;
+
+ evlist__for_each(ptr->evlist, evsel) {
+ if (evsel->attr.type == ptr->cs_etm_pmu->type)
+ return perf_evlist__enable_event_idx(ptr->evlist,
+ evsel, idx);
+ }
+
+ return -EINVAL;
+}
+
+struct auxtrace_record *cs_etm_record_init(int *err)
+{
+ struct perf_pmu *cs_etm_pmu;
+ struct cs_etm_recording *ptr;
+
+ cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME);
+
+ if (!cs_etm_pmu) {
+ *err = -EINVAL;
+ goto out;
+ }
+
+ ptr = zalloc(sizeof(struct cs_etm_recording));
+ if (!ptr) {
+ *err = -ENOMEM;
+ goto out;
+ }
+
+ ptr->cs_etm_pmu = cs_etm_pmu;
+ ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options;
+ ptr->itr.recording_options = cs_etm_recording_options;
+ ptr->itr.info_priv_size = cs_etm_info_priv_size;
+ ptr->itr.info_fill = cs_etm_info_fill;
+ ptr->itr.find_snapshot = cs_etm_find_snapshot;
+ ptr->itr.snapshot_start = cs_etm_snapshot_start;
+ ptr->itr.snapshot_finish = cs_etm_snapshot_finish;
+ ptr->itr.reference = cs_etm_reference;
+ ptr->itr.free = cs_etm_recording_free;
+ ptr->itr.read_finish = cs_etm_read_finish;
+
+ *err = 0;
+ return &ptr->itr;
+out:
+ return NULL;
+}
diff --git a/tools/perf/arch/arm/util/cs-etm.h b/tools/perf/arch/arm/util/cs-etm.h
new file mode 100644
index 000000000000..909f486d02d1
--- /dev/null
+++ b/tools/perf/arch/arm/util/cs-etm.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDE__PERF_CS_ETM_H__
+#define INCLUDE__PERF_CS_ETM_H__
+
+struct auxtrace_record *cs_etm_record_init(int *err);
+
+#endif
diff --git a/tools/perf/arch/arm/util/pmu.c b/tools/perf/arch/arm/util/pmu.c
new file mode 100644
index 000000000000..af9fb666b44f
--- /dev/null
+++ b/tools/perf/arch/arm/util/pmu.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <linux/coresight-pmu.h>
+#include <linux/perf_event.h>
+
+#include "../../util/pmu.h"
+
+struct perf_event_attr
+*perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
+{
+#ifdef HAVE_AUXTRACE_SUPPORT
+ if (!strcmp(pmu->name, CORESIGHT_ETM_PMU_NAME)) {
+ /* add ETM default config here */
+ pmu->selectable = true;
+ }
+#endif
+ return NULL;
+}
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
index e58123a8912b..f92918154fec 100644
--- a/tools/perf/arch/arm64/util/Build
+++ b/tools/perf/arch/arm64/util/Build
@@ -1,2 +1,6 @@
libperf-$(CONFIG_DWARF) += dwarf-regs.o
libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
+
+libperf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \
+ ../../arm/util/auxtrace.o \
+ ../../arm/util/cs-etm.o
diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c
index 9b94ce520917..4685a40777cc 100644
--- a/tools/perf/arch/x86/util/intel-bts.c
+++ b/tools/perf/arch/x86/util/intel-bts.c
@@ -60,7 +60,9 @@ struct branch {
u64 misc;
};
-static size_t intel_bts_info_priv_size(struct auxtrace_record *itr __maybe_unused)
+static size_t
+intel_bts_info_priv_size(struct auxtrace_record *itr __maybe_unused,
+ struct perf_evlist *evlist __maybe_unused)
{
return INTEL_BTS_AUXTRACE_PRIV_SIZE;
}
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index b02af064f0f9..e5c1f2e21f87 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -273,7 +273,9 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)
return attr;
}
-static size_t intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused)
+static size_t
+intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused,
+ struct perf_evlist *evlist __maybe_unused)
{
return INTEL_PT_AUXTRACE_PRIV_SIZE;
}
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index 99d127fe9c35..ac369c494036 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -626,12 +626,16 @@ static int __cmd_inject(struct perf_inject *inject)
ret = perf_session__process_events(session);
if (!file_out->is_pipe) {
- if (inject->build_ids) {
+ if (inject->build_ids)
perf_header__set_feat(&session->header,
HEADER_BUILD_ID);
- if (inject->have_auxtrace)
- dsos__hit_all(session);
- }
+ /*
+ * Keep all buildids when there is unprocessed AUX data because
+ * it is not known which ones the AUX trace hits.
+ */
+ if (perf_header__has_feat(&session->header, HEADER_BUILD_ID) &&
+ inject->have_auxtrace && !inject->itrace_synth_opts.set)
+ dsos__hit_all(session);
/*
* The AUX areas have been removed and replaced with
* synthesized hardware events, so clear the feature flag and
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 199fc31e3919..1b9decd5fbf1 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -276,6 +276,7 @@ static int record__open(struct record *rec)
struct perf_evlist *evlist = rec->evlist;
struct perf_session *session = rec->session;
struct record_opts *opts = &rec->opts;
+ struct perf_evsel_config_term *err_term;
int rc = 0;
perf_evlist__config(evlist, opts);
@@ -305,6 +306,14 @@ try_again:
goto out;
}
+ if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) {
+ error("failed to set config \"%s\" on event %s with %d (%s)\n",
+ err_term->val.drv_cfg, perf_evsel__name(pos), errno,
+ strerror_r(errno, msg, sizeof(msg)));
+ rc = -1;
+ goto out;
+ }
+
if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
opts->auxtrace_mmap_pages,
opts->auxtrace_snapshot_mode) < 0) {
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 72b5deb4bd79..368d1e1561f7 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -92,7 +92,8 @@ static struct {
.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
- PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
+ PERF_OUTPUT_EVNAME | PERF_OUTPUT_ADDR |
+ PERF_OUTPUT_IP |
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
PERF_OUTPUT_PERIOD,
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index de89ec574361..405c1c1e2975 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -433,6 +433,24 @@ endif
grep-libs = $(filter -l%,$(1))
strip-libs = $(filter-out -l%,$(1))
+ifdef CSTRACE_PATH
+ ifeq (${IS_64_BIT}, 1)
+ CSTRACE_LNX = linux64
+ else
+ CSTRACE_LNX = linux
+ endif
+ ifeq (${DEBUG}, 1)
+ LIBCSTRACE = -lcstraced_c_api -lcstraced
+ CSTRACE_LIB_PATH = $(CSTRACE_PATH)/lib/$(CSTRACE_LNX)/dbg
+ else
+ LIBCSTRACE = -lcstraced_c_api -lcstraced
+ CSTRACE_LIB_PATH = $(CSTRACE_PATH)/lib/$(CSTRACE_LNX)/rel
+ endif
+ $(call detected,CSTRACE)
+ $(call detected_var,CSTRACE_PATH)
+ EXTLIBS += -L$(CSTRACE_LIB_PATH) $(LIBCSTRACE) -lstdc++
+endif
+
ifdef NO_LIBPERL
CFLAGS += -DNO_LIBPERL
else
@@ -647,9 +665,14 @@ ifdef LIBBABELTRACE
endif
ifndef NO_AUXTRACE
- ifeq ($(feature-get_cpuid), 0)
- msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc);
- NO_AUXTRACE := 1
+ ifeq ($(ARCH),x86)
+ ifeq ($(feature-get_cpuid), 0)
+ msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc);
+ NO_AUXTRACE := 1
+ else
+ $(call detected,CONFIG_AUXTRACE)
+ CFLAGS += -DHAVE_AUXTRACE_SUPPORT
+ endif
else
$(call detected,CONFIG_AUXTRACE)
CFLAGS += -DHAVE_AUXTRACE_SUPPORT
diff --git a/tools/perf/scripts/python/cs-trace-disasm.py b/tools/perf/scripts/python/cs-trace-disasm.py
new file mode 100644
index 000000000000..429d0d2d7a23
--- /dev/null
+++ b/tools/perf/scripts/python/cs-trace-disasm.py
@@ -0,0 +1,124 @@
+# perf script event handlers, generated by perf script -g python
+# Licensed under the terms of the GNU GPL License version 2
+
+# The common_* event handler fields are the most useful fields common to
+# all events. They don't necessarily correspond to the 'common_*' fields
+# in the format files. Those fields not available as handler params can
+# be retrieved using Python functions of the form common_*(context).
+# See the perf-trace-python Documentation for the list of available functions.
+
+import os
+import sys
+
+sys.path.append(os.environ['PERF_EXEC_PATH'] + \
+ '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
+
+from perf_trace_context import *
+from subprocess import *
+from Core import *
+import re;
+
+from optparse import OptionParser
+
+#
+# Add options to specify vmlinux file and the objdump executable
+#
+parser = OptionParser()
+parser.add_option("-k", "--vmlinux", dest="vmlinux_name",
+ help="path to vmlinux file")
+parser.add_option("-d", "--objdump", dest="objdump_name",
+ help="name of objdump executable (in path)")
+(options, args) = parser.parse_args()
+
+if (options.objdump_name == None):
+ sys.exit("No objdump executable specified - use -d or --objdump option")
+
+# initialize global dicts and regular expression
+
+build_ids = dict();
+mmaps = dict();
+disasm_cache = dict();
+disasm_re = re.compile("^\s*([0-9a-fA-F]+):")
+
+cache_size = 16*1024
+
+def trace_begin():
+ cmd_output = check_output(["perf", "buildid-list"]).split('\n');
+ bid_re = re.compile("([a-fA-f0-9]+)[ \t]([^ \n]+)")
+ for line in cmd_output:
+ m = bid_re.search(line)
+ if (m != None) :
+ build_ids[m.group(2)] = \
+ os.environ['PERF_BUILDID_DIR'] + \
+ m.group(2) + "/" + m.group(1);
+
+ if ((options.vmlinux_name != None) and ("[kernel.kallsyms]" in build_ids)):
+ build_ids['[kernel.kallsyms]'] = options.vmlinux_name;
+ else:
+ del build_ids['[kernel.kallsyms]']
+
+ mmap_re = re.compile("PERF_RECORD_MMAP2 -?[0-9]+/[0-9]+: \[(0x[0-9a-fA-F]+).*:\s.*\s(.*.so)")
+ cmd_output= check_output("perf script --show-mmap-events | fgrep PERF_RECORD_MMAP2",shell=True).split('\n')
+ for line in cmd_output:
+ m = mmap_re.search(line)
+ if (m != None) :
+ mmaps[m.group(2)] = int(m.group(1),0)
+
+
+
+def trace_end():
+ pass
+
+def process_event(t):
+ global cache_size
+ global options
+
+ sample = t['sample']
+ dso = t['dso']
+
+ # don't let the cache get too big, but don't bother with a fancy replacement policy
+ # just clear it when it hits max size
+
+ if (len(disasm_cache) > cache_size):
+ disasm_cache.clear();
+
+ cpu = format(sample['cpu'], "d");
+ addr_range = format(sample['ip'],"x") + ":" + format(sample['addr'],"x");
+
+ try:
+ disasm_output = disasm_cache[addr_range];
+ except:
+ try:
+ fname = build_ids[dso];
+ except KeyError:
+ if (dso == '[kernel.kallsyms]'):
+ return;
+ fname = dso;
+
+ if (dso in mmaps):
+ offset = mmaps[dso];
+ disasm = [options.objdump_name,"-d","-z", "--adjust-vma="+format(offset,"#x"),"--start-address="+format(sample['ip'],"#x"),"--stop-address="+format(sample['addr'],"#x"), fname]
+ else:
+ offset = 0
+ disasm = [options.objdump_name,"-d","-z", "--start-address="+format(sample['ip'],"#x"),"--stop-address="+format(sample['addr'],"#x"),fname]
+ disasm_output = check_output(disasm).split('\n')
+ disasm_cache[addr_range] = disasm_output;
+
+ print "FILE: %s\tCPU: %s" % (dso, cpu);
+ for line in disasm_output:
+ m = disasm_re.search(line)
+ if (m != None) :
+ try:
+ print "\t",line
+ except:
+ exit(1);
+ else:
+ continue;
+
+def trace_unhandled(event_name, context, event_fields_dict):
+ print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])
+
+def print_header(event_name, cpu, secs, nsecs, pid, comm):
+ print "print_header"
+ print "%-20s %5u %05u.%09u %8u %-20s " % \
+ (event_name, cpu, secs, nsecs, pid, comm),
diff --git a/tools/perf/scripts/python/cs-trace-ranges.py b/tools/perf/scripts/python/cs-trace-ranges.py
new file mode 100644
index 000000000000..c8edacba0f83
--- /dev/null
+++ b/tools/perf/scripts/python/cs-trace-ranges.py
@@ -0,0 +1,44 @@
+#
+# Copyright(C) 2016 Linaro Limited. All rights reserved.
+# Author: Tor Jeremiassen <tor.jeremiassen@linaro.org>
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 as published by
+# the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import sys
+
+sys.path.append(os.environ['PERF_EXEC_PATH'] + \
+ '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
+
+from perf_trace_context import *
+
+def trace_begin():
+ pass;
+
+def trace_end():
+ pass
+
+def process_event(t):
+
+ sample = t['sample']
+
+ print "range:",format(sample['ip'],"x"),"-",format(sample['addr'],"x")
+
+def trace_unhandled(event_name, context, event_fields_dict):
+ print ' '.join(['%s=%s'%(k,str(v))for k,v in sorted(event_fields_dict.items())])
+
+def print_header(event_name, cpu, secs, nsecs, pid, comm):
+ print "print_header"
+ print "%-20s %5u %05u.%09u %8u %-20s " % \
+ (event_name, cpu, secs, nsecs, pid, comm),
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index ec16f7812c8b..6ebfdee3e2c6 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -146,7 +146,7 @@ prepare_bpf(void *obj_buf, size_t obj_buf_sz, const char *name)
return obj;
}
-static int __test__bpf(int index)
+static int __test__bpf(int idx)
{
int ret;
void *obj_buf;
@@ -154,27 +154,27 @@ static int __test__bpf(int index)
struct bpf_object *obj;
ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
- bpf_testcase_table[index].prog_id,
+ bpf_testcase_table[idx].prog_id,
true);
if (ret != TEST_OK || !obj_buf || !obj_buf_sz) {
pr_debug("Unable to get BPF object, %s\n",
- bpf_testcase_table[index].msg_compile_fail);
- if (index == 0)
+ bpf_testcase_table[idx].msg_compile_fail);
+ if (idx == 0)
return TEST_SKIP;
else
return TEST_FAIL;
}
obj = prepare_bpf(obj_buf, obj_buf_sz,
- bpf_testcase_table[index].name);
+ bpf_testcase_table[idx].name);
if (!obj) {
ret = TEST_FAIL;
goto out;
}
ret = do_test(obj,
- bpf_testcase_table[index].target_func,
- bpf_testcase_table[index].expect_result);
+ bpf_testcase_table[idx].target_func,
+ bpf_testcase_table[idx].expect_result);
out:
bpf__clear();
return ret;
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index bc4cf507cde5..366e38ba8b49 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -50,7 +50,7 @@ static struct {
int
test_llvm__fetch_bpf_obj(void **p_obj_buf,
size_t *p_obj_buf_sz,
- enum test_llvm__testcase index,
+ enum test_llvm__testcase idx,
bool force)
{
const char *source;
@@ -59,11 +59,11 @@ test_llvm__fetch_bpf_obj(void **p_obj_buf,
char *tmpl_new = NULL, *clang_opt_new = NULL;
int err, old_verbose, ret = TEST_FAIL;
- if (index >= __LLVM_TESTCASE_MAX)
+ if (idx >= __LLVM_TESTCASE_MAX)
return TEST_FAIL;
- source = bpf_source_table[index].source;
- desc = bpf_source_table[index].desc;
+ source = bpf_source_table[idx].source;
+ desc = bpf_source_table[idx].desc;
perf_config(perf_config_cb, NULL);
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index 591b3fe3ed49..a8d806503a45 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -84,6 +84,8 @@ libperf-$(CONFIG_AUXTRACE) += auxtrace.o
libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/
libperf-$(CONFIG_AUXTRACE) += intel-pt.o
libperf-$(CONFIG_AUXTRACE) += intel-bts.o
+libperf-$(CONFIG_AUXTRACE) += cs-etm.o
+libperf-$(CONFIG_AUXTRACE) += cs-etm-decoder/
libperf-y += parse-branch-options.o
libperf-y += parse-regs-options.o
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 7f10430af39c..67551225764e 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -49,6 +49,7 @@
#include "intel-pt.h"
#include "intel-bts.h"
+#include "cs-etm.h"
int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
struct auxtrace_mmap_params *mp,
@@ -478,10 +479,11 @@ void auxtrace_heap__pop(struct auxtrace_heap *heap)
heap_array[last].ordinal);
}
-size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr)
+size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr,
+ struct perf_evlist *evlist)
{
if (itr)
- return itr->info_priv_size(itr);
+ return itr->info_priv_size(itr, evlist);
return 0;
}
@@ -852,7 +854,7 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,
int err;
pr_debug2("Synthesizing auxtrace information\n");
- priv_size = auxtrace_record__info_priv_size(itr);
+ priv_size = auxtrace_record__info_priv_size(itr, session->evlist);
ev = zalloc(sizeof(struct auxtrace_info_event) + priv_size);
if (!ev)
return -ENOMEM;
@@ -891,6 +893,8 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
return intel_pt_process_auxtrace_info(event, session);
case PERF_AUXTRACE_INTEL_BTS:
return intel_bts_process_auxtrace_info(event, session);
+ case PERF_AUXTRACE_CS_ETM:
+ return cs_etm__process_auxtrace_info(event, session);
case PERF_AUXTRACE_UNKNOWN:
default:
return -EINVAL;
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index b86f90db1352..adb53e7bcabf 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -41,6 +41,7 @@ enum auxtrace_type {
PERF_AUXTRACE_UNKNOWN,
PERF_AUXTRACE_INTEL_PT,
PERF_AUXTRACE_INTEL_BTS,
+ PERF_AUXTRACE_CS_ETM,
};
enum itrace_period_type {
@@ -293,7 +294,8 @@ struct auxtrace_record {
int (*recording_options)(struct auxtrace_record *itr,
struct perf_evlist *evlist,
struct record_opts *opts);
- size_t (*info_priv_size)(struct auxtrace_record *itr);
+ size_t (*info_priv_size)(struct auxtrace_record *itr,
+ struct perf_evlist *evlist);
int (*info_fill)(struct auxtrace_record *itr,
struct perf_session *session,
struct auxtrace_info_event *auxtrace_info,
@@ -429,7 +431,8 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,
int auxtrace_record__options(struct auxtrace_record *itr,
struct perf_evlist *evlist,
struct record_opts *opts);
-size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr);
+size_t auxtrace_record__info_priv_size(struct auxtrace_record *itr,
+ struct perf_evlist *evlist);
int auxtrace_record__info_fill(struct auxtrace_record *itr,
struct perf_session *session,
struct auxtrace_info_event *auxtrace_info,
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 6a7e273a514a..52d320e922e3 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -145,7 +145,7 @@ static int asnprintf(char **strp, size_t size, const char *fmt, ...)
return ret;
}
-static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
+char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
{
char *tmp = bf;
int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 27a14a8a945b..eb2c2b6e1dab 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -11,6 +11,7 @@
extern struct perf_tool build_id__mark_dso_hit_ops;
struct dso;
+char *build_id__filename(const char *sbuild_id, char *bf, size_t size);
int build_id__sprintf(const u8 *build_id, int len, char *bf);
int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id);
int filename__sprintf_build_id(const char *pathname, char *sbuild_id);
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 10af1e7524fb..6523e1a8eea5 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -7,6 +7,10 @@
#include <stdlib.h>
#include "asm/bug.h"
+static int max_cpu_num;
+static int max_node_num;
+static int *cpunode_map;
+
static struct cpu_map *cpu_map__default_new(void)
{
struct cpu_map *cpus;
@@ -435,6 +439,32 @@ out:
pr_err("Failed to read max nodes, using default of %d\n", max_node_num);
}
+int cpu__max_node(void)
+{
+ if (unlikely(!max_node_num))
+ set_max_node_num();
+
+ return max_node_num;
+}
+
+int cpu__max_cpu(void)
+{
+ if (unlikely(!max_cpu_num))
+ set_max_cpu_num();
+
+ return max_cpu_num;
+}
+
+int cpu__get_node(int cpu)
+{
+ if (unlikely(cpunode_map == NULL)) {
+ pr_debug("cpu_map not initialized\n");
+ return -1;
+ }
+
+ return cpunode_map[cpu];
+}
+
static int init_cpunode_map(void)
{
int i;
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 85f7772457fa..d6184ba929b6 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -56,37 +56,11 @@ static inline bool cpu_map__empty(const struct cpu_map *map)
return map ? map->map[0] == -1 : true;
}
-int max_cpu_num;
-int max_node_num;
-int *cpunode_map;
-
int cpu__setup_cpunode_map(void);
-static inline int cpu__max_node(void)
-{
- if (unlikely(!max_node_num))
- pr_debug("cpu_map not initialized\n");
-
- return max_node_num;
-}
-
-static inline int cpu__max_cpu(void)
-{
- if (unlikely(!max_cpu_num))
- pr_debug("cpu_map not initialized\n");
-
- return max_cpu_num;
-}
-
-static inline int cpu__get_node(int cpu)
-{
- if (unlikely(cpunode_map == NULL)) {
- pr_debug("cpu_map not initialized\n");
- return -1;
- }
-
- return cpunode_map[cpu];
-}
+int cpu__max_node(void);
+int cpu__max_cpu(void);
+int cpu__get_node(int cpu);
int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
int (*f)(struct cpu_map *map, int cpu, void *data),
diff --git a/tools/perf/util/cs-etm-decoder/Build b/tools/perf/util/cs-etm-decoder/Build
new file mode 100644
index 000000000000..d4896fec940c
--- /dev/null
+++ b/tools/perf/util/cs-etm-decoder/Build
@@ -0,0 +1,7 @@
+ifeq ($(CSTRACE_PATH),)
+libperf-$(CONFIG_AUXTRACE) += cs-etm-decoder-stub.o
+else
+CFLAGS_cs-etm-decoder.o += -I$(CSTRACE_PATH)/include
+libperf-$(CONFIG_AUXTRACE) += cs-etm-decoder.o
+endif
+
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder-stub.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder-stub.c
new file mode 100644
index 000000000000..38f2b756fe10
--- /dev/null
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder-stub.c
@@ -0,0 +1,91 @@
+/*
+ *
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Tor Jeremiassen <tor.jeremiassen@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU GEneral Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+
+#include "cs-etm-decoder.h"
+#include "../util.h"
+
+
+struct cs_etm_decoder
+{
+ void *state;
+ int dummy;
+};
+
+int cs_etm_decoder__flush(struct cs_etm_decoder *decoder)
+{
+ (void) decoder;
+ return -1;
+}
+
+int cs_etm_decoder__add_bin_file(struct cs_etm_decoder *decoder, uint64_t offset, uint64_t address, uint64_t len, const char *fname)
+{
+ (void) decoder;
+ (void) offset;
+ (void) address;
+ (void) len;
+ (void) fname;
+ return -1;
+}
+
+const struct cs_etm_state *cs_etm_decoder__process_data_block(struct cs_etm_decoder *decoder,
+ uint64_t indx,
+ const uint8_t *buf,
+ size_t len,
+ size_t *consumed)
+{
+ (void) decoder;
+ (void) indx;
+ (void) buf;
+ (void) len;
+ (void) consumed;
+ return NULL;
+}
+
+int cs_etm_decoder__add_mem_access_cb(struct cs_etm_decoder *decoder, uint64_t address, uint64_t len, cs_etm_mem_cb_type cb_func)
+{
+ (void) decoder;
+ (void) address;
+ (void) len;
+ (void) cb_func;
+ return -1;
+}
+
+int cs_etm_decoder__get_packet(struct cs_etm_decoder *decoder,
+ struct cs_etm_packet *packet)
+{
+ (void) decoder;
+ (void) packet;
+ return -1;
+}
+
+struct cs_etm_decoder *cs_etm_decoder__new(uint32_t num_cpu, struct cs_etm_decoder_params *d_params, struct cs_etm_trace_params t_params[])
+{
+ (void) num_cpu;
+ (void) d_params;
+ (void) t_params;
+ return NULL;
+}
+
+
+void cs_etm_decoder__free(struct cs_etm_decoder *decoder)
+{
+ (void) decoder;
+ return;
+}
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
new file mode 100644
index 000000000000..c6f23d63590d
--- /dev/null
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
@@ -0,0 +1,503 @@
+/*
+ *
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Tor Jeremiassen <tor.jeremiassen@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU GEneral Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/err.h>
+#include <stdlib.h>
+
+#include "../cs-etm.h"
+#include "cs-etm-decoder.h"
+#include "../util.h"
+#include "../util/intlist.h"
+
+#include "c_api/opencsd_c_api.h"
+#include "ocsd_if_types.h"
+#include "etmv4/trc_pkt_types_etmv4.h"
+
+#define MAX_BUFFER 1024
+
+
+
+struct cs_etm_decoder
+{
+ struct cs_etm_state state;
+ dcd_tree_handle_t dcd_tree;
+ void (*packet_printer)(const char *);
+ cs_etm_mem_cb_type mem_access;
+ ocsd_datapath_resp_t prev_return;
+ size_t prev_processed;
+ bool trace_on;
+ bool discontinuity;
+ struct cs_etm_packet packet_buffer[MAX_BUFFER];
+ uint32_t packet_count;
+ uint32_t head;
+ uint32_t tail;
+ uint32_t end_tail;
+};
+
+static uint32_t cs_etm_decoder__mem_access(const void *context,
+ const ocsd_vaddr_t address,
+ const ocsd_mem_space_acc_t mem_space,
+ const uint32_t req_size,
+ uint8_t *buffer)
+{
+ struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
+ (void) mem_space;
+
+ return decoder->mem_access(decoder->state.data,address,req_size,buffer);
+}
+
+static int cs_etm_decoder__gen_etmv4_config(struct cs_etm_trace_params *params,
+ ocsd_etmv4_cfg *config)
+{
+ config->reg_configr = params->reg_configr;
+ config->reg_traceidr = params->reg_traceidr;
+ config->reg_idr0 = params->reg_idr0;
+ config->reg_idr1 = params->reg_idr1;
+ config->reg_idr2 = params->reg_idr2;
+ config->reg_idr8 = params->reg_idr8;
+
+ config->reg_idr9 = 0;
+ config->reg_idr10 = 0;
+ config->reg_idr11 = 0;
+ config->reg_idr12 = 0;
+ config->reg_idr13 = 0;
+ config->arch_ver = ARCH_V8;
+ config->core_prof = profile_CortexA;
+
+ return 0;
+}
+
+static int cs_etm_decoder__flush_packet(struct cs_etm_decoder *decoder)
+{
+ int err = 0;
+
+ if (decoder == NULL) return -1;
+
+ if (decoder->packet_count >= 31) return -1;
+
+ if (decoder->tail != decoder->end_tail) {
+ decoder->tail = (decoder->tail + 1) & (MAX_BUFFER - 1);
+ decoder->packet_count++;
+ }
+
+ return err;
+}
+
+int cs_etm_decoder__flush(struct cs_etm_decoder *decoder)
+{
+ return cs_etm_decoder__flush_packet(decoder);
+}
+
+static int cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
+ const ocsd_generic_trace_elem *elem,
+ const uint8_t trace_chan_id,
+ enum cs_etm_sample_type sample_type)
+{
+ int err = 0;
+ uint32_t et = 0;
+ struct int_node *inode = NULL;
+
+ if (decoder == NULL) return -1;
+
+ if (decoder->packet_count >= 31) return -1;
+
+ err = cs_etm_decoder__flush_packet(decoder);
+
+ if (err) return err;
+
+ et = decoder->end_tail;
+ /* Search the RB tree for the cpu associated with this traceID */
+ inode = intlist__find(traceid_list, trace_chan_id);
+ if (!inode)
+ return PTR_ERR(inode);
+
+ decoder->packet_buffer[et].sample_type = sample_type;
+ decoder->packet_buffer[et].start_addr = elem->st_addr;
+ decoder->packet_buffer[et].end_addr = elem->en_addr;
+ decoder->packet_buffer[et].exc = false;
+ decoder->packet_buffer[et].exc_ret = false;
+ decoder->packet_buffer[et].cpu = *((int*)inode->priv);
+
+ et = (et + 1) & (MAX_BUFFER - 1);
+
+ decoder->end_tail = et;
+
+ return err;
+}
+
+static int cs_etm_decoder__mark_exception(struct cs_etm_decoder *decoder)
+{
+ int err = 0;
+
+ if (decoder == NULL) return -1;
+
+ decoder->packet_buffer[decoder->end_tail].exc = true;
+
+ return err;
+}
+
+static int cs_etm_decoder__mark_exception_return(struct cs_etm_decoder *decoder)
+{
+ int err = 0;
+
+ if (decoder == NULL) return -1;
+
+ decoder->packet_buffer[decoder->end_tail].exc_ret = true;
+
+ return err;
+}
+
+static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
+ const void *context,
+ const ocsd_trc_index_t indx,
+ const uint8_t trace_chan_id,
+ const ocsd_generic_trace_elem *elem)
+{
+ ocsd_datapath_resp_t resp = OCSD_RESP_CONT;
+ struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
+
+ (void) indx;
+ (void) trace_chan_id;
+
+ switch (elem->elem_type) {
+ case OCSD_GEN_TRC_ELEM_UNKNOWN:
+ break;
+ case OCSD_GEN_TRC_ELEM_NO_SYNC:
+ decoder->trace_on = false;
+ break;
+ case OCSD_GEN_TRC_ELEM_TRACE_ON:
+ decoder->trace_on = true;
+ break;
+ //case OCSD_GEN_TRC_ELEM_TRACE_OVERFLOW:
+ //decoder->trace_on = false;
+ //decoder->discontinuity = true;
+ //break;
+ case OCSD_GEN_TRC_ELEM_INSTR_RANGE:
+ cs_etm_decoder__buffer_packet(decoder,elem,
+ trace_chan_id, CS_ETM_RANGE);
+ resp = OCSD_RESP_WAIT;
+ break;
+ case OCSD_GEN_TRC_ELEM_EXCEPTION:
+ cs_etm_decoder__mark_exception(decoder);
+ break;
+ case OCSD_GEN_TRC_ELEM_EXCEPTION_RET:
+ cs_etm_decoder__mark_exception_return(decoder);
+ break;
+ case OCSD_GEN_TRC_ELEM_PE_CONTEXT:
+ case OCSD_GEN_TRC_ELEM_EO_TRACE:
+ case OCSD_GEN_TRC_ELEM_ADDR_NACC:
+ case OCSD_GEN_TRC_ELEM_TIMESTAMP:
+ case OCSD_GEN_TRC_ELEM_CYCLE_COUNT:
+ //case OCSD_GEN_TRC_ELEM_TS_WITH_CC:
+ case OCSD_GEN_TRC_ELEM_EVENT:
+ default:
+ break;
+ }
+
+ decoder->state.err = 0;
+
+ return resp;
+}
+
+static ocsd_datapath_resp_t cs_etm_decoder__etmv4i_packet_printer(
+ const void *context,
+ const ocsd_datapath_op_t op,
+ const ocsd_trc_index_t indx,
+ const ocsd_etmv4_i_pkt *pkt)
+{
+ const size_t PACKET_STR_LEN = 1024;
+ ocsd_datapath_resp_t ret = OCSD_RESP_CONT;
+ char packet_str[PACKET_STR_LEN];
+ size_t offset;
+ struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context;
+
+ sprintf(packet_str,"%ld: ", (long int) indx);
+ offset = strlen(packet_str);
+
+ switch(op) {
+ case OCSD_OP_DATA:
+ if (ocsd_pkt_str(OCSD_PROTOCOL_ETMV4I,
+ (void *)pkt,
+ packet_str+offset,
+ PACKET_STR_LEN-offset) != OCSD_OK)
+ ret = OCSD_RESP_FATAL_INVALID_PARAM;
+ break;
+ case OCSD_OP_EOT:
+ sprintf(packet_str,"**** END OF TRACE ****\n");
+ break;
+ case OCSD_OP_FLUSH:
+ case OCSD_OP_RESET:
+ default:
+ break;
+ }
+
+ decoder->packet_printer(packet_str);
+
+ return ret;
+}
+
+static int cs_etm_decoder__create_etmv4i_packet_printer(struct cs_etm_decoder_params *d_params, struct cs_etm_trace_params *t_params,
+
+ struct cs_etm_decoder *decoder)
+{
+ ocsd_etmv4_cfg trace_config;
+ int ret = 0;
+
+ if (d_params->packet_printer == NULL)
+ return -1;
+
+ ret = cs_etm_decoder__gen_etmv4_config(t_params,&trace_config);
+
+ if (ret != 0)
+ return -1;
+
+ decoder->packet_printer = d_params->packet_printer;
+
+ ret = ocsd_dt_create_etmv4i_pkt_proc(decoder->dcd_tree,
+ &trace_config,
+ cs_etm_decoder__etmv4i_packet_printer,
+ decoder);
+
+ return ret;
+}
+
+static int cs_etm_decoder__create_etmv4i_packet_decoder(struct cs_etm_decoder_params *d_params, struct cs_etm_trace_params *t_params,
+ struct cs_etm_decoder *decoder)
+{
+ ocsd_etmv4_cfg trace_config;
+ int ret = 0;
+ decoder->packet_printer = d_params->packet_printer;
+
+ ret = cs_etm_decoder__gen_etmv4_config(t_params,&trace_config);
+
+ if (ret != 0)
+ return -1;
+
+ ret = ocsd_dt_create_etmv4i_decoder(decoder->dcd_tree,&trace_config);
+
+ if (ret != OCSD_OK)
+ return -1;
+
+ ret = ocsd_dt_set_gen_elem_outfn(decoder->dcd_tree,
+ cs_etm_decoder__gen_trace_elem_printer, decoder);
+ return ret;
+}
+
+int cs_etm_decoder__add_mem_access_cb(struct cs_etm_decoder *decoder, uint64_t address, uint64_t len, cs_etm_mem_cb_type cb_func)
+{
+ int err;
+
+ decoder->mem_access = cb_func;
+ err = ocsd_dt_add_callback_mem_acc(decoder->dcd_tree,
+ address,
+ address+len-1,
+ OCSD_MEM_SPACE_ANY,
+ cs_etm_decoder__mem_access,
+ decoder);
+ return err;
+}
+
+
+int cs_etm_decoder__add_bin_file(struct cs_etm_decoder *decoder, uint64_t offset, uint64_t address, uint64_t len, const char *fname)
+{
+ int err = 0;
+ file_mem_region_t region;
+
+ (void) len;
+ if (NULL == decoder)
+ return -1;
+
+ if (NULL == decoder->dcd_tree)
+ return -1;
+
+ region.file_offset = offset;
+ region.start_address = address;
+ region.region_size = len;
+ err = ocsd_dt_add_binfile_region_mem_acc(decoder->dcd_tree,
+ &region,
+ 1,
+ OCSD_MEM_SPACE_ANY,
+ fname);
+
+ return err;
+}
+
+const struct cs_etm_state *cs_etm_decoder__process_data_block(struct cs_etm_decoder *decoder,
+ uint64_t indx,
+ const uint8_t *buf,
+ size_t len,
+ size_t *consumed)
+{
+ int ret = 0;
+ ocsd_datapath_resp_t dp_ret = decoder->prev_return;
+ size_t processed = 0;
+
+ if (decoder->packet_count > 0) {
+ decoder->state.err = ret;
+ *consumed = processed;
+ return &(decoder->state);
+ }
+
+ while ((processed < len) && (0 == ret)) {
+
+ if (OCSD_DATA_RESP_IS_CONT(dp_ret)) {
+ uint32_t count;
+ dp_ret = ocsd_dt_process_data(decoder->dcd_tree,
+ OCSD_OP_DATA,
+ indx+processed,
+ len - processed,
+ &buf[processed],
+ &count);
+ processed += count;
+
+ } else if (OCSD_DATA_RESP_IS_WAIT(dp_ret)) {
+ dp_ret = ocsd_dt_process_data(decoder->dcd_tree,
+ OCSD_OP_FLUSH,
+ 0,
+ 0,
+ NULL,
+ NULL);
+ break;
+ } else {
+ ret = -1;
+ }
+ }
+ if (OCSD_DATA_RESP_IS_WAIT(dp_ret)) {
+ if (OCSD_DATA_RESP_IS_CONT(decoder->prev_return)) {
+ decoder->prev_processed = processed;
+ }
+ processed = 0;
+ } else if (OCSD_DATA_RESP_IS_WAIT(decoder->prev_return)) {
+ processed = decoder->prev_processed;
+ decoder->prev_processed = 0;
+ }
+ *consumed = processed;
+ decoder->prev_return = dp_ret;
+ decoder->state.err = ret;
+ return &(decoder->state);
+}
+
+int cs_etm_decoder__get_packet(struct cs_etm_decoder *decoder,
+ struct cs_etm_packet *packet)
+{
+ if (decoder->packet_count == 0) return -1;
+
+ if (packet == NULL) return -1;
+
+ *packet = decoder->packet_buffer[decoder->head];
+
+ decoder->head = (decoder->head + 1) & (MAX_BUFFER - 1);
+
+ decoder->packet_count--;
+
+ return 0;
+}
+
+static void cs_etm_decoder__clear_buffer(struct cs_etm_decoder *decoder)
+{
+ unsigned i;
+
+ decoder->head = 0;
+ decoder->tail = 0;
+ decoder->end_tail = 0;
+ decoder->packet_count = 0;
+ for (i = 0; i < MAX_BUFFER; i++) {
+ decoder->packet_buffer[i].start_addr = 0xdeadbeefdeadbeefUL;
+ decoder->packet_buffer[i].end_addr = 0xdeadbeefdeadbeefUL;
+ decoder->packet_buffer[i].exc = false;
+ decoder->packet_buffer[i].exc_ret = false;
+ decoder->packet_buffer[i].cpu = INT_MIN;
+ }
+}
+
+struct cs_etm_decoder *cs_etm_decoder__new(uint32_t num_cpu, struct cs_etm_decoder_params *d_params, struct cs_etm_trace_params t_params[])
+{
+ struct cs_etm_decoder *decoder;
+ ocsd_dcd_tree_src_t format;
+ uint32_t flags;
+ int ret;
+ size_t i;
+
+ if ((t_params == NULL) || (d_params == 0)) {
+ return NULL;
+ }
+
+ decoder = zalloc(sizeof(struct cs_etm_decoder));
+
+ if (decoder == NULL) {
+ return NULL;
+ }
+
+ decoder->state.data = d_params->data;
+ decoder->prev_return = OCSD_RESP_CONT;
+ cs_etm_decoder__clear_buffer(decoder);
+ format = (d_params->formatted ? OCSD_TRC_SRC_FRAME_FORMATTED :
+ OCSD_TRC_SRC_SINGLE);
+ flags = 0;
+ flags |= (d_params->fsyncs ? OCSD_DFRMTR_HAS_FSYNCS : 0);
+ flags |= (d_params->hsyncs ? OCSD_DFRMTR_HAS_HSYNCS : 0);
+ flags |= (d_params->frame_aligned ? OCSD_DFRMTR_FRAME_MEM_ALIGN : 0);
+
+ /* Create decode tree for the data source */
+ decoder->dcd_tree = ocsd_create_dcd_tree(format,flags);
+
+ if (decoder->dcd_tree == 0) {
+ goto err_free_decoder;
+ }
+
+ for (i = 0; i < num_cpu; ++i) {
+ switch (t_params[i].protocol)
+ {
+ case CS_ETM_PROTO_ETMV4i:
+ if (d_params->operation == CS_ETM_OPERATION_PRINT) {
+ ret = cs_etm_decoder__create_etmv4i_packet_printer(d_params,&t_params[i],decoder);
+ } else if (d_params->operation == CS_ETM_OPERATION_DECODE) {
+ ret = cs_etm_decoder__create_etmv4i_packet_decoder(d_params,&t_params[i],decoder);
+ } else {
+ ret = -CS_ETM_ERR_PARAM;
+ }
+ if (ret != 0) {
+ goto err_free_decoder_tree;
+ }
+ break;
+ default:
+ goto err_free_decoder_tree;
+ break;
+ }
+ }
+
+
+ return decoder;
+
+err_free_decoder_tree:
+ ocsd_destroy_dcd_tree(decoder->dcd_tree);
+err_free_decoder:
+ free(decoder);
+ return NULL;
+}
+
+
+void cs_etm_decoder__free(struct cs_etm_decoder *decoder)
+{
+ if (decoder == NULL) return;
+
+ ocsd_destroy_dcd_tree(decoder->dcd_tree);
+ decoder->dcd_tree = NULL;
+
+ free(decoder);
+}
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
new file mode 100644
index 000000000000..38c5ae84ed07
--- /dev/null
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Tor Jeremiassen <tor.jeremiassen@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
+ * Public License for more details.
+ *
+ * You should have received a copy of the GNU GEneral Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDE__CS_ETM_DECODER_H__
+#define INCLUDE__CS_ETM_DECODER_H__
+
+#include <linux/types.h>
+#include <stdio.h>
+
+struct cs_etm_decoder;
+
+struct cs_etm_buffer {
+ const unsigned char *buf;
+ size_t len;
+ uint64_t offset;
+ //bool consecutive;
+ uint64_t ref_timestamp;
+ //uint64_t trace_nr;
+};
+
+enum cs_etm_sample_type {
+ CS_ETM_RANGE = 1 << 0,
+};
+
+struct cs_etm_state {
+ int err;
+ void *data;
+ unsigned isa;
+ uint64_t start;
+ uint64_t end;
+ uint64_t timestamp;
+};
+
+struct cs_etm_packet {
+ enum cs_etm_sample_type sample_type;
+ uint64_t start_addr;
+ uint64_t end_addr;
+ bool exc;
+ bool exc_ret;
+ int cpu;
+};
+
+
+struct cs_etm_queue;
+typedef uint32_t (*cs_etm_mem_cb_type)(struct cs_etm_queue *, uint64_t, size_t, uint8_t *);
+
+struct cs_etm_trace_params {
+ void *etmv4i_packet_handler;
+ uint32_t reg_idr0;
+ uint32_t reg_idr1;
+ uint32_t reg_idr2;
+ uint32_t reg_idr8;
+ uint32_t reg_configr;
+ uint32_t reg_traceidr;
+ int protocol;
+};
+
+struct cs_etm_decoder_params {
+ int operation;
+ void (*packet_printer)(const char *);
+ cs_etm_mem_cb_type mem_acc_cb;
+ bool formatted;
+ bool fsyncs;
+ bool hsyncs;
+ bool frame_aligned;
+ void *data;
+};
+
+enum {
+ CS_ETM_PROTO_ETMV3 = 1,
+ CS_ETM_PROTO_ETMV4i,
+ CS_ETM_PROTO_ETMV4d,
+};
+
+enum {
+ CS_ETM_OPERATION_PRINT = 1,
+ CS_ETM_OPERATION_DECODE,
+};
+
+enum {
+ CS_ETM_ERR_NOMEM = 1,
+ CS_ETM_ERR_NODATA,
+ CS_ETM_ERR_PARAM,
+};
+
+
+struct cs_etm_decoder *cs_etm_decoder__new(uint32_t num_cpu, struct cs_etm_decoder_params *,struct cs_etm_trace_params []);
+
+int cs_etm_decoder__add_mem_access_cb(struct cs_etm_decoder *, uint64_t, uint64_t, cs_etm_mem_cb_type);
+
+int cs_etm_decoder__flush(struct cs_etm_decoder *);
+void cs_etm_decoder__free(struct cs_etm_decoder *);
+int cs_etm_decoder__get_packet(struct cs_etm_decoder *, struct cs_etm_packet *);
+
+int cs_etm_decoder__add_bin_file(struct cs_etm_decoder *, uint64_t, uint64_t, uint64_t, const char *);
+
+const struct cs_etm_state *cs_etm_decoder__process_data_block(struct cs_etm_decoder *,
+ uint64_t,
+ const uint8_t *,
+ size_t,
+ size_t *);
+
+#endif /* INCLUDE__CS_ETM_DECODER_H__ */
+
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
new file mode 100644
index 000000000000..ca93257a6cb7
--- /dev/null
+++ b/tools/perf/util/cs-etm.c
@@ -0,0 +1,1533 @@
+/*
+ * Copyright(C) 2016 Linaro Limited. All rights reserved.
+ * Author: Tor Jeremiassen <tor.jeremiassen@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/log2.h>
+
+#include "perf.h"
+#include "thread_map.h"
+#include "thread.h"
+#include "thread-stack.h"
+#include "callchain.h"
+#include "auxtrace.h"
+#include "evlist.h"
+#include "machine.h"
+#include "util.h"
+#include "util/intlist.h"
+#include "color.h"
+#include "cs-etm.h"
+#include "cs-etm-decoder/cs-etm-decoder.h"
+#include "debug.h"
+
+#include <stdlib.h>
+
+#define KiB(x) ((x) * 1024)
+#define MiB(x) ((x) * 1024 * 1024)
+#define MAX_TIMESTAMP (~0ULL)
+
+struct cs_etm_auxtrace {
+ struct auxtrace auxtrace;
+ struct auxtrace_queues queues;
+ struct auxtrace_heap heap;
+ u64 **metadata;
+ u32 auxtrace_type;
+ struct perf_session *session;
+ struct machine *machine;
+ struct perf_evsel *switch_evsel;
+ struct thread *unknown_thread;
+ uint32_t num_cpu;
+ bool timeless_decoding;
+ bool sampling_mode;
+ bool snapshot_mode;
+ bool data_queued;
+ bool sync_switch;
+ bool synth_needs_swap;
+ int have_sched_switch;
+
+ bool sample_instructions;
+ u64 instructions_sample_type;
+ u64 instructions_sample_period;
+ u64 instructions_id;
+ struct itrace_synth_opts synth_opts;
+ unsigned pmu_type;
+};
+
+struct cs_etm_queue {
+ struct cs_etm_auxtrace *etm;
+ unsigned queue_nr;
+ struct auxtrace_buffer *buffer;
+ const struct cs_etm_state *state;
+ struct ip_callchain *chain;
+ union perf_event *event_buf;
+ bool on_heap;
+ bool step_through_buffers;
+ bool use_buffer_pid_tid;
+ pid_t pid, tid;
+ int cpu;
+ struct thread *thread;
+ u64 time;
+ u64 timestamp;
+ bool stop;
+ struct cs_etm_decoder *decoder;
+ u64 offset;
+ bool eot;
+ bool kernel_mapped;
+};
+
+static int cs_etm__get_trace(struct cs_etm_buffer *buff, struct cs_etm_queue *etmq);
+static int cs_etm__update_queues(struct cs_etm_auxtrace *);
+static int cs_etm__process_queues(struct cs_etm_auxtrace *, u64);
+static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *, pid_t, u64);
+static uint32_t cs_etm__mem_access(struct cs_etm_queue *, uint64_t , size_t , uint8_t *);
+
+static void cs_etm__packet_dump(const char *pkt_string)
+{
+ const char *color = PERF_COLOR_BLUE;
+
+ color_fprintf(stdout,color, " %s\n", pkt_string);
+ fflush(stdout);
+}
+
+static void cs_etm__dump_event(struct cs_etm_auxtrace *etm,
+ struct auxtrace_buffer *buffer)
+{
+ const char *color = PERF_COLOR_BLUE;
+ struct cs_etm_decoder_params d_params;
+ struct cs_etm_trace_params *t_params;
+ struct cs_etm_decoder *decoder;
+ size_t buffer_used = 0;
+ size_t i;
+
+ fprintf(stdout,"\n");
+ color_fprintf(stdout, color,
+ ". ... CoreSight ETM Trace data: size %zu bytes\n",
+ buffer->size);
+
+ t_params = zalloc(sizeof(struct cs_etm_trace_params) * etm->num_cpu);
+ for (i = 0; i < etm->num_cpu; ++i) {
+ t_params[i].protocol = CS_ETM_PROTO_ETMV4i;
+ t_params[i].reg_idr0 = etm->metadata[i][CS_ETMV4_TRCIDR0];
+ t_params[i].reg_idr1 = etm->metadata[i][CS_ETMV4_TRCIDR1];
+ t_params[i].reg_idr2 = etm->metadata[i][CS_ETMV4_TRCIDR2];
+ t_params[i].reg_idr8 = etm->metadata[i][CS_ETMV4_TRCIDR8];
+ t_params[i].reg_configr = etm->metadata[i][CS_ETMV4_TRCCONFIGR];
+ t_params[i].reg_traceidr = etm->metadata[i][CS_ETMV4_TRCTRACEIDR];
+ //[CS_ETMV4_TRCAUTHSTATUS] = " TRCAUTHSTATUS %"PRIx64"\n",
+ }
+ d_params.packet_printer = cs_etm__packet_dump;
+ d_params.operation = CS_ETM_OPERATION_PRINT;
+ d_params.formatted = true;
+ d_params.fsyncs = false;
+ d_params.hsyncs = false;
+ d_params.frame_aligned = true;
+
+ decoder = cs_etm_decoder__new(etm->num_cpu,&d_params, t_params);
+
+ zfree(&t_params);
+
+ if (decoder == NULL) {
+ return;
+ }
+ do {
+ size_t consumed;
+ cs_etm_decoder__process_data_block(decoder,buffer->offset,&(((uint8_t *)buffer->data)[buffer_used]),buffer->size - buffer_used, &consumed);
+ buffer_used += consumed;
+ } while(buffer_used < buffer->size);
+ cs_etm_decoder__free(decoder);
+}
+
+static int cs_etm__flush_events(struct perf_session *session, struct perf_tool *tool){
+ struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
+ struct cs_etm_auxtrace,
+ auxtrace);
+
+ int ret;
+
+ if (dump_trace)
+ return 0;
+
+ if (!tool->ordered_events)
+ return -EINVAL;
+
+ ret = cs_etm__update_queues(etm);
+
+ if (ret < 0)
+ return ret;
+
+ if (etm->timeless_decoding)
+ return cs_etm__process_timeless_queues(etm,-1,MAX_TIMESTAMP - 1);
+
+ return cs_etm__process_queues(etm, MAX_TIMESTAMP);
+}
+
+static void cs_etm__set_pid_tid_cpu(struct cs_etm_auxtrace *etm,
+ struct auxtrace_queue *queue)
+{
+ struct cs_etm_queue *etmq = queue->priv;
+
+ if ((queue->tid == -1) || (etm->have_sched_switch)) {
+ etmq->tid = machine__get_current_tid(etm->machine, etmq->cpu);
+ thread__zput(etmq->thread);
+ }
+
+ if ((!etmq->thread) && (etmq->tid != -1)) {
+ etmq->thread = machine__find_thread(etm->machine,-1,etmq->tid);
+ }
+
+ if (etmq->thread) {
+ etmq->pid = etmq->thread->pid_;
+ if (queue->cpu == -1) {
+ etmq->cpu = etmq->thread->cpu;
+ }
+ }
+}
+
+static void cs_etm__free_queue(void *priv)
+{
+ struct cs_etm_queue *etmq = priv;
+
+ if (!etmq)
+ return;
+
+ thread__zput(etmq->thread);
+ cs_etm_decoder__free(etmq->decoder);
+ zfree(&etmq->event_buf);
+ zfree(&etmq->chain);
+ free(etmq);
+}
+
+static void cs_etm__free_events(struct perf_session *session)
+{
+ struct cs_etm_auxtrace *aux = container_of(session->auxtrace,
+ struct cs_etm_auxtrace,
+ auxtrace);
+
+ struct auxtrace_queues *queues = &(aux->queues);
+
+ unsigned i;
+
+ for (i = 0; i < queues->nr_queues; ++i) {
+ cs_etm__free_queue(queues->queue_array[i].priv);
+ queues->queue_array[i].priv = 0;
+ }
+
+ auxtrace_queues__free(queues);
+
+}
+
+static void cs_etm__free(struct perf_session *session)
+{
+
+ size_t i;
+ struct int_node *inode, *tmp;
+ struct cs_etm_auxtrace *aux = container_of(session->auxtrace,
+ struct cs_etm_auxtrace,
+ auxtrace);
+ auxtrace_heap__free(&aux->heap);
+ cs_etm__free_events(session);
+ session->auxtrace = NULL;
+
+ /* First remove all traceID/CPU# nodes from the RB tree */
+ intlist__for_each_safe(inode, tmp, traceid_list)
+ intlist__remove(traceid_list, inode);
+ /* Then the RB tree itself */
+ intlist__delete(traceid_list);
+
+ //thread__delete(aux->unknown_thread);
+ for (i = 0; i < aux->num_cpu; ++i) {
+ zfree(&aux->metadata[i]);
+ }
+ zfree(&aux->metadata);
+ free(aux);
+}
+
+static void cs_etm__use_buffer_pid_tid(struct cs_etm_queue *etmq,
+ struct auxtrace_queue *queue,
+ struct auxtrace_buffer *buffer)
+{
+ if ((queue->cpu == -1) && (buffer->cpu != -1)) {
+ etmq->cpu = buffer->cpu;
+ }
+
+ etmq->pid = buffer->pid;
+ etmq->tid = buffer->tid;
+
+ thread__zput(etmq->thread);
+
+ if (etmq->tid != -1) {
+ if (etmq->pid != -1) {
+ etmq->thread = machine__findnew_thread(etmq->etm->machine,
+ etmq->pid,
+ etmq->tid);
+ } else {
+ etmq->thread = machine__findnew_thread(etmq->etm->machine,
+ -1,
+ etmq->tid);
+ }
+ }
+}
+
+
+static int cs_etm__get_trace(struct cs_etm_buffer *buff, struct cs_etm_queue *etmq)
+{
+ struct auxtrace_buffer *aux_buffer = etmq->buffer;
+ struct auxtrace_buffer *old_buffer = aux_buffer;
+ struct auxtrace_queue *queue;
+
+ if (etmq->stop) {
+ buff->len = 0;
+ return 0;
+ }
+
+ queue = &etmq->etm->queues.queue_array[etmq->queue_nr];
+
+ aux_buffer = auxtrace_buffer__next(queue,aux_buffer);
+
+ if (!aux_buffer) {
+ if (old_buffer) {
+ auxtrace_buffer__drop_data(old_buffer);
+ }
+ buff->len = 0;
+ return 0;
+ }
+
+ etmq->buffer = aux_buffer;
+
+ if (!aux_buffer->data) {
+ int fd = perf_data_file__fd(etmq->etm->session->file);
+
+ aux_buffer->data = auxtrace_buffer__get_data(aux_buffer, fd);
+ if (!aux_buffer->data)
+ return -ENOMEM;
+ }
+
+ if (old_buffer)
+ auxtrace_buffer__drop_data(old_buffer);
+
+ if (aux_buffer->use_data) {
+ buff->offset = aux_buffer->offset;
+ buff->len = aux_buffer->use_size;
+ buff->buf = aux_buffer->use_data;
+ } else {
+ buff->offset = aux_buffer->offset;
+ buff->len = aux_buffer->size;
+ buff->buf = aux_buffer->data;
+ }
+ /*
+ buff->offset = 0;
+ buff->len = sizeof(cstrace);
+ buff->buf = cstrace;
+ */
+
+ buff->ref_timestamp = aux_buffer->reference;
+
+ if (etmq->use_buffer_pid_tid &&
+ ((etmq->pid != aux_buffer->pid) ||
+ (etmq->tid != aux_buffer->tid))) {
+ cs_etm__use_buffer_pid_tid(etmq,queue,aux_buffer);
+ }
+
+ if (etmq->step_through_buffers)
+ etmq->stop = true;
+
+ return buff->len;
+}
+
+static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm,
+ unsigned int queue_nr)
+{
+ struct cs_etm_decoder_params d_params;
+ struct cs_etm_trace_params *t_params;
+ struct cs_etm_queue *etmq;
+ size_t i;
+
+ etmq = zalloc(sizeof(struct cs_etm_queue));
+ if (!etmq)
+ return NULL;
+
+ if (etm->synth_opts.callchain) {
+ size_t sz = sizeof(struct ip_callchain);
+
+ sz += etm->synth_opts.callchain_sz * sizeof(u64);
+ etmq->chain = zalloc(sz);
+ if (!etmq->chain)
+ goto out_free;
+ } else {
+ etmq->chain = NULL;
+ }
+
+ etmq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE);
+ if (!etmq->event_buf)
+ goto out_free;
+
+ etmq->etm = etm;
+ etmq->queue_nr = queue_nr;
+ etmq->pid = -1;
+ etmq->tid = -1;
+ etmq->cpu = -1;
+ etmq->stop = false;
+ etmq->kernel_mapped = false;
+
+ t_params = zalloc(sizeof(struct cs_etm_trace_params)*etm->num_cpu);
+
+ for (i = 0; i < etm->num_cpu; ++i) {
+ t_params[i].reg_idr0 = etm->metadata[i][CS_ETMV4_TRCIDR0];
+ t_params[i].reg_idr1 = etm->metadata[i][CS_ETMV4_TRCIDR1];
+ t_params[i].reg_idr2 = etm->metadata[i][CS_ETMV4_TRCIDR2];
+ t_params[i].reg_idr8 = etm->metadata[i][CS_ETMV4_TRCIDR8];
+ t_params[i].reg_configr = etm->metadata[i][CS_ETMV4_TRCCONFIGR];
+ t_params[i].reg_traceidr = etm->metadata[i][CS_ETMV4_TRCTRACEIDR];
+ t_params[i].protocol = CS_ETM_PROTO_ETMV4i;
+ }
+ d_params.packet_printer = cs_etm__packet_dump;
+ d_params.operation = CS_ETM_OPERATION_DECODE;
+ d_params.formatted = true;
+ d_params.fsyncs = false;
+ d_params.hsyncs = false;
+ d_params.frame_aligned = true;
+ d_params.data = etmq;
+
+ etmq->decoder = cs_etm_decoder__new(etm->num_cpu,&d_params,t_params);
+
+
+ zfree(&t_params);
+
+ if (!etmq->decoder)
+ goto out_free;
+
+ etmq->offset = 0;
+ etmq->eot = false;
+
+ return etmq;
+
+out_free:
+ zfree(&etmq->event_buf);
+ zfree(&etmq->chain);
+ free(etmq);
+ return NULL;
+}
+
+static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm,
+ struct auxtrace_queue *queue,
+ unsigned int queue_nr)
+{
+ struct cs_etm_queue *etmq = queue->priv;
+
+ if (list_empty(&(queue->head)))
+ return 0;
+
+ if (etmq == NULL) {
+ etmq = cs_etm__alloc_queue(etm,queue_nr);
+
+ if (etmq == NULL) {
+ return -ENOMEM;
+ }
+
+ queue->priv = etmq;
+
+ if (queue->cpu != -1) {
+ etmq->cpu = queue->cpu;
+ }
+
+ etmq->tid = queue->tid;
+
+ if (etm->sampling_mode) {
+ if (etm->timeless_decoding)
+ etmq->step_through_buffers = true;
+ if (etm->timeless_decoding || !etm->have_sched_switch)
+ etmq->use_buffer_pid_tid = true;
+ }
+ }
+
+ if (!etmq->on_heap &&
+ (!etm->sync_switch)) {
+ const struct cs_etm_state *state;
+ int ret = 0;
+
+ if (etm->timeless_decoding)
+ return ret;
+
+ //cs_etm__log("queue %u getting timestamp\n",queue_nr);
+ //cs_etm__log("queue %u decoding cpu %d pid %d tid %d\n",
+ //queue_nr, etmq->cpu, etmq->pid, etmq->tid);
+ (void) state;
+ return ret;
+ /*
+ while (1) {
+ state = cs_etm_decoder__decode(etmq->decoder);
+ if (state->err) {
+ if (state->err == CS_ETM_ERR_NODATA) {
+ //cs_etm__log("queue %u has no timestamp\n",
+ //queue_nr);
+ return 0;
+ }
+ continue;
+ }
+ if (state->timestamp)
+ break;
+ }
+
+ etmq->timestamp = state->timestamp;
+ //cs_etm__log("queue %u timestamp 0x%"PRIx64 "\n",
+ //queue_nr, etmq->timestamp);
+ etmq->state = state;
+ etmq->have_sample = true;
+ //cs_etm__sample_flags(etmq);
+ ret = auxtrace_heap__add(&etm->heap, queue_nr, etmq->timestamp);
+ if (ret)
+ return ret;
+ etmq->on_heap = true;
+ */
+ }
+
+ return 0;
+}
+
+
+static int cs_etm__setup_queues(struct cs_etm_auxtrace *etm)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < etm->queues.nr_queues; i++) {
+ ret = cs_etm__setup_queue(etm, &(etm->queues.queue_array[i]),i);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+#if 0
+struct cs_etm_cache_entry {
+ struct auxtrace_cache_entry entry;
+ uint64_t icount;
+ uint64_t bcount;
+};
+
+static size_t cs_etm__cache_divisor(void)
+{
+ static size_t d = 64;
+
+ return d;
+}
+
+static size_t cs_etm__cache_size(struct dso *dso,
+ struct machine *machine)
+{
+ off_t size;
+
+ size = dso__data_size(dso,machine);
+ size /= cs_etm__cache_divisor();
+
+ if (size < 1000)
+ return 10;
+
+ if (size > (1 << 21))
+ return 21;
+
+ return 32 - __builtin_clz(size);
+}
+
+static struct auxtrace_cache *cs_etm__cache(struct dso *dso,
+ struct machine *machine)
+{
+ struct auxtrace_cache *c;
+ size_t bits;
+
+ if (dso->auxtrace_cache)
+ return dso->auxtrace_cache;
+
+ bits = cs_etm__cache_size(dso,machine);
+
+ c = auxtrace_cache__new(bits, sizeof(struct cs_etm_cache_entry), 200);
+
+ dso->auxtrace_cache = c;
+
+ return c;
+}
+
+static int cs_etm__cache_add(struct dso *dso, struct machine *machine,
+ uint64_t offset, uint64_t icount, uint64_t bcount)
+{
+ struct auxtrace_cache *c = cs_etm__cache(dso, machine);
+ struct cs_etm_cache_entry *e;
+ int err;
+
+ if (!c)
+ return -ENOMEM;
+
+ e = auxtrace_cache__alloc_entry(c);
+ if (!e)
+ return -ENOMEM;
+
+ e->icount = icount;
+ e->bcount = bcount;
+
+ err = auxtrace_cache__add(c, offset, &e->entry);
+
+ if (err)
+ auxtrace_cache__free_entry(c, e);
+
+ return err;
+}
+
+static struct cs_etm_cache_entry *cs_etm__cache_lookup(struct dso *dso,
+ struct machine *machine,
+ uint64_t offset)
+{
+ struct auxtrace_cache *c = cs_etm__cache(dso, machine);
+
+ if (!c)
+ return NULL;
+
+ return auxtrace_cache__lookup(dso->auxtrace_cache, offset);
+}
+#endif
+
+static int cs_etm__synth_instruction_sample(struct cs_etm_queue *etmq,
+ struct cs_etm_packet *packet)
+{
+ int ret = 0;
+ struct cs_etm_auxtrace *etm = etmq->etm;
+ union perf_event *event = etmq->event_buf;
+ struct perf_sample sample = {.ip = 0,};
+ uint64_t start_addr = packet->start_addr;
+ uint64_t end_addr = packet->end_addr;
+
+ event->sample.header.type = PERF_RECORD_SAMPLE;
+ event->sample.header.misc = PERF_RECORD_MISC_USER;
+ event->sample.header.size = sizeof(struct perf_event_header);
+
+
+ sample.ip = start_addr;
+ sample.pid = etmq->pid;
+ sample.tid = etmq->tid;
+ sample.addr = end_addr;
+ sample.id = etmq->etm->instructions_id;
+ sample.stream_id = etmq->etm->instructions_id;
+ sample.period = (end_addr - start_addr) >> 2;
+ sample.cpu = packet->cpu;
+ sample.flags = 0; // etmq->flags;
+ sample.insn_len = 1; // etmq->insn_len;
+
+ //etmq->last_insn_cnt = etmq->state->tot_insn_cnt;
+
+#if 0
+ {
+ struct addr_location al;
+ uint64_t offset;
+ struct thread *thread;
+ struct machine *machine = etmq->etm->machine;
+ uint8_t cpumode;
+ struct cs_etm_cache_entry *e;
+ uint8_t buf[256];
+ size_t bufsz;
+
+ thread = etmq->thread;
+
+ if (!thread) {
+ thread = etmq->etm->unknown_thread;
+ }
+
+ if (start_addr > 0xffffffc000000000UL) {
+ cpumode = PERF_RECORD_MISC_KERNEL;
+ } else {
+ cpumode = PERF_RECORD_MISC_USER;
+ }
+
+ thread__find_addr_map(thread, cpumode, MAP__FUNCTION, start_addr,&al);
+ if (!al.map || !al.map->dso) {
+ goto endTest;
+ }
+ if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR &&
+ dso__data_status_seen(al.map->dso,DSO_DATA_STATUS_SEEN_ITRACE)) {
+ goto endTest;
+ }
+
+ offset = al.map->map_ip(al.map,start_addr);
+
+
+ e = cs_etm__cache_lookup(al.map->dso, machine, offset);
+
+ if (e) {
+ (void) e;
+ } else {
+ int len;
+ map__load(al.map, machine->symbol_filter);
+
+ bufsz = sizeof(buf);
+ len = dso__data_read_offset(al.map->dso, machine,
+ offset, buf, bufsz);
+
+ if (len <= 0) {
+ goto endTest;
+ }
+
+ cs_etm__cache_add(al.map->dso, machine, offset, (end_addr - start_addr) >> 2, end_addr - start_addr);
+
+ }
+endTest:
+ (void) offset;
+ }
+#endif
+
+ ret = perf_session__deliver_synth_event(etm->session,event, &sample);
+
+ if (ret) {
+ pr_err("CS ETM Trace: failed to deliver instruction event, error %d\n", ret);
+
+ }
+ return ret;
+}
+
+struct cs_etm_synth {
+ struct perf_tool dummy_tool;
+ struct perf_session *session;
+};
+
+
+static int cs_etm__event_synth(struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct machine *machine)
+{
+ struct cs_etm_synth *cs_etm_synth =
+ container_of(tool, struct cs_etm_synth, dummy_tool);
+
+ (void) sample;
+ (void) machine;
+
+ return perf_session__deliver_synth_event(cs_etm_synth->session, event, NULL);
+
+}
+
+
+static int cs_etm__synth_event(struct perf_session *session,
+ struct perf_event_attr *attr, u64 id)
+{
+ struct cs_etm_synth cs_etm_synth;
+
+ memset(&cs_etm_synth, 0, sizeof(struct cs_etm_synth));
+ cs_etm_synth.session = session;
+
+ return perf_event__synthesize_attr(&cs_etm_synth.dummy_tool, attr, 1,
+ &id, cs_etm__event_synth);
+}
+
+static int cs_etm__synth_events(struct cs_etm_auxtrace *etm,
+ struct perf_session *session)
+{
+ struct perf_evlist *evlist = session->evlist;
+ struct perf_evsel *evsel;
+ struct perf_event_attr attr;
+ bool found = false;
+ u64 id;
+ int err;
+
+ evlist__for_each(evlist, evsel) {
+
+ if (evsel->attr.type == etm->pmu_type) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ pr_debug("There are no selected events with Core Sight Trace data\n");
+ return 0;
+ }
+
+ memset(&attr, 0, sizeof(struct perf_event_attr));
+ attr.size = sizeof(struct perf_event_attr);
+ attr.type = PERF_TYPE_HARDWARE;
+ attr.sample_type = evsel->attr.sample_type & PERF_SAMPLE_MASK;
+ attr.sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID |
+ PERF_SAMPLE_PERIOD;
+ if (etm->timeless_decoding)
+ attr.sample_type &= ~(u64)PERF_SAMPLE_TIME;
+ else
+ attr.sample_type |= PERF_SAMPLE_TIME;
+
+ attr.exclude_user = evsel->attr.exclude_user;
+ attr.exclude_kernel = evsel->attr.exclude_kernel;
+ attr.exclude_hv = evsel->attr.exclude_hv;
+ attr.exclude_host = evsel->attr.exclude_host;
+ attr.exclude_guest = evsel->attr.exclude_guest;
+ attr.sample_id_all = evsel->attr.sample_id_all;
+ attr.read_format = evsel->attr.read_format;
+
+ id = evsel->id[0] + 1000000000;
+
+ if (!id)
+ id = 1;
+
+ if (etm->synth_opts.instructions) {
+ attr.config = PERF_COUNT_HW_INSTRUCTIONS;
+ attr.sample_period = etm->synth_opts.period;
+ etm->instructions_sample_period = attr.sample_period;
+ err = cs_etm__synth_event(session, &attr, id);
+
+ if (err) {
+ pr_err("%s: failed to synthesize 'instructions' event type\n",
+ __func__);
+ return err;
+ }
+ etm->sample_instructions = true;
+ etm->instructions_sample_type = attr.sample_type;
+ etm->instructions_id = id;
+ id += 1;
+ }
+
+ etm->synth_needs_swap = evsel->needs_swap;
+ return 0;
+}
+
+static int cs_etm__sample(struct cs_etm_queue *etmq)
+{
+ //const struct cs_etm_state *state = etmq->state;
+ struct cs_etm_packet packet;
+ //struct cs_etm_auxtrace *etm = etmq->etm;
+ int err;
+
+ err = cs_etm_decoder__get_packet(etmq->decoder,&packet);
+ // if there is no sample, it returns err = -1, no real error
+
+ if (!err && packet.sample_type & CS_ETM_RANGE) {
+ err = cs_etm__synth_instruction_sample(etmq,&packet);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+static int cs_etm__run_decoder(struct cs_etm_queue *etmq, u64 *timestamp)
+{
+ struct cs_etm_buffer buffer;
+ size_t buffer_used;
+ int err = 0;
+
+ /* Go through each buffer in the queue and decode them one by one */
+more:
+ buffer_used = 0;
+ memset(&buffer, 0, sizeof(buffer));
+ err = cs_etm__get_trace(&buffer,etmq);
+ if (err <= 0)
+ return err;
+
+ do {
+ size_t processed = 0;
+ etmq->state = cs_etm_decoder__process_data_block(etmq->decoder,
+ etmq->offset,
+ &buffer.buf[buffer_used],
+ buffer.len-buffer_used,
+ &processed);
+ err = etmq->state->err;
+ etmq->offset += processed;
+ buffer_used += processed;
+ if (!err)
+ cs_etm__sample(etmq);
+ } while (!etmq->eot && (buffer.len > buffer_used));
+goto more;
+
+ (void) timestamp;
+
+ return err;
+}
+
+static int cs_etm__update_queues(struct cs_etm_auxtrace *etm)
+{
+ if (etm->queues.new_data) {
+ etm->queues.new_data = false;
+ return cs_etm__setup_queues(etm);
+ }
+ return 0;
+}
+
+static int cs_etm__process_queues(struct cs_etm_auxtrace *etm, u64 timestamp)
+{
+ unsigned int queue_nr;
+ u64 ts;
+ int ret;
+
+ while (1) {
+ struct auxtrace_queue *queue;
+ struct cs_etm_queue *etmq;
+
+ if (!etm->heap.heap_cnt)
+ return 0;
+
+ if (etm->heap.heap_array[0].ordinal >= timestamp)
+ return 0;
+
+ queue_nr = etm->heap.heap_array[0].queue_nr;
+ queue = &etm->queues.queue_array[queue_nr];
+ etmq = queue->priv;
+
+ //cs_etm__log("queue %u processing 0x%" PRIx64 " to 0x%" PRIx64 "\n",
+ //queue_nr, etm->heap.heap_array[0].ordinal,
+ //timestamp);
+
+ auxtrace_heap__pop(&etm->heap);
+
+ if (etm->heap.heap_cnt) {
+ ts = etm->heap.heap_array[0].ordinal + 1;
+ if (ts > timestamp)
+ ts = timestamp;
+ } else {
+ ts = timestamp;
+ }
+
+ cs_etm__set_pid_tid_cpu(etm, queue);
+
+ ret = cs_etm__run_decoder(etmq, &ts);
+
+ if (ret < 0) {
+ auxtrace_heap__add(&etm->heap, queue_nr, ts);
+ return ret;
+ }
+
+ if (!ret) {
+ ret = auxtrace_heap__add(&etm->heap, queue_nr, ts);
+ if (ret < 0)
+ return ret;
+ } else {
+ etmq->on_heap = false;
+ }
+ }
+ return 0;
+}
+
+static int cs_etm__process_timeless_queues(struct cs_etm_auxtrace *etm,
+ pid_t tid,
+ u64 time_)
+{
+ struct auxtrace_queues *queues = &etm->queues;
+ unsigned int i;
+ u64 ts = 0;
+
+ for (i = 0; i < queues->nr_queues; ++i) {
+ struct auxtrace_queue *queue = &(etm->queues.queue_array[i]);
+ struct cs_etm_queue *etmq = queue->priv;
+
+ if (etmq && ((tid == -1) || (etmq->tid == tid))) {
+ etmq->time = time_;
+ cs_etm__set_pid_tid_cpu(etm, queue);
+ cs_etm__run_decoder(etmq,&ts);
+
+ }
+ }
+ return 0;
+}
+
+static struct cs_etm_queue *cs_etm__cpu_to_etmq(struct cs_etm_auxtrace *etm,
+ int cpu)
+{
+ unsigned q,j;
+
+ if (etm->queues.nr_queues == 0)
+ return NULL;
+
+ if (cpu < 0)
+ q = 0;
+ else if ((unsigned) cpu >= etm->queues.nr_queues)
+ q = etm->queues.nr_queues - 1;
+ else
+ q = cpu;
+
+ if (etm->queues.queue_array[q].cpu == cpu)
+ return etm->queues.queue_array[q].priv;
+
+ for (j = 0; q > 0; j++) {
+ if (etm->queues.queue_array[--q].cpu == cpu)
+ return etm->queues.queue_array[q].priv;
+ }
+
+ for (; j < etm->queues.nr_queues; j++) {
+ if (etm->queues.queue_array[j].cpu == cpu)
+ return etm->queues.queue_array[j].priv;
+
+ }
+
+ return NULL;
+}
+
+static uint32_t cs_etm__mem_access(struct cs_etm_queue *etmq, uint64_t address, size_t size, uint8_t *buffer)
+{
+ struct addr_location al;
+ uint64_t offset;
+ struct thread *thread;
+ struct machine *machine;
+ uint8_t cpumode;
+ int len;
+
+ if (etmq == NULL)
+ return -1;
+
+ machine = etmq->etm->machine;
+ thread = etmq->thread;
+ if (address > 0xffffffc000000000UL) {
+ cpumode = PERF_RECORD_MISC_KERNEL;
+ } else {
+ cpumode = PERF_RECORD_MISC_USER;
+ }
+
+ thread__find_addr_map(thread, cpumode, MAP__FUNCTION, address,&al);
+
+ if (!al.map || !al.map->dso) {
+ return 0;
+ }
+
+ if (al.map->dso->data.status == DSO_DATA_STATUS_ERROR &&
+ dso__data_status_seen(al.map->dso,DSO_DATA_STATUS_SEEN_ITRACE)) {
+ return 0;
+ }
+
+ offset = al.map->map_ip(al.map,address);
+
+ map__load(al.map, machine->symbol_filter);
+
+ len = dso__data_read_offset(al.map->dso, machine,
+ offset, buffer, size);
+
+ if (len <= 0) {
+ return 0;
+ }
+
+ return len;
+}
+
+static bool check_need_swap(int file_endian)
+{
+ const int data = 1;
+ u8 *check = (u8 *)&data;
+ int host_endian;
+
+ if (check[0] == 1)
+ host_endian = ELFDATA2LSB;
+ else
+ host_endian = ELFDATA2MSB;
+
+ return host_endian != file_endian;
+}
+
+static int cs_etm__read_elf_info(const char *fname, uint64_t *foffset, uint64_t *fstart, uint64_t *fsize)
+{
+ FILE *fp;
+ u8 e_ident[EI_NIDENT];
+ int ret = -1;
+ bool need_swap = false;
+ size_t buf_size;
+ void *buf;
+ int i;
+
+ fp = fopen(fname, "r");
+ if (fp == NULL)
+ return -1;
+
+ if (fread(e_ident, sizeof(e_ident), 1, fp) != 1)
+ goto out;
+
+ if (memcmp(e_ident, ELFMAG, SELFMAG) ||
+ e_ident[EI_VERSION] != EV_CURRENT)
+ goto out;
+
+ need_swap = check_need_swap(e_ident[EI_DATA]);
+
+ /* for simplicity */
+ fseek(fp, 0, SEEK_SET);
+
+ if (e_ident[EI_CLASS] == ELFCLASS32) {
+ Elf32_Ehdr ehdr;
+ Elf32_Phdr *phdr;
+
+ if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
+ goto out;
+
+ if (need_swap) {
+ ehdr.e_phoff = bswap_32(ehdr.e_phoff);
+ ehdr.e_phentsize = bswap_16(ehdr.e_phentsize);
+ ehdr.e_phnum = bswap_16(ehdr.e_phnum);
+ }
+
+ buf_size = ehdr.e_phentsize * ehdr.e_phnum;
+ buf = malloc(buf_size);
+ if (buf == NULL)
+ goto out;
+
+ fseek(fp, ehdr.e_phoff, SEEK_SET);
+ if (fread(buf, buf_size, 1, fp) != 1)
+ goto out_free;
+
+ for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
+
+ if (need_swap) {
+ phdr->p_type = bswap_32(phdr->p_type);
+ phdr->p_offset = bswap_32(phdr->p_offset);
+ phdr->p_filesz = bswap_32(phdr->p_filesz);
+ }
+
+ if (phdr->p_type != PT_LOAD)
+ continue;
+
+ *foffset = phdr->p_offset;
+ *fstart = phdr->p_vaddr;
+ *fsize = phdr->p_filesz;
+ ret = 0;
+ break;
+ }
+ } else {
+ Elf64_Ehdr ehdr;
+ Elf64_Phdr *phdr;
+
+ if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
+ goto out;
+
+ if (need_swap) {
+ ehdr.e_phoff = bswap_64(ehdr.e_phoff);
+ ehdr.e_phentsize = bswap_16(ehdr.e_phentsize);
+ ehdr.e_phnum = bswap_16(ehdr.e_phnum);
+ }
+
+ buf_size = ehdr.e_phentsize * ehdr.e_phnum;
+ buf = malloc(buf_size);
+ if (buf == NULL)
+ goto out;
+
+ fseek(fp, ehdr.e_phoff, SEEK_SET);
+ if (fread(buf, buf_size, 1, fp) != 1)
+ goto out_free;
+
+ for (i = 0, phdr = buf; i < ehdr.e_phnum; i++, phdr++) {
+
+ if (need_swap) {
+ phdr->p_type = bswap_32(phdr->p_type);
+ phdr->p_offset = bswap_64(phdr->p_offset);
+ phdr->p_filesz = bswap_64(phdr->p_filesz);
+ }
+
+ if (phdr->p_type != PT_LOAD)
+ continue;
+
+ *foffset = phdr->p_offset;
+ *fstart = phdr->p_vaddr;
+ *fsize = phdr->p_filesz;
+ ret = 0;
+ break;
+ }
+ }
+out_free:
+ free(buf);
+out:
+ fclose(fp);
+ return ret;
+}
+
+static int cs_etm__process_event(struct perf_session *session,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct perf_tool *tool)
+{
+ struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
+ struct cs_etm_auxtrace,
+ auxtrace);
+
+ u64 timestamp;
+ int err = 0;
+
+ if (dump_trace)
+ return 0;
+
+ if (!tool->ordered_events) {
+ pr_err("CoreSight ETM Trace requires ordered events\n");
+ return -EINVAL;
+ }
+
+ if (sample->time && (sample->time != (u64)-1))
+ timestamp = sample->time;
+ else
+ timestamp = 0;
+
+ if (timestamp || etm->timeless_decoding) {
+ err = cs_etm__update_queues(etm);
+ if (err)
+ return err;
+
+ }
+
+ if (event->header.type == PERF_RECORD_MMAP2) {
+ struct dso *dso;
+ int cpu;
+ struct cs_etm_queue *etmq;
+
+ cpu = sample->cpu;
+
+ etmq = cs_etm__cpu_to_etmq(etm,cpu);
+
+ if (!etmq) {
+ return -1;
+ }
+
+ dso = dsos__find(&(etm->machine->dsos),event->mmap2.filename,false);
+ if (NULL != dso) {
+ err = cs_etm_decoder__add_mem_access_cb(
+ etmq->decoder,
+ event->mmap2.start,
+ event->mmap2.len,
+ cs_etm__mem_access);
+ }
+
+ if ((symbol_conf.vmlinux_name != NULL) && (!etmq->kernel_mapped)) {
+ uint64_t foffset;
+ uint64_t fstart;
+ uint64_t fsize;
+
+ err = cs_etm__read_elf_info(symbol_conf.vmlinux_name,
+ &foffset,&fstart,&fsize);
+
+ if (!err) {
+ cs_etm_decoder__add_bin_file(
+ etmq->decoder,
+ foffset,
+ fstart,
+ fsize & ~0x1ULL,
+ symbol_conf.vmlinux_name);
+
+ etmq->kernel_mapped = true;
+ }
+ }
+
+ }
+
+ if (etm->timeless_decoding) {
+ if (event->header.type == PERF_RECORD_EXIT) {
+ err = cs_etm__process_timeless_queues(etm,
+ event->fork.tid,
+ sample->time);
+ }
+ } else if (timestamp) {
+ err = cs_etm__process_queues(etm, timestamp);
+ }
+
+ //cs_etm__log("event %s (%u): cpu %d time%"PRIu64" tsc %#"PRIx64"\n",
+ //perf_event__name(event->header.type), event->header.type,
+ //sample->cpu, sample->time, timestamp);
+ return err;
+}
+
+static int cs_etm__process_auxtrace_event(struct perf_session *session,
+ union perf_event *event,
+ struct perf_tool *tool)
+{
+ struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
+ struct cs_etm_auxtrace,
+ auxtrace);
+
+ (void) tool;
+
+ if (!etm->data_queued) {
+ struct auxtrace_buffer *buffer;
+ off_t data_offset;
+ int fd = perf_data_file__fd(session->file);
+ bool is_pipe = perf_data_file__is_pipe(session->file);
+ int err;
+
+ if (is_pipe) {
+ data_offset = 0;
+ } else {
+ data_offset = lseek(fd, 0, SEEK_CUR);
+ if (data_offset == -1) {
+ return -errno;
+ }
+ }
+
+ err = auxtrace_queues__add_event(&etm->queues,
+ session,
+ event,
+ data_offset,
+ &buffer);
+ if (err)
+ return err;
+
+ if (dump_trace)
+ {
+ if (auxtrace_buffer__get_data(buffer,fd)) {
+ cs_etm__dump_event(etm,buffer);
+ auxtrace_buffer__put_data(buffer);
+ }
+ }
+ }
+
+ return 0;
+
+}
+
+static const char * const cs_etm_global_header_fmts[] = {
+ [CS_HEADER_VERSION_0] = " Header version %"PRIx64"\n",
+ [CS_PMU_TYPE_CPUS] = " PMU type/num cpus %"PRIx64"\n",
+ [CS_ETM_SNAPSHOT] = " Snapshot %"PRIx64"\n",
+};
+
+static const char * const cs_etm_priv_fmts[] = {
+ [CS_ETM_MAGIC] = " Magic number %"PRIx64"\n",
+ [CS_ETM_CPU] = " CPU %"PRIx64"\n",
+ [CS_ETM_ETMCR] = " ETMCR %"PRIx64"\n",
+ [CS_ETM_ETMTRACEIDR] = " ETMTRACEIDR %"PRIx64"\n",
+ [CS_ETM_ETMCCER] = " ETMCCER %"PRIx64"\n",
+ [CS_ETM_ETMIDR] = " ETMIDR %"PRIx64"\n",
+};
+
+static const char * const cs_etmv4_priv_fmts[] = {
+ [CS_ETM_MAGIC] = " Magic number %"PRIx64"\n",
+ [CS_ETM_CPU] = " CPU %"PRIx64"\n",
+ [CS_ETMV4_TRCCONFIGR] = " TRCCONFIGR %"PRIx64"\n",
+ [CS_ETMV4_TRCTRACEIDR] = " TRCTRACEIDR %"PRIx64"\n",
+ [CS_ETMV4_TRCIDR0] = " TRCIDR0 %"PRIx64"\n",
+ [CS_ETMV4_TRCIDR1] = " TRCIDR1 %"PRIx64"\n",
+ [CS_ETMV4_TRCIDR2] = " TRCIDR2 %"PRIx64"\n",
+ [CS_ETMV4_TRCIDR8] = " TRCIDR8 %"PRIx64"\n",
+ [CS_ETMV4_TRCAUTHSTATUS] = " TRCAUTHSTATUS %"PRIx64"\n",
+};
+
+static void cs_etm__print_auxtrace_info(u64 *val, size_t num)
+{
+ unsigned i,j,cpu;
+
+ for (i = 0, cpu = 0; cpu < num; ++cpu) {
+
+ if (val[i] == __perf_cs_etmv3_magic) {
+ for (j = 0; j < CS_ETM_PRIV_MAX; ++j, ++i) {
+ fprintf(stdout,cs_etm_priv_fmts[j],val[i]);
+ }
+ } else if (val[i] == __perf_cs_etmv4_magic) {
+ for (j = 0; j < CS_ETMV4_PRIV_MAX; ++j, ++i) {
+ fprintf(stdout,cs_etmv4_priv_fmts[j],val[i]);
+ }
+ } else {
+ // failure.. return
+ return;
+ }
+ }
+}
+
+int cs_etm__process_auxtrace_info(union perf_event *event,
+ struct perf_session *session)
+{
+ struct auxtrace_info_event *auxtrace_info = &(event->auxtrace_info);
+ size_t event_header_size = sizeof(struct perf_event_header);
+ size_t info_header_size = 8;
+ size_t total_size = auxtrace_info->header.size;
+ size_t priv_size = 0;
+ size_t num_cpu;
+ struct cs_etm_auxtrace *etm = 0;
+ int err = 0, idx = -1;
+ u64 *ptr;
+ u64 *hdr = NULL;
+ u64 **metadata = NULL;
+ size_t i,j,k;
+ unsigned pmu_type;
+ struct int_node *inode;
+
+ /*
+ * sizeof(auxtrace_info_event::type) +
+ * sizeof(auxtrace_info_event::reserved) == 8
+ */
+ info_header_size = 8;
+
+ if (total_size < (event_header_size + info_header_size))
+ return -EINVAL;
+
+ priv_size = total_size - event_header_size - info_header_size;
+
+ // First the global part
+
+ ptr = (u64 *) auxtrace_info->priv;
+ if (ptr[0] == 0) {
+ hdr = zalloc(sizeof(u64 *) * CS_HEADER_VERSION_0_MAX);
+ if (hdr == NULL) {
+ return -EINVAL;
+ }
+ for (i = 0; i < CS_HEADER_VERSION_0_MAX; ++i) {
+ hdr[i] = ptr[i];
+ }
+ num_cpu = hdr[CS_PMU_TYPE_CPUS] & 0xffffffff;
+ pmu_type = (unsigned) ((hdr[CS_PMU_TYPE_CPUS] >> 32) & 0xffffffff);
+ } else {
+ return -EINVAL;
+ }
+
+ /*
+ * Create an RB tree for traceID-CPU# tuple. Since the conversion has
+ * to be made for each packet that gets decoded optimizing access in
+ * anything other than a sequential array is worth doing.
+ */
+ traceid_list = intlist__new(NULL);
+ if (!traceid_list)
+ return -ENOMEM;
+
+ metadata = zalloc(sizeof(u64 *) * num_cpu);
+ if (!metadata) {
+ err = -ENOMEM;
+ goto err_free_traceid_list;
+ }
+
+ if (metadata == NULL) {
+ return -EINVAL;
+ }
+
+ for (j = 0; j < num_cpu; ++j) {
+ if (ptr[i] == __perf_cs_etmv3_magic) {
+ metadata[j] = zalloc(sizeof(u64)*CS_ETM_PRIV_MAX);
+ if (metadata == NULL)
+ return -EINVAL;
+ for (k = 0; k < CS_ETM_PRIV_MAX; k++) {
+ metadata[j][k] = ptr[i+k];
+ }
+
+ /* The traceID is our handle */
+ idx = metadata[j][CS_ETM_ETMIDR];
+ i += CS_ETM_PRIV_MAX;
+ } else if (ptr[i] == __perf_cs_etmv4_magic) {
+ metadata[j] = zalloc(sizeof(u64)*CS_ETMV4_PRIV_MAX);
+ if (metadata == NULL)
+ return -EINVAL;
+ for (k = 0; k < CS_ETMV4_PRIV_MAX; k++) {
+ metadata[j][k] = ptr[i+k];
+ }
+
+ /* The traceID is our handle */
+ idx = metadata[j][CS_ETMV4_TRCTRACEIDR];
+ i += CS_ETMV4_PRIV_MAX;
+ }
+
+ /* Get an RB node for this CPU */
+ inode = intlist__findnew(traceid_list, idx);
+
+ /* Something went wrong, no need to continue */
+ if (!inode) {
+ err = PTR_ERR(inode);
+ goto err_free_metadata;
+ }
+
+ /*
+ * The node for that CPU should not have been taken already.
+ * Backout if that's the case.
+ */
+ if (inode->priv) {
+ err = -EINVAL;
+ goto err_free_metadata;
+ }
+
+ /* All good, associate the traceID with the CPU# */
+ inode->priv = &metadata[j][CS_ETM_CPU];
+
+ }
+
+ if (i*8 != priv_size)
+ return -EINVAL;
+
+ if (dump_trace)
+ cs_etm__print_auxtrace_info(auxtrace_info->priv,num_cpu);
+
+ etm = zalloc(sizeof(struct cs_etm_auxtrace));
+
+ etm->num_cpu = num_cpu;
+ etm->pmu_type = pmu_type;
+ etm->snapshot_mode = (hdr[CS_ETM_SNAPSHOT] != 0);
+
+ if (!etm)
+ return -ENOMEM;
+
+
+ err = auxtrace_queues__init(&etm->queues);
+ if (err)
+ goto err_free;
+
+ etm->unknown_thread = thread__new(999999999,999999999);
+ if (etm->unknown_thread == NULL) {
+ err = -ENOMEM;
+ goto err_free_queues;
+ }
+ err = thread__set_comm(etm->unknown_thread, "unknown", 0);
+ if (err) {
+ goto err_delete_thread;
+ }
+
+ if (thread__init_map_groups(etm->unknown_thread,
+ etm->machine)) {
+ err = -ENOMEM;
+ goto err_delete_thread;
+ }
+
+ etm->timeless_decoding = true;
+ etm->sampling_mode = false;
+ etm->metadata = metadata;
+ etm->session = session;
+ etm->machine = &session->machines.host;
+ etm->auxtrace_type = auxtrace_info->type;
+
+ etm->auxtrace.process_event = cs_etm__process_event;
+ etm->auxtrace.process_auxtrace_event = cs_etm__process_auxtrace_event;
+ etm->auxtrace.flush_events = cs_etm__flush_events;
+ etm->auxtrace.free_events = cs_etm__free_events;
+ etm->auxtrace.free = cs_etm__free;
+ session->auxtrace = &(etm->auxtrace);
+
+ if (dump_trace)
+ return 0;
+
+ if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
+ etm->synth_opts = *session->itrace_synth_opts;
+ } else {
+ itrace_synth_opts__set_default(&etm->synth_opts);
+ }
+ etm->synth_opts.branches = false;
+ etm->synth_opts.callchain = false;
+ etm->synth_opts.calls = false;
+ etm->synth_opts.returns = false;
+
+ err = cs_etm__synth_events(etm, session);
+ if (err)
+ goto err_delete_thread;
+
+ err = auxtrace_queues__process_index(&etm->queues, session);
+ if (err)
+ goto err_delete_thread;
+
+ etm->data_queued = etm->queues.populated;
+
+ return 0;
+
+err_delete_thread:
+ thread__delete(etm->unknown_thread);
+err_free_queues:
+ auxtrace_queues__free(&etm->queues);
+ session->auxtrace = NULL;
+err_free:
+ free(etm);
+err_free_metadata:
+ /* No need to check @metadata[j], free(NULL) is supported */
+ for (j = 0; j < num_cpu; ++j)
+ free(metadata[j]);
+ free(metadata);
+err_free_traceid_list:
+ intlist__delete(traceid_list);
+
+ return err;
+}
diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h
new file mode 100644
index 000000000000..ec6ff78f1905
--- /dev/null
+++ b/tools/perf/util/cs-etm.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright(C) 2015 Linaro Limited. All rights reserved.
+ * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef INCLUDE__UTIL_PERF_CS_ETM_H__
+#define INCLUDE__UTIL_PERF_CS_ETM_H__
+
+#include "util/event.h"
+#include "util/intlist.h"
+#include "util/session.h"
+
+/* Versionning header in case things need tro change in the future. That way
+ * decoding of old snapshot is still possible.
+ */
+enum {
+ /* Starting with 0x0 */
+ CS_HEADER_VERSION_0,
+ /* PMU->type (32 bit), total # of CPUs (32 bit) */
+ CS_PMU_TYPE_CPUS,
+ CS_ETM_SNAPSHOT,
+ CS_HEADER_VERSION_0_MAX,
+};
+
+/* Beginning of header common to both ETMv3 and V4 */
+enum {
+ CS_ETM_MAGIC,
+ CS_ETM_CPU,
+};
+
+/* ETMv3/PTM metadata */
+enum {
+ /* Dynamic, configurable parameters */
+ CS_ETM_ETMCR = CS_ETM_CPU + 1,
+ CS_ETM_ETMTRACEIDR,
+ /* RO, taken from sysFS */
+ CS_ETM_ETMCCER,
+ CS_ETM_ETMIDR,
+ CS_ETM_PRIV_MAX,
+};
+
+/* ETMv4 metadata */
+enum {
+ /* Dynamic, configurable parameters */
+ CS_ETMV4_TRCCONFIGR = CS_ETM_CPU + 1,
+ CS_ETMV4_TRCTRACEIDR,
+ /* RO, taken from sysFS */
+ CS_ETMV4_TRCIDR0,
+ CS_ETMV4_TRCIDR1,
+ CS_ETMV4_TRCIDR2,
+ CS_ETMV4_TRCIDR8,
+ CS_ETMV4_TRCAUTHSTATUS,
+ CS_ETMV4_PRIV_MAX,
+};
+
+/* RB tree for quick conversion between traceID and CPUs */
+struct intlist *traceid_list;
+
+#define KiB(x) ((x) * 1024)
+#define MiB(x) ((x) * 1024 * 1024)
+
+#define CS_ETM_HEADER_SIZE (CS_HEADER_VERSION_0_MAX * sizeof(u64))
+
+static const u64 __perf_cs_etmv3_magic = 0x3030303030303030ULL;
+static const u64 __perf_cs_etmv4_magic = 0x4040404040404040ULL;
+#define CS_ETMV3_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64))
+#define CS_ETMV4_PRIV_SIZE (CS_ETMV4_PRIV_MAX * sizeof(u64))
+
+int cs_etm__process_auxtrace_info(union perf_event *event,
+ struct perf_session *session);
+
+#endif
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index b4b96120fc3b..b856cf0393ea 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -1247,6 +1247,30 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e
return err;
}
+int perf_evlist__apply_drv_configs(struct perf_evlist *evlist,
+ struct perf_evsel **err_evsel,
+ struct perf_evsel_config_term **err_term)
+{
+ struct perf_evsel *evsel;
+ int err = 0;
+ const int ncpus = cpu_map__nr(evlist->cpus),
+ nthreads = thread_map__nr(evlist->threads);
+
+ evlist__for_each(evlist, evsel) {
+ if (list_empty(&evsel->drv_config_terms))
+ continue;
+
+ err = perf_evsel__apply_drv_configs(evsel, ncpus,
+ nthreads, err_term);
+ if (err) {
+ *err_evsel = evsel;
+ break;
+ }
+ }
+
+ return err;
+}
+
int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
{
struct perf_evsel *evsel;
@@ -1486,7 +1510,7 @@ int perf_evlist__open(struct perf_evlist *evlist)
perf_evlist__update_id_pos(evlist);
evlist__for_each(evlist, evsel) {
- err = perf_evsel__open(evsel, evlist->cpus, evlist->threads);
+ err = perf_evsel__open(evsel, evsel->cpus, evsel->threads);
if (err < 0)
goto out_err;
}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index a459fe71b452..ae5c1eb1d08c 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -163,6 +163,9 @@ void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
struct thread_map *threads);
int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target);
int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel);
+int perf_evlist__apply_drv_configs(struct perf_evlist *evlist,
+ struct perf_evsel **err_evsel,
+ struct perf_evsel_config_term **term);
void __perf_evlist__set_leader(struct list_head *list);
void perf_evlist__set_leader(struct perf_evlist *evlist);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index d4913a46ee1c..6e0a16c7176a 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -211,6 +211,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
evsel->bpf_fd = -1;
INIT_LIST_HEAD(&evsel->node);
INIT_LIST_HEAD(&evsel->config_terms);
+ INIT_LIST_HEAD(&evsel->drv_config_terms);
perf_evsel__object.init(evsel);
evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
perf_evsel__calc_id_pos(evsel);
@@ -981,6 +982,27 @@ int perf_evsel__append_filter(struct perf_evsel *evsel,
return -1;
}
+int perf_evsel__apply_drv_configs(struct perf_evsel *evsel,
+ int ncpus, int nthreads,
+ struct perf_evsel_config_term **err_term)
+{
+ int err = 0;
+ struct perf_evsel_config_term *term;
+
+ list_for_each_entry(term, &evsel->drv_config_terms, list) {
+ err = perf_evsel__run_ioctl(evsel, ncpus, nthreads,
+ PERF_EVENT_IOC_SET_DRV_CONFIGS,
+ (void *)term->val.drv_cfg);
+
+ if (err) {
+ *err_term = term;
+ break;
+ }
+ }
+
+ return err;
+}
+
int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads)
{
return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
@@ -988,6 +1010,16 @@ int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads)
0);
}
+int perf_evsel__disable(struct perf_evsel *evsel)
+{
+ int nthreads = thread_map__nr(evsel->threads);
+ int ncpus = cpu_map__nr(evsel->cpus);
+
+ return perf_evsel__run_ioctl(evsel, ncpus, nthreads,
+ PERF_EVENT_IOC_DISABLE,
+ 0);
+}
+
int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads)
{
if (ncpus == 0 || nthreads == 0)
@@ -1033,6 +1065,16 @@ static void perf_evsel__free_config_terms(struct perf_evsel *evsel)
}
}
+static void perf_evsel__free_drv_config_terms(struct perf_evsel *evsel)
+{
+ struct perf_evsel_config_term *term, *h;
+
+ list_for_each_entry_safe(term, h, &evsel->drv_config_terms, list) {
+ list_del(&term->list);
+ free(term);
+ }
+}
+
void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
{
int cpu, thread;
@@ -1054,6 +1096,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)
perf_evsel__free_fd(evsel);
perf_evsel__free_id(evsel);
perf_evsel__free_config_terms(evsel);
+ perf_evsel__free_drv_config_terms(evsel);
close_cgroup(evsel->cgrp);
cpu_map__put(evsel->cpus);
cpu_map__put(evsel->own_cpus);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 0e49bd742c63..b649143ac16b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -44,6 +44,7 @@ enum {
PERF_EVSEL__CONFIG_TERM_CALLGRAPH,
PERF_EVSEL__CONFIG_TERM_STACK_USER,
PERF_EVSEL__CONFIG_TERM_INHERIT,
+ PERF_EVSEL__CONFIG_TERM_DRV_CFG,
PERF_EVSEL__CONFIG_TERM_MAX,
};
@@ -55,6 +56,7 @@ struct perf_evsel_config_term {
u64 freq;
bool time;
char *callgraph;
+ char *drv_cfg;
u64 stack_user;
bool inherit;
} val;
@@ -75,6 +77,7 @@ struct perf_evsel_config_term {
* PERF_SAMPLE_IDENTIFIER) in a non-sample event i.e. if sample_id_all
* is used there is an id sample appended to non-sample events
* @priv: And what is in its containing unnamed union are tool specific
+ * @drv_config_terms: List of configurables sent directly to the PMU driver
*/
struct perf_evsel {
struct list_head node;
@@ -123,6 +126,7 @@ struct perf_evsel {
char *group_name;
bool cmdline_group_boundary;
struct list_head config_terms;
+ struct list_head drv_config_terms;
int bpf_fd;
};
@@ -227,7 +231,11 @@ int perf_evsel__append_filter(struct perf_evsel *evsel,
const char *op, const char *filter);
int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
const char *filter);
+int perf_evsel__apply_drv_configs(struct perf_evsel *evsel,
+ int ncpus, int nthreads,
+ struct perf_evsel_config_term **err_term);
int perf_evsel__enable(struct perf_evsel *evsel, int ncpus, int nthreads);
+int perf_evsel__disable(struct perf_evsel *evsel);
int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
struct cpu_map *cpus);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 8b303ff20289..888640ffada5 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1,3 +1,4 @@
+#include "build-id.h"
#include "callchain.h"
#include "debug.h"
#include "event.h"
@@ -685,8 +686,16 @@ static struct dso *machine__get_kernel(struct machine *machine)
DSO_TYPE_GUEST_KERNEL);
}
- if (kernel != NULL && (!kernel->has_build_id))
- dso__read_running_kernel_build_id(kernel, machine);
+ if (kernel != NULL && (!kernel->has_build_id)) {
+ if (symbol_conf.vmlinux_name != NULL) {
+ filename__read_build_id(symbol_conf.vmlinux_name,
+ kernel->build_id,
+ sizeof(kernel->build_id));
+ kernel->has_build_id = 1;
+ } else {
+ dso__read_running_kernel_build_id(kernel, machine);
+ }
+ }
return kernel;
}
@@ -700,8 +709,19 @@ static void machine__get_kallsyms_filename(struct machine *machine, char *buf,
{
if (machine__is_default_guest(machine))
scnprintf(buf, bufsz, "%s", symbol_conf.default_guest_kallsyms);
- else
- scnprintf(buf, bufsz, "%s/proc/kallsyms", machine->root_dir);
+ else {
+ if (symbol_conf.vmlinux_name != 0) {
+ unsigned char build_id[BUILD_ID_SIZE];
+ char build_id_hex[SBUILD_ID_SIZE];
+ filename__read_build_id(symbol_conf.vmlinux_name,
+ build_id,
+ sizeof(build_id));
+ build_id__sprintf(build_id,sizeof(build_id), build_id_hex);
+ build_id__filename((char *)build_id_hex,buf,bufsz);
+ } else {
+ scnprintf(buf, bufsz, "%s/proc/kallsyms", machine->root_dir);
+ }
+ }
}
const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
@@ -710,7 +730,7 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
* Returns the name of the start symbol in *symbol_name. Pass in NULL as
* symbol_name if it's not that important.
*/
-static u64 machine__get_running_kernel_start(struct machine *machine,
+static u64 machine__get_kallsyms_kernel_start(struct machine *machine,
const char **symbol_name)
{
char filename[PATH_MAX];
@@ -738,7 +758,7 @@ static u64 machine__get_running_kernel_start(struct machine *machine,
int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
{
enum map_type type;
- u64 start = machine__get_running_kernel_start(machine, NULL);
+ u64 start = machine__get_kallsyms_kernel_start(machine, NULL);
for (type = 0; type < MAP__NR_TYPES; ++type) {
struct kmap *kmap;
@@ -1083,7 +1103,8 @@ int machine__create_kernel_maps(struct machine *machine)
{
struct dso *kernel = machine__get_kernel(machine);
const char *name;
- u64 addr = machine__get_running_kernel_start(machine, &name);
+ u64 addr = machine__get_kallsyms_kernel_start(machine, &name);
+
if (!addr)
return -1;
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index a35db828bd0d..854dd2105bd5 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -285,7 +285,8 @@ static struct perf_evsel *
__add_event(struct list_head *list, int *idx,
struct perf_event_attr *attr,
char *name, struct cpu_map *cpus,
- struct list_head *config_terms)
+ struct list_head *config_terms,
+ struct list_head *drv_config_terms)
{
struct perf_evsel *evsel;
@@ -304,6 +305,9 @@ __add_event(struct list_head *list, int *idx,
if (config_terms)
list_splice(config_terms, &evsel->config_terms);
+ if (drv_config_terms)
+ list_splice(drv_config_terms, &evsel->drv_config_terms);
+
list_add_tail(&evsel->node, list);
return evsel;
}
@@ -312,7 +316,8 @@ static int add_event(struct list_head *list, int *idx,
struct perf_event_attr *attr, char *name,
struct list_head *config_terms)
{
- return __add_event(list, idx, attr, name, NULL, config_terms) ? 0 : -ENOMEM;
+ return __add_event(list, idx, attr, name,
+ NULL, config_terms, NULL) ? 0 : -ENOMEM;
}
static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
@@ -823,7 +828,8 @@ static int config_term_pmu(struct perf_event_attr *attr,
struct parse_events_term *term,
struct parse_events_error *err)
{
- if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER)
+ if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER ||
+ term->type_term == PARSE_EVENTS__TERM_TYPE_DRV_CFG)
/*
* Always succeed for sysfs terms, as we dont know
* at this point what type they need to have.
@@ -869,10 +875,7 @@ static int config_attr(struct perf_event_attr *attr,
return 0;
}
-static int get_config_terms(struct list_head *head_config,
- struct list_head *head_terms __maybe_unused)
-{
-#define ADD_CONFIG_TERM(__type, __name, __val) \
+#define ADD_CONFIG_TERM(__type, __name, __val, __head_terms) \
do { \
struct perf_evsel_config_term *__t; \
\
@@ -883,33 +886,43 @@ do { \
INIT_LIST_HEAD(&__t->list); \
__t->type = PERF_EVSEL__CONFIG_TERM_ ## __type; \
__t->val.__name = __val; \
- list_add_tail(&__t->list, head_terms); \
+ list_add_tail(&__t->list, __head_terms); \
} while (0)
+static int get_config_terms(struct list_head *head_config,
+ struct list_head *head_terms __maybe_unused)
+{
struct parse_events_term *term;
list_for_each_entry(term, head_config, list) {
switch (term->type_term) {
case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
- ADD_CONFIG_TERM(PERIOD, period, term->val.num);
+ ADD_CONFIG_TERM(PERIOD, period,
+ term->val.num, head_terms);
break;
case PARSE_EVENTS__TERM_TYPE_SAMPLE_FREQ:
- ADD_CONFIG_TERM(FREQ, freq, term->val.num);
+ ADD_CONFIG_TERM(FREQ, freq,
+ term->val.num, head_terms);
break;
case PARSE_EVENTS__TERM_TYPE_TIME:
- ADD_CONFIG_TERM(TIME, time, term->val.num);
+ ADD_CONFIG_TERM(TIME, time,
+ term->val.num, head_terms);
break;
case PARSE_EVENTS__TERM_TYPE_CALLGRAPH:
- ADD_CONFIG_TERM(CALLGRAPH, callgraph, term->val.str);
+ ADD_CONFIG_TERM(CALLGRAPH, callgraph,
+ term->val.str, head_terms);
break;
case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
- ADD_CONFIG_TERM(STACK_USER, stack_user, term->val.num);
+ ADD_CONFIG_TERM(STACK_USER, stack_user,
+ term->val.num, head_terms);
break;
case PARSE_EVENTS__TERM_TYPE_INHERIT:
- ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 1 : 0);
+ ADD_CONFIG_TERM(INHERIT, inherit,
+ term->val.num ? 1 : 0, head_terms);
break;
case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
- ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1);
+ ADD_CONFIG_TERM(INHERIT, inherit,
+ term->val.num ? 0 : 1, head_terms);
break;
default:
break;
@@ -919,6 +932,21 @@ do { \
return 0;
}
+static int get_drv_config_terms(struct list_head *head_config,
+ struct list_head *head_terms)
+{
+ struct parse_events_term *term;
+
+ list_for_each_entry(term, head_config, list) {
+ if (term->type_term != PARSE_EVENTS__TERM_TYPE_DRV_CFG)
+ continue;
+
+ ADD_CONFIG_TERM(DRV_CFG, drv_cfg, term->val.str, head_terms);
+ }
+
+ return 0;
+}
+
int parse_events_add_tracepoint(struct list_head *list, int *idx,
char *sys, char *event,
struct parse_events_error *err,
@@ -989,6 +1017,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
struct perf_pmu *pmu;
struct perf_evsel *evsel;
LIST_HEAD(config_terms);
+ LIST_HEAD(drv_config_terms);
pmu = perf_pmu__find(name);
if (!pmu)
@@ -1003,7 +1032,8 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
if (!head_config) {
attr.type = pmu->type;
- evsel = __add_event(list, &data->idx, &attr, NULL, pmu->cpus, NULL);
+ evsel = __add_event(list, &data->idx, &attr,
+ NULL, pmu->cpus, NULL, NULL);
return evsel ? 0 : -ENOMEM;
}
@@ -1020,12 +1050,15 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
if (get_config_terms(head_config, &config_terms))
return -ENOMEM;
+ if (get_drv_config_terms(head_config, &drv_config_terms))
+ return -ENOMEM;
+
if (perf_pmu__config(pmu, &attr, head_config, data->error))
return -EINVAL;
evsel = __add_event(list, &data->idx, &attr,
pmu_event_name(head_config), pmu->cpus,
- &config_terms);
+ &config_terms, &drv_config_terms);
if (evsel) {
evsel->unit = info.unit;
evsel->scale = info.scale;
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index f1a6db107241..09c3ee2df45c 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -68,7 +68,8 @@ enum {
PARSE_EVENTS__TERM_TYPE_CALLGRAPH,
PARSE_EVENTS__TERM_TYPE_STACKSIZE,
PARSE_EVENTS__TERM_TYPE_NOINHERIT,
- PARSE_EVENTS__TERM_TYPE_INHERIT
+ PARSE_EVENTS__TERM_TYPE_INHERIT,
+ PARSE_EVENTS__TERM_TYPE_DRV_CFG,
};
struct parse_events_term {
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 58c5831ffd5c..de260ed0dd54 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -53,6 +53,16 @@ static int str(yyscan_t scanner, int token)
return token;
}
+static int drv_str(yyscan_t scanner, int token)
+{
+ YYSTYPE *yylval = parse_events_get_lval(scanner);
+ char *text = parse_events_get_text(scanner);
+
+ /* Strip off the '@' */
+ yylval->str = strdup(text + 1);
+ return token;
+}
+
#define REWIND(__alloc) \
do { \
YYSTYPE *__yylval = parse_events_get_lval(yyscanner); \
@@ -123,6 +133,7 @@ num_hex 0x[a-fA-F0-9]+
num_raw_hex [a-fA-F0-9]+
name [a-zA-Z_*?][a-zA-Z0-9_*?.]*
name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.]*
+drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
/* If you add a modifier you need to update check_modifier() */
modifier_event [ukhpPGHSDI]+
modifier_bp [rwx]{1,3}
@@ -196,6 +207,7 @@ no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
, { return ','; }
"/" { BEGIN(INITIAL); return '/'; }
{name_minus} { return str(yyscanner, PE_NAME); }
+@{drv_cfg_term} { return drv_str(yyscanner, PE_DRV_CFG_TERM); }
}
<mem>{
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index ad379968d4c1..d35c10275ba4 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -48,6 +48,7 @@ static inc_group_count(struct list_head *list,
%token PE_PREFIX_MEM PE_PREFIX_RAW PE_PREFIX_GROUP
%token PE_ERROR
%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
+%token PE_DRV_CFG_TERM
%type <num> PE_VALUE
%type <num> PE_VALUE_SYM_HW
%type <num> PE_VALUE_SYM_SW
@@ -62,6 +63,7 @@ static inc_group_count(struct list_head *list,
%type <str> PE_MODIFIER_BP
%type <str> PE_EVENT_NAME
%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
+%type <str> PE_DRV_CFG_TERM
%type <num> value_sym
%type <head> event_config
%type <term> event_term
@@ -573,6 +575,15 @@ PE_TERM
ABORT_ON(parse_events_term__num(&term, (int)$1, NULL, 1, &@1, NULL));
$$ = term;
}
+|
+PE_DRV_CFG_TERM
+{
+ struct parse_events_term *term;
+
+ ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG,
+ $1, $1, &@1, NULL));
+ $$ = term;
+}
sep_dc: ':' |
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index a8e825fca42a..df49c0035170 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -806,6 +806,8 @@ static void python_process_general_event(struct perf_sample *sample,
PyInt_FromLong(sample->cpu));
pydict_set_item_string_decref(dict_sample, "ip",
PyLong_FromUnsignedLongLong(sample->ip));
+ pydict_set_item_string_decref(dict_sample, "addr",
+ PyLong_FromUnsignedLongLong(sample->addr));
pydict_set_item_string_decref(dict_sample, "time",
PyLong_FromUnsignedLongLong(sample->time));
pydict_set_item_string_decref(dict_sample, "period",
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 468de95bc8bb..010ff659b82f 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -224,14 +224,6 @@ static int process_event_stub(struct perf_tool *tool __maybe_unused,
return 0;
}
-static int process_build_id_stub(struct perf_tool *tool __maybe_unused,
- union perf_event *event __maybe_unused,
- struct perf_session *session __maybe_unused)
-{
- dump_printf(": unhandled!\n");
- return 0;
-}
-
static int process_finished_round_stub(struct perf_tool *tool __maybe_unused,
union perf_event *event __maybe_unused,
struct ordered_events *oe __maybe_unused)
@@ -244,23 +236,6 @@ static int process_finished_round(struct perf_tool *tool,
union perf_event *event,
struct ordered_events *oe);
-static int process_id_index_stub(struct perf_tool *tool __maybe_unused,
- union perf_event *event __maybe_unused,
- struct perf_session *perf_session
- __maybe_unused)
-{
- dump_printf(": unhandled!\n");
- return 0;
-}
-
-static int process_event_auxtrace_info_stub(struct perf_tool *tool __maybe_unused,
- union perf_event *event __maybe_unused,
- struct perf_session *session __maybe_unused)
-{
- dump_printf(": unhandled!\n");
- return 0;
-}
-
static int skipn(int fd, off_t n)
{
char buf[4096];
@@ -287,10 +262,9 @@ static s64 process_event_auxtrace_stub(struct perf_tool *tool __maybe_unused,
return event->auxtrace.size;
}
-static
-int process_event_auxtrace_error_stub(struct perf_tool *tool __maybe_unused,
- union perf_event *event __maybe_unused,
- struct perf_session *session __maybe_unused)
+static int process_event_op2_stub(struct perf_tool *tool __maybe_unused,
+ union perf_event *event __maybe_unused,
+ struct perf_session *session __maybe_unused)
{
dump_printf(": unhandled!\n");
return 0;
@@ -331,7 +305,7 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
if (tool->tracing_data == NULL)
tool->tracing_data = process_event_synth_tracing_data_stub;
if (tool->build_id == NULL)
- tool->build_id = process_build_id_stub;
+ tool->build_id = process_event_op2_stub;
if (tool->finished_round == NULL) {
if (tool->ordered_events)
tool->finished_round = process_finished_round;
@@ -339,13 +313,13 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
tool->finished_round = process_finished_round_stub;
}
if (tool->id_index == NULL)
- tool->id_index = process_id_index_stub;
+ tool->id_index = process_event_op2_stub;
if (tool->auxtrace_info == NULL)
- tool->auxtrace_info = process_event_auxtrace_info_stub;
+ tool->auxtrace_info = process_event_op2_stub;
if (tool->auxtrace == NULL)
tool->auxtrace = process_event_auxtrace_stub;
if (tool->auxtrace_error == NULL)
- tool->auxtrace_error = process_event_auxtrace_error_stub;
+ tool->auxtrace_error = process_event_op2_stub;
}
static void swap_sample_id_all(union perf_event *event, void *data)
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 48906333a858..9be16712ce74 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -344,7 +344,7 @@ int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
if (ret >= 0)
dso->is_64_bit = ret;
- if (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0) {
+ if ((!dso->has_build_id) && (filename__read_build_id(ss->name, build_id, BUILD_ID_SIZE) > 0)) {
dso__set_build_id(dso, build_id);
}
return 0;
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index cd08027a6d2c..1d0d8bff4a5b 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -1465,7 +1465,8 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
* Read the build id if possible. This is required for
* DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work
*/
- if (filename__read_build_id(dso->name, build_id, BUILD_ID_SIZE) > 0)
+ if ((!dso->has_build_id) &&
+ (filename__read_build_id(dso->name, build_id, BUILD_ID_SIZE) > 0))
dso__set_build_id(dso, build_id);
/*
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index f0b08a2a48ba..7d31d8c5b9ea 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -40,7 +40,7 @@ int kvm_irq_map_gsi(struct kvm *kvm,
irq_rt = srcu_dereference_check(kvm->irq_routing, &kvm->irq_srcu,
lockdep_is_held(&kvm->irq_lock));
- if (gsi < irq_rt->nr_rt_entries) {
+ if (irq_rt && gsi < irq_rt->nr_rt_entries) {
hlist_for_each_entry(e, &irq_rt->map[gsi], link) {
entries[n] = *e;
++n;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index fefbf2d148ef..510df220d1b5 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2861,7 +2861,7 @@ static long kvm_vm_ioctl(struct file *filp,
if (copy_from_user(&routing, argp, sizeof(routing)))
goto out;
r = -EINVAL;
- if (routing.nr >= KVM_MAX_IRQ_ROUTES)
+ if (routing.nr > KVM_MAX_IRQ_ROUTES)
goto out;
if (routing.flags)
goto out;