msm-4.14/drivers/clk/clk-mux.c
Isaac J. Manjarres bbea3fef30 Merge android-4.14.51 (a51b40c) into msm-4.14
* remotes/origin/tmp-a51b40c:
  Linux 4.14.51
  tcp: do not overshoot window_clamp in tcp_rcv_space_adjust()
  Btrfs: make raid6 rebuild retry more
  Btrfs: fix scrub to repair raid6 corruption
  Revert "Btrfs: fix scrub to repair raid6 corruption"
  ARM: kexec: fix kdump register saving on panic()
  ARM: 8758/1: decompressor: restore r1 and r2 just before jumping to the kernel
  ARM: 8753/1: decompressor: add a missing parameter to the addruart macro
  efi/libstub/arm64: Handle randomized TEXT_OFFSET
  parisc: Move setup_profiling_timer() out of init section
  sched/deadline: Make the grub_reclaim() function static
  sched/debug: Move the print_rt_rq() and print_dl_rq() declarations to kernel/sched/sched.h
  drm/dumb-buffers: Integer overflow in drm_mode_create_ioctl()
  locking/percpu-rwsem: Annotate rwsem ownership transfer by setting RWSEM_OWNER_UNKNOWN
  locking/rwsem: Add a new RWSEM_ANONYMOUSLY_OWNED flag
  clk: imx6ull: use OSC clock during AXI rate change
  ARM: davinci: board-dm646x-evm: set VPIF capture card name
  ARM: davinci: board-dm646x-evm: pass correct I2C adapter id for VPIF
  ARM: davinci: dm646x: fix timer interrupt generation
  i2c: viperboard: return message count on master_xfer success
  i2c: pmcmsp: fix error return from master_xfer
  i2c: pmcmsp: return message count on master_xfer success
  ARM: keystone: fix platform_domain_notifier array overrun
  usb: musb: fix remote wakeup racing with suspend
  afs: Fix the non-encryption of calls
  mtd: Fix comparison in map_word_andequal()
  x86/pkeys/selftests: Add a test for pkey 0
  x86/pkeys/selftests: Save off 'prot' for allocations
  x86/pkeys/selftests: Fix pointer math
  x86/pkeys/selftests: Fix pkey exhaustion test off-by-one
  x86/pkeys/selftests: Add PROT_EXEC test
  x86/pkeys/selftests: Factor out "instruction page"
  x86/pkeys/selftests: Allow faults on unknown keys
  x86/pkeys/selftests: Remove dead debugging code, fix dprint_in_signal
  x86/pkeys/selftests: Stop using assert()
  x86/pkeys/selftests: Give better unexpected fault error messages
  x86/selftests: Add mov_to_ss test
  x86/mpx/selftests: Adjust the self-test to fresh distros that export the MPX ABI
  x86/pkeys/selftests: Adjust the self-test to fresh distros that export the pkeys ABI
  objtool, kprobes/x86: Sync the latest <asm/insn.h> header with tools/objtool/arch/x86/include/asm/insn.h
  uprobes/x86: Prohibit probing on MOV SS instruction
  kprobes/x86: Prohibit probing on exception masking instructions
  ocfs2: take inode cluster lock before moving reflinked inode from orphan dir
  proc/kcore: don't bounds check against address 0
  init: fix false positives in W+X checking
  net sched actions: fix invalid pointer dereferencing if skbedit flags missing
  ixgbe: return error on unsupported SFP module when resetting
  x86: Delay skip of emulated hypercall instruction
  KVM: Extend MAX_IRQ_ROUTES to 4096 for all archs
  rxrpc: Fix the min security level for kernel calls
  rxrpc: Fix error reception on AF_INET6 sockets
  qede: Fix gfp flags sent to rdma event node allocation
  qed: Fix l2 initializations over iWARP personality
  tipc: eliminate KMSAN uninit-value in strcmp complaint
  agp: uninorth: make two functions static
  cifs: smb2ops: Fix listxattr() when there are no EAs
  arm64: Add MIDR encoding for NVIDIA CPUs
  can: dev: increase bus-off message severity
  net: aquantia: driver should correctly declare vlan_features bits
  x86/xen: Reset VCPU0 info pointer after shared_info remap
  mac80211: use timeout from the AddBA response instead of the request
  ARM: dts: cygnus: fix irq type for arm global timer
  driver core: add __printf verification to __ata_ehi_pushv_desc
  drm/omap: handle alloc failures in omap_connector
  drm/omap: check return value from soc_device_match
  drm/omap: fix possible NULL ref issue in tiler_reserve_2d
  drm/omap: fix uninitialized ret variable
  drm/omap: silence unititialized variable warning
  mac80211: Adjust SAE authentication timeout
  tee: check shm references are consistent in offset/size
  sh: fix build failure for J2 cpu with SMP disabled
  sched/core: Introduce set_special_state()
  spi: bcm2835aux: ensure interrupts are enabled for shared handler
  RDMA/cma: Do not query GID during QP state transition to RTR
  IB/hfi1: Fix memory leak in exception path in get_irq_affinity()
  IB/hfi1 Use correct type for num_user_context
  smc: fix sendpage() call
  ARM: OMAP1: ams-delta: fix deferred_fiq handler
  nvme: Set integrity flag for user passthrough commands
  nvme: fix potential memory leak in option parsing
  iommu/vt-d: fix shift-out-of-bounds in bug checking
  arm64: tegra: Make BCM89610 PHY interrupt as active low
  kthread, sched/wait: Fix kthread_parkme() wait-loop
  stop_machine, sched: Fix migrate_swap() vs. active_balance() deadlock
  parisc: drivers.c: Fix section mismatches
  bpf, x64: fix memleak when not converging after image
  scsi: vmw-pvscsi: return DID_BUS_BUSY for adapter-initated aborts
  hexagon: export csum_partial_copy_nocheck
  hexagon: add memset_io() helper
  Input: atmel_mxt_ts - fix the firmware update
  ARM: dts: logicpd-som-lv: Fix Audio Mute
  ARM: dts: logicpd-som-lv: Fix WL127x Startup Issues
  ARM: OMAP2+: powerdomain: use raw_smp_processor_id() for trace
  dt-bindings: panel: lvds: Fix path to display timing bindings
  ARM: davinci: board-dm355-evm: fix broken networking
  ARM: davinci: board-omapl138-hawk: fix GPIO numbers for MMC/SD lookup
  ARM: davinci: board-da850-evm: fix GPIO lookup for MMC/SD
  ARM: davinci: board-da830-evm: fix GPIO lookup for MMC/SD
  IB/core: Make ib_mad_client_id atomic
  <linux/stringhash.h>: fix end_name_hash() for 64bit long
  IB/rxe: avoid double kfree_skb
  IB/rxe: add RXE_START_MASK for rxe_opcode IB_OPCODE_RC_SEND_ONLY_INV
  RDMA/iwpm: fix memory leak on map_info
  RDMA/cma: Fix use after destroy access to net namespace for IPoIB
  IB/uverbs: Fix validating mandatory attributes
  IB: make INFINIBAND_ADDR_TRANS configurable
  ib_srp: depend on INFINIBAND_ADDR_TRANS
  ib_srpt: depend on INFINIBAND_ADDR_TRANS
  nvmet-rdma: depend on INFINIBAND_ADDR_TRANS
  nvme: depend on INFINIBAND_ADDR_TRANS
  tipc: fix bug in function tipc_nl_node_dump_monitor
  i2c: sprd: Fix the i2c count issue
  i2c: sprd: Prevent i2c accesses after suspend is called
  bpf: fix uninitialized variable in bpf tools
  x86/cpu/intel: Add missing TLB cpuid values
  ata: ahci: mvebu: override ahci_stop_engine for mvebu AHCI
  libahci: Allow drivers to override stop_engine
  KVM: arm/arm64: vgic: fix possible spectre-v1 in vgic_mmio_read_apr()
  arm64: fix possible spectre-v1 in ptrace_hbp_get_event()
  blk-mq: fix sysfs inflight counter
  HID: intel-ish-hid: use put_device() instead of kfree()
  rpmsg: added MODULE_ALIAS for rpmsg_char
  remoteproc: qcom: Fix potential device node leaks
  perf/x86/intel: Don't enable freeze-on-smi for PerfMon V1
  rds: ib: Fix missing call to rds_ib_dev_put in rds_ib_setup_qp
  selftests: ftrace: Add a testcase for multiple actions on trigger
  HID: wacom: Release device resource data obtained by devres_alloc()
  HID: lenovo: Add support for IBM/Lenovo Scrollpoint mice
  arm64: ptrace: remove addr_limit manipulation
  net: ethtool: Add missing kernel doc for FEC parameters
  thermal: int3403_thermal: Fix NULL pointer deref on module load / probe
  drm/amdkfd: fix clock counter retrieval for node without GPU
  ACPI / watchdog: Prefer iTCO_wdt on Lenovo Z50-70
  ARM: dts: da850: fix W=1 warnings with pinmux node
  net: phy: marvell: clear wol event before setting it
  powerpc/powernv/memtrace: Let the arch hotunplug code flush cache
  dt-bindings: meson-uart: DT fix s/clocks-names/clock-names/
  ACPI / PM: Blacklist Low Power S0 Idle _DSM for ThinkPad X1 Tablet(2016)
  usb: typec: ucsi: fix tracepoint related build error
  mm: memcg: add __GFP_NOWARN in __memcg_schedule_kmem_cache_create()
  kexec_file: do not add extra alignment to efi memmap
  proc: revalidate kernel thread inodes to root:root
  mm, pagemap: fix swap offset value for PMD migration entry
  scsi: isci: Fix infinite loop in while loop
  scsi: storvsc: Set up correct queue depth values for IDE devices
  parisc: time: Convert read_persistent_clock() to read_persistent_clock64()
  vfs: Undo an overly zealous MS_RDONLY -> SB_RDONLY conversion
  net: hns: Avoid action name truncation
  blkcg: init root blkcg_gq under lock
  drm/msm: don't deref error pointer in the msm_fbdev_create error path
  drm/msm/dsi: use correct enum in dsi_get_cmd_fmt
  drm/msm: Fix possible null dereference on failure of get_pages()
  ASoC: msm8916-wcd-analog: use threaded context for mbhc events
  netfilter: nf_tables: fix out-of-bounds in nft_chain_commit_update
  netfilter: nf_tables: NAT chain and extensions require NF_TABLES
  scsi: target: fix crash with iscsi target and dvd
  scsi: megaraid_sas: Do not log an error if FW successfully initializes.
  scsi: iscsi: respond to netlink with unicast when appropriate
  tipc: fix infinite loop when dumping link monitor summary
  blkcg: don't hold blkcg lock when deactivating policy
  spi: cadence: Add usleep_range() for cdns_spi_fill_tx_fifo()
  ASoC: topology: Check widget kcontrols before deref.
  xen: xenbus_dev_frontend: Really return response string
  ASoC: topology: Fix bugs of freeing soc topology
  PCI: kirin: Fix reset gpio name
  soc: bcm2835: Make !RASPBERRYPI_FIRMWARE dummies return failure
  soc: bcm: raspberrypi-power: Fix use of __packed
  eCryptfs: don't pass up plaintext names when using filename encryption
  ASoC: rt5514: Add the missing register in the readable table
  clk: honor CLK_MUX_ROUND_CLOSEST in generic clk mux
  dt-bindings: dmaengine: rcar-dmac: document R8A77965 support
  dt-bindings: serial: sh-sci: Add support for r8a77965 (H)SCIF
  dt-bindings: pinctrl: sunxi: Fix reference to driver
  doc: Add vendor prefix for Kieback & Peter GmbH
  spi: sh-msiof: Fix bit field overflow writes to TSCR/RSCR
  MIPS: dts: Boston: Fix PCI bus dtc warnings:
  isofs: fix potential memory leak in mount option parsing
  s390/smsgiucv: disable SMSG on module unload
  MIPS: io: Add barrier after register read in readX()
  fsnotify: fix ignore mask logic in send_to_group()
  perf report: Fix switching to another perf.data file
  nfp: ignore signals when communicating with management FW
  MIPS: io: Prevent compiler reordering writeX()
  x86: Add check for APIC access address for vmentry of L2 guests
  KVM: X86: fix incorrect reference of trace_kvm_pi_irte_update
  Input: synaptics-rmi4 - fix an unchecked out of memory error path
  clocksource/drivers/imx-tpm: Correct some registers operation flow

  stop_machine: Disable preemption when waking two stopper threads

  When cpu_stop_queue_two_works() begins to wake the stopper
  threads, it does so without preemption disabled, which leads
  to the following race condition:

  The source CPU calls cpu_stop_queue_two_works(), with cpu1
  as the source CPU, and cpu2 as the destination CPU. When
  adding the stopper threads to the wake queue used in this
  function, the source CPU stopper thread is added first,
  and the destination CPU stopper thread is added last.

  When wake_up_q() is invoked to wake the stopper threads, the
  threads are woken up in the order that they are queued in,
  so the source CPU's stopper thread is woken up first, and
  it preempts the thread running on the source CPU.

  The stopper thread will then execute on the source CPU,
  disable preemption, and begin executing multi_cpu_stop()
  and wait for an ack from the destination CPU's stopper thread,
  with preemption still disabled. Since the worker thread that
  woke up the stopper thread on the source CPU is affine to the
  source CPU, and preemption is disabled on the source CPU, that
  thread will never run to dequeue the destination CPU's stopper
  thread from the wake queue, and thus, the destination CPU's
  stopper thread will never run, causing the source CPU's stopper
  thread to wait forever, and stall.

  Disable preemption when waking the stopper threads in
  cpu_stop_queue_two_works() to ensure that the worker thread
  that is waking up the stopper threads isn't preempted
  by the source CPU's stopper thread, and permanently
  scheduled out, leaving the remaining stopper thread asleep
  in the wake queue.

Conflicts:
	drivers/gpu/drm/msm/msm_gem.c
	include/linux/sched.h
	kernel/kthread.c

Change-Id: I177cb8516cdfe50d61cb948ed342d330e61376a1
Signed-off-by: Prasad Sodagudi <psodagud@codeaurora.org>
Signed-off-by: Isaac J. Manjarres <isaacm@codeaurora.org>
2018-06-28 09:30:40 -07:00

251 lines
5.9 KiB
C

/*
* Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
* Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
* Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Simple multiplexer clock implementation
*/
#include <linux/clk-provider.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/err.h>
/*
* DOC: basic adjustable multiplexer clock that cannot gate
*
* Traits of this clock:
* prepare - clk_prepare only ensures that parents are prepared
* enable - clk_enable only ensures that parents are enabled
* rate - rate is only affected by parent switching. No clk_set_rate support
* parent - parent is adjustable through clk_set_parent
*/
static u8 clk_mux_get_parent(struct clk_hw *hw)
{
struct clk_mux *mux = to_clk_mux(hw);
int num_parents = clk_hw_get_num_parents(hw);
u32 val;
/*
* FIXME need a mux-specific flag to determine if val is bitwise or numeric
* e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
* to 0x7 (index starts at one)
* OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
* val = 0x4 really means "bit 2, index starts at bit 0"
*/
val = clk_readl(mux->reg) >> mux->shift;
val &= mux->mask;
if (mux->table) {
int i;
for (i = 0; i < num_parents; i++)
if (mux->table[i] == val)
return i;
return -EINVAL;
}
if (val && (mux->flags & CLK_MUX_INDEX_BIT))
val = ffs(val) - 1;
if (val && (mux->flags & CLK_MUX_INDEX_ONE))
val--;
if (val >= num_parents)
return -EINVAL;
return val;
}
static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_mux *mux = to_clk_mux(hw);
u32 val;
unsigned long flags = 0;
if (mux->table) {
index = mux->table[index];
} else {
if (mux->flags & CLK_MUX_INDEX_BIT)
index = 1 << index;
if (mux->flags & CLK_MUX_INDEX_ONE)
index++;
}
if (mux->lock)
spin_lock_irqsave(mux->lock, flags);
else
__acquire(mux->lock);
if (mux->flags & CLK_MUX_HIWORD_MASK) {
val = mux->mask << (mux->shift + 16);
} else {
val = clk_readl(mux->reg);
val &= ~(mux->mask << mux->shift);
}
val |= index << mux->shift;
clk_writel(val, mux->reg);
if (mux->lock)
spin_unlock_irqrestore(mux->lock, flags);
else
__release(mux->lock);
return 0;
}
static int clk_mux_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct clk_mux *mux = to_clk_mux(hw);
return clk_mux_determine_rate_flags(hw, req, mux->flags);
}
const struct clk_ops clk_mux_ops = {
.get_parent = clk_mux_get_parent,
.set_parent = clk_mux_set_parent,
.determine_rate = clk_mux_determine_rate,
};
EXPORT_SYMBOL_GPL(clk_mux_ops);
const struct clk_ops clk_mux_ro_ops = {
.get_parent = clk_mux_get_parent,
};
EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
const char * const *parent_names, u8 num_parents,
unsigned long flags,
void __iomem *reg, u8 shift, u32 mask,
u8 clk_mux_flags, u32 *table, spinlock_t *lock)
{
struct clk_mux *mux;
struct clk_hw *hw;
struct clk_init_data init = {};
u8 width = 0;
int ret;
if (clk_mux_flags & CLK_MUX_HIWORD_MASK) {
width = fls(mask) - ffs(mask) + 1;
if (width + shift > 16) {
pr_err("mux value exceeds LOWORD field\n");
return ERR_PTR(-EINVAL);
}
}
/* allocate the mux */
mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
if (!mux) {
pr_err("%s: could not allocate mux clk\n", __func__);
return ERR_PTR(-ENOMEM);
}
init.name = name;
if (clk_mux_flags & CLK_MUX_READ_ONLY)
init.ops = &clk_mux_ro_ops;
else
init.ops = &clk_mux_ops;
init.flags = flags | CLK_IS_BASIC;
init.parent_names = parent_names;
init.num_parents = num_parents;
/* struct clk_mux assignments */
mux->reg = reg;
mux->shift = shift;
mux->mask = mask;
mux->flags = clk_mux_flags;
mux->lock = lock;
mux->table = table;
mux->hw.init = &init;
hw = &mux->hw;
ret = clk_hw_register(dev, hw);
if (ret) {
kfree(mux);
hw = ERR_PTR(ret);
}
return hw;
}
EXPORT_SYMBOL_GPL(clk_hw_register_mux_table);
struct clk *clk_register_mux_table(struct device *dev, const char *name,
const char * const *parent_names, u8 num_parents,
unsigned long flags,
void __iomem *reg, u8 shift, u32 mask,
u8 clk_mux_flags, u32 *table, spinlock_t *lock)
{
struct clk_hw *hw;
hw = clk_hw_register_mux_table(dev, name, parent_names, num_parents,
flags, reg, shift, mask, clk_mux_flags,
table, lock);
if (IS_ERR(hw))
return ERR_CAST(hw);
return hw->clk;
}
EXPORT_SYMBOL_GPL(clk_register_mux_table);
struct clk *clk_register_mux(struct device *dev, const char *name,
const char * const *parent_names, u8 num_parents,
unsigned long flags,
void __iomem *reg, u8 shift, u8 width,
u8 clk_mux_flags, spinlock_t *lock)
{
u32 mask = BIT(width) - 1;
return clk_register_mux_table(dev, name, parent_names, num_parents,
flags, reg, shift, mask, clk_mux_flags,
NULL, lock);
}
EXPORT_SYMBOL_GPL(clk_register_mux);
struct clk_hw *clk_hw_register_mux(struct device *dev, const char *name,
const char * const *parent_names, u8 num_parents,
unsigned long flags,
void __iomem *reg, u8 shift, u8 width,
u8 clk_mux_flags, spinlock_t *lock)
{
u32 mask = BIT(width) - 1;
return clk_hw_register_mux_table(dev, name, parent_names, num_parents,
flags, reg, shift, mask, clk_mux_flags,
NULL, lock);
}
EXPORT_SYMBOL_GPL(clk_hw_register_mux);
void clk_unregister_mux(struct clk *clk)
{
struct clk_mux *mux;
struct clk_hw *hw;
hw = __clk_get_hw(clk);
if (!hw)
return;
mux = to_clk_mux(hw);
clk_unregister(clk);
kfree(mux);
}
EXPORT_SYMBOL_GPL(clk_unregister_mux);
void clk_hw_unregister_mux(struct clk_hw *hw)
{
struct clk_mux *mux;
mux = to_clk_mux(hw);
clk_hw_unregister(hw);
kfree(mux);
}
EXPORT_SYMBOL_GPL(clk_hw_unregister_mux);