Files
kernel_google_wahoo/kernel/locking/spinlock_debug.c
Nathan Chancellor 4747b04527 Merge 4.9.209 into android-msm-bluecross-4.9
Changes in 4.9.209: (90 commits)
        PM / devfreq: Don't fail devfreq_dev_release if not in list
        RDMA/cma: add missed unregister_pernet_subsys in init failure
        scsi: lpfc: Fix memory leak on lpfc_bsg_write_ebuf_set func
        scsi: qla2xxx: Don't call qlt_async_event twice
        scsi: iscsi: qla4xxx: fix double free in probe
        scsi: libsas: stop discovering if oob mode is disconnected
        usb: gadget: fix wrong endpoint desc
        md: raid1: check rdev before reference in raid1_sync_request func
        s390/cpum_sf: Adjust sampling interval to avoid hitting sample limits
        s390/cpum_sf: Avoid SBD overflow condition in irq handler
        IB/mlx4: Follow mirror sequence of device add during device removal
        xen-blkback: prevent premature module unload
        xen/balloon: fix ballooned page accounting without hotplug enabled
        PM / hibernate: memory_bm_find_bit(): Tighten node optimisation
        xfs: fix mount failure crash on invalid iclog memory access
        taskstats: fix data-race
        drm: limit to INT_MAX in create_blob ioctl
        Revert "perf report: Add warning when libunwind not compiled in"
        ALSA: ice1724: Fix sleep-in-atomic in Infrasonic Quartet support code
        MIPS: Avoid VDSO ABI breakage due to global register variable
        mm/zsmalloc.c: fix the migrated zspage statistics.
        memcg: account security cred as well to kmemcg
        locks: print unsigned ino in /proc/locks
        dmaengine: Fix access to uninitialized dma_slave_caps
        compat_ioctl: block: handle Persistent Reservations
        ata: libahci_platform: Export again ahci_platform_<en/dis>able_phys()
        ata: ahci_brcm: Allow optional reset controller to be used
        ata: ahci_brcm: Fix AHCI resources management
        gpiolib: fix up emulated open drain outputs
        tracing: Have the histogram compare functions convert to u64 first
        ALSA: cs4236: fix error return comparison of an unsigned integer
        ftrace: Avoid potential division by zero in function profiler
        arm64: Revert support for execute-only user mappings
        PM / devfreq: Check NULL governor in available_governors_show
        nfsd4: fix up replay_matches_cache()
        xfs: don't check for AG deadlock for realtime files in bunmapi
        Bluetooth: btusb: fix PM leak in error case of setup
        Bluetooth: delete a stray unlock
        Bluetooth: Fix memory leak in hci_connect_le_scan
        media: flexcop-usb: ensure -EIO is returned on error condition
        regulator: ab8500: Remove AB8505 USB regulator
        media: usb: fix memory leak in af9005_identify_state
        tty: serial: msm_serial: Fix lockup for sysrq and oops
        fix compat handling of FICLONERANGE, FIDEDUPERANGE and FS_IOC_FIEMAP
        drm/mst: Fix MST sideband up-reply failure handling
        powerpc/pseries/hvconsole: Fix stack overread via udbg
        rxrpc: Fix possible NULL pointer access in ICMP handling
        ath9k_htc: Modify byte order for an error message
        ath9k_htc: Discard undersized packets
        net: add annotations on hh->hh_len lockless accesses
        s390/smp: fix physical to logical CPU map for SMT
        xen/blkback: Avoid unmapping unmapped grant pages
        locking/x86: Remove the unused atomic_inc_short() methd
        pstore/ram: Write new dumps to start of recycled zones
        locking/spinlock/debug: Fix various data races
        netfilter: ctnetlink: netns exit must wait for callbacks
        efi/gop: Return EFI_NOT_FOUND if there are no usable GOPs
        efi/gop: Return EFI_SUCCESS if a usable GOP was found
        efi/gop: Fix memory leak in __gop_query32/64()
        ARM: vexpress: Set-up shared OPP table instead of individual for each CPU
        netfilter: uapi: Avoid undefined left-shift in xt_sctp.h
        spi: spi-cavium-thunderx: Add missing pci_release_regions()
        ARM: dts: am437x-gp/epos-evm: fix panel compatible
        samples: bpf: Replace symbol compare of trace_event
        powerpc: Ensure that swiotlb buffer is allocated from low memory
        bnx2x: Do not handle requests from VFs after parity
        bnx2x: Fix logic to get total no. of PFs per engine
        net: usb: lan78xx: Fix error message format specifier
        rfkill: Fix incorrect check to avoid NULL pointer dereference
        ASoC: wm8962: fix lambda value
        regulator: rn5t618: fix module aliases
        kconfig: don't crash on NULL expressions in expr_eq()
        perf/x86/intel: Fix PT PMI handling
        net: stmmac: RX buffer size must be 16 byte aligned
        block: fix memleak when __blk_rq_map_user_iov() is failed
        parisc: Fix compiler warnings in debug_core.c
        llc2: Fix return statement of llc_stat_ev_rx_null_dsap_xid_c (and _test_c)
        macvlan: do not assume mac_header is set in macvlan_broadcast()
        net: stmmac: dwmac-sunxi: Allow all RGMII modes
        net: usb: lan78xx: fix possible skb leak
        pkt_sched: fq: do not accept silly TCA_FQ_QUANTUM
        sctp: free cmd->obj.chunk for the unprocessed SCTP_CMD_REPLY
        tcp: fix "old stuff" D-SACK causing SACK to be treated as D-SACK
        vxlan: fix tos value before xmit
        vlan: vlan_changelink() should propagate errors
        net: sch_prio: When ungrafting, replace with FIFO
        vlan: fix memory leak in vlan_dev_set_egress_priority
        USB: core: fix check for duplicate endpoints
        USB: serial: option: add Telit ME910G1 0x110a composition
        Linux 4.9.209

Signed-off-by: Nathan Chancellor <natechancellor@gmail.com>

Conflicts:
	arch/arm64/mm/fault.c
	drivers/gpu/drm/drm_property.c
	kernel/locking/spinlock_debug.c
2020-01-12 11:10:25 -07:00

315 lines
7.6 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);
}
static void __spin_lock_debug(raw_spinlock_t *lock)
{
u64 i;
u64 loops = loops_per_jiffy * HZ;
for (i = 0; i < loops; i++) {
if (arch_spin_trylock(&lock->raw_lock))
return;
__delay(1);
}
/* lockup suspected: */
spin_bug(lock, "lockup suspected");
#ifdef CONFIG_SMP
trigger_all_cpu_backtrace();
#endif
/*
* The trylock above was causing a livelock. Give the lower level arch
* specific lock code a chance to acquire the lock. We have already
* printed a warning/backtrace at this point. The non-debug arch
* specific code might actually succeed in acquiring the lock. If it is
* not successful, the end-result is the same - there is no forward
* progress.
*/
arch_spin_lock(&lock->raw_lock);
}
void do_raw_spin_lock(raw_spinlock_t *lock)
{
debug_spin_lock_before(lock);
if (unlikely(!arch_spin_trylock(&lock->raw_lock)))
__spin_lock_debug(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)
#if 0 /* __write_lock_debug() can lock up - maybe this can too? */
static void __read_lock_debug(rwlock_t *lock)
{
u64 i;
u64 loops = loops_per_jiffy * HZ;
int print_once = 1;
for (;;) {
for (i = 0; i < loops; i++) {
if (arch_read_trylock(&lock->raw_lock))
return;
__delay(1);
}
/* lockup suspected: */
if (print_once) {
print_once = 0;
printk(KERN_EMERG "BUG: read-lock lockup on CPU#%d, "
"%s/%d, %p\n",
raw_smp_processor_id(), current->comm,
current->pid, lock);
dump_stack();
}
}
}
#endif
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);
}
#if 0 /* This can cause lockups */
static void __write_lock_debug(rwlock_t *lock)
{
u64 i;
u64 loops = loops_per_jiffy * HZ;
int print_once = 1;
for (;;) {
for (i = 0; i < loops; i++) {
if (arch_write_trylock(&lock->raw_lock))
return;
__delay(1);
}
/* lockup suspected: */
if (print_once) {
print_once = 0;
printk(KERN_EMERG "BUG: write-lock lockup on CPU#%d, "
"%s/%d, %p\n",
raw_smp_processor_id(), current->comm,
current->pid, lock);
dump_stack();
}
}
}
#endif
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);
}