kernel-fxtec-pro1x/kernel/locking/spinlock_debug.c
Ivaylo Georgiev 9459964334 Merge android-4.19-q.95 (138a4a6) into msm-4.19
* refs/heads/tmp-138a4a6:
  Linux 4.19.95
  usb: missing parentheses in USE_NEW_SCHEME
  USB: serial: option: add Telit ME910G1 0x110a composition
  USB: core: fix check for duplicate endpoints
  usb: dwc3: gadget: Fix request complete check
  net: sch_prio: When ungrafting, replace with FIFO
  mlxsw: spectrum_qdisc: Ignore grafting of invisible FIFO
  vlan: vlan_changelink() should propagate errors
  vlan: fix memory leak in vlan_dev_set_egress_priority
  vxlan: fix tos value before xmit
  tcp: fix "old stuff" D-SACK causing SACK to be treated as D-SACK
  sctp: free cmd->obj.chunk for the unprocessed SCTP_CMD_REPLY
  sch_cake: avoid possible divide by zero in cake_enqueue()
  pkt_sched: fq: do not accept silly TCA_FQ_QUANTUM
  net: usb: lan78xx: fix possible skb leak
  net: stmmac: dwmac-sunxi: Allow all RGMII modes
  net: stmmac: dwmac-sun8i: Allow all RGMII modes
  net: dsa: mv88e6xxx: Preserve priority when setting CPU port.
  macvlan: do not assume mac_header is set in macvlan_broadcast()
  gtp: fix bad unlock balance in gtp_encap_enable_socket
  PCI/switchtec: Read all 64 bits of part_event_bitmap
  ARM: dts: imx6ul: use nvmem-cells for cpu speed grading
  cpufreq: imx6q: read OCOTP through nvmem for imx6ul/imx6ull
  powerpc/spinlocks: Include correct header for static key
  powerpc/vcpu: Assume dedicated processors as non-preempt
  hv_netvsc: Fix unwanted rx_table reset
  llc2: Fix return statement of llc_stat_ev_rx_null_dsap_xid_c (and _test_c)
  parisc: Fix compiler warnings in debug_core.c
  block: fix memleak when __blk_rq_map_user_iov() is failed
  s390/dasd: fix memleak in path handling error case
  s390/dasd/cio: Interpret ccw_device_get_mdc return value correctly
  drm/exynos: gsc: add missed component_del
  s390/purgatory: do not build purgatory with kcov, kasan and friends
  net: stmmac: Always arm TX Timer at end of transmission start
  net: stmmac: RX buffer size must be 16 byte aligned
  net: stmmac: xgmac: Clear previous RX buffer size
  net: stmmac: Do not accept invalid MTU values
  fs: avoid softlockups in s_inodes iterators
  perf/x86/intel: Fix PT PMI handling
  kconfig: don't crash on NULL expressions in expr_eq()
  iommu/iova: Init the struct iova to fix the possible memleak
  regulator: rn5t618: fix module aliases
  ASoC: wm8962: fix lambda value
  rfkill: Fix incorrect check to avoid NULL pointer dereference
  parisc: add missing __init annotation
  net: usb: lan78xx: Fix error message format specifier
  cxgb4: Fix kernel panic while accessing sge_info
  bnx2x: Fix logic to get total no. of PFs per engine
  bnx2x: Do not handle requests from VFs after parity
  bpf: Clear skb->tstamp in bpf_redirect when necessary
  btrfs: Fix error messages in qgroup_rescan_init
  powerpc: Ensure that swiotlb buffer is allocated from low memory
  samples: bpf: fix syscall_tp due to unused syscall
  samples: bpf: Replace symbol compare of trace_event
  ARM: dts: am437x-gp/epos-evm: fix panel compatible
  spi: spi-ti-qspi: Fix a bug when accessing non default CS
  bpf, mips: Limit to 33 tail calls
  bnxt_en: Return error if FW returns more data than dump length
  ARM: dts: bcm283x: Fix critical trip point
  ASoC: topology: Check return value for soc_tplg_pcm_create()
  spi: spi-cavium-thunderx: Add missing pci_release_regions()
  ARM: dts: Cygnus: Fix MDIO node address/size cells
  selftests/ftrace: Fix multiple kprobe testcase
  ARM: dts: BCM5301X: Fix MDIO node address/size cells
  netfilter: nf_tables: validate NFT_DATA_VALUE after nft_data_init()
  netfilter: nf_tables: validate NFT_SET_ELEM_INTERVAL_END
  netfilter: nft_set_rbtree: bogus lookup/get on consecutive elements in named sets
  netfilter: uapi: Avoid undefined left-shift in xt_sctp.h
  ARM: vexpress: Set-up shared OPP table instead of individual for each CPU
  ARM: dts: imx6ul: imx6ul-14x14-evk.dtsi: Fix SPI NOR probing
  efi/gop: Fix memory leak in __gop_query32/64()
  efi/gop: Return EFI_SUCCESS if a usable GOP was found
  efi/gop: Return EFI_NOT_FOUND if there are no usable GOPs
  ASoC: Intel: bytcr_rt5640: Update quirk for Teclast X89
  x86/efi: Update e820 with reserved EFI boot services data to fix kexec breakage
  libtraceevent: Fix lib installation with O=
  mwifiex: Fix heap overflow in mmwifiex_process_tdls_action_frame()
  netfilter: ctnetlink: netns exit must wait for callbacks
  locking/spinlock/debug: Fix various data races
  ASoC: max98090: fix possible race conditions
  regulator: fix use after free issue
  bpf: Fix passing modified ctx to ld/abs/ind instruction
  USB: dummy-hcd: increase max number of devices to 32
  USB: dummy-hcd: use usb_urb_dir_in instead of usb_pipein

Conflicts:
	kernel/locking/spinlock_debug.c

1683149 ("usb: dwc3: gadget: Fix logical condition") was reverted
on importing android-4.19-q.90 into msm-4.19 as this change
prevented the adbd userspace daemon from ever receiving packets
from the kernel USB driver. android-4.19-q.95 introduced new
change ceaeb21b ("usb: dwc3: gadget: Fix request complete check")
that fixed the regression, hence it is safe to restore the revert.
It is done in this merge.

Change-Id: I5f839319ad7746728a98c01f8b5c3dab9c9f368a
Signed-off-by: Ivaylo Georgiev <irgeorgiev@codeaurora.org>
2020-02-03 21:43:57 -08:00

238 lines
5.9 KiB
C

/*
* Copyright 2005, Red Hat, Inc., Ingo Molnar
* Released under the General Public License (GPL).
*
* This file contains the spinlock/rwlock implementations for
* DEBUG_SPINLOCK.
*/
#include <linux/spinlock.h>
#include <linux/nmi.h>
#include <linux/interrupt.h>
#include <linux/debug_locks.h>
#include <linux/delay.h>
#include <linux/export.h>
#include <linux/bug.h>
#include <soc/qcom/watchdog.h>
void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name,
struct lock_class_key *key)
{
#ifdef CONFIG_DEBUG_LOCK_ALLOC
/*
* Make sure we are not reinitializing a held lock:
*/
debug_check_no_locks_freed((void *)lock, sizeof(*lock));
lockdep_init_map(&lock->dep_map, name, key, 0);
#endif
lock->raw_lock = (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
lock->magic = SPINLOCK_MAGIC;
lock->owner = SPINLOCK_OWNER_INIT;
lock->owner_cpu = -1;
}
EXPORT_SYMBOL(__raw_spin_lock_init);
void __rwlock_init(rwlock_t *lock, const char *name,
struct lock_class_key *key)
{
#ifdef CONFIG_DEBUG_LOCK_ALLOC
/*
* Make sure we are not reinitializing a held lock:
*/
debug_check_no_locks_freed((void *)lock, sizeof(*lock));
lockdep_init_map(&lock->dep_map, name, key, 0);
#endif
lock->raw_lock = (arch_rwlock_t) __ARCH_RW_LOCK_UNLOCKED;
lock->magic = RWLOCK_MAGIC;
lock->owner = SPINLOCK_OWNER_INIT;
lock->owner_cpu = -1;
}
EXPORT_SYMBOL(__rwlock_init);
static void spin_dump(raw_spinlock_t *lock, const char *msg)
{
struct task_struct *owner = READ_ONCE(lock->owner);
if (owner == SPINLOCK_OWNER_INIT)
owner = NULL;
printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n",
msg, raw_smp_processor_id(),
current->comm, task_pid_nr(current));
printk(KERN_EMERG " lock: %pS, .magic: %08x, .owner: %s/%d, "
".owner_cpu: %d\n",
lock, READ_ONCE(lock->magic),
owner ? owner->comm : "<none>",
owner ? task_pid_nr(owner) : -1,
READ_ONCE(lock->owner_cpu));
#ifdef CONFIG_DEBUG_SPINLOCK_BITE_ON_BUG
msm_trigger_wdog_bite();
#elif defined(CONFIG_DEBUG_SPINLOCK_PANIC_ON_BUG)
BUG();
#endif
dump_stack();
}
static void spin_bug(raw_spinlock_t *lock, const char *msg)
{
if (!debug_locks_off())
return;
spin_dump(lock, msg);
}
#define SPIN_BUG_ON(cond, lock, msg) if (unlikely(cond)) spin_bug(lock, msg)
static inline void
debug_spin_lock_before(raw_spinlock_t *lock)
{
SPIN_BUG_ON(READ_ONCE(lock->magic) != SPINLOCK_MAGIC, lock, "bad magic");
SPIN_BUG_ON(READ_ONCE(lock->owner) == current, lock, "recursion");
SPIN_BUG_ON(READ_ONCE(lock->owner_cpu) == raw_smp_processor_id(),
lock, "cpu recursion");
}
static inline void debug_spin_lock_after(raw_spinlock_t *lock)
{
WRITE_ONCE(lock->owner_cpu, raw_smp_processor_id());
WRITE_ONCE(lock->owner, current);
}
static inline void debug_spin_unlock(raw_spinlock_t *lock)
{
SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
SPIN_BUG_ON(!raw_spin_is_locked(lock), lock, "already unlocked");
SPIN_BUG_ON(lock->owner != current, lock, "wrong owner");
SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
lock, "wrong CPU");
WRITE_ONCE(lock->owner, SPINLOCK_OWNER_INIT);
WRITE_ONCE(lock->owner_cpu, -1);
}
/*
* We are now relying on the NMI watchdog to detect lockup instead of doing
* the detection here with an unfair lock which can cause problem of its own.
*/
void do_raw_spin_lock(raw_spinlock_t *lock)
{
debug_spin_lock_before(lock);
arch_spin_lock(&lock->raw_lock);
debug_spin_lock_after(lock);
}
int do_raw_spin_trylock(raw_spinlock_t *lock)
{
int ret = arch_spin_trylock(&lock->raw_lock);
if (ret)
debug_spin_lock_after(lock);
#ifndef CONFIG_SMP
/*
* Must not happen on UP:
*/
SPIN_BUG_ON(!ret, lock, "trylock failure on UP");
#endif
return ret;
}
void do_raw_spin_unlock(raw_spinlock_t *lock)
{
debug_spin_unlock(lock);
arch_spin_unlock(&lock->raw_lock);
}
static void rwlock_bug(rwlock_t *lock, const char *msg)
{
if (!debug_locks_off())
return;
printk(KERN_EMERG "BUG: rwlock %s on CPU#%d, %s/%d, %p\n",
msg, raw_smp_processor_id(), current->comm,
task_pid_nr(current), lock);
#ifdef CONFIG_DEBUG_SPINLOCK_BITE_ON_BUG
msm_trigger_wdog_bite();
#elif defined(CONFIG_DEBUG_SPINLOCK_PANIC_ON_BUG)
BUG();
#endif
dump_stack();
}
#define RWLOCK_BUG_ON(cond, lock, msg) if (unlikely(cond)) rwlock_bug(lock, msg)
void do_raw_read_lock(rwlock_t *lock)
{
RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
arch_read_lock(&lock->raw_lock);
}
int do_raw_read_trylock(rwlock_t *lock)
{
int ret = arch_read_trylock(&lock->raw_lock);
#ifndef CONFIG_SMP
/*
* Must not happen on UP:
*/
RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
#endif
return ret;
}
void do_raw_read_unlock(rwlock_t *lock)
{
RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
arch_read_unlock(&lock->raw_lock);
}
static inline void debug_write_lock_before(rwlock_t *lock)
{
RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
RWLOCK_BUG_ON(lock->owner == current, lock, "recursion");
RWLOCK_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
lock, "cpu recursion");
}
static inline void debug_write_lock_after(rwlock_t *lock)
{
WRITE_ONCE(lock->owner_cpu, raw_smp_processor_id());
WRITE_ONCE(lock->owner, current);
}
static inline void debug_write_unlock(rwlock_t *lock)
{
RWLOCK_BUG_ON(lock->magic != RWLOCK_MAGIC, lock, "bad magic");
RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner");
RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
lock, "wrong CPU");
WRITE_ONCE(lock->owner, SPINLOCK_OWNER_INIT);
WRITE_ONCE(lock->owner_cpu, -1);
}
void do_raw_write_lock(rwlock_t *lock)
{
debug_write_lock_before(lock);
arch_write_lock(&lock->raw_lock);
debug_write_lock_after(lock);
}
int do_raw_write_trylock(rwlock_t *lock)
{
int ret = arch_write_trylock(&lock->raw_lock);
if (ret)
debug_write_lock_after(lock);
#ifndef CONFIG_SMP
/*
* Must not happen on UP:
*/
RWLOCK_BUG_ON(!ret, lock, "trylock failure on UP");
#endif
return ret;
}
void do_raw_write_unlock(rwlock_t *lock)
{
debug_write_unlock(lock);
arch_write_unlock(&lock->raw_lock);
}