Merge android11-5.4.281 (d62984a) into msm-5.4
* remotes/origin/tmp-d62984a:
ANDROID: delete tool added by mistake
ANDROID: fix ENOMEM check of binder_proc_ext
ANDROID: binder: fix KMI issues due to frozen notification
BACKPORT: FROMGIT: binder: frozen notification binder_features flag
BACKPORT: FROMGIT: binder: frozen notification
BACKPORT: selftests/binderfs: add test for feature files
UPSTREAM: docs: binderfs: add section about feature files
BACKPORT: binderfs: add support for feature files
FROMLIST: binder: fix memory leaks of spam and pending work
FROMGIT: Binder: add TF_UPDATE_TXN to replace outdated txn
BACKPORT: binder: tell userspace to dump current backtrace when detected oneway spamming
UPSTREAM: net: sched: sch_multiq: fix possible OOB write in multiq_tune()
FROMLIST: binder: fix UAF caused by offsets overwrite
Revert "net: mac802154: Fix racy device stats updates by DEV_STATS_INC() and DEV_STATS_ADD()"
Linux 5.4.281
tap: add missing verification for short frame
tun: add missing verification for short frame
filelock: Fix fcntl/close race recovery compat path
ALSA: hda/realtek: Enable headset mic on Positivo SU C1400
jfs: don't walk off the end of ealist
ocfs2: add bounds checking to ocfs2_check_dir_entry()
net: relax socket state check at accept time.
drm/amdgpu: Fix signedness bug in sdma_v4_0_process_trap_irq()
ACPI: processor_idle: Fix invalid comparison with insertion sort for latency
ARM: 9324/1: fix get_user() broken with veneer
hfsplus: fix uninit-value in copy_name
selftests/vDSO: fix clang build errors and warnings
spi: imx: Don't expect DMA for i.MX{25,35,50,51,53} cspi devices
fs: better handle deep ancestor chains in is_subdir()
Bluetooth: hci_core: cancel all works upon hci_unregister_dev()
scsi: libsas: Fix exp-attached device scan after probe failure scanned in again after probe failed
powerpc/eeh: avoid possible crash when edev->pdev changes
powerpc/pseries: Whitelist dtl slub object for copying to userspace
net: mac802154: Fix racy device stats updates by DEV_STATS_INC() and DEV_STATS_ADD()
net: usb: qmi_wwan: add Telit FN912 compositions
ALSA: dmaengine_pcm: terminate dmaengine before synchronize
s390/sclp: Fix sclp_init() cleanup on failure
can: kvaser_usb: fix return value for hif_usb_send_regout
ASoC: ti: omap-hdmi: Fix too long driver name
ASoC: ti: davinci-mcasp: Set min period size using FIFO config
bytcr_rt5640 : inverse jack detect for Archos 101 cesium
Input: elantech - fix touchpad state on resume for Lenovo N24
mips: fix compat_sys_lseek syscall
ALSA: hda/realtek: Add more codec ID to no shutup pins list
KVM: PPC: Book3S HV: Prevent UAF in kvm_spapr_tce_attach_iommu_group()
wifi: cfg80211: wext: add extra SIOCSIWSCAN data check
mei: demote client disconnect warning on suspend to debug
fs/file: fix the check in find_next_fd()
kconfig: remove wrong expr_trans_bool()
kconfig: gconf: give a proper initial state to the Save button
ila: block BH in ila_output()
Input: silead - Always support 10 fingers
wifi: mac80211: fix UBSAN noise in ieee80211_prep_hw_scan()
wifi: mac80211: mesh: init nonpeer_pm to active by default in mesh sdata
ACPI: EC: Avoid returning AE_OK on errors in address space handler
ACPI: EC: Abort address space access upon error
scsi: qedf: Set qed_slowpath_params to zero before use
filelock: Remove locks reliably when fcntl/close race is detected
gcc-plugins: Rename last_stmt() for GCC 14+
ANDROID: GKI: refresh ABI to include kimage_vaddr
ANDROID: preserve CRC for struct tcp_sock
Linux 5.4.280
i2c: rcar: bring hardware to known state when probing
nilfs2: fix kernel bug on rename operation of broken directory
tcp: avoid too many retransmit packets
tcp: use signed arithmetic in tcp_rtx_probe0_timed_out()
net: tcp: fix unexcepted socket die when snd_wnd is 0
tcp: refactor tcp_retransmit_timer()
SUNRPC: Fix RPC client cleaned up the freed pipefs dentries
libceph: fix race between delayed_work() and ceph_monc_stop()
ALSA: hda/realtek: Limit mic boost on VAIO PRO PX
nvmem: meson-efuse: Fix return value of nvmem callbacks
hpet: Support 32-bit userspace
USB: core: Fix duplicate endpoint bug by clearing reserved bits in the descriptor
usb: gadget: configfs: Prevent OOB read/write in usb_string_copy()
USB: Add USB_QUIRK_NO_SET_INTF quirk for START BP-850k
USB: serial: option: add Rolling RW350-GL variants
USB: serial: option: add Netprisma LCUK54 series modules
USB: serial: option: add support for Foxconn T99W651
USB: serial: option: add Fibocom FM350-GL
USB: serial: option: add Telit FN912 rmnet compositions
USB: serial: option: add Telit generic core-dump composition
octeontx2-af: fix detection of IP layer
ARM: davinci: Convert comma to semicolon
s390: Mark psw in __load_psw_mask() as __unitialized
udp: Set SOCK_RCU_FREE earlier in udp_lib_get_port().
ppp: reject claimed-as-LCP but actually malformed packets
net: ethernet: lantiq_etop: fix double free in detach
net: lantiq_etop: add blank line after declaration
octeontx2-af: Fix incorrect value output on error path in rvu_check_rsrc_availability()
tcp: fix incorrect undo caused by DSACK of TLP retransmit
tcp: add TCP_INFO status for failed client TFO
vfs: don't mod negative dentry count when on shrinker list
fs/dcache: Re-use value stored to dentry->d_flags instead of re-reading
filelock: fix potential use-after-free in posix_lock_inode
nilfs2: fix incorrect inode allocation from reserved inodes
nvme-multipath: find NUMA path only for online numa-node
ALSA: hda/realtek: Enable headset mic of JP-IK LEAP W502 with ALC897
i2c: pnx: Fix potential deadlock warning from del_timer_sync() call in isr
media: dw2102: fix a potential buffer overflow
bnx2x: Fix multiple UBSAN array-index-out-of-bounds
drm/amdgpu/atomfirmware: silence UBSAN warning
drm/nouveau: fix null pointer dereference in nouveau_connector_get_modes
Revert "mm/writeback: fix possible divide-by-zero in wb_dirty_limits(), again"
fsnotify: Do not generate events for O_PATH file descriptors
can: kvaser_usb: Explicitly initialize family in leafimx driver_info struct
mm: optimize the redundant loop of mm_update_owner_next()
nilfs2: add missing check for inode numbers on directory entries
nilfs2: fix inode number range checks
inet_diag: Initialize pad field in struct inet_diag_req_v2
selftests: make order checking verbose in msg_zerocopy selftest
selftests: fix OOM in msg_zerocopy selftest
bonding: Fix out-of-bounds read in bond_option_arp_ip_targets_set()
wifi: wilc1000: fix ies_len type in connect path
tcp_metrics: validate source addr length
UPSTREAM: tcp: fix DSACK undo in fast recovery to call tcp_try_to_open()
net: tcp better handling of reordering then loss cases
tcp: add ece_ack flag to reno sack functions
tcp: tcp_mark_head_lost is only valid for sack-tcp
s390/pkey: Wipe sensitive data on failure
jffs2: Fix potential illegal address access in jffs2_free_inode
powerpc/xmon: Check cpu id in commands "c#", "dp#" and "dx#"
orangefs: fix out-of-bounds fsid access
powerpc/64: Set _IO_BASE to POISON_POINTER_DELTA not 0 for CONFIG_PCI=n
i2c: i801: Annotate apanel_addr as __ro_after_init
media: dvb-frontends: tda10048: Fix integer overflow
media: s2255: Use refcount_t instead of atomic_t for num_channels
media: dvb-frontends: tda18271c2dd: Remove casting during div
net: dsa: mv88e6xxx: Correct check for empty list
Input: ff-core - prefer struct_size over open coded arithmetic
firmware: dmi: Stop decoding on broken entry
sctp: prefer struct_size over open coded arithmetic
media: dw2102: Don't translate i2c read into write
drm/amd/display: Skip finding free audio for unknown engine_id
drm/amdgpu: Initialize timestamp for some legacy SOCs
scsi: qedf: Make qedf_execute_tmf() non-preemptible
IB/core: Implement a limit on UMAD receive List
media: dvb-usb: dib0700_devices: Add missing release_firmware()
media: dvb: as102-fe: Fix as10x_register_addr packing
drm/lima: fix shared irq handling on driver remove
Compiler Attributes: Add __uninitialized macro
Linux 5.4.279
arm64: dts: rockchip: Add sound-dai-cells for RK3368
ARM: dts: rockchip: rk3066a: add #sound-dai-cells to hdmi node
tcp: Fix data races around icsk->icsk_af_ops.
ipv6: Fix data races around sk->sk_prot.
ipv6: annotate some data-races around sk->sk_prot
nfs: Leave pages in the pagecache if readpage failed
pwm: stm32: Refuse too small period requests
mtd: spinand: macronix: Add support for serial NAND flash
ftruncate: pass a signed offset
ata: libata-core: Fix double free on error
batman-adv: Don't accept TT entries for out-of-spec VIDs
drm/nouveau/dispnv04: fix null pointer dereference in nv17_tv_get_hd_modes
drm/nouveau/dispnv04: fix null pointer dereference in nv17_tv_get_ld_modes
hexagon: fix fadvise64_64 calling conventions
csky, hexagon: fix broken sys_sync_file_range
net: can: j1939: enhanced error handling for tightly received RTS messages in xtp_rx_rts_session_new
net: can: j1939: recover socket queue on CAN bus error during BAM transmission
net: can: j1939: Initialize unused data in j1939_send_one()
tty: mcf: MCF54418 has 10 UARTS
usb: atm: cxacru: fix endpoint checking in cxacru_bind()
usb: musb: da8xx: fix a resource leak in probe()
usb: gadget: printer: SS+ support
net: usb: ax88179_178a: improve link status logs
iio: chemical: bme680: Fix sensor data read operation
iio: chemical: bme680: Fix overflows in compensate() functions
iio: chemical: bme680: Fix calibration data variable
iio: chemical: bme680: Fix pressure value output
iio: adc: ad7266: Fix variable checking bug
mmc: sdhci: Do not lock spinlock around mmc_gpio_get_ro()
mmc: sdhci: Do not invert write-protect twice
mmc: sdhci-pci: Convert PCIBIOS_* return codes to errnos
x86: stop playing stack games in profile_pc()
gpio: davinci: Validate the obtained number of IRQs
nvme: fixup comment for nvme RDMA Provider Type
soc: ti: wkup_m3_ipc: Send NULL dummy message instead of pointer message
media: dvbdev: Initialize sbuf
ALSA: emux: improve patch ioctl data validation
net/dpaa2: Avoid explicit cpumask var allocation on stack
net/iucv: Avoid explicit cpumask var allocation on stack
mtd: partitions: redboot: Added conversion of operands to a larger type
drm/panel: ilitek-ili9881c: Fix warning with GPIO controllers that sleep
netfilter: nf_tables: fully validate NFT_DATA_VALUE on store to data registers
parisc: use correct compat recv/recvfrom syscalls
sparc: fix old compat_sys_select()
net: phy: micrel: add Microchip KSZ 9477 to the device table
net: phy: mchp: Add support for LAN8814 QUAD PHY
net: dsa: microchip: fix initial port flush problem
ASoC: fsl-asoc-card: set priv->pdev before using it
netfilter: nf_tables: validate family when identifying table via handle
drm/amdgpu: fix UBSAN warning in kv_dpm.c
pinctrl: rockchip: fix pinmux reset in rockchip_pmx_set
pinctrl: rockchip: fix pinmux bits for RK3328 GPIO3-B pins
pinctrl: rockchip: fix pinmux bits for RK3328 GPIO2-B pins
pinctrl: fix deadlock in create_pinctrl() when handling -EPROBE_DEFER
iio: dac: ad5592r: fix temperature channel scaling value
iio: dac: ad5592r: un-indent code-block for scale read
iio: dac: ad5592r-base: Replace indio_dev->mlock with own device lock
x86/amd_nb: Check for invalid SMN reads
PCI: Add PCI_ERROR_RESPONSE and related definitions
perf/core: Fix missing wakeup when waiting for context reference
kheaders: explicitly define file modes for archived headers
Revert "kheaders: substituting --sort in archive creation"
tracing: Add MODULE_DESCRIPTION() to preemptirq_delay_test
arm64: dts: qcom: qcs404: fix bluetooth device address
ARM: dts: samsung: smdk4412: fix keypad no-autorepeat
ARM: dts: samsung: exynos4412-origen: fix keypad no-autorepeat
ARM: dts: samsung: smdkv310: fix keypad no-autorepeat
i2c: ocores: set IACK bit after core is enabled
gcov: add support for GCC 14
drm/radeon: fix UBSAN warning in kv_dpm.c
ACPICA: Revert "ACPICA: avoid Info: mapping multiple BARs. Your kernel is fine."
dmaengine: ioatdma: Fix missing kmem_cache_destroy()
regulator: core: Fix modpost error "regulator_get_regmap" undefined
net: usb: rtl8150 fix unintiatilzed variables in rtl8150_get_link_ksettings
netfilter: ipset: Fix suspicious rcu_dereference_protected()
virtio_net: checksum offloading handling fix
net/sched: act_api: fix possible infinite loop in tcf_idr_check_alloc()
net/sched: act_api: rely on rcu in tcf_idr_check_alloc
netns: Make get_net_ns() handle zero refcount net
xfrm6: check ip6_dst_idev() return value in xfrm6_get_saddr()
ipv6: prevent possible NULL dereference in rt6_probe()
ipv6: prevent possible NULL deref in fib6_nh_init()
netrom: Fix a memory leak in nr_heartbeat_expiry()
cipso: fix total option length computation
mips: bmips: BCM6358: make sure CBR is correctly set
MIPS: Routerboard 532: Fix vendor retry check code
MIPS: Octeon: Add PCIe link status check
PCI/PM: Avoid D3cold for HP Pavilion 17 PC/1972 PCIe Ports
udf: udftime: prevent overflow in udf_disk_stamp_to_time()
usb: misc: uss720: check for incompatible versions of the Belkin F5U002
powerpc/io: Avoid clang null pointer arithmetic warnings
powerpc/pseries: Enforce hcall result buffer validity and size
Bluetooth: ath3k: Fix multiple issues reported by checkpatch.pl
scsi: qedi: Fix crash while reading debugfs attribute
drop_monitor: replace spin_lock by raw_spin_lock
batman-adv: bypass empty buckets in batadv_purge_orig_ref()
selftests/bpf: Prevent client connect before server bind in test_tc_tunnel.sh
rcutorture: Fix rcu_torture_one_read() pipe_count overflow comment
i2c: at91: Fix the functionality flags of the slave-only interface
usb-storage: alauda: Check whether the media is initialized
greybus: Fix use-after-free bug in gb_interface_release due to race condition.
netfilter: nftables: exthdr: fix 4-byte stack OOB write
hugetlb_encode.h: fix undefined behaviour (34 << 26)
hv_utils: drain the timesync packets on onchannelcallback
tick/nohz_full: Don't abuse smp_call_function_single() in tick_setup_device()
nilfs2: fix potential kernel bug due to lack of writeback flag waiting
intel_th: pci: Add Lunar Lake support
intel_th: pci: Add Meteor Lake-S support
intel_th: pci: Add Sapphire Rapids SOC support
intel_th: pci: Add Granite Rapids SOC support
intel_th: pci: Add Granite Rapids support
dmaengine: axi-dmac: fix possible race in remove()
PCI: rockchip-ep: Remove wrong mask on subsys_vendor_id
ocfs2: fix races between hole punching and AIO+DIO
ocfs2: use coarse time for new created files
fs/proc: fix softlockup in __read_vmcore
vmci: prevent speculation leaks by sanitizing event in event_deliver()
tracing/selftests: Fix kprobe event name test for .isra. functions
drm/exynos: hdmi: report safe 640x480 mode as a fallback when no EDID found
drm/exynos/vidi: fix memory leak in .get_modes()
drivers: core: synchronize really_probe() and dev_uevent()
ionic: fix use after netif_napi_del()
net/ipv6: Fix the RT cache flush via sysctl using a previous delay
netfilter: ipset: Fix race between namespace cleanup and gc in the list:set type
Bluetooth: L2CAP: Fix rejecting L2CAP_CONN_PARAM_UPDATE_REQ
net/mlx5e: Fix features validation check for tunneled UDP (non-VXLAN) packets
tcp: fix race in tcp_v6_syn_recv_sock()
drm/bridge/panel: Fix runtime warning on panel bridge release
drm/komeda: check for error-valued pointer
liquidio: Adjust a NULL pointer handling path in lio_vf_rep_copy_packet
HID: logitech-dj: Fix memory leak in logi_dj_recv_switch_to_dj_mode()
iommu: Return right value in iommu_sva_bind_device()
iommu/amd: Fix sysfs leak in iommu init
HID: core: remove unnecessary WARN_ON() in implement()
gpio: tqmx86: fix typo in Kconfig label
SUNRPC: return proper error from gss_wrap_req_priv
Input: try trimming too long modalias strings
scsi: mpt3sas: Avoid test/set_bit() operating in non-allocated memory
xhci: Apply broken streams quirk to Etron EJ188 xHCI host
xhci: Apply reset resume quirk to Etron EJ188 xHCI host
xhci: Set correct transferred length for cancelled bulk transfers
jfs: xattr: fix buffer overflow for invalid xattr
mei: me: release irq in mei_me_pci_resume error path
USB: class: cdc-wdm: Fix CPU lockup caused by excessive log messages
nilfs2: fix nilfs_empty_dir() misjudgment and long loop on I/O errors
nilfs2: return the mapped address from nilfs_get_page()
nilfs2: Remove check for PageError
selftests/mm: compaction_test: fix bogus test success on Aarch64
selftests/mm: conform test to TAP format output
selftests/mm: compaction_test: fix incorrect write of zero to nr_hugepages
serial: sc16is7xx: fix bug in sc16is7xx_set_baud() when using prescaler
serial: sc16is7xx: replace hardcoded divisor value with BIT() macro
drm/amd/display: Handle Y carry-over in VCP X.Y calculation
ASoC: ti: davinci-mcasp: Fix race condition during probe
ASoC: ti: davinci-mcasp: Handle missing required DT properties
ASoC: ti: davinci-mcasp: Simplify the configuration parameter handling
ASoC: ti: davinci-mcasp: Remove legacy dma_request parsing
ASoC: ti: davinci-mcasp: Use platform_get_irq_byname_optional
ASoC: ti: davinci-mcasp: remove always zero of davinci_mcasp_get_dt_params
ASoC: ti: davinci-mcasp: remove redundant assignment to variable ret
usb: gadget: f_fs: Fix race between aio_cancel() and AIO request complete
ipv6: fix possible race in __fib6_drop_pcpu_from()
af_unix: Annotate data-race of sk->sk_shutdown in sk_diag_fill().
af_unix: Use skb_queue_len_lockless() in sk_diag_show_rqlen().
af_unix: Use unix_recvq_full_lockless() in unix_stream_connect().
af_unix: Annotate data-race of net->unx.sysctl_max_dgram_qlen.
af_unix: Annotate data-races around sk->sk_state in UNIX_DIAG.
af_unix: Annotate data-races around sk->sk_state in sendmsg() and recvmsg().
af_unix: Annotate data-races around sk->sk_state in unix_write_space() and poll().
af_unix: Annotate data-race of sk->sk_state in unix_inq_len().
ptp: Fix error message on failed pin verification
net/sched: taprio: always validate TCA_TAPRIO_ATTR_PRIOMAP
net/mlx5: Stop waiting for PCI if pci channel is offline
tcp: count CLOSE-WAIT sockets for TCP_MIB_CURRESTAB
vxlan: Fix regression when dropping packets due to invalid src addresses
net: sched: sch_multiq: fix possible OOB write in multiq_tune()
ipv6: sr: block BH in seg6_output_core() and seg6_input_core()
wifi: iwlwifi: mvm: don't read past the mfuart notifcation
wifi: iwlwifi: dbg_ini: move iwl_dbg_tlv_free outside of debugfs ifdef
wifi: iwlwifi: mvm: revert gen2 TX A-MPDU size to 64
wifi: cfg80211: pmsr: use correct nla_get_uX functions
wifi: mac80211: Fix deadlock in ieee80211_sta_ps_deliver_wakeup()
wifi: mac80211: mesh: Fix leak of mesh_preq_queue objects
Conflicts:
kernel/gen_kheaders.sh
Change-Id: I4a0de5504b5e61a23b78a1a8f06aceaac810f3c7
Signed-off-by: kamasali Satyanarayan <quic_kamasali@quicinc.com>
This commit is contained in:
committed by
Kamasali Satyanarayan
commit
222ee0825f
@@ -66,3 +66,16 @@ that the `rm() <rm_>`_ tool can be used to delete them. Note that the
|
||||
``binder-control`` device cannot be deleted since this would make the binderfs
|
||||
instance unuseable. The ``binder-control`` device will be deleted when the
|
||||
binderfs instance is unmounted and all references to it have been dropped.
|
||||
|
||||
Binder features
|
||||
---------------
|
||||
|
||||
Assuming an instance of binderfs has been mounted at ``/dev/binderfs``, the
|
||||
features supported by the binder driver can be located under
|
||||
``/dev/binderfs/features/``. The presence of individual files can be tested
|
||||
to determine whether a particular feature is supported by the driver.
|
||||
|
||||
Example::
|
||||
|
||||
cat /dev/binderfs/features/oneway_spam_detection
|
||||
1
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 5
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 278
|
||||
SUBLEVEL = 281
|
||||
EXTRAVERSION =
|
||||
NAME = Kleptomaniac Octopus
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
LTS_5.4.278_7453ecf4d1fe
|
||||
LTS_5.4.281_d62984adb112
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -64,7 +64,7 @@
|
||||
&keypad {
|
||||
samsung,keypad-num-rows = <2>;
|
||||
samsung,keypad-num-columns = <8>;
|
||||
linux,keypad-no-autorepeat;
|
||||
linux,input-no-autorepeat;
|
||||
wakeup-source;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&keypad_rows &keypad_cols>;
|
||||
|
||||
@@ -431,7 +431,7 @@
|
||||
&keypad {
|
||||
samsung,keypad-num-rows = <3>;
|
||||
samsung,keypad-num-columns = <2>;
|
||||
linux,keypad-no-autorepeat;
|
||||
linux,input-no-autorepeat;
|
||||
wakeup-source;
|
||||
pinctrl-0 = <&keypad_rows &keypad_cols>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
&keypad {
|
||||
samsung,keypad-num-rows = <3>;
|
||||
samsung,keypad-num-columns = <8>;
|
||||
linux,keypad-no-autorepeat;
|
||||
linux,input-no-autorepeat;
|
||||
wakeup-source;
|
||||
pinctrl-0 = <&keypad_rows &keypad_cols>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
@@ -124,6 +124,7 @@
|
||||
pinctrl-0 = <&hdmii2c_xfer>, <&hdmi_hpd>;
|
||||
power-domains = <&power RK3066_PD_VIO>;
|
||||
rockchip,grf = <&grf>;
|
||||
#sound-dai-cells = <0>;
|
||||
status = "disabled";
|
||||
|
||||
ports {
|
||||
|
||||
@@ -143,16 +143,6 @@ extern int __get_user_64t_1(void *);
|
||||
extern int __get_user_64t_2(void *);
|
||||
extern int __get_user_64t_4(void *);
|
||||
|
||||
#define __GUP_CLOBBER_1 "lr", "cc"
|
||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
||||
#define __GUP_CLOBBER_2 "ip", "lr", "cc"
|
||||
#else
|
||||
#define __GUP_CLOBBER_2 "lr", "cc"
|
||||
#endif
|
||||
#define __GUP_CLOBBER_4 "lr", "cc"
|
||||
#define __GUP_CLOBBER_32t_8 "lr", "cc"
|
||||
#define __GUP_CLOBBER_8 "lr", "cc"
|
||||
|
||||
#define __get_user_x(__r2, __p, __e, __l, __s) \
|
||||
__asm__ __volatile__ ( \
|
||||
__asmeq("%0", "r0") __asmeq("%1", "r2") \
|
||||
@@ -160,7 +150,7 @@ extern int __get_user_64t_4(void *);
|
||||
"bl __get_user_" #__s \
|
||||
: "=&r" (__e), "=r" (__r2) \
|
||||
: "0" (__p), "r" (__l) \
|
||||
: __GUP_CLOBBER_##__s)
|
||||
: "ip", "lr", "cc")
|
||||
|
||||
/* narrowing a double-word get into a single 32bit word register: */
|
||||
#ifdef __ARMEB__
|
||||
@@ -182,7 +172,7 @@ extern int __get_user_64t_4(void *);
|
||||
"bl __get_user_64t_" #__s \
|
||||
: "=&r" (__e), "=r" (__r2) \
|
||||
: "0" (__p), "r" (__l) \
|
||||
: __GUP_CLOBBER_##__s)
|
||||
: "ip", "lr", "cc")
|
||||
#else
|
||||
#define __get_user_x_64t __get_user_x
|
||||
#endif
|
||||
|
||||
@@ -62,7 +62,7 @@ static void davinci_pm_suspend(void)
|
||||
|
||||
/* Configure sleep count in deep sleep register */
|
||||
val = __raw_readl(pm_config.deepsleep_reg);
|
||||
val &= ~DEEPSLEEP_SLEEPCOUNT_MASK,
|
||||
val &= ~DEEPSLEEP_SLEEPCOUNT_MASK;
|
||||
val |= pm_config.sleepcount;
|
||||
__raw_writel(val, pm_config.deepsleep_reg);
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
vddrf-supply = <&vreg_l1_1p3>;
|
||||
vddch0-supply = <&vdd_ch0_3p3>;
|
||||
|
||||
local-bd-address = [ 02 00 00 00 5a ad ];
|
||||
local-bd-address = [ 00 00 00 00 00 00 ];
|
||||
|
||||
max-speed = <3200000>;
|
||||
};
|
||||
|
||||
@@ -686,6 +686,7 @@
|
||||
dma-names = "tx";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&spdif_tx>;
|
||||
#sound-dai-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@@ -697,6 +698,7 @@
|
||||
clocks = <&cru SCLK_I2S_2CH>, <&cru HCLK_I2S_2CH>;
|
||||
dmas = <&dmac_bus 6>, <&dmac_bus 7>;
|
||||
dma-names = "tx", "rx";
|
||||
#sound-dai-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
@@ -710,6 +712,7 @@
|
||||
dma-names = "tx", "rx";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&i2s_8ch_bus>;
|
||||
#sound-dai-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define __ARCH_WANT_SYS_CLONE3
|
||||
#define __ARCH_WANT_SET_GET_RLIMIT
|
||||
#define __ARCH_WANT_TIME32_SYSCALLS
|
||||
#define __ARCH_WANT_SYNC_FILE_RANGE2
|
||||
#include <asm-generic/unistd.h>
|
||||
|
||||
#define __NR_set_thread_area (__NR_arch_specific_syscall + 0)
|
||||
|
||||
6
arch/hexagon/include/asm/syscalls.h
Normal file
6
arch/hexagon/include/asm/syscalls.h
Normal file
@@ -0,0 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#include <asm-generic/syscalls.h>
|
||||
|
||||
asmlinkage long sys_hexagon_fadvise64_64(int fd, int advice,
|
||||
u32 a2, u32 a3, u32 a4, u32 a5);
|
||||
@@ -36,5 +36,6 @@
|
||||
#define __ARCH_WANT_SYS_VFORK
|
||||
#define __ARCH_WANT_SYS_FORK
|
||||
#define __ARCH_WANT_TIME32_SYSCALLS
|
||||
#define __ARCH_WANT_SYNC_FILE_RANGE2
|
||||
|
||||
#include <asm-generic/unistd.h>
|
||||
|
||||
@@ -14,6 +14,13 @@
|
||||
#undef __SYSCALL
|
||||
#define __SYSCALL(nr, call) [nr] = (call),
|
||||
|
||||
SYSCALL_DEFINE6(hexagon_fadvise64_64, int, fd, int, advice,
|
||||
SC_ARG64(offset), SC_ARG64(len))
|
||||
{
|
||||
return ksys_fadvise64_64(fd, SC_VAL64(loff_t, offset), SC_VAL64(loff_t, len), advice);
|
||||
}
|
||||
#define sys_fadvise64_64 sys_hexagon_fadvise64_64
|
||||
|
||||
void *sys_call_table[__NR_syscalls] = {
|
||||
#include <asm/unistd.h>
|
||||
};
|
||||
|
||||
@@ -110,7 +110,8 @@ static void bcm6358_quirks(void)
|
||||
* RAC flush causes kernel panics on BCM6358 when booting from TP1
|
||||
* because the bootloader is not initializing it properly.
|
||||
*/
|
||||
bmips_rac_flush_disable = !!(read_c0_brcm_cmt_local() & (1 << 31));
|
||||
bmips_rac_flush_disable = !!(read_c0_brcm_cmt_local() & (1 << 31)) ||
|
||||
!!BMIPS_GET_CBR();
|
||||
}
|
||||
|
||||
static void bcm6368_quirks(void)
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
17 o32 break sys_ni_syscall
|
||||
# 18 was sys_stat
|
||||
18 o32 unused18 sys_ni_syscall
|
||||
19 o32 lseek sys_lseek
|
||||
19 o32 lseek sys_lseek compat_sys_lseek
|
||||
20 o32 getpid sys_getpid
|
||||
21 o32 mount sys_mount compat_sys_mount
|
||||
22 o32 umount sys_oldumount
|
||||
|
||||
@@ -112,8 +112,8 @@ retry:
|
||||
* gives them time to settle
|
||||
*/
|
||||
if (where == PCI_VENDOR_ID) {
|
||||
if (ret == 0xffffffff || ret == 0x00000000 ||
|
||||
ret == 0x0000ffff || ret == 0xffff0000) {
|
||||
if (*val == 0xffffffff || *val == 0x00000000 ||
|
||||
*val == 0x0000ffff || *val == 0xffff0000) {
|
||||
if (delay > 4)
|
||||
return 0;
|
||||
delay *= 2;
|
||||
|
||||
6
arch/mips/pci/pcie-octeon.c
Normal file → Executable file
6
arch/mips/pci/pcie-octeon.c
Normal file → Executable file
@@ -230,12 +230,18 @@ static inline uint64_t __cvmx_pcie_build_config_addr(int pcie_port, int bus,
|
||||
{
|
||||
union cvmx_pcie_address pcie_addr;
|
||||
union cvmx_pciercx_cfg006 pciercx_cfg006;
|
||||
union cvmx_pciercx_cfg032 pciercx_cfg032;
|
||||
|
||||
pciercx_cfg006.u32 =
|
||||
cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG006(pcie_port));
|
||||
if ((bus <= pciercx_cfg006.s.pbnum) && (dev != 0))
|
||||
return 0;
|
||||
|
||||
pciercx_cfg032.u32 =
|
||||
cvmx_pcie_cfgx_read(pcie_port, CVMX_PCIERCX_CFG032(pcie_port));
|
||||
if ((pciercx_cfg032.s.dlla == 0) || (pciercx_cfg032.s.lt == 1))
|
||||
return 0;
|
||||
|
||||
pcie_addr.u64 = 0;
|
||||
pcie_addr.config.upper = 2;
|
||||
pcie_addr.config.io = 1;
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
95 common fchown sys_fchown
|
||||
96 common getpriority sys_getpriority
|
||||
97 common setpriority sys_setpriority
|
||||
98 common recv sys_recv
|
||||
98 common recv sys_recv compat_sys_recv
|
||||
99 common statfs sys_statfs compat_sys_statfs
|
||||
100 common fstatfs sys_fstatfs compat_sys_fstatfs
|
||||
101 common stat64 sys_stat64
|
||||
@@ -135,7 +135,7 @@
|
||||
120 common clone sys_clone_wrapper
|
||||
121 common setdomainname sys_setdomainname
|
||||
122 common sendfile sys_sendfile compat_sys_sendfile
|
||||
123 common recvfrom sys_recvfrom
|
||||
123 common recvfrom sys_recvfrom compat_sys_recvfrom
|
||||
124 32 adjtimex sys_adjtimex_time32
|
||||
124 64 adjtimex sys_adjtimex
|
||||
125 common mprotect sys_mprotect
|
||||
|
||||
@@ -403,7 +403,7 @@ long plpar_hcall_norets(unsigned long opcode, ...);
|
||||
* Used for all but the craziest of phyp interfaces (see plpar_hcall9)
|
||||
*/
|
||||
#define PLPAR_HCALL_BUFSIZE 4
|
||||
long plpar_hcall(unsigned long opcode, unsigned long *retbuf, ...);
|
||||
long plpar_hcall(unsigned long opcode, unsigned long retbuf[static PLPAR_HCALL_BUFSIZE], ...);
|
||||
|
||||
/**
|
||||
* plpar_hcall_raw: - Make a hypervisor call without calculating hcall stats
|
||||
@@ -417,7 +417,7 @@ long plpar_hcall(unsigned long opcode, unsigned long *retbuf, ...);
|
||||
* plpar_hcall, but plpar_hcall_raw works in real mode and does not
|
||||
* calculate hypervisor call statistics.
|
||||
*/
|
||||
long plpar_hcall_raw(unsigned long opcode, unsigned long *retbuf, ...);
|
||||
long plpar_hcall_raw(unsigned long opcode, unsigned long retbuf[static PLPAR_HCALL_BUFSIZE], ...);
|
||||
|
||||
/**
|
||||
* plpar_hcall9: - Make a pseries hypervisor call with up to 9 return arguments
|
||||
@@ -428,8 +428,8 @@ long plpar_hcall_raw(unsigned long opcode, unsigned long *retbuf, ...);
|
||||
* PLPAR_HCALL9_BUFSIZE to size the return argument buffer.
|
||||
*/
|
||||
#define PLPAR_HCALL9_BUFSIZE 9
|
||||
long plpar_hcall9(unsigned long opcode, unsigned long *retbuf, ...);
|
||||
long plpar_hcall9_raw(unsigned long opcode, unsigned long *retbuf, ...);
|
||||
long plpar_hcall9(unsigned long opcode, unsigned long retbuf[static PLPAR_HCALL9_BUFSIZE], ...);
|
||||
long plpar_hcall9_raw(unsigned long opcode, unsigned long retbuf[static PLPAR_HCALL9_BUFSIZE], ...);
|
||||
|
||||
struct hvcall_mpp_data {
|
||||
unsigned long entitled_mem;
|
||||
|
||||
@@ -46,7 +46,7 @@ extern struct pci_dev *isa_bridge_pcidev;
|
||||
* define properly based on the platform
|
||||
*/
|
||||
#ifndef CONFIG_PCI
|
||||
#define _IO_BASE 0
|
||||
#define _IO_BASE POISON_POINTER_DELTA
|
||||
#define _ISA_MEM_BASE 0
|
||||
#define PCI_DRAM_OFFSET 0
|
||||
#elif defined(CONFIG_PPC32)
|
||||
@@ -542,12 +542,12 @@ __do_out_asm(_rec_outl, "stwbrx")
|
||||
#define __do_inw(port) _rec_inw(port)
|
||||
#define __do_inl(port) _rec_inl(port)
|
||||
#else /* CONFIG_PPC32 */
|
||||
#define __do_outb(val, port) writeb(val,(PCI_IO_ADDR)_IO_BASE+port);
|
||||
#define __do_outw(val, port) writew(val,(PCI_IO_ADDR)_IO_BASE+port);
|
||||
#define __do_outl(val, port) writel(val,(PCI_IO_ADDR)_IO_BASE+port);
|
||||
#define __do_inb(port) readb((PCI_IO_ADDR)_IO_BASE + port);
|
||||
#define __do_inw(port) readw((PCI_IO_ADDR)_IO_BASE + port);
|
||||
#define __do_inl(port) readl((PCI_IO_ADDR)_IO_BASE + port);
|
||||
#define __do_outb(val, port) writeb(val,(PCI_IO_ADDR)(_IO_BASE+port));
|
||||
#define __do_outw(val, port) writew(val,(PCI_IO_ADDR)(_IO_BASE+port));
|
||||
#define __do_outl(val, port) writel(val,(PCI_IO_ADDR)(_IO_BASE+port));
|
||||
#define __do_inb(port) readb((PCI_IO_ADDR)(_IO_BASE + port));
|
||||
#define __do_inw(port) readw((PCI_IO_ADDR)(_IO_BASE + port));
|
||||
#define __do_inl(port) readl((PCI_IO_ADDR)(_IO_BASE + port));
|
||||
#endif /* !CONFIG_PPC32 */
|
||||
|
||||
#ifdef CONFIG_EEH
|
||||
@@ -563,12 +563,12 @@ __do_out_asm(_rec_outl, "stwbrx")
|
||||
#define __do_writesw(a, b, n) _outsw(PCI_FIX_ADDR(a),(b),(n))
|
||||
#define __do_writesl(a, b, n) _outsl(PCI_FIX_ADDR(a),(b),(n))
|
||||
|
||||
#define __do_insb(p, b, n) readsb((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
|
||||
#define __do_insw(p, b, n) readsw((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
|
||||
#define __do_insl(p, b, n) readsl((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
|
||||
#define __do_outsb(p, b, n) writesb((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
|
||||
#define __do_outsw(p, b, n) writesw((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
|
||||
#define __do_outsl(p, b, n) writesl((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
|
||||
#define __do_insb(p, b, n) readsb((PCI_IO_ADDR)(_IO_BASE+(p)), (b), (n))
|
||||
#define __do_insw(p, b, n) readsw((PCI_IO_ADDR)(_IO_BASE+(p)), (b), (n))
|
||||
#define __do_insl(p, b, n) readsl((PCI_IO_ADDR)(_IO_BASE+(p)), (b), (n))
|
||||
#define __do_outsb(p, b, n) writesb((PCI_IO_ADDR)(_IO_BASE+(p)),(b),(n))
|
||||
#define __do_outsw(p, b, n) writesw((PCI_IO_ADDR)(_IO_BASE+(p)),(b),(n))
|
||||
#define __do_outsl(p, b, n) writesl((PCI_IO_ADDR)(_IO_BASE+(p)),(b),(n))
|
||||
|
||||
#define __do_memset_io(addr, c, n) \
|
||||
_memset_io(PCI_FIX_ADDR(addr), c, n)
|
||||
|
||||
@@ -922,6 +922,7 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
|
||||
{
|
||||
struct eeh_dev *edev;
|
||||
struct pci_dev *pdev;
|
||||
struct pci_bus *bus = NULL;
|
||||
|
||||
if (pe->type & EEH_PE_PHB)
|
||||
return pe->phb->bus;
|
||||
@@ -932,9 +933,11 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
|
||||
|
||||
/* Retrieve the parent PCI bus of first (top) PCI device */
|
||||
edev = list_first_entry_or_null(&pe->edevs, struct eeh_dev, entry);
|
||||
pci_lock_rescan_remove();
|
||||
pdev = eeh_dev_to_pci_dev(edev);
|
||||
if (pdev)
|
||||
return pdev->bus;
|
||||
bus = pdev->bus;
|
||||
pci_unlock_rescan_remove();
|
||||
|
||||
return NULL;
|
||||
return bus;
|
||||
}
|
||||
|
||||
@@ -118,14 +118,16 @@ extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
fdput(f);
|
||||
|
||||
if (!found)
|
||||
if (!found) {
|
||||
fdput(f);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
table_group = iommu_group_get_iommudata(grp);
|
||||
if (WARN_ON(!table_group))
|
||||
if (WARN_ON(!table_group)) {
|
||||
fdput(f);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
for (i = 0; i < IOMMU_TABLE_GROUP_MAX_TABLES; ++i) {
|
||||
struct iommu_table *tbltmp = table_group->tables[i];
|
||||
@@ -146,8 +148,10 @@ extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!tbl)
|
||||
if (!tbl) {
|
||||
fdput(f);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(stit, &stt->iommu_tables, next) {
|
||||
@@ -158,6 +162,7 @@ extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
|
||||
/* stit is being destroyed */
|
||||
iommu_tce_table_put(tbl);
|
||||
rcu_read_unlock();
|
||||
fdput(f);
|
||||
return -ENOTTY;
|
||||
}
|
||||
/*
|
||||
@@ -165,6 +170,7 @@ extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
|
||||
* its KVM reference counter and can return.
|
||||
*/
|
||||
rcu_read_unlock();
|
||||
fdput(f);
|
||||
return 0;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
@@ -172,6 +178,7 @@ extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
|
||||
stit = kzalloc(sizeof(*stit), GFP_KERNEL);
|
||||
if (!stit) {
|
||||
iommu_tce_table_put(tbl);
|
||||
fdput(f);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -180,6 +187,7 @@ extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
|
||||
|
||||
list_add_rcu(&stit->next, &stt->iommu_tables);
|
||||
|
||||
fdput(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -305,8 +305,8 @@ static int alloc_dispatch_log_kmem_cache(void)
|
||||
{
|
||||
void (*ctor)(void *) = get_dtl_cache_ctor();
|
||||
|
||||
dtl_cache = kmem_cache_create("dtl", DISPATCH_LOG_BYTES,
|
||||
DISPATCH_LOG_BYTES, 0, ctor);
|
||||
dtl_cache = kmem_cache_create_usercopy("dtl", DISPATCH_LOG_BYTES,
|
||||
DISPATCH_LOG_BYTES, 0, 0, DISPATCH_LOG_BYTES, ctor);
|
||||
if (!dtl_cache) {
|
||||
pr_warn("Failed to create dispatch trace log buffer cache\n");
|
||||
pr_warn("Stolen time statistics will be unreliable\n");
|
||||
|
||||
@@ -1214,7 +1214,7 @@ static int cpu_cmd(void)
|
||||
unsigned long cpu, first_cpu, last_cpu;
|
||||
int timeout;
|
||||
|
||||
if (!scanhex(&cpu)) {
|
||||
if (!scanhex(&cpu) || cpu >= num_possible_cpus()) {
|
||||
/* print cpus waiting or in xmon */
|
||||
printf("cpus stopped:");
|
||||
last_cpu = first_cpu = NR_CPUS;
|
||||
@@ -2571,7 +2571,7 @@ static void dump_pacas(void)
|
||||
|
||||
termch = c; /* Put c back, it wasn't 'a' */
|
||||
|
||||
if (scanhex(&num))
|
||||
if (scanhex(&num) && num < num_possible_cpus())
|
||||
dump_one_paca(num);
|
||||
else
|
||||
dump_one_paca(xmon_owner);
|
||||
@@ -2668,7 +2668,7 @@ static void dump_xives(void)
|
||||
|
||||
termch = c; /* Put c back, it wasn't 'a' */
|
||||
|
||||
if (scanhex(&num))
|
||||
if (scanhex(&num) && num < num_possible_cpus())
|
||||
dump_one_xive(num);
|
||||
else
|
||||
dump_one_xive(xmon_owner);
|
||||
|
||||
@@ -256,8 +256,8 @@ static inline void __load_psw(psw_t psw)
|
||||
*/
|
||||
static __always_inline void __load_psw_mask(unsigned long mask)
|
||||
{
|
||||
psw_t psw __uninitialized;
|
||||
unsigned long addr;
|
||||
psw_t psw;
|
||||
|
||||
psw.mask = mask;
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
90 common dup2 sys_dup2
|
||||
91 32 setfsuid32 sys_setfsuid
|
||||
92 common fcntl sys_fcntl compat_sys_fcntl
|
||||
93 common select sys_select
|
||||
93 common select sys_select compat_sys_select
|
||||
94 32 setfsgid32 sys_setfsgid
|
||||
95 common fsync sys_fsync
|
||||
96 common setpriority sys_setpriority
|
||||
|
||||
@@ -166,7 +166,14 @@ out:
|
||||
|
||||
int amd_smn_read(u16 node, u32 address, u32 *value)
|
||||
{
|
||||
return __amd_smn_rw(node, address, value, false);
|
||||
int err = __amd_smn_rw(node, address, value, false);
|
||||
|
||||
if (PCI_POSSIBLE_ERROR(*value)) {
|
||||
err = -ENODEV;
|
||||
*value = 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(amd_smn_read);
|
||||
|
||||
|
||||
@@ -27,25 +27,7 @@
|
||||
|
||||
unsigned long profile_pc(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long pc = instruction_pointer(regs);
|
||||
|
||||
if (!user_mode(regs) && in_lock_functions(pc)) {
|
||||
#ifdef CONFIG_FRAME_POINTER
|
||||
return *(unsigned long *)(regs->bp + sizeof(long));
|
||||
#else
|
||||
unsigned long *sp = (unsigned long *)regs->sp;
|
||||
/*
|
||||
* Return address is either directly at stack pointer
|
||||
* or above a saved flags. Eflags has bits 22-31 zero,
|
||||
* kernel addresses don't.
|
||||
*/
|
||||
if (sp[0] >> 22)
|
||||
return sp[0];
|
||||
if (sp[1] >> 22)
|
||||
return sp[1];
|
||||
#endif
|
||||
}
|
||||
return pc;
|
||||
return instruction_pointer(regs);
|
||||
}
|
||||
EXPORT_SYMBOL(profile_pc);
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ acpi_ex_system_memory_space_handler(u32 function,
|
||||
struct acpi_mem_space_context *mem_info = region_context;
|
||||
u32 length;
|
||||
acpi_size map_length;
|
||||
acpi_size page_boundary_map_length;
|
||||
#ifdef ACPI_MISALIGNMENT_NOT_SUPPORTED
|
||||
u32 remainder;
|
||||
#endif
|
||||
@@ -120,26 +119,8 @@ acpi_ex_system_memory_space_handler(u32 function,
|
||||
map_length = (acpi_size)
|
||||
((mem_info->address + mem_info->length) - address);
|
||||
|
||||
/*
|
||||
* If mapping the entire remaining portion of the region will cross
|
||||
* a page boundary, just map up to the page boundary, do not cross.
|
||||
* On some systems, crossing a page boundary while mapping regions
|
||||
* can cause warnings if the pages have different attributes
|
||||
* due to resource management.
|
||||
*
|
||||
* This has the added benefit of constraining a single mapping to
|
||||
* one page, which is similar to the original code that used a 4k
|
||||
* maximum window.
|
||||
*/
|
||||
page_boundary_map_length = (acpi_size)
|
||||
(ACPI_ROUND_UP(address, ACPI_DEFAULT_PAGE_SIZE) - address);
|
||||
if (page_boundary_map_length == 0) {
|
||||
page_boundary_map_length = ACPI_DEFAULT_PAGE_SIZE;
|
||||
}
|
||||
|
||||
if (map_length > page_boundary_map_length) {
|
||||
map_length = page_boundary_map_length;
|
||||
}
|
||||
if (map_length > ACPI_DEFAULT_PAGE_SIZE)
|
||||
map_length = ACPI_DEFAULT_PAGE_SIZE;
|
||||
|
||||
/* Create a new mapping starting at the address given */
|
||||
|
||||
|
||||
@@ -1310,10 +1310,13 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
|
||||
if (ec->busy_polling || bits > 8)
|
||||
acpi_ec_burst_enable(ec);
|
||||
|
||||
for (i = 0; i < bytes; ++i, ++address, ++value)
|
||||
for (i = 0; i < bytes; ++i, ++address, ++value) {
|
||||
result = (function == ACPI_READ) ?
|
||||
acpi_ec_read(ec, address, value) :
|
||||
acpi_ec_write(ec, address, *value);
|
||||
if (result < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ec->busy_polling || bits > 8)
|
||||
acpi_ec_burst_disable(ec);
|
||||
@@ -1325,8 +1328,10 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address,
|
||||
return AE_NOT_FOUND;
|
||||
case -ETIME:
|
||||
return AE_TIME;
|
||||
default:
|
||||
case 0:
|
||||
return AE_OK;
|
||||
default:
|
||||
return AE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <linux/sched.h> /* need_resched() */
|
||||
#include <linux/sort.h>
|
||||
#include <linux/tick.h>
|
||||
#include <linux/cpuidle.h>
|
||||
#include <linux/cpu.h>
|
||||
@@ -541,28 +540,24 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
|
||||
return;
|
||||
}
|
||||
|
||||
static int acpi_cst_latency_cmp(const void *a, const void *b)
|
||||
static void acpi_cst_latency_sort(struct acpi_processor_cx *states, size_t length)
|
||||
{
|
||||
const struct acpi_processor_cx *x = a, *y = b;
|
||||
int i, j, k;
|
||||
|
||||
if (!(x->valid && y->valid))
|
||||
return 0;
|
||||
if (x->latency > y->latency)
|
||||
return 1;
|
||||
if (x->latency < y->latency)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
static void acpi_cst_latency_swap(void *a, void *b, int n)
|
||||
{
|
||||
struct acpi_processor_cx *x = a, *y = b;
|
||||
u32 tmp;
|
||||
for (i = 1; i < length; i++) {
|
||||
if (!states[i].valid)
|
||||
continue;
|
||||
|
||||
if (!(x->valid && y->valid))
|
||||
return;
|
||||
tmp = x->latency;
|
||||
x->latency = y->latency;
|
||||
y->latency = tmp;
|
||||
for (j = i - 1, k = i; j >= 0; j--) {
|
||||
if (!states[j].valid)
|
||||
continue;
|
||||
|
||||
if (states[j].latency > states[k].latency)
|
||||
swap(states[j].latency, states[k].latency);
|
||||
|
||||
k = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int acpi_processor_power_verify(struct acpi_processor *pr)
|
||||
@@ -607,10 +602,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
|
||||
|
||||
if (buggy_latency) {
|
||||
pr_notice("FW issue: working around C-state latencies out of order\n");
|
||||
sort(&pr->power.states[1], max_cstate,
|
||||
sizeof(struct acpi_processor_cx),
|
||||
acpi_cst_latency_cmp,
|
||||
acpi_cst_latency_swap);
|
||||
acpi_cst_latency_sort(&pr->power.states[1], max_cstate);
|
||||
}
|
||||
|
||||
lapic_timer_propagate_broadcast(pr);
|
||||
|
||||
@@ -1439,6 +1439,7 @@ static void binder_free_ref(struct binder_ref *ref)
|
||||
if (ref->node)
|
||||
binder_free_node(ref->node);
|
||||
kfree(ref->death);
|
||||
kfree(ref->freeze);
|
||||
kfree(ref);
|
||||
}
|
||||
|
||||
@@ -2814,6 +2815,56 @@ static int binder_fixup_parent(struct list_head *pf_head,
|
||||
return binder_add_fixup(pf_head, buffer_offset, bp->buffer, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* binder_can_update_transaction() - Can a txn be superseded by an updated one?
|
||||
* @t1: the pending async txn in the frozen process
|
||||
* @t2: the new async txn to supersede the outdated pending one
|
||||
*
|
||||
* Return: true if t2 can supersede t1
|
||||
* false if t2 can not supersede t1
|
||||
*/
|
||||
static bool binder_can_update_transaction(struct binder_transaction *t1,
|
||||
struct binder_transaction *t2)
|
||||
{
|
||||
if ((t1->flags & t2->flags & (TF_ONE_WAY | TF_UPDATE_TXN)) !=
|
||||
(TF_ONE_WAY | TF_UPDATE_TXN) || !t1->to_proc || !t2->to_proc)
|
||||
return false;
|
||||
if (t1->to_proc->tsk == t2->to_proc->tsk && t1->code == t2->code &&
|
||||
t1->flags == t2->flags && t1->buffer->pid == t2->buffer->pid &&
|
||||
t1->buffer->target_node->ptr == t2->buffer->target_node->ptr &&
|
||||
t1->buffer->target_node->cookie == t2->buffer->target_node->cookie)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* binder_find_outdated_transaction_ilocked() - Find the outdated transaction
|
||||
* @t: new async transaction
|
||||
* @target_list: list to find outdated transaction
|
||||
*
|
||||
* Return: the outdated transaction if found
|
||||
* NULL if no outdated transacton can be found
|
||||
*
|
||||
* Requires the proc->inner_lock to be held.
|
||||
*/
|
||||
static struct binder_transaction *
|
||||
binder_find_outdated_transaction_ilocked(struct binder_transaction *t,
|
||||
struct list_head *target_list)
|
||||
{
|
||||
struct binder_work *w;
|
||||
|
||||
list_for_each_entry(w, target_list, entry) {
|
||||
struct binder_transaction *t_queued;
|
||||
|
||||
if (w->type != BINDER_WORK_TRANSACTION)
|
||||
continue;
|
||||
t_queued = container_of(w, struct binder_transaction, work);
|
||||
if (binder_can_update_transaction(t_queued, t))
|
||||
return t_queued;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* binder_proc_transaction() - sends a transaction to a process and wakes it up
|
||||
* @t: transaction to send
|
||||
@@ -2839,6 +2890,7 @@ static int binder_proc_transaction(struct binder_transaction *t,
|
||||
struct binder_node *node = t->buffer->target_node;
|
||||
bool oneway = !!(t->flags & TF_ONE_WAY);
|
||||
bool pending_async = false;
|
||||
struct binder_transaction *t_outdated = NULL;
|
||||
|
||||
BUG_ON(!node);
|
||||
binder_node_lock(node);
|
||||
@@ -2874,6 +2926,17 @@ static int binder_proc_transaction(struct binder_transaction *t,
|
||||
} else if (!pending_async) {
|
||||
binder_enqueue_work_ilocked(&t->work, &proc->todo);
|
||||
} else {
|
||||
if ((t->flags & TF_UPDATE_TXN) && proc->is_frozen) {
|
||||
t_outdated = binder_find_outdated_transaction_ilocked(t,
|
||||
&node->async_todo);
|
||||
if (t_outdated) {
|
||||
binder_debug(BINDER_DEBUG_TRANSACTION,
|
||||
"txn %d supersedes %d\n",
|
||||
t->debug_id, t_outdated->debug_id);
|
||||
list_del_init(&t_outdated->work.entry);
|
||||
proc->outstanding_txns--;
|
||||
}
|
||||
}
|
||||
binder_enqueue_work_ilocked(&t->work, &node->async_todo);
|
||||
}
|
||||
|
||||
@@ -2884,6 +2947,22 @@ static int binder_proc_transaction(struct binder_transaction *t,
|
||||
binder_inner_proc_unlock(proc);
|
||||
binder_node_unlock(node);
|
||||
|
||||
/*
|
||||
* To reduce potential contention, free the outdated transaction and
|
||||
* buffer after releasing the locks.
|
||||
*/
|
||||
if (t_outdated) {
|
||||
struct binder_buffer *buffer = t_outdated->buffer;
|
||||
|
||||
t_outdated->buffer = NULL;
|
||||
buffer->transaction = NULL;
|
||||
trace_binder_transaction_update_buffer_release(buffer);
|
||||
binder_transaction_buffer_release(proc, NULL, buffer, 0, 0);
|
||||
binder_alloc_free_buf(&proc->alloc, buffer);
|
||||
kfree(t_outdated);
|
||||
binder_stats_deleted(BINDER_STAT_TRANSACTION);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3342,6 +3421,7 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
*/
|
||||
copy_size = object_offset - user_offset;
|
||||
if (copy_size && (user_offset > object_offset ||
|
||||
object_offset > tr->data_size ||
|
||||
binder_alloc_copy_user_to_buffer(
|
||||
&target_proc->alloc,
|
||||
t->buffer, user_offset,
|
||||
@@ -3585,7 +3665,10 @@ static void binder_transaction(struct binder_proc *proc,
|
||||
return_error_line = __LINE__;
|
||||
goto err_copy_data_failed;
|
||||
}
|
||||
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
|
||||
if (t->buffer->oneway_spam_suspect)
|
||||
tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
|
||||
else
|
||||
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
|
||||
t->work.type = BINDER_WORK_TRANSACTION;
|
||||
|
||||
if (reply) {
|
||||
@@ -3734,6 +3817,154 @@ err_invalid_target_handle:
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
binder_request_freeze_notification(struct binder_proc *proc,
|
||||
struct binder_thread *thread,
|
||||
struct binder_handle_cookie *handle_cookie)
|
||||
{
|
||||
struct binder_ref_freeze *freeze;
|
||||
struct binder_ref *ref;
|
||||
bool is_frozen;
|
||||
|
||||
freeze = kzalloc(sizeof(*freeze), GFP_KERNEL);
|
||||
if (!freeze)
|
||||
return -ENOMEM;
|
||||
binder_proc_lock(proc);
|
||||
ref = binder_get_ref_olocked(proc, handle_cookie->handle, false);
|
||||
if (!ref) {
|
||||
binder_user_error("%d:%d BC_REQUEST_FREEZE_NOTIFICATION invalid ref %d\n",
|
||||
proc->pid, thread->pid, handle_cookie->handle);
|
||||
binder_proc_unlock(proc);
|
||||
kfree(freeze);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
binder_node_lock(ref->node);
|
||||
|
||||
if (ref->freeze || !ref->node->proc) {
|
||||
binder_user_error("%d:%d invalid BC_REQUEST_FREEZE_NOTIFICATION %s\n",
|
||||
proc->pid, thread->pid,
|
||||
ref->freeze ? "already set" : "dead node");
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
kfree(freeze);
|
||||
return -EINVAL;
|
||||
}
|
||||
binder_inner_proc_lock(ref->node->proc);
|
||||
is_frozen = ref->node->proc->is_frozen;
|
||||
binder_inner_proc_unlock(ref->node->proc);
|
||||
|
||||
INIT_LIST_HEAD(&freeze->work.entry);
|
||||
freeze->cookie = handle_cookie->cookie;
|
||||
freeze->work.type = BINDER_WORK_FROZEN_BINDER;
|
||||
freeze->is_frozen = is_frozen;
|
||||
|
||||
ref->freeze = freeze;
|
||||
|
||||
binder_inner_proc_lock(proc);
|
||||
binder_enqueue_work_ilocked(&ref->freeze->work, &proc->todo);
|
||||
binder_wakeup_proc_ilocked(proc);
|
||||
binder_inner_proc_unlock(proc);
|
||||
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
binder_clear_freeze_notification(struct binder_proc *proc,
|
||||
struct binder_thread *thread,
|
||||
struct binder_handle_cookie *handle_cookie)
|
||||
{
|
||||
struct binder_ref_freeze *freeze;
|
||||
struct binder_ref *ref;
|
||||
|
||||
binder_proc_lock(proc);
|
||||
ref = binder_get_ref_olocked(proc, handle_cookie->handle, false);
|
||||
if (!ref) {
|
||||
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION invalid ref %d\n",
|
||||
proc->pid, thread->pid, handle_cookie->handle);
|
||||
binder_proc_unlock(proc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
binder_node_lock(ref->node);
|
||||
|
||||
if (!ref->freeze) {
|
||||
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION freeze notification not active\n",
|
||||
proc->pid, thread->pid);
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
return -EINVAL;
|
||||
}
|
||||
freeze = ref->freeze;
|
||||
binder_inner_proc_lock(proc);
|
||||
if (freeze->cookie != handle_cookie->cookie) {
|
||||
binder_user_error("%d:%d BC_CLEAR_FREEZE_NOTIFICATION freeze notification cookie mismatch %016llx != %016llx\n",
|
||||
proc->pid, thread->pid, (u64)freeze->cookie,
|
||||
(u64)handle_cookie->cookie);
|
||||
binder_inner_proc_unlock(proc);
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
return -EINVAL;
|
||||
}
|
||||
ref->freeze = NULL;
|
||||
/*
|
||||
* Take the existing freeze object and overwrite its work type. There are three cases here:
|
||||
* 1. No pending notification. In this case just add the work to the queue.
|
||||
* 2. A notification was sent and is pending an ack from userspace. Once an ack arrives, we
|
||||
* should resend with the new work type.
|
||||
* 3. A notification is pending to be sent. Since the work is already in the queue, nothing
|
||||
* needs to be done here.
|
||||
*/
|
||||
freeze->work.type = BINDER_WORK_CLEAR_FREEZE_NOTIFICATION;
|
||||
if (list_empty(&freeze->work.entry)) {
|
||||
binder_enqueue_work_ilocked(&freeze->work, &proc->todo);
|
||||
binder_wakeup_proc_ilocked(proc);
|
||||
} else if (freeze->sent) {
|
||||
freeze->resend = true;
|
||||
}
|
||||
binder_inner_proc_unlock(proc);
|
||||
binder_node_unlock(ref->node);
|
||||
binder_proc_unlock(proc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
binder_freeze_notification_done(struct binder_proc *proc,
|
||||
struct binder_thread *thread,
|
||||
binder_uintptr_t cookie)
|
||||
{
|
||||
struct binder_ref_freeze *freeze = NULL;
|
||||
struct binder_work *w;
|
||||
|
||||
binder_inner_proc_lock(proc);
|
||||
list_for_each_entry(w, &proc_wrapper(proc)->delivered_freeze, entry) {
|
||||
struct binder_ref_freeze *tmp_freeze =
|
||||
container_of(w, struct binder_ref_freeze, work);
|
||||
|
||||
if (tmp_freeze->cookie == cookie) {
|
||||
freeze = tmp_freeze;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!freeze) {
|
||||
binder_user_error("%d:%d BC_FREEZE_NOTIFICATION_DONE %016llx not found\n",
|
||||
proc->pid, thread->pid, (u64)cookie);
|
||||
binder_inner_proc_unlock(proc);
|
||||
return -EINVAL;
|
||||
}
|
||||
binder_dequeue_work_ilocked(&freeze->work);
|
||||
freeze->sent = false;
|
||||
if (freeze->resend) {
|
||||
freeze->resend = false;
|
||||
binder_enqueue_work_ilocked(&freeze->work, &proc->todo);
|
||||
binder_wakeup_proc_ilocked(proc);
|
||||
}
|
||||
binder_inner_proc_unlock(proc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* binder_free_buf() - free the specified buffer
|
||||
* @proc: binder proc that owns buffer
|
||||
@@ -4209,6 +4440,44 @@ static int binder_thread_write(struct binder_proc *proc,
|
||||
binder_inner_proc_unlock(proc);
|
||||
} break;
|
||||
|
||||
case BC_REQUEST_FREEZE_NOTIFICATION: {
|
||||
struct binder_handle_cookie handle_cookie;
|
||||
int error;
|
||||
|
||||
if (copy_from_user(&handle_cookie, ptr, sizeof(handle_cookie)))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(handle_cookie);
|
||||
error = binder_request_freeze_notification(proc, thread,
|
||||
&handle_cookie);
|
||||
if (error)
|
||||
return error;
|
||||
} break;
|
||||
|
||||
case BC_CLEAR_FREEZE_NOTIFICATION: {
|
||||
struct binder_handle_cookie handle_cookie;
|
||||
int error;
|
||||
|
||||
if (copy_from_user(&handle_cookie, ptr, sizeof(handle_cookie)))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(handle_cookie);
|
||||
error = binder_clear_freeze_notification(proc, thread, &handle_cookie);
|
||||
if (error)
|
||||
return error;
|
||||
} break;
|
||||
|
||||
case BC_FREEZE_NOTIFICATION_DONE: {
|
||||
binder_uintptr_t cookie;
|
||||
int error;
|
||||
|
||||
if (get_user(cookie, (binder_uintptr_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
|
||||
ptr += sizeof(cookie);
|
||||
error = binder_freeze_notification_done(proc, thread, cookie);
|
||||
if (error)
|
||||
return error;
|
||||
} break;
|
||||
|
||||
default:
|
||||
pr_err("%d:%d unknown command %d\n",
|
||||
proc->pid, thread->pid, cmd);
|
||||
@@ -4462,9 +4731,14 @@ retry:
|
||||
|
||||
binder_stat_br(proc, thread, cmd);
|
||||
} break;
|
||||
case BINDER_WORK_TRANSACTION_COMPLETE: {
|
||||
case BINDER_WORK_TRANSACTION_COMPLETE:
|
||||
case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT: {
|
||||
if (proc->oneway_spam_detection_enabled &&
|
||||
w->type == BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT)
|
||||
cmd = BR_ONEWAY_SPAM_SUSPECT;
|
||||
else
|
||||
cmd = BR_TRANSACTION_COMPLETE;
|
||||
binder_inner_proc_unlock(proc);
|
||||
cmd = BR_TRANSACTION_COMPLETE;
|
||||
kfree(w);
|
||||
binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
|
||||
if (put_user(cmd, (uint32_t __user *)ptr))
|
||||
@@ -4604,6 +4878,45 @@ retry:
|
||||
if (cmd == BR_DEAD_BINDER)
|
||||
goto done; /* DEAD_BINDER notifications can cause transactions */
|
||||
} break;
|
||||
|
||||
case BINDER_WORK_FROZEN_BINDER: {
|
||||
struct binder_ref_freeze *freeze;
|
||||
struct binder_frozen_state_info info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
freeze = container_of(w, struct binder_ref_freeze, work);
|
||||
info.is_frozen = freeze->is_frozen;
|
||||
info.cookie = freeze->cookie;
|
||||
freeze->sent = true;
|
||||
binder_enqueue_work_ilocked(w, &proc_wrapper(proc)->delivered_freeze);
|
||||
binder_inner_proc_unlock(proc);
|
||||
|
||||
if (put_user(BR_FROZEN_BINDER, (uint32_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(uint32_t);
|
||||
if (copy_to_user(ptr, &info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(info);
|
||||
binder_stat_br(proc, thread, BR_FROZEN_BINDER);
|
||||
goto done; /* BR_FROZEN_BINDER notifications can cause transactions */
|
||||
} break;
|
||||
|
||||
case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION: {
|
||||
struct binder_ref_freeze *freeze =
|
||||
container_of(w, struct binder_ref_freeze, work);
|
||||
binder_uintptr_t cookie = freeze->cookie;
|
||||
|
||||
binder_inner_proc_unlock(proc);
|
||||
kfree(freeze);
|
||||
if (put_user(BR_CLEAR_FREEZE_NOTIFICATION_DONE, (uint32_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(uint32_t);
|
||||
if (put_user(cookie, (binder_uintptr_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
ptr += sizeof(binder_uintptr_t);
|
||||
binder_stat_br(proc, thread, BR_CLEAR_FREEZE_NOTIFICATION_DONE);
|
||||
} break;
|
||||
|
||||
default:
|
||||
binder_inner_proc_unlock(proc);
|
||||
pr_err("%d:%d: bad work type %d\n",
|
||||
@@ -4791,6 +5104,7 @@ static void binder_release_work(struct binder_proc *proc,
|
||||
"undelivered TRANSACTION_ERROR: %u\n",
|
||||
e->cmd);
|
||||
} break;
|
||||
case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT:
|
||||
case BINDER_WORK_TRANSACTION_COMPLETE: {
|
||||
binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
|
||||
"undelivered TRANSACTION_COMPLETE\n");
|
||||
@@ -5220,6 +5534,48 @@ static bool binder_txns_pending_ilocked(struct binder_proc *proc)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
|
||||
{
|
||||
struct rb_node *n;
|
||||
struct binder_ref *ref;
|
||||
|
||||
binder_inner_proc_lock(proc);
|
||||
for (n = rb_first(&proc->nodes); n; n = rb_next(n)) {
|
||||
struct binder_node *node;
|
||||
|
||||
node = rb_entry(n, struct binder_node, rb_node);
|
||||
binder_inner_proc_unlock(proc);
|
||||
binder_node_lock(node);
|
||||
hlist_for_each_entry(ref, &node->refs, node_entry) {
|
||||
/*
|
||||
* Need the node lock to synchronize
|
||||
* with new notification requests and the
|
||||
* inner lock to synchronize with queued
|
||||
* freeze notifications.
|
||||
*/
|
||||
binder_inner_proc_lock(ref->proc);
|
||||
if (!ref->freeze) {
|
||||
binder_inner_proc_unlock(ref->proc);
|
||||
continue;
|
||||
}
|
||||
ref->freeze->work.type = BINDER_WORK_FROZEN_BINDER;
|
||||
if (list_empty(&ref->freeze->work.entry)) {
|
||||
ref->freeze->is_frozen = is_frozen;
|
||||
binder_enqueue_work_ilocked(&ref->freeze->work, &ref->proc->todo);
|
||||
binder_wakeup_proc_ilocked(ref->proc);
|
||||
} else {
|
||||
if (ref->freeze->sent && ref->freeze->is_frozen != is_frozen)
|
||||
ref->freeze->resend = true;
|
||||
ref->freeze->is_frozen = is_frozen;
|
||||
}
|
||||
binder_inner_proc_unlock(ref->proc);
|
||||
}
|
||||
binder_node_unlock(node);
|
||||
binder_inner_proc_lock(proc);
|
||||
}
|
||||
binder_inner_proc_unlock(proc);
|
||||
}
|
||||
|
||||
static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
||||
struct binder_proc *target_proc)
|
||||
{
|
||||
@@ -5231,6 +5587,7 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
||||
target_proc->async_recv = false;
|
||||
target_proc->is_frozen = false;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
binder_add_freeze_work(target_proc, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5263,6 +5620,8 @@ static int binder_ioctl_freeze(struct binder_freeze_info *info,
|
||||
binder_inner_proc_lock(target_proc);
|
||||
target_proc->is_frozen = false;
|
||||
binder_inner_proc_unlock(target_proc);
|
||||
} else {
|
||||
binder_add_freeze_work(target_proc, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -5494,6 +5853,18 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BINDER_ENABLE_ONEWAY_SPAM_DETECTION: {
|
||||
uint32_t enable;
|
||||
|
||||
if (copy_from_user(&enable, ubuf, sizeof(enable))) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
binder_inner_proc_lock(proc);
|
||||
proc->oneway_spam_detection_enabled = (bool)enable;
|
||||
binder_inner_proc_unlock(proc);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
@@ -5594,9 +5965,9 @@ static int binder_open(struct inode *nodp, struct file *filp)
|
||||
current->group_leader->pid, current->pid);
|
||||
|
||||
eproc = kzalloc(sizeof(*eproc), GFP_KERNEL);
|
||||
proc = &eproc->proc;
|
||||
if (proc == NULL)
|
||||
if (eproc == NULL)
|
||||
return -ENOMEM;
|
||||
proc = &eproc->proc;
|
||||
spin_lock_init(&proc->inner_lock);
|
||||
spin_lock_init(&proc->outer_lock);
|
||||
get_task_struct(current->group_leader);
|
||||
@@ -5628,6 +5999,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
|
||||
binder_stats_created(BINDER_STAT_PROC);
|
||||
proc->pid = current->group_leader->pid;
|
||||
INIT_LIST_HEAD(&proc->delivered_death);
|
||||
INIT_LIST_HEAD(&proc_wrapper(proc)->delivered_freeze);
|
||||
INIT_LIST_HEAD(&proc->waiting_threads);
|
||||
filp->private_data = proc;
|
||||
|
||||
@@ -6180,6 +6552,7 @@ static const char * const binder_return_strings[] = {
|
||||
"BR_CLEAR_DEATH_NOTIFICATION_DONE",
|
||||
"BR_FAILED_REPLY",
|
||||
"BR_FROZEN_REPLY",
|
||||
"BR_ONEWAY_SPAM_SUSPECT",
|
||||
};
|
||||
|
||||
static const char * const binder_command_strings[] = {
|
||||
@@ -6211,7 +6584,7 @@ static const char * const binder_objstat_strings[] = {
|
||||
"ref",
|
||||
"death",
|
||||
"transaction",
|
||||
"transaction_complete"
|
||||
"transaction_complete",
|
||||
};
|
||||
|
||||
static void print_binder_stats(struct seq_file *m, const char *prefix,
|
||||
|
||||
@@ -339,7 +339,7 @@ static inline struct vm_area_struct *binder_alloc_get_vma(
|
||||
return vma;
|
||||
}
|
||||
|
||||
static void debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
|
||||
static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
|
||||
{
|
||||
/*
|
||||
* Find the amount and size of buffers allocated by the current caller;
|
||||
@@ -367,13 +367,19 @@ static void debug_low_async_space_locked(struct binder_alloc *alloc, int pid)
|
||||
|
||||
/*
|
||||
* Warn if this pid has more than 50 transactions, or more than 50% of
|
||||
* async space (which is 25% of total buffer size).
|
||||
* async space (which is 25% of total buffer size). Oneway spam is only
|
||||
* detected when the threshold is exceeded.
|
||||
*/
|
||||
if (num_buffers > 50 || total_alloc_size > alloc->buffer_size / 4) {
|
||||
binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
|
||||
"%d: pid %d spamming oneway? %zd buffers allocated for a total size of %zd\n",
|
||||
alloc->pid, pid, num_buffers, total_alloc_size);
|
||||
if (!alloc->oneway_spam_detected) {
|
||||
alloc->oneway_spam_detected = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct binder_buffer *binder_alloc_new_buf_locked(
|
||||
@@ -526,6 +532,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
|
||||
buffer->async_transaction = is_async;
|
||||
buffer->extra_buffers_size = extra_buffers_size;
|
||||
buffer->pid = pid;
|
||||
buffer->oneway_spam_suspect = false;
|
||||
if (is_async) {
|
||||
alloc->free_async_space -= size;
|
||||
binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC_ASYNC,
|
||||
@@ -537,7 +544,9 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
|
||||
* of async space left (which is less than 10% of total
|
||||
* buffer size).
|
||||
*/
|
||||
debug_low_async_space_locked(alloc, pid);
|
||||
buffer->oneway_spam_suspect = debug_low_async_space_locked(alloc, pid);
|
||||
} else {
|
||||
alloc->oneway_spam_detected = false;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
|
||||
@@ -26,6 +26,8 @@ struct binder_transaction;
|
||||
* @clear_on_free: %true if buffer must be zeroed after use
|
||||
* @allow_user_free: %true if user is allowed to free buffer
|
||||
* @async_transaction: %true if buffer is in use for an async txn
|
||||
* @oneway_spam_suspect: %true if total async allocate size just exceed
|
||||
* spamming detect threshold
|
||||
* @debug_id: unique ID for debugging
|
||||
* @transaction: pointer to associated struct binder_transaction
|
||||
* @target_node: struct binder_node associated with this buffer
|
||||
@@ -45,7 +47,8 @@ struct binder_buffer {
|
||||
unsigned clear_on_free:1;
|
||||
unsigned allow_user_free:1;
|
||||
unsigned async_transaction:1;
|
||||
unsigned debug_id:28;
|
||||
unsigned oneway_spam_suspect:1;
|
||||
unsigned debug_id:27;
|
||||
|
||||
struct binder_transaction *transaction;
|
||||
|
||||
@@ -87,6 +90,8 @@ struct binder_lru_page {
|
||||
* @buffer_size: size of address space specified via mmap
|
||||
* @pid: pid for associated binder_proc (invariant after init)
|
||||
* @pages_high: high watermark of offset in @pages
|
||||
* @oneway_spam_detected: %true if oneway spam detection fired, clear that
|
||||
* flag once the async buffer has returned to a healthy state
|
||||
*
|
||||
* Bookkeeping structure for per-proc address space management for binder
|
||||
* buffers. It is normally initialized during binder_init() and binder_mmap()
|
||||
@@ -107,6 +112,7 @@ struct binder_alloc {
|
||||
uint32_t buffer_free;
|
||||
int pid;
|
||||
size_t pages_high;
|
||||
bool oneway_spam_detected;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ANDROID_BINDER_IPC_SELFTEST
|
||||
|
||||
@@ -155,7 +155,7 @@ enum binder_stat_types {
|
||||
};
|
||||
|
||||
struct binder_stats {
|
||||
atomic_t br[_IOC_NR(BR_FROZEN_REPLY) + 1];
|
||||
atomic_t br[_IOC_NR(BR_ONEWAY_SPAM_SUSPECT) + 1];
|
||||
atomic_t bc[_IOC_NR(BC_REPLY_SG) + 1];
|
||||
atomic_t obj_created[BINDER_STAT_COUNT];
|
||||
atomic_t obj_deleted[BINDER_STAT_COUNT];
|
||||
@@ -174,11 +174,16 @@ struct binder_work {
|
||||
enum binder_work_type {
|
||||
BINDER_WORK_TRANSACTION = 1,
|
||||
BINDER_WORK_TRANSACTION_COMPLETE,
|
||||
BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT,
|
||||
BINDER_WORK_RETURN_ERROR,
|
||||
BINDER_WORK_NODE,
|
||||
BINDER_WORK_DEAD_BINDER,
|
||||
BINDER_WORK_DEAD_BINDER_AND_CLEAR,
|
||||
BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
|
||||
#ifndef __GENKSYMS__
|
||||
BINDER_WORK_FROZEN_BINDER,
|
||||
BINDER_WORK_CLEAR_FREEZE_NOTIFICATION,
|
||||
#endif
|
||||
} type;
|
||||
};
|
||||
|
||||
@@ -300,6 +305,14 @@ struct binder_ref_death {
|
||||
binder_uintptr_t cookie;
|
||||
};
|
||||
|
||||
struct binder_ref_freeze {
|
||||
struct binder_work work;
|
||||
binder_uintptr_t cookie;
|
||||
bool is_frozen:1;
|
||||
bool sent:1;
|
||||
bool resend:1;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct binder_ref_data - binder_ref counts and id
|
||||
* @debug_id: unique ID for the ref
|
||||
@@ -332,6 +345,8 @@ struct binder_ref_data {
|
||||
* @node indicates the node must be freed
|
||||
* @death: pointer to death notification (ref_death) if requested
|
||||
* (protected by @node->lock)
|
||||
* @freeze: pointer to freeze notification (ref_freeze) if requested
|
||||
* (protected by @node->lock)
|
||||
*
|
||||
* Structure to track references from procA to target node (on procB). This
|
||||
* structure is unsafe to access without holding @proc->outer_lock.
|
||||
@@ -348,6 +363,7 @@ struct binder_ref {
|
||||
struct binder_proc *proc;
|
||||
struct binder_node *node;
|
||||
struct binder_ref_death *death;
|
||||
struct binder_ref_freeze *freeze;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -438,6 +454,8 @@ enum binder_prio_state {
|
||||
* @outer_lock: no nesting under innor or node lock
|
||||
* Lock order: 1) outer, 2) node, 3) inner
|
||||
* @binderfs_entry: process-specific binderfs log file
|
||||
* @oneway_spam_detection_enabled: process enabled oneway spam detection
|
||||
* or not
|
||||
*
|
||||
* Bookkeeping structure for binder processes
|
||||
*/
|
||||
@@ -473,6 +491,7 @@ struct binder_proc {
|
||||
spinlock_t inner_lock;
|
||||
spinlock_t outer_lock;
|
||||
struct dentry *binderfs_entry;
|
||||
bool oneway_spam_detection_enabled;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -481,6 +500,8 @@ struct binder_proc {
|
||||
* @cred struct cred associated with the `struct file`
|
||||
* in binder_open()
|
||||
* (invariant after initialized)
|
||||
* @delivered_freeze: list of delivered freeze notification
|
||||
* (protected by @inner_lock)
|
||||
*
|
||||
* Extended binder_proc -- needed to add the "cred" field without
|
||||
* changing the KMI for binder_proc.
|
||||
@@ -488,6 +509,7 @@ struct binder_proc {
|
||||
struct binder_proc_ext {
|
||||
struct binder_proc proc;
|
||||
const struct cred *cred;
|
||||
struct list_head delivered_freeze;
|
||||
};
|
||||
|
||||
static inline const struct cred *binder_get_cred(struct binder_proc *proc)
|
||||
@@ -498,6 +520,12 @@ static inline const struct cred *binder_get_cred(struct binder_proc *proc)
|
||||
return eproc->cred;
|
||||
}
|
||||
|
||||
static inline
|
||||
struct binder_proc_ext *proc_wrapper(struct binder_proc *proc)
|
||||
{
|
||||
return container_of(proc, struct binder_proc_ext, proc);
|
||||
}
|
||||
|
||||
/**
|
||||
* struct binder_thread - binder thread bookkeeping
|
||||
* @proc: binder process for this thread
|
||||
|
||||
@@ -306,6 +306,10 @@ DEFINE_EVENT(binder_buffer_class, binder_transaction_failed_buffer_release,
|
||||
TP_PROTO(struct binder_buffer *buffer),
|
||||
TP_ARGS(buffer));
|
||||
|
||||
DEFINE_EVENT(binder_buffer_class, binder_transaction_update_buffer_release,
|
||||
TP_PROTO(struct binder_buffer *buffer),
|
||||
TP_ARGS(buffer));
|
||||
|
||||
TRACE_EVENT(binder_update_page_range,
|
||||
TP_PROTO(struct binder_alloc *alloc, bool allocate,
|
||||
void __user *start, void __user *end),
|
||||
|
||||
@@ -59,12 +59,22 @@ enum binderfs_stats_mode {
|
||||
STATS_GLOBAL,
|
||||
};
|
||||
|
||||
struct binder_features {
|
||||
bool oneway_spam_detection;
|
||||
bool freeze_notification;
|
||||
};
|
||||
|
||||
static const match_table_t tokens = {
|
||||
{ Opt_max, "max=%d" },
|
||||
{ Opt_stats_mode, "stats=%s" },
|
||||
{ Opt_err, NULL }
|
||||
};
|
||||
|
||||
static struct binder_features binder_features = {
|
||||
.oneway_spam_detection = true,
|
||||
.freeze_notification = true,
|
||||
};
|
||||
|
||||
static inline struct binderfs_info *BINDERFS_I(const struct inode *inode)
|
||||
{
|
||||
return inode->i_sb->s_fs_info;
|
||||
@@ -589,6 +599,39 @@ out:
|
||||
return dentry;
|
||||
}
|
||||
|
||||
static int binder_features_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
bool *feature = m->private;
|
||||
|
||||
seq_printf(m, "%d\n", *feature);
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(binder_features);
|
||||
|
||||
static int init_binder_features(struct super_block *sb)
|
||||
{
|
||||
struct dentry *dentry, *dir;
|
||||
|
||||
dir = binderfs_create_dir(sb->s_root, "features");
|
||||
if (IS_ERR(dir))
|
||||
return PTR_ERR(dir);
|
||||
|
||||
dentry = binderfs_create_file(dir, "oneway_spam_detection",
|
||||
&binder_features_fops,
|
||||
&binder_features.oneway_spam_detection);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
dentry = binderfs_create_file(dir, "freeze_notification",
|
||||
&binder_features_fops,
|
||||
&binder_features.freeze_notification);
|
||||
if (IS_ERR(dentry))
|
||||
return PTR_ERR(dentry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_binder_logs(struct super_block *sb)
|
||||
{
|
||||
struct dentry *binder_logs_root_dir, *dentry, *proc_log_dir;
|
||||
@@ -730,6 +773,10 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
|
||||
name++;
|
||||
}
|
||||
|
||||
ret = init_binder_features(sb);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (info->mount_opts.stats_mode == STATS_GLOBAL)
|
||||
return init_binder_logs(sb);
|
||||
|
||||
|
||||
@@ -6194,8 +6194,10 @@ struct ata_host *ata_host_alloc(struct device *dev, int max_ports)
|
||||
if (!host)
|
||||
return NULL;
|
||||
|
||||
if (!devres_open_group(dev, NULL, GFP_KERNEL))
|
||||
goto err_free;
|
||||
if (!devres_open_group(dev, NULL, GFP_KERNEL)) {
|
||||
kfree(host);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dr = devres_alloc(ata_devres_release, 0, GFP_KERNEL);
|
||||
if (!dr)
|
||||
@@ -6227,8 +6229,6 @@ struct ata_host *ata_host_alloc(struct device *dev, int max_ports)
|
||||
|
||||
err_out:
|
||||
devres_release_group(dev, NULL);
|
||||
err_free:
|
||||
kfree(host);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1942,8 +1942,11 @@ static ssize_t uevent_show(struct device *dev, struct device_attribute *attr,
|
||||
if (!env)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Synchronize with really_probe() */
|
||||
device_lock(dev);
|
||||
/* let the kset specific function add its keys */
|
||||
retval = kset->uevent_ops->uevent(kset, &dev->kobj, env);
|
||||
device_unlock(dev);
|
||||
if (retval)
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
* Copyright (c) 2008-2009 Atheros Communications Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
@@ -129,7 +128,6 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);
|
||||
* for AR3012
|
||||
*/
|
||||
static const struct usb_device_id ath3k_blist_tbl[] = {
|
||||
|
||||
/* Atheros AR3012 with sflash firmware*/
|
||||
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04d), .driver_info = BTUSB_ATH3012 },
|
||||
@@ -203,7 +201,7 @@ static inline void ath3k_log_failed_loading(int err, int len, int size,
|
||||
#define TIMEGAP_USEC_MAX 100
|
||||
|
||||
static int ath3k_load_firmware(struct usb_device *udev,
|
||||
const struct firmware *firmware)
|
||||
const struct firmware *firmware)
|
||||
{
|
||||
u8 *send_buf;
|
||||
int len = 0;
|
||||
@@ -241,9 +239,9 @@ static int ath3k_load_firmware(struct usb_device *udev,
|
||||
memcpy(send_buf, firmware->data + sent, size);
|
||||
|
||||
err = usb_bulk_msg(udev, pipe, send_buf, size,
|
||||
&len, 3000);
|
||||
&len, 3000);
|
||||
|
||||
if (err || (len != size)) {
|
||||
if (err || len != size) {
|
||||
ath3k_log_failed_loading(err, len, size, count);
|
||||
goto error;
|
||||
}
|
||||
@@ -278,7 +276,7 @@ static int ath3k_get_state(struct usb_device *udev, unsigned char *state)
|
||||
}
|
||||
|
||||
static int ath3k_get_version(struct usb_device *udev,
|
||||
struct ath3k_version *version)
|
||||
struct ath3k_version *version)
|
||||
{
|
||||
int ret, pipe = 0;
|
||||
struct ath3k_version *buf;
|
||||
@@ -300,7 +298,7 @@ static int ath3k_get_version(struct usb_device *udev,
|
||||
}
|
||||
|
||||
static int ath3k_load_fwfile(struct usb_device *udev,
|
||||
const struct firmware *firmware)
|
||||
const struct firmware *firmware)
|
||||
{
|
||||
u8 *send_buf;
|
||||
int len = 0;
|
||||
@@ -341,8 +339,8 @@ static int ath3k_load_fwfile(struct usb_device *udev,
|
||||
memcpy(send_buf, firmware->data + sent, size);
|
||||
|
||||
err = usb_bulk_msg(udev, pipe, send_buf, size,
|
||||
&len, 3000);
|
||||
if (err || (len != size)) {
|
||||
&len, 3000);
|
||||
if (err || len != size) {
|
||||
ath3k_log_failed_loading(err, len, size, count);
|
||||
kfree(send_buf);
|
||||
return err;
|
||||
@@ -461,7 +459,6 @@ static int ath3k_load_syscfg(struct usb_device *udev)
|
||||
}
|
||||
|
||||
switch (fw_version.ref_clock) {
|
||||
|
||||
case ATH3K_XTAL_FREQ_26M:
|
||||
clk_value = 26;
|
||||
break;
|
||||
@@ -477,7 +474,7 @@ static int ath3k_load_syscfg(struct usb_device *udev)
|
||||
}
|
||||
|
||||
snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s",
|
||||
le32_to_cpu(fw_version.rom_version), clk_value, ".dfu");
|
||||
le32_to_cpu(fw_version.rom_version), clk_value, ".dfu");
|
||||
|
||||
ret = request_firmware(&firmware, filename, &udev->dev);
|
||||
if (ret < 0) {
|
||||
@@ -492,7 +489,7 @@ static int ath3k_load_syscfg(struct usb_device *udev)
|
||||
}
|
||||
|
||||
static int ath3k_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
const struct firmware *firmware;
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
@@ -541,10 +538,10 @@ static int ath3k_probe(struct usb_interface *intf,
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOENT)
|
||||
BT_ERR("Firmware file \"%s\" not found",
|
||||
ATH3K_FIRMWARE);
|
||||
ATH3K_FIRMWARE);
|
||||
else
|
||||
BT_ERR("Firmware file \"%s\" request failed (err=%d)",
|
||||
ATH3K_FIRMWARE, ret);
|
||||
ATH3K_FIRMWARE, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -304,8 +304,13 @@ hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
|
||||
if (!devp->hd_ireqfreq)
|
||||
return -EIO;
|
||||
|
||||
if (count < sizeof(unsigned long))
|
||||
return -EINVAL;
|
||||
if (in_compat_syscall()) {
|
||||
if (count < sizeof(compat_ulong_t))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
if (count < sizeof(unsigned long))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
add_wait_queue(&devp->hd_waitqueue, &wait);
|
||||
|
||||
@@ -329,9 +334,16 @@ hpet_read(struct file *file, char __user *buf, size_t count, loff_t * ppos)
|
||||
schedule();
|
||||
}
|
||||
|
||||
retval = put_user(data, (unsigned long __user *)buf);
|
||||
if (!retval)
|
||||
retval = sizeof(unsigned long);
|
||||
if (in_compat_syscall()) {
|
||||
retval = put_user(data, (compat_ulong_t __user *)buf);
|
||||
if (!retval)
|
||||
retval = sizeof(compat_ulong_t);
|
||||
} else {
|
||||
retval = put_user(data, (unsigned long __user *)buf);
|
||||
if (!retval)
|
||||
retval = sizeof(unsigned long);
|
||||
}
|
||||
|
||||
out:
|
||||
__set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&devp->hd_waitqueue, &wait);
|
||||
@@ -686,12 +698,24 @@ struct compat_hpet_info {
|
||||
unsigned short hi_timer;
|
||||
};
|
||||
|
||||
/* 32-bit types would lead to different command codes which should be
|
||||
* translated into 64-bit ones before passed to hpet_ioctl_common
|
||||
*/
|
||||
#define COMPAT_HPET_INFO _IOR('h', 0x03, struct compat_hpet_info)
|
||||
#define COMPAT_HPET_IRQFREQ _IOW('h', 0x6, compat_ulong_t)
|
||||
|
||||
static long
|
||||
hpet_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct hpet_info info;
|
||||
int err;
|
||||
|
||||
if (cmd == COMPAT_HPET_INFO)
|
||||
cmd = HPET_INFO;
|
||||
|
||||
if (cmd == COMPAT_HPET_IRQFREQ)
|
||||
cmd = HPET_IRQFREQ;
|
||||
|
||||
mutex_lock(&hpet_mutex);
|
||||
err = hpet_ioctl_common(file->private_data, cmd, arg, &info);
|
||||
mutex_unlock(&hpet_mutex);
|
||||
|
||||
@@ -947,8 +947,8 @@ static int axi_dmac_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct axi_dmac *dmac = platform_get_drvdata(pdev);
|
||||
|
||||
of_dma_controller_free(pdev->dev.of_node);
|
||||
free_irq(dmac->irq, dmac);
|
||||
of_dma_controller_free(pdev->dev.of_node);
|
||||
tasklet_kill(&dmac->chan.vchan.task);
|
||||
dma_async_device_unregister(&dmac->dma_dev);
|
||||
clk_disable_unprepare(dmac->clk);
|
||||
|
||||
@@ -1446,6 +1446,7 @@ module_init(ioat_init_module);
|
||||
static void __exit ioat_exit_module(void)
|
||||
{
|
||||
pci_unregister_driver(&ioat_pci_driver);
|
||||
kmem_cache_destroy(ioat_sed_cache);
|
||||
kmem_cache_destroy(ioat_cache);
|
||||
}
|
||||
module_exit(ioat_exit_module);
|
||||
|
||||
@@ -96,6 +96,17 @@ static void dmi_decode_table(u8 *buf,
|
||||
(data - buf + sizeof(struct dmi_header)) <= dmi_len) {
|
||||
const struct dmi_header *dm = (const struct dmi_header *)data;
|
||||
|
||||
/*
|
||||
* If a short entry is found (less than 4 bytes), not only it
|
||||
* is invalid, but we cannot reliably locate the next entry.
|
||||
*/
|
||||
if (dm->length < sizeof(struct dmi_header)) {
|
||||
pr_warn(FW_BUG
|
||||
"Corrupted DMI table, offset %zd (only %d entries processed)\n",
|
||||
data - buf, i);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We want to know the total length (formatted area and
|
||||
* strings) before decoding to make sure we won't run off the
|
||||
|
||||
@@ -1230,7 +1230,7 @@ config GPIO_TPS68470
|
||||
drivers are loaded.
|
||||
|
||||
config GPIO_TQMX86
|
||||
tristate "TQ-Systems QTMX86 GPIO"
|
||||
tristate "TQ-Systems TQMx86 GPIO"
|
||||
depends on MFD_TQMX86 || COMPILE_TEST
|
||||
depends on HAS_IOPORT_MAP
|
||||
select GPIOLIB_IRQCHIP
|
||||
|
||||
@@ -227,6 +227,11 @@ static int davinci_gpio_probe(struct platform_device *pdev)
|
||||
else
|
||||
nirq = DIV_ROUND_UP(ngpio, 16);
|
||||
|
||||
if (nirq > MAX_INT_PER_BANK) {
|
||||
dev_err(dev, "Too many IRQs!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
chips = devm_kzalloc(dev, sizeof(*chips), GFP_KERNEL);
|
||||
if (!chips)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -384,6 +384,14 @@ void amdgpu_irq_dispatch(struct amdgpu_device *adev,
|
||||
int r;
|
||||
|
||||
entry.iv_entry = (const uint32_t *)&ih->ring[ring_index];
|
||||
|
||||
/*
|
||||
* timestamp is not supported on some legacy SOCs (cik, cz, iceland,
|
||||
* si and tonga), so initialize timestamp and timestamp_src to 0
|
||||
*/
|
||||
entry.timestamp = 0;
|
||||
entry.timestamp_src = 0;
|
||||
|
||||
amdgpu_ih_decode_iv(adev, &entry);
|
||||
|
||||
trace_amdgpu_iv(ih - &adev->irq.ih, &entry);
|
||||
|
||||
@@ -163,6 +163,8 @@ static void sumo_construct_vid_mapping_table(struct amdgpu_device *adev,
|
||||
|
||||
for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
|
||||
if (table[i].ulSupportedSCLK != 0) {
|
||||
if (table[i].usVoltageIndex >= SUMO_MAX_NUMBER_VOLTAGES)
|
||||
continue;
|
||||
vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit =
|
||||
table[i].usVoltageID;
|
||||
vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit =
|
||||
|
||||
@@ -2003,7 +2003,7 @@ static int sdma_v4_0_process_trap_irq(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
uint32_t instance;
|
||||
int instance;
|
||||
|
||||
DRM_DEBUG("IH: SDMA trap\n");
|
||||
instance = sdma_v4_0_irq_id_to_seq(entry->client_id);
|
||||
|
||||
@@ -1646,6 +1646,9 @@ static struct audio *find_first_free_audio(
|
||||
{
|
||||
int i, available_audio_count;
|
||||
|
||||
if (id == ENGINE_ID_UNKNOWN)
|
||||
return NULL;
|
||||
|
||||
available_audio_count = pool->audio_count;
|
||||
|
||||
for (i = 0; i < available_audio_count; i++) {
|
||||
|
||||
@@ -635,6 +635,12 @@ void enc1_stream_encoder_set_mst_bandwidth(
|
||||
x),
|
||||
26));
|
||||
|
||||
// If y rounds up to integer, carry it over to x.
|
||||
if (y >> 26) {
|
||||
x += 1;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
REG_SET_2(DP_MSE_RATE_CNTL, 0,
|
||||
DP_MSE_RATE_X, x,
|
||||
DP_MSE_RATE_Y, y);
|
||||
|
||||
@@ -653,7 +653,7 @@ struct atom_gpio_pin_lut_v2_1
|
||||
{
|
||||
struct atom_common_table_header table_header;
|
||||
/*the real number of this included in the structure is calcualted by using the (whole structure size - the header size)/size of atom_gpio_pin_lut */
|
||||
struct atom_gpio_pin_assignment gpio_pin[8];
|
||||
struct atom_gpio_pin_assignment gpio_pin[];
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -259,7 +259,7 @@ komeda_component_get_avail_scaler(struct komeda_component *c,
|
||||
u32 avail_scalers;
|
||||
|
||||
pipe_st = komeda_pipeline_get_state(c->pipeline, state);
|
||||
if (!pipe_st)
|
||||
if (IS_ERR_OR_NULL(pipe_st))
|
||||
return NULL;
|
||||
|
||||
avail_scalers = (pipe_st->active_comps & KOMEDA_PIPELINE_SCALERS) ^
|
||||
|
||||
@@ -203,9 +203,12 @@ EXPORT_SYMBOL(drm_panel_bridge_remove);
|
||||
|
||||
static void devm_drm_panel_bridge_release(struct device *dev, void *res)
|
||||
{
|
||||
struct drm_bridge **bridge = res;
|
||||
struct drm_bridge *bridge = *(struct drm_bridge **)res;
|
||||
|
||||
drm_panel_bridge_remove(*bridge);
|
||||
if (!bridge)
|
||||
return;
|
||||
|
||||
drm_bridge_remove(bridge);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -301,6 +301,7 @@ static int vidi_get_modes(struct drm_connector *connector)
|
||||
struct vidi_context *ctx = ctx_from_connector(connector);
|
||||
struct edid *edid;
|
||||
int edid_len;
|
||||
int count;
|
||||
|
||||
/*
|
||||
* the edid data comes from user side and it would be set
|
||||
@@ -320,7 +321,11 @@ static int vidi_get_modes(struct drm_connector *connector)
|
||||
|
||||
drm_connector_update_edid_property(connector, edid);
|
||||
|
||||
return drm_add_edid_modes(connector, edid);
|
||||
count = drm_add_edid_modes(connector, edid);
|
||||
|
||||
kfree(edid);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs vidi_connector_helper_funcs = {
|
||||
|
||||
@@ -876,11 +876,11 @@ static int hdmi_get_modes(struct drm_connector *connector)
|
||||
int ret;
|
||||
|
||||
if (!hdata->ddc_adpt)
|
||||
return 0;
|
||||
goto no_edid;
|
||||
|
||||
edid = drm_get_edid(connector, hdata->ddc_adpt);
|
||||
if (!edid)
|
||||
return 0;
|
||||
goto no_edid;
|
||||
|
||||
hdata->dvi_mode = !drm_detect_hdmi_monitor(edid);
|
||||
DRM_DEV_DEBUG_KMS(hdata->dev, "%s : width[%d] x height[%d]\n",
|
||||
@@ -895,6 +895,9 @@ static int hdmi_get_modes(struct drm_connector *connector)
|
||||
kfree(edid);
|
||||
|
||||
return ret;
|
||||
|
||||
no_edid:
|
||||
return drm_add_modes_noedid(connector, 640, 480);
|
||||
}
|
||||
|
||||
static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
|
||||
|
||||
@@ -244,7 +244,9 @@ int lima_gp_init(struct lima_ip *ip)
|
||||
|
||||
void lima_gp_fini(struct lima_ip *ip)
|
||||
{
|
||||
struct lima_device *dev = ip->dev;
|
||||
|
||||
devm_free_irq(dev->dev, ip->irq, ip);
|
||||
}
|
||||
|
||||
int lima_gp_pipe_init(struct lima_device *dev)
|
||||
|
||||
@@ -97,7 +97,12 @@ int lima_mmu_init(struct lima_ip *ip)
|
||||
|
||||
void lima_mmu_fini(struct lima_ip *ip)
|
||||
{
|
||||
struct lima_device *dev = ip->dev;
|
||||
|
||||
if (ip->id == lima_ip_ppmmu_bcast)
|
||||
return;
|
||||
|
||||
devm_free_irq(dev->dev, ip->irq, ip);
|
||||
}
|
||||
|
||||
void lima_mmu_switch_vm(struct lima_ip *ip, struct lima_vm *vm)
|
||||
|
||||
@@ -251,7 +251,9 @@ int lima_pp_init(struct lima_ip *ip)
|
||||
|
||||
void lima_pp_fini(struct lima_ip *ip)
|
||||
{
|
||||
struct lima_device *dev = ip->dev;
|
||||
|
||||
devm_free_irq(dev->dev, ip->irq, ip);
|
||||
}
|
||||
|
||||
int lima_pp_bcast_init(struct lima_ip *ip)
|
||||
@@ -272,7 +274,9 @@ int lima_pp_bcast_init(struct lima_ip *ip)
|
||||
|
||||
void lima_pp_bcast_fini(struct lima_ip *ip)
|
||||
{
|
||||
struct lima_device *dev = ip->dev;
|
||||
|
||||
devm_free_irq(dev->dev, ip->irq, ip);
|
||||
}
|
||||
|
||||
static int lima_pp_task_validate(struct lima_sched_pipe *pipe,
|
||||
|
||||
@@ -208,6 +208,8 @@ static int nv17_tv_get_ld_modes(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(encoder->dev, tv_mode);
|
||||
if (!mode)
|
||||
continue;
|
||||
|
||||
mode->clock = tv_norm->tv_enc_mode.vrefresh *
|
||||
mode->htotal / 1000 *
|
||||
@@ -257,6 +259,8 @@ static int nv17_tv_get_hd_modes(struct drm_encoder *encoder,
|
||||
if (modes[i].hdisplay == output_mode->hdisplay &&
|
||||
modes[i].vdisplay == output_mode->vdisplay) {
|
||||
mode = drm_mode_duplicate(encoder->dev, output_mode);
|
||||
if (!mode)
|
||||
continue;
|
||||
mode->type |= DRM_MODE_TYPE_PREFERRED;
|
||||
|
||||
} else {
|
||||
@@ -264,6 +268,8 @@ static int nv17_tv_get_hd_modes(struct drm_encoder *encoder,
|
||||
modes[i].vdisplay, 60, false,
|
||||
(output_mode->flags &
|
||||
DRM_MODE_FLAG_INTERLACE), false);
|
||||
if (!mode)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* CVT modes are sometimes unsuitable... */
|
||||
|
||||
@@ -968,6 +968,9 @@ nouveau_connector_get_modes(struct drm_connector *connector)
|
||||
struct drm_display_mode *mode;
|
||||
|
||||
mode = drm_mode_duplicate(dev, nv_connector->native_mode);
|
||||
if (!mode)
|
||||
return 0;
|
||||
|
||||
drm_mode_probed_add(connector, mode);
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
@@ -307,10 +307,10 @@ static int ili9881c_prepare(struct drm_panel *panel)
|
||||
msleep(5);
|
||||
|
||||
/* And reset it */
|
||||
gpiod_set_value(ctx->reset, 1);
|
||||
gpiod_set_value_cansleep(ctx->reset, 1);
|
||||
msleep(20);
|
||||
|
||||
gpiod_set_value(ctx->reset, 0);
|
||||
gpiod_set_value_cansleep(ctx->reset, 0);
|
||||
msleep(20);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ili9881c_init); i++) {
|
||||
@@ -367,7 +367,7 @@ static int ili9881c_unprepare(struct drm_panel *panel)
|
||||
|
||||
mipi_dsi_dcs_enter_sleep_mode(ctx->dsi);
|
||||
regulator_disable(ctx->power);
|
||||
gpiod_set_value(ctx->reset, 1);
|
||||
gpiod_set_value_cansleep(ctx->reset, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1621,6 +1621,8 @@ void sumo_construct_vid_mapping_table(struct radeon_device *rdev,
|
||||
|
||||
for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) {
|
||||
if (table[i].ulSupportedSCLK != 0) {
|
||||
if (table[i].usVoltageIndex >= SUMO_MAX_NUMBER_VOLTAGES)
|
||||
continue;
|
||||
vid_mapping_table->entries[table[i].usVoltageIndex].vid_7bit =
|
||||
table[i].usVoltageID;
|
||||
vid_mapping_table->entries[table[i].usVoltageIndex].vid_2bit =
|
||||
|
||||
@@ -694,6 +694,7 @@ static void gb_interface_release(struct device *dev)
|
||||
|
||||
trace_gb_interface_release(intf);
|
||||
|
||||
cancel_work_sync(&intf->mode_switch_work);
|
||||
kfree(intf);
|
||||
}
|
||||
|
||||
|
||||
@@ -1433,7 +1433,6 @@ static void implement(const struct hid_device *hid, u8 *report,
|
||||
hid_warn(hid,
|
||||
"%s() called with too large value %d (n: %d)! (%s)\n",
|
||||
__func__, value, n, current->comm);
|
||||
WARN_ON(1);
|
||||
value &= m;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1213,8 +1213,10 @@ static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
|
||||
*/
|
||||
msleep(50);
|
||||
|
||||
if (retval)
|
||||
if (retval) {
|
||||
kfree(dj_report);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -283,10 +283,23 @@ static void timesync_onchannelcallback(void *context)
|
||||
struct ictimesync_ref_data *refdata;
|
||||
u8 *time_txf_buf = util_timesynch.recv_buffer;
|
||||
|
||||
vmbus_recvpacket(channel, time_txf_buf,
|
||||
PAGE_SIZE, &recvlen, &requestid);
|
||||
/*
|
||||
* Drain the ring buffer and use the last packet to update
|
||||
* host_ts
|
||||
*/
|
||||
while (1) {
|
||||
int ret = vmbus_recvpacket(channel, time_txf_buf,
|
||||
HV_HYP_PAGE_SIZE, &recvlen,
|
||||
&requestid);
|
||||
if (ret) {
|
||||
pr_warn_once("TimeSync IC pkt recv failed (Err: %d)\n",
|
||||
ret);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!recvlen)
|
||||
break;
|
||||
|
||||
if (recvlen > 0) {
|
||||
icmsghdrp = (struct icmsg_hdr *)&time_txf_buf[
|
||||
sizeof(struct vmbuspipe_hdr)];
|
||||
|
||||
|
||||
@@ -294,11 +294,36 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xae24),
|
||||
.driver_data = (kernel_ulong_t)&intel_th_2x,
|
||||
},
|
||||
{
|
||||
/* Meteor Lake-S */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7f26),
|
||||
.driver_data = (kernel_ulong_t)&intel_th_2x,
|
||||
},
|
||||
{
|
||||
/* Raptor Lake-S */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7a26),
|
||||
.driver_data = (kernel_ulong_t)&intel_th_2x,
|
||||
},
|
||||
{
|
||||
/* Granite Rapids */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0963),
|
||||
.driver_data = (kernel_ulong_t)&intel_th_2x,
|
||||
},
|
||||
{
|
||||
/* Granite Rapids SOC */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3256),
|
||||
.driver_data = (kernel_ulong_t)&intel_th_2x,
|
||||
},
|
||||
{
|
||||
/* Sapphire Rapids SOC */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x3456),
|
||||
.driver_data = (kernel_ulong_t)&intel_th_2x,
|
||||
},
|
||||
{
|
||||
/* Lunar Lake */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa824),
|
||||
.driver_data = (kernel_ulong_t)&intel_th_2x,
|
||||
},
|
||||
{
|
||||
/* Rocket Lake CPU */
|
||||
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4c19),
|
||||
|
||||
@@ -106,8 +106,7 @@ static int at91_unreg_slave(struct i2c_client *slave)
|
||||
|
||||
static u32 at91_twi_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_SLAVE | I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
|
||||
| I2C_FUNC_SMBUS_READ_BLOCK_DATA;
|
||||
return I2C_FUNC_SLAVE;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm at91_twi_algorithm_slave = {
|
||||
|
||||
@@ -1057,7 +1057,7 @@ static const struct pci_device_id i801_ids[] = {
|
||||
MODULE_DEVICE_TABLE(pci, i801_ids);
|
||||
|
||||
#if defined CONFIG_X86 && defined CONFIG_DMI
|
||||
static unsigned char apanel_addr;
|
||||
static unsigned char apanel_addr __ro_after_init;
|
||||
|
||||
/* Scan the system ROM for the signature "FJKEYINF" */
|
||||
static __init const void __iomem *bios_signature(const void __iomem *bios)
|
||||
|
||||
@@ -443,8 +443,8 @@ static int ocores_init(struct device *dev, struct ocores_i2c *i2c)
|
||||
oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8);
|
||||
|
||||
/* Init the device */
|
||||
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
|
||||
oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_EN);
|
||||
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
@@ -32,7 +31,6 @@ struct i2c_pnx_mif {
|
||||
int ret; /* Return value */
|
||||
int mode; /* Interface mode */
|
||||
struct completion complete; /* I/O completion */
|
||||
struct timer_list timer; /* Timeout */
|
||||
u8 * buf; /* Data buffer */
|
||||
int len; /* Length of data buffer */
|
||||
int order; /* RX Bytes to order via TX */
|
||||
@@ -117,24 +115,6 @@ static inline int wait_reset(struct i2c_pnx_algo_data *data)
|
||||
return (timeout <= 0);
|
||||
}
|
||||
|
||||
static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
|
||||
{
|
||||
struct timer_list *timer = &alg_data->mif.timer;
|
||||
unsigned long expires = msecs_to_jiffies(alg_data->timeout);
|
||||
|
||||
if (expires <= 1)
|
||||
expires = 2;
|
||||
|
||||
del_timer_sync(timer);
|
||||
|
||||
dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %lu jiffies.\n",
|
||||
jiffies, expires);
|
||||
|
||||
timer->expires = jiffies + expires;
|
||||
|
||||
add_timer(timer);
|
||||
}
|
||||
|
||||
/**
|
||||
* i2c_pnx_start - start a device
|
||||
* @slave_addr: slave address
|
||||
@@ -259,8 +239,6 @@ static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
|
||||
~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
|
||||
I2C_REG_CTL(alg_data));
|
||||
|
||||
del_timer_sync(&alg_data->mif.timer);
|
||||
|
||||
dev_dbg(&alg_data->adapter.dev,
|
||||
"%s(): Waking up xfer routine.\n",
|
||||
__func__);
|
||||
@@ -276,8 +254,6 @@ static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
|
||||
~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
|
||||
I2C_REG_CTL(alg_data));
|
||||
|
||||
/* Stop timer. */
|
||||
del_timer_sync(&alg_data->mif.timer);
|
||||
dev_dbg(&alg_data->adapter.dev,
|
||||
"%s(): Waking up xfer routine after zero-xfer.\n",
|
||||
__func__);
|
||||
@@ -364,8 +340,6 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
|
||||
mcntrl_drmie | mcntrl_daie);
|
||||
iowrite32(ctl, I2C_REG_CTL(alg_data));
|
||||
|
||||
/* Kill timer. */
|
||||
del_timer_sync(&alg_data->mif.timer);
|
||||
complete(&alg_data->mif.complete);
|
||||
}
|
||||
}
|
||||
@@ -400,8 +374,6 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
|
||||
mcntrl_drmie);
|
||||
iowrite32(ctl, I2C_REG_CTL(alg_data));
|
||||
|
||||
/* Stop timer, to prevent timeout. */
|
||||
del_timer_sync(&alg_data->mif.timer);
|
||||
complete(&alg_data->mif.complete);
|
||||
} else if (stat & mstatus_nai) {
|
||||
/* Slave did not acknowledge, generate a STOP */
|
||||
@@ -419,8 +391,6 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
|
||||
/* Our return value. */
|
||||
alg_data->mif.ret = -EIO;
|
||||
|
||||
/* Stop timer, to prevent timeout. */
|
||||
del_timer_sync(&alg_data->mif.timer);
|
||||
complete(&alg_data->mif.complete);
|
||||
} else {
|
||||
/*
|
||||
@@ -453,9 +423,8 @@ static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void i2c_pnx_timeout(struct timer_list *t)
|
||||
static void i2c_pnx_timeout(struct i2c_pnx_algo_data *alg_data)
|
||||
{
|
||||
struct i2c_pnx_algo_data *alg_data = from_timer(alg_data, t, mif.timer);
|
||||
u32 ctl;
|
||||
|
||||
dev_err(&alg_data->adapter.dev,
|
||||
@@ -472,7 +441,6 @@ static void i2c_pnx_timeout(struct timer_list *t)
|
||||
iowrite32(ctl, I2C_REG_CTL(alg_data));
|
||||
wait_reset(alg_data);
|
||||
alg_data->mif.ret = -EIO;
|
||||
complete(&alg_data->mif.complete);
|
||||
}
|
||||
|
||||
static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data)
|
||||
@@ -514,6 +482,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
struct i2c_msg *pmsg;
|
||||
int rc = 0, completed = 0, i;
|
||||
struct i2c_pnx_algo_data *alg_data = adap->algo_data;
|
||||
unsigned long time_left;
|
||||
u32 stat;
|
||||
|
||||
dev_dbg(&alg_data->adapter.dev,
|
||||
@@ -548,7 +517,6 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n",
|
||||
__func__, alg_data->mif.mode, alg_data->mif.len);
|
||||
|
||||
i2c_pnx_arm_timer(alg_data);
|
||||
|
||||
/* initialize the completion var */
|
||||
init_completion(&alg_data->mif.complete);
|
||||
@@ -564,7 +532,10 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
break;
|
||||
|
||||
/* Wait for completion */
|
||||
wait_for_completion(&alg_data->mif.complete);
|
||||
time_left = wait_for_completion_timeout(&alg_data->mif.complete,
|
||||
alg_data->timeout);
|
||||
if (time_left == 0)
|
||||
i2c_pnx_timeout(alg_data);
|
||||
|
||||
if (!(rc = alg_data->mif.ret))
|
||||
completed++;
|
||||
@@ -657,7 +628,10 @@ static int i2c_pnx_probe(struct platform_device *pdev)
|
||||
alg_data->adapter.algo_data = alg_data;
|
||||
alg_data->adapter.nr = pdev->id;
|
||||
|
||||
alg_data->timeout = I2C_PNX_TIMEOUT_DEFAULT;
|
||||
alg_data->timeout = msecs_to_jiffies(I2C_PNX_TIMEOUT_DEFAULT);
|
||||
if (alg_data->timeout <= 1)
|
||||
alg_data->timeout = 2;
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
alg_data->adapter.dev.of_node = of_node_get(pdev->dev.of_node);
|
||||
if (pdev->dev.of_node) {
|
||||
@@ -677,8 +651,6 @@ static int i2c_pnx_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(alg_data->clk))
|
||||
return PTR_ERR(alg_data->clk);
|
||||
|
||||
timer_setup(&alg_data->mif.timer, i2c_pnx_timeout, 0);
|
||||
|
||||
snprintf(alg_data->adapter.name, sizeof(alg_data->adapter.name),
|
||||
"%s", pdev->name);
|
||||
|
||||
|
||||
@@ -218,6 +218,14 @@ static void rcar_i2c_init(struct rcar_i2c_priv *priv)
|
||||
|
||||
}
|
||||
|
||||
static void rcar_i2c_reset_slave(struct rcar_i2c_priv *priv)
|
||||
{
|
||||
rcar_i2c_write(priv, ICSIER, 0);
|
||||
rcar_i2c_write(priv, ICSSR, 0);
|
||||
rcar_i2c_write(priv, ICSCR, SDBS);
|
||||
rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
|
||||
}
|
||||
|
||||
static int rcar_i2c_bus_barrier(struct rcar_i2c_priv *priv)
|
||||
{
|
||||
int i;
|
||||
@@ -863,11 +871,8 @@ static int rcar_unreg_slave(struct i2c_client *slave)
|
||||
|
||||
/* ensure no irq is running before clearing ptr */
|
||||
disable_irq(priv->irq);
|
||||
rcar_i2c_write(priv, ICSIER, 0);
|
||||
rcar_i2c_write(priv, ICSSR, 0);
|
||||
rcar_i2c_reset_slave(priv);
|
||||
enable_irq(priv->irq);
|
||||
rcar_i2c_write(priv, ICSCR, SDBS);
|
||||
rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
|
||||
|
||||
priv->slave = NULL;
|
||||
|
||||
@@ -973,7 +978,9 @@ static int rcar_i2c_probe(struct platform_device *pdev)
|
||||
if (ret < 0)
|
||||
goto out_pm_put;
|
||||
|
||||
rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */
|
||||
/* Bring hardware to known state */
|
||||
rcar_i2c_init(priv);
|
||||
rcar_i2c_reset_slave(priv);
|
||||
|
||||
if (priv->devtype == I2C_RCAR_GEN3) {
|
||||
priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);
|
||||
|
||||
@@ -159,6 +159,8 @@ static int ad7266_read_raw(struct iio_dev *indio_dev,
|
||||
ret = ad7266_read_single(st, val, chan->address);
|
||||
iio_device_release_direct_mode(indio_dev);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
*val = (*val >> 2) & 0xfff;
|
||||
if (chan->scan_type.sign == 's')
|
||||
*val = sign_extend32(*val, 11);
|
||||
|
||||
@@ -54,7 +54,9 @@
|
||||
#define BME680_NB_CONV_MASK GENMASK(3, 0)
|
||||
|
||||
#define BME680_REG_MEAS_STAT_0 0x1D
|
||||
#define BME680_NEW_DATA_BIT BIT(7)
|
||||
#define BME680_GAS_MEAS_BIT BIT(6)
|
||||
#define BME680_MEAS_BIT BIT(5)
|
||||
|
||||
/* Calibration Parameters */
|
||||
#define BME680_T2_LSB_REG 0x8A
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/log2.h>
|
||||
@@ -38,7 +39,7 @@ struct bme680_calib {
|
||||
s8 par_h3;
|
||||
s8 par_h4;
|
||||
s8 par_h5;
|
||||
s8 par_h6;
|
||||
u8 par_h6;
|
||||
s8 par_h7;
|
||||
s8 par_gh1;
|
||||
s16 par_gh2;
|
||||
@@ -334,10 +335,10 @@ static s16 bme680_compensate_temp(struct bme680_data *data,
|
||||
if (!calib->par_t2)
|
||||
bme680_read_calib(data, calib);
|
||||
|
||||
var1 = (adc_temp >> 3) - (calib->par_t1 << 1);
|
||||
var1 = (adc_temp >> 3) - ((s32)calib->par_t1 << 1);
|
||||
var2 = (var1 * calib->par_t2) >> 11;
|
||||
var3 = ((var1 >> 1) * (var1 >> 1)) >> 12;
|
||||
var3 = (var3 * (calib->par_t3 << 4)) >> 14;
|
||||
var3 = (var3 * ((s32)calib->par_t3 << 4)) >> 14;
|
||||
data->t_fine = var2 + var3;
|
||||
calc_temp = (data->t_fine * 5 + 128) >> 8;
|
||||
|
||||
@@ -360,9 +361,9 @@ static u32 bme680_compensate_press(struct bme680_data *data,
|
||||
var1 = (data->t_fine >> 1) - 64000;
|
||||
var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * calib->par_p6) >> 2;
|
||||
var2 = var2 + (var1 * calib->par_p5 << 1);
|
||||
var2 = (var2 >> 2) + (calib->par_p4 << 16);
|
||||
var2 = (var2 >> 2) + ((s32)calib->par_p4 << 16);
|
||||
var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) *
|
||||
(calib->par_p3 << 5)) >> 3) +
|
||||
((s32)calib->par_p3 << 5)) >> 3) +
|
||||
((calib->par_p2 * var1) >> 1);
|
||||
var1 = var1 >> 18;
|
||||
var1 = ((32768 + var1) * calib->par_p1) >> 15;
|
||||
@@ -380,7 +381,7 @@ static u32 bme680_compensate_press(struct bme680_data *data,
|
||||
var3 = ((press_comp >> 8) * (press_comp >> 8) *
|
||||
(press_comp >> 8) * calib->par_p10) >> 17;
|
||||
|
||||
press_comp += (var1 + var2 + var3 + (calib->par_p7 << 7)) >> 4;
|
||||
press_comp += (var1 + var2 + var3 + ((s32)calib->par_p7 << 7)) >> 4;
|
||||
|
||||
return press_comp;
|
||||
}
|
||||
@@ -406,7 +407,7 @@ static u32 bme680_compensate_humid(struct bme680_data *data,
|
||||
(((temp_scaled * ((temp_scaled * calib->par_h5) / 100))
|
||||
>> 6) / 100) + (1 << 14))) >> 10;
|
||||
var3 = var1 * var2;
|
||||
var4 = calib->par_h6 << 7;
|
||||
var4 = (s32)calib->par_h6 << 7;
|
||||
var4 = (var4 + ((temp_scaled * calib->par_h7) / 100)) >> 4;
|
||||
var5 = ((var3 >> 14) * (var3 >> 14)) >> 10;
|
||||
var6 = (var4 * var5) >> 1;
|
||||
@@ -524,6 +525,43 @@ static u8 bme680_oversampling_to_reg(u8 val)
|
||||
return ilog2(val) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Taken from Bosch BME680 API:
|
||||
* https://github.com/boschsensortec/BME68x_SensorAPI/blob/v4.4.8/bme68x.c#L490
|
||||
*/
|
||||
static int bme680_wait_for_eoc(struct bme680_data *data)
|
||||
{
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
unsigned int check;
|
||||
int ret;
|
||||
/*
|
||||
* (Sum of oversampling ratios * time per oversampling) +
|
||||
* TPH measurement + gas measurement + wait transition from forced mode
|
||||
* + heater duration
|
||||
*/
|
||||
int wait_eoc_us = ((data->oversampling_temp + data->oversampling_press +
|
||||
data->oversampling_humid) * 1936) + (477 * 4) +
|
||||
(477 * 5) + 1000 + (data->heater_dur * 1000);
|
||||
|
||||
usleep_range(wait_eoc_us, wait_eoc_us + 100);
|
||||
|
||||
ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &check);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to read measurement status register.\n");
|
||||
return ret;
|
||||
}
|
||||
if (check & BME680_MEAS_BIT) {
|
||||
dev_err(dev, "Device measurement cycle incomplete.\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
if (!(check & BME680_NEW_DATA_BIT)) {
|
||||
dev_err(dev, "No new data available from the device.\n");
|
||||
return -ENODATA;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bme680_chip_config(struct bme680_data *data)
|
||||
{
|
||||
struct device *dev = regmap_get_device(data->regmap);
|
||||
@@ -614,6 +652,10 @@ static int bme680_read_temp(struct bme680_data *data, int *val)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = bme680_wait_for_eoc(data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, BME680_REG_TEMP_MSB,
|
||||
(u8 *) &tmp, 3);
|
||||
if (ret < 0) {
|
||||
@@ -670,7 +712,7 @@ static int bme680_read_press(struct bme680_data *data,
|
||||
}
|
||||
|
||||
*val = bme680_compensate_press(data, adc_press);
|
||||
*val2 = 100;
|
||||
*val2 = 1000;
|
||||
return IIO_VAL_FRACTIONAL;
|
||||
}
|
||||
|
||||
@@ -730,6 +772,10 @@ static int bme680_read_gas(struct bme680_data *data,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = bme680_wait_for_eoc(data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &check);
|
||||
if (check & BME680_GAS_MEAS_BIT) {
|
||||
dev_err(dev, "gas measurement incomplete\n");
|
||||
|
||||
@@ -157,7 +157,6 @@ static void ad5592r_gpio_cleanup(struct ad5592r_state *st)
|
||||
static int ad5592r_reset(struct ad5592r_state *st)
|
||||
{
|
||||
struct gpio_desc *gpio;
|
||||
struct iio_dev *iio_dev = iio_priv_to_dev(st);
|
||||
|
||||
gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(gpio))
|
||||
@@ -167,10 +166,10 @@ static int ad5592r_reset(struct ad5592r_state *st)
|
||||
udelay(1);
|
||||
gpiod_set_value(gpio, 1);
|
||||
} else {
|
||||
mutex_lock(&iio_dev->mlock);
|
||||
mutex_lock(&st->lock);
|
||||
/* Writing this magic value resets the device */
|
||||
st->ops->reg_write(st, AD5592R_REG_RESET, 0xdac);
|
||||
mutex_unlock(&iio_dev->mlock);
|
||||
mutex_unlock(&st->lock);
|
||||
}
|
||||
|
||||
udelay(250);
|
||||
@@ -198,7 +197,6 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
|
||||
const struct ad5592r_rw_ops *ops = st->ops;
|
||||
int ret;
|
||||
unsigned i;
|
||||
struct iio_dev *iio_dev = iio_priv_to_dev(st);
|
||||
u8 pulldown = 0, tristate = 0, dac = 0, adc = 0;
|
||||
u16 read_back;
|
||||
|
||||
@@ -248,7 +246,7 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&iio_dev->mlock);
|
||||
mutex_lock(&st->lock);
|
||||
|
||||
/* Pull down unused pins to GND */
|
||||
ret = ops->reg_write(st, AD5592R_REG_PULLDOWN, pulldown);
|
||||
@@ -286,7 +284,7 @@ static int ad5592r_set_channel_modes(struct ad5592r_state *st)
|
||||
ret = -EIO;
|
||||
|
||||
err_unlock:
|
||||
mutex_unlock(&iio_dev->mlock);
|
||||
mutex_unlock(&st->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -315,11 +313,11 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev,
|
||||
if (!chan->output)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&iio_dev->mlock);
|
||||
mutex_lock(&st->lock);
|
||||
ret = st->ops->write_dac(st, chan->channel, val);
|
||||
if (!ret)
|
||||
st->cached_dac[chan->channel] = val;
|
||||
mutex_unlock(&iio_dev->mlock);
|
||||
mutex_unlock(&st->lock);
|
||||
return ret;
|
||||
case IIO_CHAN_INFO_SCALE:
|
||||
if (chan->type == IIO_VOLTAGE) {
|
||||
@@ -334,12 +332,12 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev,
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&iio_dev->mlock);
|
||||
mutex_lock(&st->lock);
|
||||
|
||||
ret = st->ops->reg_read(st, AD5592R_REG_CTRL,
|
||||
&st->cached_gp_ctrl);
|
||||
if (ret < 0) {
|
||||
mutex_unlock(&iio_dev->mlock);
|
||||
mutex_unlock(&st->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -361,7 +359,7 @@ static int ad5592r_write_raw(struct iio_dev *iio_dev,
|
||||
|
||||
ret = st->ops->reg_write(st, AD5592R_REG_CTRL,
|
||||
st->cached_gp_ctrl);
|
||||
mutex_unlock(&iio_dev->mlock);
|
||||
mutex_unlock(&st->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -379,11 +377,11 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
|
||||
{
|
||||
struct ad5592r_state *st = iio_priv(iio_dev);
|
||||
u16 read_val;
|
||||
int ret;
|
||||
int ret, mult;
|
||||
|
||||
switch (m) {
|
||||
case IIO_CHAN_INFO_RAW:
|
||||
mutex_lock(&iio_dev->mlock);
|
||||
mutex_lock(&st->lock);
|
||||
|
||||
if (!chan->output) {
|
||||
ret = st->ops->read_adc(st, chan->channel, &read_val);
|
||||
@@ -416,29 +414,27 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
|
||||
s64 tmp = *val * (3767897513LL / 25LL);
|
||||
*val = div_s64_rem(tmp, 1000000000LL, val2);
|
||||
|
||||
return IIO_VAL_INT_PLUS_MICRO;
|
||||
} else {
|
||||
int mult;
|
||||
|
||||
mutex_lock(&iio_dev->mlock);
|
||||
|
||||
if (chan->output)
|
||||
mult = !!(st->cached_gp_ctrl &
|
||||
AD5592R_REG_CTRL_DAC_RANGE);
|
||||
else
|
||||
mult = !!(st->cached_gp_ctrl &
|
||||
AD5592R_REG_CTRL_ADC_RANGE);
|
||||
|
||||
*val *= ++mult;
|
||||
|
||||
*val2 = chan->scan_type.realbits;
|
||||
ret = IIO_VAL_FRACTIONAL_LOG2;
|
||||
return IIO_VAL_INT_PLUS_NANO;
|
||||
}
|
||||
|
||||
mutex_lock(&st->lock);
|
||||
|
||||
if (chan->output)
|
||||
mult = !!(st->cached_gp_ctrl &
|
||||
AD5592R_REG_CTRL_DAC_RANGE);
|
||||
else
|
||||
mult = !!(st->cached_gp_ctrl &
|
||||
AD5592R_REG_CTRL_ADC_RANGE);
|
||||
|
||||
*val *= ++mult;
|
||||
|
||||
*val2 = chan->scan_type.realbits;
|
||||
ret = IIO_VAL_FRACTIONAL_LOG2;
|
||||
break;
|
||||
case IIO_CHAN_INFO_OFFSET:
|
||||
ret = ad5592r_get_vref(st);
|
||||
|
||||
mutex_lock(&iio_dev->mlock);
|
||||
mutex_lock(&st->lock);
|
||||
|
||||
if (st->cached_gp_ctrl & AD5592R_REG_CTRL_ADC_RANGE)
|
||||
*val = (-34365 * 25) / ret;
|
||||
@@ -451,7 +447,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev,
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&iio_dev->mlock);
|
||||
mutex_unlock(&st->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -626,6 +622,8 @@ int ad5592r_probe(struct device *dev, const char *name,
|
||||
iio_dev->info = &ad5592r_info;
|
||||
iio_dev->modes = INDIO_DIRECT_MODE;
|
||||
|
||||
mutex_init(&st->lock);
|
||||
|
||||
ad5592r_init_scales(st, ad5592r_get_vref(st));
|
||||
|
||||
ret = ad5592r_reset(st);
|
||||
|
||||
@@ -52,6 +52,7 @@ struct ad5592r_state {
|
||||
struct regulator *reg;
|
||||
struct gpio_chip gpiochip;
|
||||
struct mutex gpio_lock; /* Protect cached gpio_out, gpio_val, etc. */
|
||||
struct mutex lock;
|
||||
unsigned int num_channels;
|
||||
const struct ad5592r_rw_ops *ops;
|
||||
int scale_avail[2][2];
|
||||
|
||||
@@ -63,6 +63,8 @@ MODULE_AUTHOR("Roland Dreier");
|
||||
MODULE_DESCRIPTION("InfiniBand userspace MAD packet access");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
#define MAX_UMAD_RECV_LIST_SIZE 200000
|
||||
|
||||
enum {
|
||||
IB_UMAD_MAX_PORTS = RDMA_MAX_PORTS,
|
||||
IB_UMAD_MAX_AGENTS = 32,
|
||||
@@ -113,6 +115,7 @@ struct ib_umad_file {
|
||||
struct mutex mutex;
|
||||
struct ib_umad_port *port;
|
||||
struct list_head recv_list;
|
||||
atomic_t recv_list_size;
|
||||
struct list_head send_list;
|
||||
struct list_head port_list;
|
||||
spinlock_t send_lock;
|
||||
@@ -180,24 +183,28 @@ static struct ib_mad_agent *__get_agent(struct ib_umad_file *file, int id)
|
||||
return file->agents_dead ? NULL : file->agent[id];
|
||||
}
|
||||
|
||||
static int queue_packet(struct ib_umad_file *file,
|
||||
struct ib_mad_agent *agent,
|
||||
struct ib_umad_packet *packet)
|
||||
static int queue_packet(struct ib_umad_file *file, struct ib_mad_agent *agent,
|
||||
struct ib_umad_packet *packet, bool is_recv_mad)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
mutex_lock(&file->mutex);
|
||||
|
||||
if (is_recv_mad &&
|
||||
atomic_read(&file->recv_list_size) > MAX_UMAD_RECV_LIST_SIZE)
|
||||
goto unlock;
|
||||
|
||||
for (packet->mad.hdr.id = 0;
|
||||
packet->mad.hdr.id < IB_UMAD_MAX_AGENTS;
|
||||
packet->mad.hdr.id++)
|
||||
if (agent == __get_agent(file, packet->mad.hdr.id)) {
|
||||
list_add_tail(&packet->list, &file->recv_list);
|
||||
atomic_inc(&file->recv_list_size);
|
||||
wake_up_interruptible(&file->recv_wait);
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&file->mutex);
|
||||
|
||||
return ret;
|
||||
@@ -224,7 +231,7 @@ static void send_handler(struct ib_mad_agent *agent,
|
||||
if (send_wc->status == IB_WC_RESP_TIMEOUT_ERR) {
|
||||
packet->length = IB_MGMT_MAD_HDR;
|
||||
packet->mad.hdr.status = ETIMEDOUT;
|
||||
if (!queue_packet(file, agent, packet))
|
||||
if (!queue_packet(file, agent, packet, false))
|
||||
return;
|
||||
}
|
||||
kfree(packet);
|
||||
@@ -284,7 +291,7 @@ static void recv_handler(struct ib_mad_agent *agent,
|
||||
rdma_destroy_ah_attr(&ah_attr);
|
||||
}
|
||||
|
||||
if (queue_packet(file, agent, packet))
|
||||
if (queue_packet(file, agent, packet, true))
|
||||
goto err2;
|
||||
return;
|
||||
|
||||
@@ -409,6 +416,7 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
|
||||
|
||||
packet = list_entry(file->recv_list.next, struct ib_umad_packet, list);
|
||||
list_del(&packet->list);
|
||||
atomic_dec(&file->recv_list_size);
|
||||
|
||||
mutex_unlock(&file->mutex);
|
||||
|
||||
@@ -421,6 +429,7 @@ static ssize_t ib_umad_read(struct file *filp, char __user *buf,
|
||||
/* Requeue packet */
|
||||
mutex_lock(&file->mutex);
|
||||
list_add(&packet->list, &file->recv_list);
|
||||
atomic_inc(&file->recv_list_size);
|
||||
mutex_unlock(&file->mutex);
|
||||
} else {
|
||||
if (packet->recv_wc)
|
||||
|
||||
@@ -12,8 +12,10 @@
|
||||
/* #define DEBUG */
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/overflow.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
@@ -318,9 +320,8 @@ int input_ff_create(struct input_dev *dev, unsigned int max_effects)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ff_dev_size = sizeof(struct ff_device) +
|
||||
max_effects * sizeof(struct file *);
|
||||
if (ff_dev_size < max_effects) /* overflow */
|
||||
ff_dev_size = struct_size(ff, effect_owners, max_effects);
|
||||
if (ff_dev_size == SIZE_MAX) /* overflow */
|
||||
return -EINVAL;
|
||||
|
||||
ff = kzalloc(ff_dev_size, GFP_KERNEL);
|
||||
|
||||
@@ -1358,19 +1358,19 @@ static int input_print_modalias_bits(char *buf, int size,
|
||||
char name, unsigned long *bm,
|
||||
unsigned int min_bit, unsigned int max_bit)
|
||||
{
|
||||
int len = 0, i;
|
||||
int bit = min_bit;
|
||||
int len = 0;
|
||||
|
||||
len += snprintf(buf, max(size, 0), "%c", name);
|
||||
for (i = min_bit; i < max_bit; i++)
|
||||
if (bm[BIT_WORD(i)] & BIT_MASK(i))
|
||||
len += snprintf(buf + len, max(size - len, 0), "%X,", i);
|
||||
for_each_set_bit_from(bit, bm, max_bit)
|
||||
len += snprintf(buf + len, max(size - len, 0), "%X,", bit);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int input_print_modalias(char *buf, int size, struct input_dev *id,
|
||||
int add_cr)
|
||||
static int input_print_modalias_parts(char *buf, int size, int full_len,
|
||||
struct input_dev *id)
|
||||
{
|
||||
int len;
|
||||
int len, klen, remainder, space;
|
||||
|
||||
len = snprintf(buf, max(size, 0),
|
||||
"input:b%04Xv%04Xp%04Xe%04X-",
|
||||
@@ -1379,8 +1379,49 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
|
||||
|
||||
len += input_print_modalias_bits(buf + len, size - len,
|
||||
'e', id->evbit, 0, EV_MAX);
|
||||
len += input_print_modalias_bits(buf + len, size - len,
|
||||
|
||||
/*
|
||||
* Calculate the remaining space in the buffer making sure we
|
||||
* have place for the terminating 0.
|
||||
*/
|
||||
space = max(size - (len + 1), 0);
|
||||
|
||||
klen = input_print_modalias_bits(buf + len, size - len,
|
||||
'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
|
||||
len += klen;
|
||||
|
||||
/*
|
||||
* If we have more data than we can fit in the buffer, check
|
||||
* if we can trim key data to fit in the rest. We will indicate
|
||||
* that key data is incomplete by adding "+" sign at the end, like
|
||||
* this: * "k1,2,3,45,+,".
|
||||
*
|
||||
* Note that we shortest key info (if present) is "k+," so we
|
||||
* can only try to trim if key data is longer than that.
|
||||
*/
|
||||
if (full_len && size < full_len + 1 && klen > 3) {
|
||||
remainder = full_len - len;
|
||||
/*
|
||||
* We can only trim if we have space for the remainder
|
||||
* and also for at least "k+," which is 3 more characters.
|
||||
*/
|
||||
if (remainder <= space - 3) {
|
||||
int i;
|
||||
/*
|
||||
* We are guaranteed to have 'k' in the buffer, so
|
||||
* we need at least 3 additional bytes for storing
|
||||
* "+," in addition to the remainder.
|
||||
*/
|
||||
for (i = size - 1 - remainder - 3; i >= 0; i--) {
|
||||
if (buf[i] == 'k' || buf[i] == ',') {
|
||||
strcpy(buf + i + 1, "+,");
|
||||
len = i + 3; /* Not counting '\0' */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
len += input_print_modalias_bits(buf + len, size - len,
|
||||
'r', id->relbit, 0, REL_MAX);
|
||||
len += input_print_modalias_bits(buf + len, size - len,
|
||||
@@ -1396,12 +1437,25 @@ static int input_print_modalias(char *buf, int size, struct input_dev *id,
|
||||
len += input_print_modalias_bits(buf + len, size - len,
|
||||
'w', id->swbit, 0, SW_MAX);
|
||||
|
||||
if (add_cr)
|
||||
len += snprintf(buf + len, max(size - len, 0), "\n");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int input_print_modalias(char *buf, int size, struct input_dev *id)
|
||||
{
|
||||
int full_len;
|
||||
|
||||
/*
|
||||
* Printing is done in 2 passes: first one figures out total length
|
||||
* needed for the modalias string, second one will try to trim key
|
||||
* data in case when buffer is too small for the entire modalias.
|
||||
* If the buffer is too small regardless, it will fill as much as it
|
||||
* can (without trimming key data) into the buffer and leave it to
|
||||
* the caller to figure out what to do with the result.
|
||||
*/
|
||||
full_len = input_print_modalias_parts(NULL, 0, 0, id);
|
||||
return input_print_modalias_parts(buf, size, full_len, id);
|
||||
}
|
||||
|
||||
static ssize_t input_dev_show_modalias(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
@@ -1409,7 +1463,9 @@ static ssize_t input_dev_show_modalias(struct device *dev,
|
||||
struct input_dev *id = to_input_dev(dev);
|
||||
ssize_t len;
|
||||
|
||||
len = input_print_modalias(buf, PAGE_SIZE, id, 1);
|
||||
len = input_print_modalias(buf, PAGE_SIZE, id);
|
||||
if (len < PAGE_SIZE - 2)
|
||||
len += snprintf(buf + len, PAGE_SIZE - len, "\n");
|
||||
|
||||
return min_t(int, len, PAGE_SIZE);
|
||||
}
|
||||
@@ -1584,6 +1640,23 @@ static int input_add_uevent_bm_var(struct kobj_uevent_env *env,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a pretty gross hack. When building uevent data the driver core
|
||||
* may try adding more environment variables to kobj_uevent_env without
|
||||
* telling us, so we have no idea how much of the buffer we can use to
|
||||
* avoid overflows/-ENOMEM elsewhere. To work around this let's artificially
|
||||
* reduce amount of memory we will use for the modalias environment variable.
|
||||
*
|
||||
* The potential additions are:
|
||||
*
|
||||
* SEQNUM=18446744073709551615 - (%llu - 28 bytes)
|
||||
* HOME=/ (6 bytes)
|
||||
* PATH=/sbin:/bin:/usr/sbin:/usr/bin (34 bytes)
|
||||
*
|
||||
* 68 bytes total. Allow extra buffer - 96 bytes
|
||||
*/
|
||||
#define UEVENT_ENV_EXTRA_LEN 96
|
||||
|
||||
static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
|
||||
struct input_dev *dev)
|
||||
{
|
||||
@@ -1593,9 +1666,11 @@ static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
|
||||
return -ENOMEM;
|
||||
|
||||
len = input_print_modalias(&env->buf[env->buflen - 1],
|
||||
sizeof(env->buf) - env->buflen,
|
||||
dev, 0);
|
||||
if (len >= (sizeof(env->buf) - env->buflen))
|
||||
(int)sizeof(env->buf) - env->buflen -
|
||||
UEVENT_ENV_EXTRA_LEN,
|
||||
dev);
|
||||
if (len >= ((int)sizeof(env->buf) - env->buflen -
|
||||
UEVENT_ENV_EXTRA_LEN))
|
||||
return -ENOMEM;
|
||||
|
||||
env->buflen += len;
|
||||
|
||||
@@ -1476,16 +1476,47 @@ static void elantech_disconnect(struct psmouse *psmouse)
|
||||
psmouse->private = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some hw_version 4 models fail to properly activate absolute mode on
|
||||
* resume without going through disable/enable cycle.
|
||||
*/
|
||||
static const struct dmi_system_id elantech_needs_reenable[] = {
|
||||
#if defined(CONFIG_DMI) && defined(CONFIG_X86)
|
||||
{
|
||||
/* Lenovo N24 */
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "81AF"),
|
||||
},
|
||||
},
|
||||
#endif
|
||||
{ }
|
||||
};
|
||||
|
||||
/*
|
||||
* Put the touchpad back into absolute mode when reconnecting
|
||||
*/
|
||||
static int elantech_reconnect(struct psmouse *psmouse)
|
||||
{
|
||||
int err;
|
||||
|
||||
psmouse_reset(psmouse);
|
||||
|
||||
if (elantech_detect(psmouse, 0))
|
||||
return -1;
|
||||
|
||||
if (dmi_check_system(elantech_needs_reenable)) {
|
||||
err = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_DISABLE);
|
||||
if (err)
|
||||
psmouse_warn(psmouse, "failed to deactivate mouse on %s: %d\n",
|
||||
psmouse->ps2dev.serio->phys, err);
|
||||
|
||||
err = ps2_command(&psmouse->ps2dev, NULL, PSMOUSE_CMD_ENABLE);
|
||||
if (err)
|
||||
psmouse_warn(psmouse, "failed to reactivate mouse on %s: %d\n",
|
||||
psmouse->ps2dev.serio->phys, err);
|
||||
}
|
||||
|
||||
if (elantech_set_absolute_mode(psmouse)) {
|
||||
psmouse_err(psmouse,
|
||||
"failed to put touchpad back into absolute mode.\n");
|
||||
|
||||
@@ -70,7 +70,6 @@ struct silead_ts_data {
|
||||
struct regulator_bulk_data regulators[2];
|
||||
char fw_name[64];
|
||||
struct touchscreen_properties prop;
|
||||
u32 max_fingers;
|
||||
u32 chip_id;
|
||||
struct input_mt_pos pos[SILEAD_MAX_FINGERS];
|
||||
int slots[SILEAD_MAX_FINGERS];
|
||||
@@ -98,7 +97,7 @@ static int silead_ts_request_input_dev(struct silead_ts_data *data)
|
||||
input_set_abs_params(data->input, ABS_MT_POSITION_Y, 0, 4095, 0, 0);
|
||||
touchscreen_parse_properties(data->input, true, &data->prop);
|
||||
|
||||
input_mt_init_slots(data->input, data->max_fingers,
|
||||
input_mt_init_slots(data->input, SILEAD_MAX_FINGERS,
|
||||
INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED |
|
||||
INPUT_MT_TRACK);
|
||||
|
||||
@@ -145,10 +144,10 @@ static void silead_ts_read_data(struct i2c_client *client)
|
||||
return;
|
||||
}
|
||||
|
||||
if (buf[0] > data->max_fingers) {
|
||||
if (buf[0] > SILEAD_MAX_FINGERS) {
|
||||
dev_warn(dev, "More touches reported then supported %d > %d\n",
|
||||
buf[0], data->max_fingers);
|
||||
buf[0] = data->max_fingers;
|
||||
buf[0], SILEAD_MAX_FINGERS);
|
||||
buf[0] = SILEAD_MAX_FINGERS;
|
||||
}
|
||||
|
||||
touch_nr = 0;
|
||||
@@ -200,7 +199,6 @@ static void silead_ts_read_data(struct i2c_client *client)
|
||||
|
||||
static int silead_ts_init(struct i2c_client *client)
|
||||
{
|
||||
struct silead_ts_data *data = i2c_get_clientdata(client);
|
||||
int error;
|
||||
|
||||
error = i2c_smbus_write_byte_data(client, SILEAD_REG_RESET,
|
||||
@@ -210,7 +208,7 @@ static int silead_ts_init(struct i2c_client *client)
|
||||
usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
|
||||
|
||||
error = i2c_smbus_write_byte_data(client, SILEAD_REG_TOUCH_NR,
|
||||
data->max_fingers);
|
||||
SILEAD_MAX_FINGERS);
|
||||
if (error)
|
||||
goto i2c_write_err;
|
||||
usleep_range(SILEAD_CMD_SLEEP_MIN, SILEAD_CMD_SLEEP_MAX);
|
||||
@@ -437,13 +435,6 @@ static void silead_ts_read_props(struct i2c_client *client)
|
||||
const char *str;
|
||||
int error;
|
||||
|
||||
error = device_property_read_u32(dev, "silead,max-fingers",
|
||||
&data->max_fingers);
|
||||
if (error) {
|
||||
dev_dbg(dev, "Max fingers read error %d\n", error);
|
||||
data->max_fingers = 5; /* Most devices handle up-to 5 fingers */
|
||||
}
|
||||
|
||||
error = device_property_read_string(dev, "firmware-name", &str);
|
||||
if (!error)
|
||||
snprintf(data->fw_name, sizeof(data->fw_name),
|
||||
|
||||
@@ -1410,8 +1410,17 @@ static int __init init_iommu_from_acpi(struct amd_iommu *iommu,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __init free_sysfs(struct amd_iommu *iommu)
|
||||
{
|
||||
if (iommu->iommu.dev) {
|
||||
iommu_device_unregister(&iommu->iommu);
|
||||
iommu_device_sysfs_remove(&iommu->iommu);
|
||||
}
|
||||
}
|
||||
|
||||
static void __init free_iommu_one(struct amd_iommu *iommu)
|
||||
{
|
||||
free_sysfs(iommu);
|
||||
free_command_buffer(iommu);
|
||||
free_event_buffer(iommu);
|
||||
free_ppr_log(iommu);
|
||||
|
||||
@@ -974,7 +974,7 @@ int dvb_usercopy(struct file *file,
|
||||
int (*func)(struct file *file,
|
||||
unsigned int cmd, void *arg))
|
||||
{
|
||||
char sbuf[128];
|
||||
char sbuf[128] = {};
|
||||
void *mbuf = NULL;
|
||||
void *parg = NULL;
|
||||
int err = -EINVAL;
|
||||
|
||||
@@ -174,6 +174,6 @@ struct as10x_register_addr {
|
||||
uint32_t addr;
|
||||
/* register mode access */
|
||||
uint8_t mode;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -410,6 +410,7 @@ static int tda10048_set_if(struct dvb_frontend *fe, u32 bw)
|
||||
struct tda10048_config *config = &state->config;
|
||||
int i;
|
||||
u32 if_freq_khz;
|
||||
u64 sample_freq;
|
||||
|
||||
dprintk(1, "%s(bw = %d)\n", __func__, bw);
|
||||
|
||||
@@ -451,9 +452,11 @@ static int tda10048_set_if(struct dvb_frontend *fe, u32 bw)
|
||||
dprintk(1, "- pll_pfactor = %d\n", state->pll_pfactor);
|
||||
|
||||
/* Calculate the sample frequency */
|
||||
state->sample_freq = state->xtal_hz * (state->pll_mfactor + 45);
|
||||
state->sample_freq /= (state->pll_nfactor + 1);
|
||||
state->sample_freq /= (state->pll_pfactor + 4);
|
||||
sample_freq = state->xtal_hz;
|
||||
sample_freq *= state->pll_mfactor + 45;
|
||||
do_div(sample_freq, state->pll_nfactor + 1);
|
||||
do_div(sample_freq, state->pll_pfactor + 4);
|
||||
state->sample_freq = sample_freq;
|
||||
dprintk(1, "- sample_freq = %d\n", state->sample_freq);
|
||||
|
||||
/* Update the I/F */
|
||||
|
||||
@@ -331,7 +331,7 @@ static int CalcMainPLL(struct tda_state *state, u32 freq)
|
||||
|
||||
OscFreq = (u64) freq * (u64) Div;
|
||||
OscFreq *= (u64) 16384;
|
||||
do_div(OscFreq, (u64)16000000);
|
||||
do_div(OscFreq, 16000000);
|
||||
MainDiv = OscFreq;
|
||||
|
||||
state->m_Regs[MPD] = PostDiv & 0x77;
|
||||
@@ -355,7 +355,7 @@ static int CalcCalPLL(struct tda_state *state, u32 freq)
|
||||
OscFreq = (u64)freq * (u64)Div;
|
||||
/* CalDiv = u32( OscFreq * 16384 / 16000000 ); */
|
||||
OscFreq *= (u64)16384;
|
||||
do_div(OscFreq, (u64)16000000);
|
||||
do_div(OscFreq, 16000000);
|
||||
CalDiv = OscFreq;
|
||||
|
||||
state->m_Regs[CPD] = PostDiv;
|
||||
|
||||
@@ -2424,7 +2424,12 @@ static int stk9090m_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &stk9090m_config);
|
||||
|
||||
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
|
||||
if (!adap->fe_adap[0].fe) {
|
||||
release_firmware(state->frontend_firmware);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dib9090_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
@@ -2497,8 +2502,10 @@ static int nim9090md_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, 0x80);
|
||||
adap->fe_adap[0].fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &nim9090md_config[0]);
|
||||
|
||||
if (adap->fe_adap[0].fe == NULL)
|
||||
if (!adap->fe_adap[0].fe) {
|
||||
release_firmware(state->frontend_firmware);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
i2c = dib9000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_3_4, 0);
|
||||
dib9000_i2c_enumeration(i2c, 1, 0x12, 0x82);
|
||||
@@ -2506,7 +2513,12 @@ static int nim9090md_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
fe_slave = dvb_attach(dib9000_attach, i2c, 0x82, &nim9090md_config[1]);
|
||||
dib9000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
|
||||
|
||||
return fe_slave == NULL ? -ENODEV : 0;
|
||||
if (!fe_slave) {
|
||||
release_firmware(state->frontend_firmware);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
@@ -716,6 +716,7 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
struct dw2102_state *state;
|
||||
int j;
|
||||
|
||||
if (!d)
|
||||
return -ENODEV;
|
||||
@@ -729,11 +730,11 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
switch (num) {
|
||||
case 1:
|
||||
switch (msg[0].addr) {
|
||||
j = 0;
|
||||
while (j < num) {
|
||||
switch (msg[j].addr) {
|
||||
case SU3000_STREAM_CTRL:
|
||||
state->data[0] = msg[0].buf[0] + 0x36;
|
||||
state->data[0] = msg[j].buf[0] + 0x36;
|
||||
state->data[1] = 3;
|
||||
state->data[2] = 0;
|
||||
if (dvb_usb_generic_rw(d, state->data, 3,
|
||||
@@ -745,61 +746,86 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
|
||||
if (dvb_usb_generic_rw(d, state->data, 1,
|
||||
state->data, 2, 0) < 0)
|
||||
err("i2c transfer failed.");
|
||||
msg[0].buf[1] = state->data[0];
|
||||
msg[0].buf[0] = state->data[1];
|
||||
msg[j].buf[1] = state->data[0];
|
||||
msg[j].buf[0] = state->data[1];
|
||||
break;
|
||||
default:
|
||||
if (3 + msg[0].len > sizeof(state->data)) {
|
||||
warn("i2c wr: len=%d is too big!\n",
|
||||
msg[0].len);
|
||||
/* if the current write msg is followed by a another
|
||||
* read msg to/from the same address
|
||||
*/
|
||||
if ((j+1 < num) && (msg[j+1].flags & I2C_M_RD) &&
|
||||
(msg[j].addr == msg[j+1].addr)) {
|
||||
/* join both i2c msgs to one usb read command */
|
||||
if (4 + msg[j].len > sizeof(state->data)) {
|
||||
warn("i2c combined wr/rd: write len=%d is too big!\n",
|
||||
msg[j].len);
|
||||
num = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
if (1 + msg[j+1].len > sizeof(state->data)) {
|
||||
warn("i2c combined wr/rd: read len=%d is too big!\n",
|
||||
msg[j+1].len);
|
||||
num = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
state->data[0] = 0x09;
|
||||
state->data[1] = msg[j].len;
|
||||
state->data[2] = msg[j+1].len;
|
||||
state->data[3] = msg[j].addr;
|
||||
memcpy(&state->data[4], msg[j].buf, msg[j].len);
|
||||
|
||||
if (dvb_usb_generic_rw(d, state->data, msg[j].len + 4,
|
||||
state->data, msg[j+1].len + 1, 0) < 0)
|
||||
err("i2c transfer failed.");
|
||||
|
||||
memcpy(msg[j+1].buf, &state->data[1], msg[j+1].len);
|
||||
j++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg[j].flags & I2C_M_RD) {
|
||||
/* single read */
|
||||
if (4 + msg[j].len > sizeof(state->data)) {
|
||||
warn("i2c rd: len=%d is too big!\n", msg[j].len);
|
||||
num = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
state->data[0] = 0x09;
|
||||
state->data[1] = 0;
|
||||
state->data[2] = msg[j].len;
|
||||
state->data[3] = msg[j].addr;
|
||||
memcpy(&state->data[4], msg[j].buf, msg[j].len);
|
||||
|
||||
if (dvb_usb_generic_rw(d, state->data, 4,
|
||||
state->data, msg[j].len + 1, 0) < 0)
|
||||
err("i2c transfer failed.");
|
||||
|
||||
memcpy(msg[j].buf, &state->data[1], msg[j].len);
|
||||
break;
|
||||
}
|
||||
|
||||
/* single write */
|
||||
if (3 + msg[j].len > sizeof(state->data)) {
|
||||
warn("i2c wr: len=%d is too big!\n", msg[j].len);
|
||||
num = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
/* always i2c write*/
|
||||
state->data[0] = 0x08;
|
||||
state->data[1] = msg[0].addr;
|
||||
state->data[2] = msg[0].len;
|
||||
state->data[1] = msg[j].addr;
|
||||
state->data[2] = msg[j].len;
|
||||
|
||||
memcpy(&state->data[3], msg[0].buf, msg[0].len);
|
||||
memcpy(&state->data[3], msg[j].buf, msg[j].len);
|
||||
|
||||
if (dvb_usb_generic_rw(d, state->data, msg[0].len + 3,
|
||||
if (dvb_usb_generic_rw(d, state->data, msg[j].len + 3,
|
||||
state->data, 1, 0) < 0)
|
||||
err("i2c transfer failed.");
|
||||
} // switch
|
||||
j++;
|
||||
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
/* always i2c read */
|
||||
if (4 + msg[0].len > sizeof(state->data)) {
|
||||
warn("i2c rd: len=%d is too big!\n",
|
||||
msg[0].len);
|
||||
num = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
if (1 + msg[1].len > sizeof(state->data)) {
|
||||
warn("i2c rd: len=%d is too big!\n",
|
||||
msg[1].len);
|
||||
num = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
state->data[0] = 0x09;
|
||||
state->data[1] = msg[0].len;
|
||||
state->data[2] = msg[1].len;
|
||||
state->data[3] = msg[0].addr;
|
||||
memcpy(&state->data[4], msg[0].buf, msg[0].len);
|
||||
|
||||
if (dvb_usb_generic_rw(d, state->data, msg[0].len + 4,
|
||||
state->data, msg[1].len + 1, 0) < 0)
|
||||
err("i2c transfer failed.");
|
||||
|
||||
memcpy(msg[1].buf, &state->data[1], msg[1].len);
|
||||
break;
|
||||
default:
|
||||
warn("more than 2 i2c messages at a time is not handled yet.");
|
||||
break;
|
||||
}
|
||||
} // while
|
||||
mutex_unlock(&d->data_mutex);
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
return num;
|
||||
|
||||
@@ -247,7 +247,7 @@ struct s2255_vc {
|
||||
struct s2255_dev {
|
||||
struct s2255_vc vc[MAX_CHANNELS];
|
||||
struct v4l2_device v4l2_dev;
|
||||
atomic_t num_channels;
|
||||
refcount_t num_channels;
|
||||
int frames;
|
||||
struct mutex lock; /* channels[].vdev.lock */
|
||||
struct mutex cmdlock; /* protects cmdbuf */
|
||||
@@ -1552,11 +1552,11 @@ static void s2255_video_device_release(struct video_device *vdev)
|
||||
container_of(vdev, struct s2255_vc, vdev);
|
||||
|
||||
dprintk(dev, 4, "%s, chnls: %d\n", __func__,
|
||||
atomic_read(&dev->num_channels));
|
||||
refcount_read(&dev->num_channels));
|
||||
|
||||
v4l2_ctrl_handler_free(&vc->hdl);
|
||||
|
||||
if (atomic_dec_and_test(&dev->num_channels))
|
||||
if (refcount_dec_and_test(&dev->num_channels))
|
||||
s2255_destroy(dev);
|
||||
return;
|
||||
}
|
||||
@@ -1661,7 +1661,7 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
|
||||
"failed to register video device!\n");
|
||||
break;
|
||||
}
|
||||
atomic_inc(&dev->num_channels);
|
||||
refcount_inc(&dev->num_channels);
|
||||
v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
|
||||
video_device_node_name(&vc->vdev));
|
||||
|
||||
@@ -1669,11 +1669,11 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
|
||||
pr_info("Sensoray 2255 V4L driver Revision: %s\n",
|
||||
S2255_VERSION);
|
||||
/* if no channels registered, return error and probe will fail*/
|
||||
if (atomic_read(&dev->num_channels) == 0) {
|
||||
if (refcount_read(&dev->num_channels) == 0) {
|
||||
v4l2_device_unregister(&dev->v4l2_dev);
|
||||
return ret;
|
||||
}
|
||||
if (atomic_read(&dev->num_channels) != MAX_CHANNELS)
|
||||
if (refcount_read(&dev->num_channels) != MAX_CHANNELS)
|
||||
pr_warn("s2255: Not all channels available.\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -2222,7 +2222,7 @@ static int s2255_probe(struct usb_interface *interface,
|
||||
goto errorFWDATA1;
|
||||
}
|
||||
|
||||
atomic_set(&dev->num_channels, 0);
|
||||
refcount_set(&dev->num_channels, 0);
|
||||
dev->pid = id->idProduct;
|
||||
dev->fw_data = kzalloc(sizeof(struct s2255_fw), GFP_KERNEL);
|
||||
if (!dev->fw_data)
|
||||
@@ -2342,12 +2342,12 @@ static void s2255_disconnect(struct usb_interface *interface)
|
||||
{
|
||||
struct s2255_dev *dev = to_s2255_dev(usb_get_intfdata(interface));
|
||||
int i;
|
||||
int channels = atomic_read(&dev->num_channels);
|
||||
int channels = refcount_read(&dev->num_channels);
|
||||
mutex_lock(&dev->lock);
|
||||
v4l2_device_disconnect(&dev->v4l2_dev);
|
||||
mutex_unlock(&dev->lock);
|
||||
/*see comments in the uvc_driver.c usb disconnect function */
|
||||
atomic_inc(&dev->num_channels);
|
||||
refcount_inc(&dev->num_channels);
|
||||
/* unregister each video device. */
|
||||
for (i = 0; i < channels; i++)
|
||||
video_unregister_device(&dev->vc[i].vdev);
|
||||
@@ -2360,7 +2360,7 @@ static void s2255_disconnect(struct usb_interface *interface)
|
||||
dev->vc[i].vidstatus_ready = 1;
|
||||
wake_up(&dev->vc[i].wait_vidstatus);
|
||||
}
|
||||
if (atomic_dec_and_test(&dev->num_channels))
|
||||
if (refcount_dec_and_test(&dev->num_channels))
|
||||
s2255_destroy(dev);
|
||||
dev_info(&interface->dev, "%s\n", __func__);
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
|
||||
}
|
||||
|
||||
if (!mei_cl_is_connected(cl)) {
|
||||
cl_err(dev, cl, "is not connected");
|
||||
cl_dbg(dev, cl, "is not connected");
|
||||
rets = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -379,8 +379,10 @@ static int mei_me_pci_resume(struct device *device)
|
||||
}
|
||||
|
||||
err = mei_restart(dev);
|
||||
if (err)
|
||||
if (err) {
|
||||
free_irq(pdev->irq, dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Start timer if stopped in suspend */
|
||||
schedule_delayed_work(&dev->timer_work, HZ);
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/vmw_vmci_api.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/nospec.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/rculist.h>
|
||||
@@ -86,9 +87,12 @@ static void event_deliver(struct vmci_event_msg *event_msg)
|
||||
{
|
||||
struct vmci_subscription *cur;
|
||||
struct list_head *subscriber_list;
|
||||
u32 sanitized_event, max_vmci_event;
|
||||
|
||||
rcu_read_lock();
|
||||
subscriber_list = &subscriber_array[event_msg->event_data.event];
|
||||
max_vmci_event = ARRAY_SIZE(subscriber_array);
|
||||
sanitized_event = array_index_nospec(event_msg->event_data.event, max_vmci_event);
|
||||
subscriber_list = &subscriber_array[sanitized_event];
|
||||
list_for_each_entry_rcu(cur, subscriber_list, node) {
|
||||
cur->callback(cur->id, &event_msg->event_data,
|
||||
cur->callback_data);
|
||||
|
||||
@@ -1376,7 +1376,7 @@ static int jmicron_pmos(struct sdhci_pci_chip *chip, int on)
|
||||
|
||||
ret = pci_read_config_byte(chip->pdev, 0xAE, &scratch);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto fail;
|
||||
|
||||
/*
|
||||
* Turn PMOS on [bit 0], set over current detection to 2.4 V
|
||||
@@ -1387,7 +1387,10 @@ static int jmicron_pmos(struct sdhci_pci_chip *chip, int on)
|
||||
else
|
||||
scratch &= ~0x47;
|
||||
|
||||
return pci_write_config_byte(chip->pdev, 0xAE, scratch);
|
||||
ret = pci_write_config_byte(chip->pdev, 0xAE, scratch);
|
||||
|
||||
fail:
|
||||
return pcibios_err_to_errno(ret);
|
||||
}
|
||||
|
||||
static int jmicron_probe(struct sdhci_pci_chip *chip)
|
||||
@@ -2303,7 +2306,7 @@ static int sdhci_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots);
|
||||
if (ret)
|
||||
return ret;
|
||||
return pcibios_err_to_errno(ret);
|
||||
|
||||
slots = PCI_SLOT_INFO_SLOTS(slots) + 1;
|
||||
dev_dbg(&pdev->dev, "found %d slot(s)\n", slots);
|
||||
@@ -2312,7 +2315,7 @@ static int sdhci_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar);
|
||||
if (ret)
|
||||
return ret;
|
||||
return pcibios_err_to_errno(ret);
|
||||
|
||||
first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK;
|
||||
|
||||
|
||||
@@ -2274,26 +2274,29 @@ static int sdhci_get_cd(struct mmc_host *mmc)
|
||||
|
||||
static int sdhci_check_ro(struct sdhci_host *host)
|
||||
{
|
||||
unsigned long flags;
|
||||
bool allow_invert = false;
|
||||
int is_readonly;
|
||||
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
|
||||
if (host->flags & SDHCI_DEVICE_DEAD)
|
||||
if (host->flags & SDHCI_DEVICE_DEAD) {
|
||||
is_readonly = 0;
|
||||
else if (host->ops->get_ro)
|
||||
} else if (host->ops->get_ro) {
|
||||
is_readonly = host->ops->get_ro(host);
|
||||
else if (mmc_can_gpio_ro(host->mmc))
|
||||
} else if (mmc_can_gpio_ro(host->mmc)) {
|
||||
is_readonly = mmc_gpio_get_ro(host->mmc);
|
||||
else
|
||||
/* Do not invert twice */
|
||||
allow_invert = !(host->mmc->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
|
||||
} else {
|
||||
is_readonly = !(sdhci_readl(host, SDHCI_PRESENT_STATE)
|
||||
& SDHCI_WRITE_PROTECT);
|
||||
allow_invert = true;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
if (is_readonly >= 0 &&
|
||||
allow_invert &&
|
||||
(host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT))
|
||||
is_readonly = !is_readonly;
|
||||
|
||||
/* This quirk needs to be replaced by a callback-function later */
|
||||
return host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT ?
|
||||
!is_readonly : is_readonly;
|
||||
return is_readonly;
|
||||
}
|
||||
|
||||
#define SAMPLE_COUNT 5
|
||||
|
||||
@@ -132,6 +132,105 @@ static const struct spinand_info macronix_spinand_table[] = {
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)),
|
||||
SPINAND_INFO("MX35LF2G14AC", 0x20,
|
||||
NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
|
||||
NAND_ECCREQ(4, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
|
||||
mx35lf1ge4ab_ecc_get_status)),
|
||||
SPINAND_INFO("MX35UF4G24AD", 0xb5,
|
||||
NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 2, 1, 1),
|
||||
NAND_ECCREQ(8, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
|
||||
mx35lf1ge4ab_ecc_get_status)),
|
||||
SPINAND_INFO("MX35UF4GE4AD", 0xb7,
|
||||
NAND_MEMORG(1, 4096, 256, 64, 2048, 40, 1, 1, 1),
|
||||
NAND_ECCREQ(8, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
|
||||
mx35lf1ge4ab_ecc_get_status)),
|
||||
SPINAND_INFO("MX35UF2G14AC", 0xa0,
|
||||
NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 2, 1, 1),
|
||||
NAND_ECCREQ(4, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
|
||||
mx35lf1ge4ab_ecc_get_status)),
|
||||
SPINAND_INFO("MX35UF2G24AD", 0xa4,
|
||||
NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1),
|
||||
NAND_ECCREQ(8, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
|
||||
mx35lf1ge4ab_ecc_get_status)),
|
||||
SPINAND_INFO("MX35UF2GE4AD", 0xa6,
|
||||
NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1),
|
||||
NAND_ECCREQ(8, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
|
||||
mx35lf1ge4ab_ecc_get_status)),
|
||||
SPINAND_INFO("MX35UF2GE4AC", 0xa2,
|
||||
NAND_MEMORG(1, 2048, 64, 64, 2048, 40, 1, 1, 1),
|
||||
NAND_ECCREQ(4, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
|
||||
mx35lf1ge4ab_ecc_get_status)),
|
||||
SPINAND_INFO("MX35UF1G14AC", 0x90,
|
||||
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
|
||||
NAND_ECCREQ(4, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
|
||||
mx35lf1ge4ab_ecc_get_status)),
|
||||
SPINAND_INFO("MX35UF1G24AD", 0x94,
|
||||
NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
|
||||
NAND_ECCREQ(8, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
|
||||
mx35lf1ge4ab_ecc_get_status)),
|
||||
SPINAND_INFO("MX35UF1GE4AD", 0x96,
|
||||
NAND_MEMORG(1, 2048, 128, 64, 1024, 20, 1, 1, 1),
|
||||
NAND_ECCREQ(8, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
|
||||
mx35lf1ge4ab_ecc_get_status)),
|
||||
SPINAND_INFO("MX35UF1GE4AC", 0x92,
|
||||
NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1),
|
||||
NAND_ECCREQ(4, 512),
|
||||
SPINAND_INFO_OP_VARIANTS(&read_cache_variants,
|
||||
&write_cache_variants,
|
||||
&update_cache_variants),
|
||||
SPINAND_HAS_QE_BIT,
|
||||
SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout,
|
||||
mx35lf1ge4ab_ecc_get_status)),
|
||||
};
|
||||
|
||||
static int macronix_spinand_detect(struct spinand_device *spinand)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user