Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 166477
b: refs/heads/master
c: 2c86963
h: refs/heads/master
i:
  166475: cf2c311
v: v3
  • Loading branch information
Tony Luck committed Sep 25, 2009
1 parent 7c32651 commit cfa892b
Show file tree
Hide file tree
Showing 109 changed files with 1,682 additions and 4,617 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0d9df2515dbceb67d343c0f10fd3ff218380d524
refs/heads/master: 2c86963b093c1a0887dfc6b32c6e5ea3a80f2922
48 changes: 21 additions & 27 deletions trunk/Documentation/laptops/thinkpad-acpi.txt
Original file line number Diff line number Diff line change
Expand Up @@ -199,22 +199,18 @@ kind to allow it (and it often doesn't!).

Not all bits in the mask can be modified. Not all bits that can be
modified do anything. Not all hot keys can be individually controlled
by the mask. Some models do not support the mask at all. The behaviour
of the mask is, therefore, highly dependent on the ThinkPad model.

The driver will filter out any unmasked hotkeys, so even if the firmware
doesn't allow disabling an specific hotkey, the driver will not report
events for unmasked hotkeys.
by the mask. Some models do not support the mask at all, and in those
models, hot keys cannot be controlled individually. The behaviour of
the mask is, therefore, highly dependent on the ThinkPad model.

Note that unmasking some keys prevents their default behavior. For
example, if Fn+F5 is unmasked, that key will no longer enable/disable
Bluetooth by itself in firmware.
Bluetooth by itself.

Note also that not all Fn key combinations are supported through ACPI
depending on the ThinkPad model and firmware version. On those
ThinkPads, it is still possible to support some extra hotkeys by
polling the "CMOS NVRAM" at least 10 times per second. The driver
attempts to enables this functionality automatically when required.
Note also that not all Fn key combinations are supported through ACPI.
For example, on the X40, the brightness, volume and "Access IBM" buttons
do not generate ACPI events even with this driver. They *can* be used
through the "ThinkPad Buttons" utility, see http://www.nongnu.org/tpb/

procfs notes:

Expand Down Expand Up @@ -259,11 +255,18 @@ sysfs notes:
1: does nothing

hotkey_mask:
bit mask to enable reporting (and depending on
bit mask to enable driver-handling (and depending on
the firmware, ACPI event generation) for each hot key
(see above). Returns the current status of the hot keys
mask, and allows one to modify it.

Note: when NVRAM polling is active, the firmware mask
will be different from the value returned by
hotkey_mask. The driver will retain enabled bits for
hotkeys that are under NVRAM polling even if the
firmware refuses them, and will not set these bits on
the firmware hot key mask.

hotkey_all_mask:
bit mask that should enable event reporting for all
supported hot keys, when echoed to hotkey_mask above.
Expand All @@ -276,19 +279,17 @@ sysfs notes:
bit mask that should enable event reporting for all
supported hot keys, except those which are always
handled by the firmware anyway. Echo it to
hotkey_mask above, to use. This is the default mask
used by the driver.
hotkey_mask above, to use.

hotkey_source_mask:
bit mask that selects which hot keys will the driver
poll the NVRAM for. This is auto-detected by the driver
based on the capabilities reported by the ACPI firmware,
but it can be overridden at runtime.

Hot keys whose bits are set in hotkey_source_mask are
polled for in NVRAM, and reported as hotkey events if
enabled in hotkey_mask. Only a few hot keys are
available through CMOS NVRAM polling.
Hot keys whose bits are set in both hotkey_source_mask
and also on hotkey_mask are polled for in NVRAM. Only a
few hot keys are available through CMOS NVRAM polling.

Warning: when in NVRAM mode, the volume up/down/mute
keys are synthesized according to changes in the mixer,
Expand Down Expand Up @@ -524,14 +525,14 @@ compatibility purposes when hotkey_report_mode is set to 1.
0x2305 System is waking up from suspend to eject bay
0x2404 System is waking up from hibernation to undock
0x2405 System is waking up from hibernation to eject bay
0x5010 Brightness level changed/control event

The above events are never propagated by the driver.

0x3003 Bay ejection (see 0x2x05) complete, can sleep again
0x4003 Undocked (see 0x2x04), can sleep again
0x500B Tablet pen inserted into its storage bay
0x500C Tablet pen removed from its storage bay
0x5010 Brightness level changed (newer Lenovo BIOSes)

The above events are propagated by the driver.

Expand Down Expand Up @@ -620,8 +621,6 @@ For Lenovo models *with* ACPI backlight control:
2. Do *NOT* load up ACPI video, enable the hotkeys in thinkpad-acpi,
and map them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN. Process
these keys on userspace somehow (e.g. by calling xbacklight).
The driver will do this automatically if it detects that ACPI video
has been disabled.


Bluetooth
Expand Down Expand Up @@ -1460,8 +1459,3 @@ Sysfs interface changelog:
0x020400: Marker for 16 LEDs support. Also, LEDs that are known
to not exist in a given model are not registered with
the LED sysfs class anymore.

0x020500: Updated hotkey driver, hotkey_mask is always available
and it is always able to disable hot keys. Very old
thinkpads are properly supported. hotkey_bios_mask
is deprecated and marked for removal.
1 change: 0 additions & 1 deletion trunk/arch/alpha/kernel/vmlinux.lds.S
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include <asm-generic/vmlinux.lds.h>
#include <asm/thread_info.h>
#include <asm/page.h>
#include <asm/thread_info.h>

Expand Down
2 changes: 0 additions & 2 deletions trunk/arch/arm/kernel/entry-header.S
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@
ldr r0, [sp]
strex r1, r2, [sp] @ clear the exclusive monitor
ldmib sp, {r1 - pc}^ @ load r1 - pc, cpsr
#else
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
#endif
.endm

Expand Down
4 changes: 1 addition & 3 deletions trunk/arch/ia64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ config IOMMU_HELPER
bool

config GENERIC_LOCKBREAK
bool
default y
depends on SMP && PREEMPT
def_bool n

config RWSEM_XCHGADD_ALGORITHM
bool
Expand Down
175 changes: 89 additions & 86 deletions trunk/arch/ia64/include/asm/spinlock.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,103 +19,106 @@

#define __raw_spin_lock_init(x) ((x)->lock = 0)

#ifdef ASM_SUPPORTED
/*
* Try to get the lock. If we fail to get the lock, make a non-standard call to
* ia64_spinlock_contention(). We do not use a normal call because that would force all
* callers of __raw_spin_lock() to be non-leaf routines. Instead, ia64_spinlock_contention() is
* carefully coded to touch only those registers that __raw_spin_lock() marks "clobbered".
* Ticket locks are conceptually two parts, one indicating the current head of
* the queue, and the other indicating the current tail. The lock is acquired
* by atomically noting the tail and incrementing it by one (thus adding
* ourself to the queue and noting our position), then waiting until the head
* becomes equal to the the initial value of the tail.
*
* 63 32 31 0
* +----------------------------------------------------+
* | next_ticket_number | now_serving |
* +----------------------------------------------------+
*/

#define IA64_SPINLOCK_CLOBBERS "ar.ccv", "ar.pfs", "p14", "p15", "r27", "r28", "r29", "r30", "b6", "memory"
#define TICKET_SHIFT 32

static inline void
__raw_spin_lock_flags (raw_spinlock_t *lock, unsigned long flags)
static __always_inline void __ticket_spin_lock(raw_spinlock_t *lock)
{
register volatile unsigned int *ptr asm ("r31") = &lock->lock;

#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
# ifdef CONFIG_ITANIUM
/* don't use brl on Itanium... */
asm volatile ("{\n\t"
" mov ar.ccv = r0\n\t"
" mov r28 = ip\n\t"
" mov r30 = 1;;\n\t"
"}\n\t"
"cmpxchg4.acq r30 = [%1], r30, ar.ccv\n\t"
"movl r29 = ia64_spinlock_contention_pre3_4;;\n\t"
"cmp4.ne p14, p0 = r30, r0\n\t"
"mov b6 = r29;;\n\t"
"mov r27=%2\n\t"
"(p14) br.cond.spnt.many b6"
: "=r"(ptr) : "r"(ptr), "r" (flags) : IA64_SPINLOCK_CLOBBERS);
# else
asm volatile ("{\n\t"
" mov ar.ccv = r0\n\t"
" mov r28 = ip\n\t"
" mov r30 = 1;;\n\t"
"}\n\t"
"cmpxchg4.acq r30 = [%1], r30, ar.ccv;;\n\t"
"cmp4.ne p14, p0 = r30, r0\n\t"
"mov r27=%2\n\t"
"(p14) brl.cond.spnt.many ia64_spinlock_contention_pre3_4;;"
: "=r"(ptr) : "r"(ptr), "r" (flags) : IA64_SPINLOCK_CLOBBERS);
# endif /* CONFIG_MCKINLEY */
#else
# ifdef CONFIG_ITANIUM
/* don't use brl on Itanium... */
/* mis-declare, so we get the entry-point, not it's function descriptor: */
asm volatile ("mov r30 = 1\n\t"
"mov r27=%2\n\t"
"mov ar.ccv = r0;;\n\t"
"cmpxchg4.acq r30 = [%0], r30, ar.ccv\n\t"
"movl r29 = ia64_spinlock_contention;;\n\t"
"cmp4.ne p14, p0 = r30, r0\n\t"
"mov b6 = r29;;\n\t"
"(p14) br.call.spnt.many b6 = b6"
: "=r"(ptr) : "r"(ptr), "r" (flags) : IA64_SPINLOCK_CLOBBERS);
# else
asm volatile ("mov r30 = 1\n\t"
"mov r27=%2\n\t"
"mov ar.ccv = r0;;\n\t"
"cmpxchg4.acq r30 = [%0], r30, ar.ccv;;\n\t"
"cmp4.ne p14, p0 = r30, r0\n\t"
"(p14) brl.call.spnt.many b6=ia64_spinlock_contention;;"
: "=r"(ptr) : "r"(ptr), "r" (flags) : IA64_SPINLOCK_CLOBBERS);
# endif /* CONFIG_MCKINLEY */
#endif
int *p = (int *)&lock->lock, turn, now_serving;

now_serving = *p;
turn = ia64_fetchadd(1, p+1, acq);

if (turn == now_serving)
return;

do {
cpu_relax();
} while (ACCESS_ONCE(*p) != turn);
}

#define __raw_spin_lock(lock) __raw_spin_lock_flags(lock, 0)
static __always_inline int __ticket_spin_trylock(raw_spinlock_t *lock)
{
long tmp = ACCESS_ONCE(lock->lock), try;

/* Unlock by doing an ordered store and releasing the cacheline with nta */
static inline void __raw_spin_unlock(raw_spinlock_t *x) {
barrier();
asm volatile ("st4.rel.nta [%0] = r0\n\t" :: "r"(x));
if (!(((tmp >> TICKET_SHIFT) ^ tmp) & ((1L << TICKET_SHIFT) - 1))) {
try = tmp + (1L << TICKET_SHIFT);

return ia64_cmpxchg(acq, &lock->lock, tmp, try, sizeof (tmp)) == tmp;
}
return 0;
}

#else /* !ASM_SUPPORTED */
#define __raw_spin_lock_flags(lock, flags) __raw_spin_lock(lock)
# define __raw_spin_lock(x) \
do { \
__u32 *ia64_spinlock_ptr = (__u32 *) (x); \
__u64 ia64_spinlock_val; \
ia64_spinlock_val = ia64_cmpxchg4_acq(ia64_spinlock_ptr, 1, 0); \
if (unlikely(ia64_spinlock_val)) { \
do { \
while (*ia64_spinlock_ptr) \
ia64_barrier(); \
ia64_spinlock_val = ia64_cmpxchg4_acq(ia64_spinlock_ptr, 1, 0); \
} while (ia64_spinlock_val); \
} \
} while (0)
#define __raw_spin_unlock(x) do { barrier(); ((raw_spinlock_t *) x)->lock = 0; } while (0)
#endif /* !ASM_SUPPORTED */
static __always_inline void __ticket_spin_unlock(raw_spinlock_t *lock)
{
int *p = (int *)&lock->lock;

(void)ia64_fetchadd(1, p, rel);
}

static inline int __ticket_spin_is_locked(raw_spinlock_t *lock)
{
long tmp = ACCESS_ONCE(lock->lock);

return !!(((tmp >> TICKET_SHIFT) ^ tmp) & ((1L << TICKET_SHIFT) - 1));
}

static inline int __ticket_spin_is_contended(raw_spinlock_t *lock)
{
long tmp = ACCESS_ONCE(lock->lock);

#define __raw_spin_is_locked(x) ((x)->lock != 0)
#define __raw_spin_trylock(x) (cmpxchg_acq(&(x)->lock, 0, 1) == 0)
#define __raw_spin_unlock_wait(lock) \
do { while (__raw_spin_is_locked(lock)) cpu_relax(); } while (0)
return (((tmp >> TICKET_SHIFT) - tmp) & ((1L << TICKET_SHIFT) - 1)) > 1;
}

static inline int __raw_spin_is_locked(raw_spinlock_t *lock)
{
return __ticket_spin_is_locked(lock);
}

static inline int __raw_spin_is_contended(raw_spinlock_t *lock)
{
return __ticket_spin_is_contended(lock);
}
#define __raw_spin_is_contended __raw_spin_is_contended

static __always_inline void __raw_spin_lock(raw_spinlock_t *lock)
{
__ticket_spin_lock(lock);
}

static __always_inline int __raw_spin_trylock(raw_spinlock_t *lock)
{
return __ticket_spin_trylock(lock);
}

static __always_inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
__ticket_spin_unlock(lock);
}

static __always_inline void __raw_spin_lock_flags(raw_spinlock_t *lock,
unsigned long flags)
{
__raw_spin_lock(lock);
}

static inline void __raw_spin_unlock_wait(raw_spinlock_t *lock)
{
while (__raw_spin_is_locked(lock))
cpu_relax();
}

#define __raw_read_can_lock(rw) (*(volatile int *)(rw) >= 0)
#define __raw_write_can_lock(rw) (*(volatile int *)(rw) == 0)
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/ia64/include/asm/spinlock_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#endif

typedef struct {
volatile unsigned int lock;
volatile unsigned long lock;
} raw_spinlock_t;

#define __RAW_SPIN_LOCK_UNLOCKED { 0 }
Expand Down
Loading

0 comments on commit cfa892b

Please sign in to comment.