summaryrefslogtreecommitdiffstats
path: root/arch/sparc/include/asm/backoff.h
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2012-11-16 16:59:17 +0100
committerArnd Bergmann <arnd@arndb.de>2012-11-16 16:59:17 +0100
commitdb2f95de7e6ab3d5cd7cc047bb09eb9ada07e3ba (patch)
tree46543712dbbb15075f7532621b0311f1de653e57 /arch/sparc/include/asm/backoff.h
parent1bf0bc1e050fc425cc776b10d3ce8754389aabbe (diff)
parentd6aef84a48fa54ac606ae719fcd125199939f43d (diff)
Merge tag 'imx-soc' of git://git.pengutronix.de/git/imx/linux-2.6 into next/soc
From Sascha Hauer <s.hauer@pengutronix.de>: ARM i.MX SoC updates based on imx-multiplatform branch. * tag 'imx-soc' of git://git.pengutronix.de/git/imx/linux-2.6: ARM i.MX51 babbage: Add display support ARM i.MX6: Add IPU support ARM i.MX51: Add IPU support ARM i.MX53: Add IPU support ARM i.MX5: switch IPU clk support to devicetree bindings ARM i.MX6: fix ldb_di_sel mux ARM i.MX51: setup MIPI during startup mx2_camera: Fix regression caused by clock conversion ARM: clk-imx27: Add missing clock for mx2-camera ARM i.MX27: Fix low reference clock path ARM: dts: imx27-3ds: Remove local watchdog inclusion watchdog: Support imx watchdog on SOC_IMX53 ARM: mach-imx: Support for DryIce RTC in i.MX53 ARM : i.MX27 : split code for allocation of ressources of camera and eMMA Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'arch/sparc/include/asm/backoff.h')
-rw-r--r--arch/sparc/include/asm/backoff.h69
1 files changed, 59 insertions, 10 deletions
diff --git a/arch/sparc/include/asm/backoff.h b/arch/sparc/include/asm/backoff.h
index db3af0d30fb..4e02086b839 100644
--- a/arch/sparc/include/asm/backoff.h
+++ b/arch/sparc/include/asm/backoff.h
@@ -1,6 +1,46 @@
#ifndef _SPARC64_BACKOFF_H
#define _SPARC64_BACKOFF_H
+/* The macros in this file implement an exponential backoff facility
+ * for atomic operations.
+ *
+ * When multiple threads compete on an atomic operation, it is
+ * possible for one thread to be continually denied a successful
+ * completion of the compare-and-swap instruction. Heavily
+ * threaded cpu implementations like Niagara can compound this
+ * problem even further.
+ *
+ * When an atomic operation fails and needs to be retried, we spin a
+ * certain number of times. At each subsequent failure of the same
+ * operation we double the spin count, realizing an exponential
+ * backoff.
+ *
+ * When we spin, we try to use an operation that will cause the
+ * current cpu strand to block, and therefore make the core fully
+ * available to any other other runnable strands. There are two
+ * options, based upon cpu capabilities.
+ *
+ * On all cpus prior to SPARC-T4 we do three dummy reads of the
+ * condition code register. Each read blocks the strand for something
+ * between 40 and 50 cpu cycles.
+ *
+ * For SPARC-T4 and later we have a special "pause" instruction
+ * available. This is implemented using writes to register %asr27.
+ * The cpu will block the number of cycles written into the register,
+ * unless a disrupting trap happens first. SPARC-T4 specifically
+ * implements pause with a granularity of 8 cycles. Each strand has
+ * an internal pause counter which decrements every 8 cycles. So the
+ * chip shifts the %asr27 value down by 3 bits, and writes the result
+ * into the pause counter. If a value smaller than 8 is written, the
+ * chip blocks for 1 cycle.
+ *
+ * To achieve the same amount of backoff as the three %ccr reads give
+ * on earlier chips, we shift the backoff value up by 7 bits. (Three
+ * %ccr reads block for about 128 cycles, 1 << 7 == 128) We write the
+ * whole amount we want to block into the pause register, rather than
+ * loop writing 128 each time.
+ */
+
#define BACKOFF_LIMIT (4 * 1024)
#ifdef CONFIG_SMP
@@ -11,16 +51,25 @@
#define BACKOFF_LABEL(spin_label, continue_label) \
spin_label
-#define BACKOFF_SPIN(reg, tmp, label) \
- mov reg, tmp; \
-88: brnz,pt tmp, 88b; \
- sub tmp, 1, tmp; \
- set BACKOFF_LIMIT, tmp; \
- cmp reg, tmp; \
- bg,pn %xcc, label; \
- nop; \
- ba,pt %xcc, label; \
- sllx reg, 1, reg;
+#define BACKOFF_SPIN(reg, tmp, label) \
+ mov reg, tmp; \
+88: rd %ccr, %g0; \
+ rd %ccr, %g0; \
+ rd %ccr, %g0; \
+ .section .pause_3insn_patch,"ax";\
+ .word 88b; \
+ sllx tmp, 7, tmp; \
+ wr tmp, 0, %asr27; \
+ clr tmp; \
+ .previous; \
+ brnz,pt tmp, 88b; \
+ sub tmp, 1, tmp; \
+ set BACKOFF_LIMIT, tmp; \
+ cmp reg, tmp; \
+ bg,pn %xcc, label; \
+ nop; \
+ ba,pt %xcc, label; \
+ sllx reg, 1, reg;
#else