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