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:
kamasali Satyanarayan
2024-10-29 12:14:11 +05:30
committed by Kamasali Satyanarayan
274 changed files with 4181 additions and 2365 deletions

View File

@@ -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

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 4
SUBLEVEL = 278
SUBLEVEL = 281
EXTRAVERSION =
NAME = Kleptomaniac Octopus

View File

@@ -1 +1 @@
LTS_5.4.278_7453ecf4d1fe
LTS_5.4.281_d62984adb112

File diff suppressed because it is too large Load Diff

View File

@@ -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>;

View File

@@ -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";

View File

@@ -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";

View File

@@ -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 {

View File

@@ -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

View File

@@ -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);

View File

@@ -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>;
};

View File

@@ -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";
};

View File

@@ -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)

View 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);

View File

@@ -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>

View File

@@ -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>
};

View File

@@ -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)

View File

@@ -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

View File

@@ -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
View 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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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");

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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,

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View File

@@ -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),

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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);

View File

@@ -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 =

View File

@@ -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);

View File

@@ -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++) {

View File

@@ -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);

View File

@@ -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[];
};

View File

@@ -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) ^

View File

@@ -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);
}
/**

View File

@@ -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 = {

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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,

View File

@@ -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... */

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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 =

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}
/*

View File

@@ -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)];

View File

@@ -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),

View File

@@ -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 = {

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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");

View File

@@ -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);

View File

@@ -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];

View File

@@ -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)

View File

@@ -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);

View File

@@ -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;

View File

@@ -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");

View File

@@ -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),

View File

@@ -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);

View File

@@ -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;

View File

@@ -174,6 +174,6 @@ struct as10x_register_addr {
uint32_t addr;
/* register mode access */
uint8_t mode;
};
} __packed;
#endif

View File

@@ -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 */

View File

@@ -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;

View File

@@ -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)

View File

@@ -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;

View File

@@ -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__);
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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