Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
This commit is contained in:
commit
0a2f38193d
|
@ -1676,8 +1676,7 @@ F: kernel/cgroup*
|
|||
F: mm/*cgroup*
|
||||
|
||||
CORETEMP HARDWARE MONITORING DRIVER
|
||||
M: Rudolf Marek <r.marek@assembler.cz>
|
||||
M: Huaxu Wan <huaxu.wan@intel.com>
|
||||
M: Fenghua Yu <fenghua.yu@intel.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/coretemp
|
||||
|
|
|
@ -279,13 +279,13 @@ static void __init eukrea_cpuimx27_init(void)
|
|||
#if defined(CONFIG_USB_ULPI)
|
||||
if (otg_mode_host) {
|
||||
otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
|
||||
USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
|
||||
ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
|
||||
|
||||
mxc_register_device(&mxc_otg_host, &otg_pdata);
|
||||
}
|
||||
|
||||
usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
|
||||
USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
|
||||
ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
|
||||
|
||||
mxc_register_device(&mxc_usbh2, &usbh2_pdata);
|
||||
#endif
|
||||
|
|
|
@ -419,13 +419,13 @@ static void __init pca100_init(void)
|
|||
#if defined(CONFIG_USB_ULPI)
|
||||
if (otg_mode_host) {
|
||||
otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
|
||||
USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
|
||||
ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
|
||||
|
||||
mxc_register_device(&mxc_otg_host, &otg_pdata);
|
||||
}
|
||||
|
||||
usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
|
||||
USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
|
||||
ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
|
||||
|
||||
mxc_register_device(&mxc_usbh2, &usbh2_pdata);
|
||||
#endif
|
||||
|
|
|
@ -138,7 +138,7 @@ static void __init eukrea_cpuimx25_init(void)
|
|||
#if defined(CONFIG_USB_ULPI)
|
||||
if (otg_mode_host) {
|
||||
otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
|
||||
USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
|
||||
ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
|
||||
|
||||
mxc_register_device(&mxc_otg, &otg_pdata);
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ static void __init mxc_board_init(void)
|
|||
#if defined(CONFIG_USB_ULPI)
|
||||
if (otg_mode_host) {
|
||||
otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
|
||||
USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
|
||||
ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
|
||||
|
||||
mxc_register_device(&mxc_otg_host, &otg_pdata);
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/
|
|||
all: zImage
|
||||
|
||||
# With make 3.82 we cannot mix normal and wildcard targets
|
||||
BOOT_TARGETS1 := zImage zImage.initrd uImaged
|
||||
BOOT_TARGETS1 := zImage zImage.initrd uImage
|
||||
BOOT_TARGETS2 := zImage% dtbImage% treeImage.% cuImage.% simpleImage.%
|
||||
|
||||
PHONY += $(BOOT_TARGETS1) $(BOOT_TARGETS2)
|
||||
|
|
|
@ -163,6 +163,14 @@
|
|||
interrupts = <0x1e 4>;
|
||||
};
|
||||
|
||||
SATA0: sata@bffd1000 {
|
||||
compatible = "amcc,sata-460ex";
|
||||
reg = <4 0xbffd1000 0x800 4 0xbffd0800 0x400>;
|
||||
interrupt-parent = <&UIC3>;
|
||||
interrupts = <0x0 0x4 /* SATA */
|
||||
0x5 0x4>; /* AHBDMA */
|
||||
};
|
||||
|
||||
POB0: opb {
|
||||
compatible = "ibm,opb-460ex", "ibm,opb";
|
||||
#address-cells = <1>;
|
||||
|
|
|
@ -433,7 +433,7 @@ typedef struct {
|
|||
* with. However gcc is not clever enough to compute the
|
||||
* modulus (2^n-1) without a second multiply.
|
||||
*/
|
||||
#define vsid_scrample(protovsid, size) \
|
||||
#define vsid_scramble(protovsid, size) \
|
||||
((((protovsid) * VSID_MULTIPLIER_##size) % VSID_MODULUS_##size))
|
||||
|
||||
#else /* 1 */
|
||||
|
|
|
@ -951,7 +951,14 @@
|
|||
#ifdef CONFIG_PPC64
|
||||
|
||||
extern void ppc64_runlatch_on(void);
|
||||
extern void ppc64_runlatch_off(void);
|
||||
extern void __ppc64_runlatch_off(void);
|
||||
|
||||
#define ppc64_runlatch_off() \
|
||||
do { \
|
||||
if (cpu_has_feature(CPU_FTR_CTRL) && \
|
||||
test_thread_flag(TIF_RUNLATCH)) \
|
||||
__ppc64_runlatch_off(); \
|
||||
} while (0)
|
||||
|
||||
extern unsigned long scom970_read(unsigned int address);
|
||||
extern void scom970_write(unsigned int address, unsigned long value);
|
||||
|
|
|
@ -21,15 +21,20 @@
|
|||
/*
|
||||
* the semaphore definition
|
||||
*/
|
||||
struct rw_semaphore {
|
||||
/* XXX this should be able to be an atomic_t -- paulus */
|
||||
signed int count;
|
||||
#define RWSEM_UNLOCKED_VALUE 0x00000000
|
||||
#define RWSEM_ACTIVE_BIAS 0x00000001
|
||||
#define RWSEM_ACTIVE_MASK 0x0000ffff
|
||||
#define RWSEM_WAITING_BIAS (-0x00010000)
|
||||
#ifdef CONFIG_PPC64
|
||||
# define RWSEM_ACTIVE_MASK 0xffffffffL
|
||||
#else
|
||||
# define RWSEM_ACTIVE_MASK 0x0000ffffL
|
||||
#endif
|
||||
|
||||
#define RWSEM_UNLOCKED_VALUE 0x00000000L
|
||||
#define RWSEM_ACTIVE_BIAS 0x00000001L
|
||||
#define RWSEM_WAITING_BIAS (-RWSEM_ACTIVE_MASK-1)
|
||||
#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
|
||||
#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
|
||||
|
||||
struct rw_semaphore {
|
||||
long count;
|
||||
spinlock_t wait_lock;
|
||||
struct list_head wait_list;
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
|
@ -43,9 +48,13 @@ struct rw_semaphore {
|
|||
# define __RWSEM_DEP_MAP_INIT(lockname)
|
||||
#endif
|
||||
|
||||
#define __RWSEM_INITIALIZER(name) \
|
||||
{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
|
||||
LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
|
||||
#define __RWSEM_INITIALIZER(name) \
|
||||
{ \
|
||||
RWSEM_UNLOCKED_VALUE, \
|
||||
__SPIN_LOCK_UNLOCKED((name).wait_lock), \
|
||||
LIST_HEAD_INIT((name).wait_list) \
|
||||
__RWSEM_DEP_MAP_INIT(name) \
|
||||
}
|
||||
|
||||
#define DECLARE_RWSEM(name) \
|
||||
struct rw_semaphore name = __RWSEM_INITIALIZER(name)
|
||||
|
@ -70,13 +79,13 @@ extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
|
|||
*/
|
||||
static inline void __down_read(struct rw_semaphore *sem)
|
||||
{
|
||||
if (unlikely(atomic_inc_return((atomic_t *)(&sem->count)) <= 0))
|
||||
if (unlikely(atomic_long_inc_return((atomic_long_t *)&sem->count) <= 0))
|
||||
rwsem_down_read_failed(sem);
|
||||
}
|
||||
|
||||
static inline int __down_read_trylock(struct rw_semaphore *sem)
|
||||
{
|
||||
int tmp;
|
||||
long tmp;
|
||||
|
||||
while ((tmp = sem->count) >= 0) {
|
||||
if (tmp == cmpxchg(&sem->count, tmp,
|
||||
|
@ -92,10 +101,10 @@ static inline int __down_read_trylock(struct rw_semaphore *sem)
|
|||
*/
|
||||
static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
|
||||
{
|
||||
int tmp;
|
||||
long tmp;
|
||||
|
||||
tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
|
||||
(atomic_t *)(&sem->count));
|
||||
tmp = atomic_long_add_return(RWSEM_ACTIVE_WRITE_BIAS,
|
||||
(atomic_long_t *)&sem->count);
|
||||
if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS))
|
||||
rwsem_down_write_failed(sem);
|
||||
}
|
||||
|
@ -107,7 +116,7 @@ static inline void __down_write(struct rw_semaphore *sem)
|
|||
|
||||
static inline int __down_write_trylock(struct rw_semaphore *sem)
|
||||
{
|
||||
int tmp;
|
||||
long tmp;
|
||||
|
||||
tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
|
||||
RWSEM_ACTIVE_WRITE_BIAS);
|
||||
|
@ -119,9 +128,9 @@ static inline int __down_write_trylock(struct rw_semaphore *sem)
|
|||
*/
|
||||
static inline void __up_read(struct rw_semaphore *sem)
|
||||
{
|
||||
int tmp;
|
||||
long tmp;
|
||||
|
||||
tmp = atomic_dec_return((atomic_t *)(&sem->count));
|
||||
tmp = atomic_long_dec_return((atomic_long_t *)&sem->count);
|
||||
if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0))
|
||||
rwsem_wake(sem);
|
||||
}
|
||||
|
@ -131,17 +140,17 @@ static inline void __up_read(struct rw_semaphore *sem)
|
|||
*/
|
||||
static inline void __up_write(struct rw_semaphore *sem)
|
||||
{
|
||||
if (unlikely(atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
|
||||
(atomic_t *)(&sem->count)) < 0))
|
||||
if (unlikely(atomic_long_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
|
||||
(atomic_long_t *)&sem->count) < 0))
|
||||
rwsem_wake(sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* implement atomic add functionality
|
||||
*/
|
||||
static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
|
||||
static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
|
||||
{
|
||||
atomic_add(delta, (atomic_t *)(&sem->count));
|
||||
atomic_long_add(delta, (atomic_long_t *)&sem->count);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -149,9 +158,10 @@ static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
|
|||
*/
|
||||
static inline void __downgrade_write(struct rw_semaphore *sem)
|
||||
{
|
||||
int tmp;
|
||||
long tmp;
|
||||
|
||||
tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
|
||||
tmp = atomic_long_add_return(-RWSEM_WAITING_BIAS,
|
||||
(atomic_long_t *)&sem->count);
|
||||
if (tmp < 0)
|
||||
rwsem_downgrade_wake(sem);
|
||||
}
|
||||
|
@ -159,14 +169,14 @@ static inline void __downgrade_write(struct rw_semaphore *sem)
|
|||
/*
|
||||
* implement exchange and add functionality
|
||||
*/
|
||||
static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
|
||||
static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
|
||||
{
|
||||
return atomic_add_return(delta, (atomic_t *)(&sem->count));
|
||||
return atomic_long_add_return(delta, (atomic_long_t *)&sem->count);
|
||||
}
|
||||
|
||||
static inline int rwsem_is_locked(struct rw_semaphore *sem)
|
||||
{
|
||||
return (sem->count != 0);
|
||||
return sem->count != 0;
|
||||
}
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
|
|
@ -326,3 +326,6 @@ SYSCALL_SPU(perf_event_open)
|
|||
COMPAT_SYS_SPU(preadv)
|
||||
COMPAT_SYS_SPU(pwritev)
|
||||
COMPAT_SYS(rt_tgsigqueueinfo)
|
||||
SYSCALL(fanotify_init)
|
||||
COMPAT_SYS(fanotify_mark)
|
||||
SYSCALL_SPU(prlimit64)
|
||||
|
|
|
@ -345,10 +345,13 @@
|
|||
#define __NR_preadv 320
|
||||
#define __NR_pwritev 321
|
||||
#define __NR_rt_tgsigqueueinfo 322
|
||||
#define __NR_fanotify_init 323
|
||||
#define __NR_fanotify_mark 324
|
||||
#define __NR_prlimit64 325
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#define __NR_syscalls 323
|
||||
#define __NR_syscalls 326
|
||||
|
||||
#define __NR__exit __NR_exit
|
||||
#define NR_syscalls __NR_syscalls
|
||||
|
|
|
@ -1826,7 +1826,6 @@ static struct cpu_spec __initdata cpu_specs[] = {
|
|||
.cpu_features = CPU_FTRS_47X,
|
||||
.cpu_user_features = COMMON_USER_BOOKE |
|
||||
PPC_FEATURE_HAS_FPU,
|
||||
.cpu_user_features = COMMON_USER_BOOKE,
|
||||
.mmu_features = MMU_FTR_TYPE_47x |
|
||||
MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL,
|
||||
.icache_bsize = 32,
|
||||
|
|
|
@ -402,6 +402,18 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
|
|||
*/
|
||||
hard_irq_disable();
|
||||
|
||||
/*
|
||||
* Make a note of crashing cpu. Will be used in machine_kexec
|
||||
* such that another IPI will not be sent.
|
||||
*/
|
||||
crashing_cpu = smp_processor_id();
|
||||
crash_save_cpu(regs, crashing_cpu);
|
||||
crash_kexec_prepare_cpus(crashing_cpu);
|
||||
cpu_set(crashing_cpu, cpus_in_crash);
|
||||
#if defined(CONFIG_PPC_STD_MMU_64) && defined(CONFIG_SMP)
|
||||
crash_kexec_wait_realmode(crashing_cpu);
|
||||
#endif
|
||||
|
||||
for_each_irq(i) {
|
||||
struct irq_desc *desc = irq_to_desc(i);
|
||||
|
||||
|
@ -438,18 +450,8 @@ void default_machine_crash_shutdown(struct pt_regs *regs)
|
|||
crash_shutdown_cpu = -1;
|
||||
__debugger_fault_handler = old_handler;
|
||||
|
||||
/*
|
||||
* Make a note of crashing cpu. Will be used in machine_kexec
|
||||
* such that another IPI will not be sent.
|
||||
*/
|
||||
crashing_cpu = smp_processor_id();
|
||||
crash_save_cpu(regs, crashing_cpu);
|
||||
crash_kexec_prepare_cpus(crashing_cpu);
|
||||
cpu_set(crashing_cpu, cpus_in_crash);
|
||||
crash_kexec_stop_spus();
|
||||
#if defined(CONFIG_PPC_STD_MMU_64) && defined(CONFIG_SMP)
|
||||
crash_kexec_wait_realmode(crashing_cpu);
|
||||
#endif
|
||||
|
||||
if (ppc_md.kexec_cpu_down)
|
||||
ppc_md.kexec_cpu_down(1, 0);
|
||||
}
|
||||
|
|
|
@ -113,6 +113,10 @@ _ENTRY(_start);
|
|||
stw r5, 0(r4) /* Save abatron_pteptrs at a fixed location */
|
||||
stw r6, 0(r5)
|
||||
|
||||
/* Clear the Machine Check Syndrome Register */
|
||||
li r0,0
|
||||
mtspr SPRN_MCSR,r0
|
||||
|
||||
/* Let's move on */
|
||||
lis r4,start_kernel@h
|
||||
ori r4,r4,start_kernel@l
|
||||
|
|
|
@ -572,9 +572,6 @@ __secondary_start:
|
|||
/* Set thread priority to MEDIUM */
|
||||
HMT_MEDIUM
|
||||
|
||||
/* Do early setup for that CPU (stab, slb, hash table pointer) */
|
||||
bl .early_setup_secondary
|
||||
|
||||
/* Initialize the kernel stack. Just a repeat for iSeries. */
|
||||
LOAD_REG_ADDR(r3, current_set)
|
||||
sldi r28,r24,3 /* get current_set[cpu#] */
|
||||
|
@ -582,6 +579,9 @@ __secondary_start:
|
|||
addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
|
||||
std r1,PACAKSAVE(r13)
|
||||
|
||||
/* Do early setup for that CPU (stab, slb, hash table pointer) */
|
||||
bl .early_setup_secondary
|
||||
|
||||
/* Clear backchain so we get nice backtraces */
|
||||
li r7,0
|
||||
mtlr r7
|
||||
|
|
|
@ -94,9 +94,9 @@ void cpu_idle(void)
|
|||
HMT_medium();
|
||||
ppc64_runlatch_on();
|
||||
tick_nohz_restart_sched_tick();
|
||||
preempt_enable_no_resched();
|
||||
if (cpu_should_die())
|
||||
cpu_die();
|
||||
preempt_enable_no_resched();
|
||||
schedule();
|
||||
preempt_disable();
|
||||
}
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
#include <asm/machdep.h>
|
||||
#include <asm/udbg.h>
|
||||
#include <asm/dbell.h>
|
||||
#include <asm/smp.h>
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#include <asm/paca.h>
|
||||
|
@ -446,22 +447,23 @@ struct thread_info *mcheckirq_ctx[NR_CPUS] __read_mostly;
|
|||
void exc_lvl_ctx_init(void)
|
||||
{
|
||||
struct thread_info *tp;
|
||||
int i;
|
||||
int i, hw_cpu;
|
||||
|
||||
for_each_possible_cpu(i) {
|
||||
memset((void *)critirq_ctx[i], 0, THREAD_SIZE);
|
||||
tp = critirq_ctx[i];
|
||||
hw_cpu = get_hard_smp_processor_id(i);
|
||||
memset((void *)critirq_ctx[hw_cpu], 0, THREAD_SIZE);
|
||||
tp = critirq_ctx[hw_cpu];
|
||||
tp->cpu = i;
|
||||
tp->preempt_count = 0;
|
||||
|
||||
#ifdef CONFIG_BOOKE
|
||||
memset((void *)dbgirq_ctx[i], 0, THREAD_SIZE);
|
||||
tp = dbgirq_ctx[i];
|
||||
memset((void *)dbgirq_ctx[hw_cpu], 0, THREAD_SIZE);
|
||||
tp = dbgirq_ctx[hw_cpu];
|
||||
tp->cpu = i;
|
||||
tp->preempt_count = 0;
|
||||
|
||||
memset((void *)mcheckirq_ctx[i], 0, THREAD_SIZE);
|
||||
tp = mcheckirq_ctx[i];
|
||||
memset((void *)mcheckirq_ctx[hw_cpu], 0, THREAD_SIZE);
|
||||
tp = mcheckirq_ctx[hw_cpu];
|
||||
tp->cpu = i;
|
||||
tp->preempt_count = HARDIRQ_OFFSET;
|
||||
#endif
|
||||
|
|
|
@ -336,7 +336,7 @@ static void __devinit __of_scan_bus(struct device_node *node,
|
|||
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
|
||||
dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
|
||||
struct device_node *child = pci_device_to_OF_node(dev);
|
||||
if (dev)
|
||||
if (child)
|
||||
of_scan_pci_bridge(child, dev);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -728,7 +728,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
|
|||
p->thread.regs = childregs;
|
||||
if (clone_flags & CLONE_SETTLS) {
|
||||
#ifdef CONFIG_PPC64
|
||||
if (!test_thread_flag(TIF_32BIT))
|
||||
if (!is_32bit_task())
|
||||
childregs->gpr[13] = childregs->gpr[6];
|
||||
else
|
||||
#endif
|
||||
|
@ -823,7 +823,7 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp)
|
|||
regs->nip = start;
|
||||
regs->msr = MSR_USER;
|
||||
#else
|
||||
if (!test_thread_flag(TIF_32BIT)) {
|
||||
if (!is_32bit_task()) {
|
||||
unsigned long entry, toc;
|
||||
|
||||
/* start is a relocated pointer to the function descriptor for
|
||||
|
@ -995,7 +995,7 @@ int sys_clone(unsigned long clone_flags, unsigned long usp,
|
|||
if (usp == 0)
|
||||
usp = regs->gpr[1]; /* stack pointer for child */
|
||||
#ifdef CONFIG_PPC64
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
if (is_32bit_task()) {
|
||||
parent_tidp = TRUNC_PTR(parent_tidp);
|
||||
child_tidp = TRUNC_PTR(child_tidp);
|
||||
}
|
||||
|
@ -1199,19 +1199,17 @@ void ppc64_runlatch_on(void)
|
|||
}
|
||||
}
|
||||
|
||||
void ppc64_runlatch_off(void)
|
||||
void __ppc64_runlatch_off(void)
|
||||
{
|
||||
unsigned long ctrl;
|
||||
|
||||
if (cpu_has_feature(CPU_FTR_CTRL) && test_thread_flag(TIF_RUNLATCH)) {
|
||||
HMT_medium();
|
||||
HMT_medium();
|
||||
|
||||
clear_thread_flag(TIF_RUNLATCH);
|
||||
clear_thread_flag(TIF_RUNLATCH);
|
||||
|
||||
ctrl = mfspr(SPRN_CTRLF);
|
||||
ctrl &= ~CTRL_RUNLATCH;
|
||||
mtspr(SPRN_CTRLT, ctrl);
|
||||
}
|
||||
ctrl = mfspr(SPRN_CTRLF);
|
||||
ctrl &= ~CTRL_RUNLATCH;
|
||||
mtspr(SPRN_CTRLT, ctrl);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -258,17 +258,18 @@ static void __init irqstack_early_init(void)
|
|||
#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
|
||||
static void __init exc_lvl_early_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int i, hw_cpu;
|
||||
|
||||
/* interrupt stacks must be in lowmem, we get that for free on ppc32
|
||||
* as the memblock is limited to lowmem by MEMBLOCK_REAL_LIMIT */
|
||||
for_each_possible_cpu(i) {
|
||||
critirq_ctx[i] = (struct thread_info *)
|
||||
hw_cpu = get_hard_smp_processor_id(i);
|
||||
critirq_ctx[hw_cpu] = (struct thread_info *)
|
||||
__va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
|
||||
#ifdef CONFIG_BOOKE
|
||||
dbgirq_ctx[i] = (struct thread_info *)
|
||||
dbgirq_ctx[hw_cpu] = (struct thread_info *)
|
||||
__va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
|
||||
mcheckirq_ctx[i] = (struct thread_info *)
|
||||
mcheckirq_ctx[hw_cpu] = (struct thread_info *)
|
||||
__va(memblock_alloc(THREAD_SIZE, THREAD_SIZE));
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ int ucache_bsize;
|
|||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
static int smt_enabled_cmdline;
|
||||
static char *smt_enabled_cmdline;
|
||||
|
||||
/* Look for ibm,smt-enabled OF option */
|
||||
static void check_smt_enabled(void)
|
||||
|
@ -103,37 +103,46 @@ static void check_smt_enabled(void)
|
|||
struct device_node *dn;
|
||||
const char *smt_option;
|
||||
|
||||
/* Default to enabling all threads */
|
||||
smt_enabled_at_boot = threads_per_core;
|
||||
|
||||
/* Allow the command line to overrule the OF option */
|
||||
if (smt_enabled_cmdline)
|
||||
return;
|
||||
if (smt_enabled_cmdline) {
|
||||
if (!strcmp(smt_enabled_cmdline, "on"))
|
||||
smt_enabled_at_boot = threads_per_core;
|
||||
else if (!strcmp(smt_enabled_cmdline, "off"))
|
||||
smt_enabled_at_boot = 0;
|
||||
else {
|
||||
long smt;
|
||||
int rc;
|
||||
|
||||
dn = of_find_node_by_path("/options");
|
||||
rc = strict_strtol(smt_enabled_cmdline, 10, &smt);
|
||||
if (!rc)
|
||||
smt_enabled_at_boot =
|
||||
min(threads_per_core, (int)smt);
|
||||
}
|
||||
} else {
|
||||
dn = of_find_node_by_path("/options");
|
||||
if (dn) {
|
||||
smt_option = of_get_property(dn, "ibm,smt-enabled",
|
||||
NULL);
|
||||
|
||||
if (dn) {
|
||||
smt_option = of_get_property(dn, "ibm,smt-enabled", NULL);
|
||||
if (smt_option) {
|
||||
if (!strcmp(smt_option, "on"))
|
||||
smt_enabled_at_boot = threads_per_core;
|
||||
else if (!strcmp(smt_option, "off"))
|
||||
smt_enabled_at_boot = 0;
|
||||
}
|
||||
|
||||
if (smt_option) {
|
||||
if (!strcmp(smt_option, "on"))
|
||||
smt_enabled_at_boot = 1;
|
||||
else if (!strcmp(smt_option, "off"))
|
||||
smt_enabled_at_boot = 0;
|
||||
}
|
||||
}
|
||||
of_node_put(dn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Look for smt-enabled= cmdline option */
|
||||
static int __init early_smt_enabled(char *p)
|
||||
{
|
||||
smt_enabled_cmdline = 1;
|
||||
|
||||
if (!p)
|
||||
return 0;
|
||||
|
||||
if (!strcmp(p, "on") || !strcmp(p, "1"))
|
||||
smt_enabled_at_boot = 1;
|
||||
else if (!strcmp(p, "off") || !strcmp(p, "0"))
|
||||
smt_enabled_at_boot = 0;
|
||||
|
||||
smt_enabled_cmdline = p;
|
||||
return 0;
|
||||
}
|
||||
early_param("smt-enabled", early_smt_enabled);
|
||||
|
@ -380,8 +389,8 @@ void __init setup_system(void)
|
|||
*/
|
||||
xmon_setup();
|
||||
|
||||
check_smt_enabled();
|
||||
smp_setup_cpu_maps();
|
||||
check_smt_enabled();
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Release secondary cpus out of their spinloops at 0x60 now that
|
||||
|
|
|
@ -427,11 +427,11 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
|||
#endif
|
||||
|
||||
if (!cpu_callin_map[cpu]) {
|
||||
printk("Processor %u is stuck.\n", cpu);
|
||||
printk(KERN_ERR "Processor %u is stuck.\n", cpu);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
printk("Processor %u found.\n", cpu);
|
||||
DBG("Processor %u found.\n", cpu);
|
||||
|
||||
if (smp_ops->give_timebase)
|
||||
smp_ops->give_timebase();
|
||||
|
|
|
@ -616,3 +616,11 @@ asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags,
|
|||
|
||||
return sys_sync_file_range(fd, offset, nbytes, flags);
|
||||
}
|
||||
|
||||
asmlinkage long compat_sys_fanotify_mark(int fanotify_fd, unsigned int flags,
|
||||
unsigned mask_hi, unsigned mask_lo,
|
||||
int dfd, const char __user *pathname)
|
||||
{
|
||||
u64 mask = ((u64)mask_hi << 32) | mask_lo;
|
||||
return sys_fanotify_mark(fanotify_fd, flags, mask, dfd, pathname);
|
||||
}
|
||||
|
|
|
@ -1059,7 +1059,7 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
|
|||
if (!dma_window)
|
||||
return NULL;
|
||||
|
||||
tbl = kmalloc(sizeof(*tbl), GFP_KERNEL);
|
||||
tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
|
||||
if (tbl == NULL)
|
||||
return NULL;
|
||||
|
||||
|
@ -1072,6 +1072,7 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev)
|
|||
tbl->it_offset = offset >> IOMMU_PAGE_SHIFT;
|
||||
tbl->it_busno = 0;
|
||||
tbl->it_type = TCE_VB;
|
||||
tbl->it_blocksize = 16;
|
||||
|
||||
return iommu_init_table(tbl, -1);
|
||||
}
|
||||
|
|
|
@ -79,7 +79,9 @@
|
|||
#endif /* CONFIG_PPC_STD_MMU_64 */
|
||||
|
||||
phys_addr_t memstart_addr = ~0;
|
||||
EXPORT_SYMBOL_GPL(memstart_addr);
|
||||
phys_addr_t kernstart_addr;
|
||||
EXPORT_SYMBOL_GPL(kernstart_addr);
|
||||
|
||||
void free_initmem(void)
|
||||
{
|
||||
|
|
|
@ -200,6 +200,7 @@ _GLOBAL(_tlbivax_bcast)
|
|||
rlwimi r5,r4,0,16,31
|
||||
wrteei 0
|
||||
mtspr SPRN_MMUCR,r5
|
||||
isync
|
||||
/* tlbivax 0,r3 - use .long to avoid binutils deps */
|
||||
.long 0x7c000624 | (r3 << 11)
|
||||
isync
|
||||
|
|
|
@ -106,8 +106,7 @@ config MMIO_NVRAM
|
|||
|
||||
config MPIC_U3_HT_IRQS
|
||||
bool
|
||||
depends on PPC_MAPLE
|
||||
default y
|
||||
default n
|
||||
|
||||
config MPIC_BROKEN_REGREAD
|
||||
bool
|
||||
|
|
|
@ -477,7 +477,7 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
|
|||
|
||||
ioid = cell_iommu_get_ioid(np);
|
||||
|
||||
window = kmalloc_node(sizeof(*window), GFP_KERNEL, iommu->nid);
|
||||
window = kzalloc_node(sizeof(*window), GFP_KERNEL, iommu->nid);
|
||||
BUG_ON(window == NULL);
|
||||
|
||||
window->offset = offset;
|
||||
|
|
|
@ -184,7 +184,7 @@ static void pci_dma_dev_setup_iseries(struct pci_dev *pdev)
|
|||
|
||||
BUG_ON(lsn == NULL);
|
||||
|
||||
tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
|
||||
tbl = kzalloc(sizeof(struct iommu_table), GFP_KERNEL);
|
||||
|
||||
iommu_table_getparms_iSeries(pdn->busno, *lsn, 0, tbl);
|
||||
|
||||
|
|
|
@ -2873,12 +2873,11 @@ set_initial_features(void)
|
|||
|
||||
/* Switch airport off */
|
||||
for_each_node_by_name(np, "radio") {
|
||||
if (np && np->parent == macio_chips[0].of_node) {
|
||||
if (np->parent == macio_chips[0].of_node) {
|
||||
macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON;
|
||||
core99_airport_enable(np, 0, 0);
|
||||
}
|
||||
}
|
||||
of_node_put(np);
|
||||
}
|
||||
|
||||
/* On all machines that support sound PM, switch sound off */
|
||||
|
|
|
@ -1155,13 +1155,11 @@ void __init pmac_pcibios_after_init(void)
|
|||
pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0);
|
||||
}
|
||||
}
|
||||
of_node_put(nd);
|
||||
for_each_node_by_name(nd, "ethernet") {
|
||||
if (nd->parent && of_device_is_compatible(nd, "gmac")
|
||||
&& of_device_is_compatible(nd->parent, "uni-north"))
|
||||
pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0);
|
||||
}
|
||||
of_node_put(nd);
|
||||
}
|
||||
|
||||
void pmac_pci_fixup_cardbus(struct pci_dev* dev)
|
||||
|
|
|
@ -403,7 +403,7 @@ static void pci_dma_bus_setup_pSeries(struct pci_bus *bus)
|
|||
pci->phb->dma_window_size = 0x8000000ul;
|
||||
pci->phb->dma_window_base_cur = 0x8000000ul;
|
||||
|
||||
tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
|
||||
tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
|
||||
pci->phb->node);
|
||||
|
||||
iommu_table_setparms(pci->phb, dn, tbl);
|
||||
|
@ -448,7 +448,7 @@ static void pci_dma_bus_setup_pSeriesLP(struct pci_bus *bus)
|
|||
pdn->full_name, ppci->iommu_table);
|
||||
|
||||
if (!ppci->iommu_table) {
|
||||
tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
|
||||
tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
|
||||
ppci->phb->node);
|
||||
iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window,
|
||||
bus->number);
|
||||
|
@ -478,7 +478,7 @@ static void pci_dma_dev_setup_pSeries(struct pci_dev *dev)
|
|||
struct pci_controller *phb = PCI_DN(dn)->phb;
|
||||
|
||||
pr_debug(" --> first child, no bridge. Allocating iommu table.\n");
|
||||
tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
|
||||
tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
|
||||
phb->node);
|
||||
iommu_table_setparms(phb, dn, tbl);
|
||||
PCI_DN(dn)->iommu_table = iommu_init_table(tbl, phb->node);
|
||||
|
@ -544,7 +544,7 @@ static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
|
|||
|
||||
pci = PCI_DN(pdn);
|
||||
if (!pci->iommu_table) {
|
||||
tbl = kmalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
|
||||
tbl = kzalloc_node(sizeof(struct iommu_table), GFP_KERNEL,
|
||||
pci->phb->node);
|
||||
iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window,
|
||||
pci->phb->bus->number);
|
||||
|
|
|
@ -182,10 +182,13 @@ static int smp_pSeries_cpu_bootable(unsigned int nr)
|
|||
/* Special case - we inhibit secondary thread startup
|
||||
* during boot if the user requests it.
|
||||
*/
|
||||
if (system_state < SYSTEM_RUNNING &&
|
||||
cpu_has_feature(CPU_FTR_SMT) &&
|
||||
!smt_enabled_at_boot && cpu_thread_in_core(nr) != 0)
|
||||
return 0;
|
||||
if (system_state < SYSTEM_RUNNING && cpu_has_feature(CPU_FTR_SMT)) {
|
||||
if (!smt_enabled_at_boot && cpu_thread_in_core(nr) != 0)
|
||||
return 0;
|
||||
if (smt_enabled_at_boot
|
||||
&& cpu_thread_in_core(nr) >= smt_enabled_at_boot)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -928,8 +928,10 @@ void xics_migrate_irqs_away(void)
|
|||
if (xics_status[0] != hw_cpu)
|
||||
goto unlock;
|
||||
|
||||
printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
|
||||
virq, cpu);
|
||||
/* This is expected during cpu offline. */
|
||||
if (cpu_online(cpu))
|
||||
printk(KERN_WARNING "IRQ %u affinity broken off cpu %u\n",
|
||||
virq, cpu);
|
||||
|
||||
/* Reset affinity to all cpus */
|
||||
cpumask_setall(irq_to_desc(virq)->affinity);
|
||||
|
|
|
@ -97,6 +97,7 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
|
|||
{
|
||||
pte_t pte = huge_ptep_get(ptep);
|
||||
|
||||
mm->context.flush_mm = 1;
|
||||
pmd_clear((pmd_t *) ptep);
|
||||
return pte;
|
||||
}
|
||||
|
@ -167,7 +168,8 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm,
|
|||
({ \
|
||||
pte_t __pte = huge_ptep_get(__ptep); \
|
||||
if (pte_write(__pte)) { \
|
||||
if (atomic_read(&(__mm)->mm_users) > 1 || \
|
||||
(__mm)->context.flush_mm = 1; \
|
||||
if (atomic_read(&(__mm)->context.attach_count) > 1 || \
|
||||
(__mm) != current->active_mm) \
|
||||
huge_ptep_invalidate(__mm, __addr, __ptep); \
|
||||
set_huge_pte_at(__mm, __addr, __ptep, \
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#define __MMU_H
|
||||
|
||||
typedef struct {
|
||||
atomic_t attach_count;
|
||||
unsigned int flush_mm;
|
||||
spinlock_t list_lock;
|
||||
struct list_head crst_list;
|
||||
struct list_head pgtable_list;
|
||||
|
|
|
@ -11,11 +11,14 @@
|
|||
|
||||
#include <asm/pgalloc.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/tlbflush.h>
|
||||
#include <asm-generic/mm_hooks.h>
|
||||
|
||||
static inline int init_new_context(struct task_struct *tsk,
|
||||
struct mm_struct *mm)
|
||||
{
|
||||
atomic_set(&mm->context.attach_count, 0);
|
||||
mm->context.flush_mm = 0;
|
||||
mm->context.asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS;
|
||||
#ifdef CONFIG_64BIT
|
||||
mm->context.asce_bits |= _ASCE_TYPE_REGION3;
|
||||
|
@ -76,6 +79,12 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
|
|||
{
|
||||
cpumask_set_cpu(smp_processor_id(), mm_cpumask(next));
|
||||
update_mm(next, tsk);
|
||||
atomic_dec(&prev->context.attach_count);
|
||||
WARN_ON(atomic_read(&prev->context.attach_count) < 0);
|
||||
atomic_inc(&next->context.attach_count);
|
||||
/* Check for TLBs not flushed yet */
|
||||
if (next->context.flush_mm)
|
||||
__tlb_flush_mm(next);
|
||||
}
|
||||
|
||||
#define enter_lazy_tlb(mm,tsk) do { } while (0)
|
||||
|
|
|
@ -880,7 +880,8 @@ static inline void ptep_invalidate(struct mm_struct *mm,
|
|||
#define ptep_get_and_clear(__mm, __address, __ptep) \
|
||||
({ \
|
||||
pte_t __pte = *(__ptep); \
|
||||
if (atomic_read(&(__mm)->mm_users) > 1 || \
|
||||
(__mm)->context.flush_mm = 1; \
|
||||
if (atomic_read(&(__mm)->context.attach_count) > 1 || \
|
||||
(__mm) != current->active_mm) \
|
||||
ptep_invalidate(__mm, __address, __ptep); \
|
||||
else \
|
||||
|
@ -923,7 +924,8 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm,
|
|||
({ \
|
||||
pte_t __pte = *(__ptep); \
|
||||
if (pte_write(__pte)) { \
|
||||
if (atomic_read(&(__mm)->mm_users) > 1 || \
|
||||
(__mm)->context.flush_mm = 1; \
|
||||
if (atomic_read(&(__mm)->context.attach_count) > 1 || \
|
||||
(__mm) != current->active_mm) \
|
||||
ptep_invalidate(__mm, __addr, __ptep); \
|
||||
set_pte_at(__mm, __addr, __ptep, pte_wrprotect(__pte)); \
|
||||
|
|
|
@ -50,8 +50,7 @@ static inline struct mmu_gather *tlb_gather_mmu(struct mm_struct *mm,
|
|||
struct mmu_gather *tlb = &get_cpu_var(mmu_gathers);
|
||||
|
||||
tlb->mm = mm;
|
||||
tlb->fullmm = full_mm_flush || (num_online_cpus() == 1) ||
|
||||
(atomic_read(&mm->mm_users) <= 1 && mm == current->active_mm);
|
||||
tlb->fullmm = full_mm_flush;
|
||||
tlb->nr_ptes = 0;
|
||||
tlb->nr_pxds = TLB_NR_PTRS;
|
||||
if (tlb->fullmm)
|
||||
|
|
|
@ -94,8 +94,12 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
|
|||
|
||||
static inline void __tlb_flush_mm_cond(struct mm_struct * mm)
|
||||
{
|
||||
if (atomic_read(&mm->mm_users) <= 1 && mm == current->active_mm)
|
||||
spin_lock(&mm->page_table_lock);
|
||||
if (mm->context.flush_mm) {
|
||||
__tlb_flush_mm(mm);
|
||||
mm->context.flush_mm = 0;
|
||||
}
|
||||
spin_unlock(&mm->page_table_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -42,8 +42,8 @@ long sys_clone(unsigned long newsp, unsigned long clone_flags,
|
|||
int __user *parent_tidptr, int __user *child_tidptr);
|
||||
long sys_vfork(void);
|
||||
void execve_tail(void);
|
||||
long sys_execve(const char __user *name, char __user * __user *argv,
|
||||
char __user * __user *envp);
|
||||
long sys_execve(const char __user *name, const char __user *const __user *argv,
|
||||
const char __user *const __user *envp);
|
||||
long sys_sigsuspend(int history0, int history1, old_sigset_t mask);
|
||||
long sys_sigaction(int sig, const struct old_sigaction __user *act,
|
||||
struct old_sigaction __user *oact);
|
||||
|
|
|
@ -583,6 +583,7 @@ int __cpuinit __cpu_up(unsigned int cpu)
|
|||
sf->gprs[9] = (unsigned long) sf;
|
||||
cpu_lowcore->save_area[15] = (unsigned long) sf;
|
||||
__ctl_store(cpu_lowcore->cregs_save_area, 0, 15);
|
||||
atomic_inc(&init_mm.context.attach_count);
|
||||
asm volatile(
|
||||
" stam 0,15,0(%0)"
|
||||
: : "a" (&cpu_lowcore->access_regs_save_area) : "memory");
|
||||
|
@ -659,6 +660,7 @@ void __cpu_die(unsigned int cpu)
|
|||
while (sigp_p(0, cpu, sigp_set_prefix) == sigp_busy)
|
||||
udelay(10);
|
||||
smp_free_lowcore(cpu);
|
||||
atomic_dec(&init_mm.context.attach_count);
|
||||
pr_info("Processor %d stopped\n", cpu);
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,8 @@ void __init paging_init(void)
|
|||
__ctl_load(S390_lowcore.kernel_asce, 13, 13);
|
||||
__raw_local_irq_ssm(ssm_mask);
|
||||
|
||||
atomic_set(&init_mm.context.attach_count, 1);
|
||||
|
||||
sparse_memory_present_with_active_regions(MAX_NUMNODES);
|
||||
sparse_init();
|
||||
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
|
||||
|
|
|
@ -20,14 +20,14 @@
|
|||
#define atomic64_set(v, i) (((v)->counter) = i)
|
||||
|
||||
extern void atomic_add(int, atomic_t *);
|
||||
extern void atomic64_add(int, atomic64_t *);
|
||||
extern void atomic64_add(long, atomic64_t *);
|
||||
extern void atomic_sub(int, atomic_t *);
|
||||
extern void atomic64_sub(int, atomic64_t *);
|
||||
extern void atomic64_sub(long, atomic64_t *);
|
||||
|
||||
extern int atomic_add_ret(int, atomic_t *);
|
||||
extern long atomic64_add_ret(int, atomic64_t *);
|
||||
extern long atomic64_add_ret(long, atomic64_t *);
|
||||
extern int atomic_sub_ret(int, atomic_t *);
|
||||
extern long atomic64_sub_ret(int, atomic64_t *);
|
||||
extern long atomic64_sub_ret(long, atomic64_t *);
|
||||
|
||||
#define atomic_dec_return(v) atomic_sub_ret(1, v)
|
||||
#define atomic64_dec_return(v) atomic64_sub_ret(1, v)
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
#define BACKOFF_SETUP(reg) \
|
||||
mov 1, reg
|
||||
|
||||
#define BACKOFF_LABEL(spin_label, continue_label) \
|
||||
spin_label
|
||||
|
||||
#define BACKOFF_SPIN(reg, tmp, label) \
|
||||
mov reg, tmp; \
|
||||
88: brnz,pt tmp, 88b; \
|
||||
|
@ -22,9 +25,11 @@
|
|||
#else
|
||||
|
||||
#define BACKOFF_SETUP(reg)
|
||||
#define BACKOFF_SPIN(reg, tmp, label) \
|
||||
ba,pt %xcc, label; \
|
||||
nop;
|
||||
|
||||
#define BACKOFF_LABEL(spin_label, continue_label) \
|
||||
continue_label
|
||||
|
||||
#define BACKOFF_SPIN(reg, tmp, label)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -185,9 +185,8 @@ extern int prom_getunumber(int syndrome_code,
|
|||
char *buf, int buflen);
|
||||
|
||||
/* Retain physical memory to the caller across soft resets. */
|
||||
extern unsigned long prom_retain(const char *name,
|
||||
unsigned long pa_low, unsigned long pa_high,
|
||||
long size, long align);
|
||||
extern int prom_retain(const char *name, unsigned long size,
|
||||
unsigned long align, unsigned long *paddr);
|
||||
|
||||
/* Load explicit I/D TLB entries into the calling processor. */
|
||||
extern long prom_itlb_load(unsigned long index,
|
||||
|
@ -287,26 +286,6 @@ extern void prom_sun4v_guest_soft_state(void);
|
|||
extern int prom_ihandle2path(int handle, char *buffer, int bufsize);
|
||||
|
||||
/* Client interface level routines. */
|
||||
extern long p1275_cmd(const char *, long, ...);
|
||||
|
||||
#if 0
|
||||
#define P1275_SIZE(x) ((((long)((x) / 32)) << 32) | (x))
|
||||
#else
|
||||
#define P1275_SIZE(x) x
|
||||
#endif
|
||||
|
||||
/* We support at most 16 input and 1 output argument */
|
||||
#define P1275_ARG_NUMBER 0
|
||||
#define P1275_ARG_IN_STRING 1
|
||||
#define P1275_ARG_OUT_BUF 2
|
||||
#define P1275_ARG_OUT_32B 3
|
||||
#define P1275_ARG_IN_FUNCTION 4
|
||||
#define P1275_ARG_IN_BUF 5
|
||||
#define P1275_ARG_IN_64B 6
|
||||
|
||||
#define P1275_IN(x) ((x) & 0xf)
|
||||
#define P1275_OUT(x) (((x) << 4) & 0xf0)
|
||||
#define P1275_INOUT(i,o) (P1275_IN(i)|P1275_OUT(o))
|
||||
#define P1275_ARG(n,x) ((x) << ((n)*3 + 8))
|
||||
extern void p1275_cmd_direct(unsigned long *);
|
||||
|
||||
#endif /* !(__SPARC64_OPLIB_H) */
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/* rwsem-const.h: RW semaphore counter constants. */
|
||||
#ifndef _SPARC64_RWSEM_CONST_H
|
||||
#define _SPARC64_RWSEM_CONST_H
|
||||
|
||||
#define RWSEM_UNLOCKED_VALUE 0x00000000
|
||||
#define RWSEM_ACTIVE_BIAS 0x00000001
|
||||
#define RWSEM_ACTIVE_MASK 0x0000ffff
|
||||
#define RWSEM_WAITING_BIAS (-0x00010000)
|
||||
#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
|
||||
#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
|
||||
|
||||
#endif /* _SPARC64_RWSEM_CONST_H */
|
|
@ -15,16 +15,21 @@
|
|||
|
||||
#include <linux/list.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/rwsem-const.h>
|
||||
|
||||
struct rwsem_waiter;
|
||||
|
||||
struct rw_semaphore {
|
||||
signed int count;
|
||||
spinlock_t wait_lock;
|
||||
struct list_head wait_list;
|
||||
signed long count;
|
||||
#define RWSEM_UNLOCKED_VALUE 0x00000000L
|
||||
#define RWSEM_ACTIVE_BIAS 0x00000001L
|
||||
#define RWSEM_ACTIVE_MASK 0xffffffffL
|
||||
#define RWSEM_WAITING_BIAS (-RWSEM_ACTIVE_MASK-1)
|
||||
#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
|
||||
#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
|
||||
spinlock_t wait_lock;
|
||||
struct list_head wait_list;
|
||||
#ifdef CONFIG_DEBUG_LOCK_ALLOC
|
||||
struct lockdep_map dep_map;
|
||||
struct lockdep_map dep_map;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -41,6 +46,11 @@ struct rw_semaphore {
|
|||
#define DECLARE_RWSEM(name) \
|
||||
struct rw_semaphore name = __RWSEM_INITIALIZER(name)
|
||||
|
||||
extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
|
||||
extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
|
||||
extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
|
||||
extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
|
||||
|
||||
extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
|
||||
struct lock_class_key *key);
|
||||
|
||||
|
@ -51,27 +61,103 @@ do { \
|
|||
__init_rwsem((sem), #sem, &__key); \
|
||||
} while (0)
|
||||
|
||||
extern void __down_read(struct rw_semaphore *sem);
|
||||
extern int __down_read_trylock(struct rw_semaphore *sem);
|
||||
extern void __down_write(struct rw_semaphore *sem);
|
||||
extern int __down_write_trylock(struct rw_semaphore *sem);
|
||||
extern void __up_read(struct rw_semaphore *sem);
|
||||
extern void __up_write(struct rw_semaphore *sem);
|
||||
extern void __downgrade_write(struct rw_semaphore *sem);
|
||||
/*
|
||||
* lock for reading
|
||||
*/
|
||||
static inline void __down_read(struct rw_semaphore *sem)
|
||||
{
|
||||
if (unlikely(atomic64_inc_return((atomic64_t *)(&sem->count)) <= 0L))
|
||||
rwsem_down_read_failed(sem);
|
||||
}
|
||||
|
||||
static inline int __down_read_trylock(struct rw_semaphore *sem)
|
||||
{
|
||||
long tmp;
|
||||
|
||||
while ((tmp = sem->count) >= 0L) {
|
||||
if (tmp == cmpxchg(&sem->count, tmp,
|
||||
tmp + RWSEM_ACTIVE_READ_BIAS)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* lock for writing
|
||||
*/
|
||||
static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
|
||||
{
|
||||
__down_write(sem);
|
||||
long tmp;
|
||||
|
||||
tmp = atomic64_add_return(RWSEM_ACTIVE_WRITE_BIAS,
|
||||
(atomic64_t *)(&sem->count));
|
||||
if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS))
|
||||
rwsem_down_write_failed(sem);
|
||||
}
|
||||
|
||||
static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
|
||||
static inline void __down_write(struct rw_semaphore *sem)
|
||||
{
|
||||
return atomic_add_return(delta, (atomic_t *)(&sem->count));
|
||||
__down_write_nested(sem, 0);
|
||||
}
|
||||
|
||||
static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
|
||||
static inline int __down_write_trylock(struct rw_semaphore *sem)
|
||||
{
|
||||
atomic_add(delta, (atomic_t *)(&sem->count));
|
||||
long tmp;
|
||||
|
||||
tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
|
||||
RWSEM_ACTIVE_WRITE_BIAS);
|
||||
return tmp == RWSEM_UNLOCKED_VALUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* unlock after reading
|
||||
*/
|
||||
static inline void __up_read(struct rw_semaphore *sem)
|
||||
{
|
||||
long tmp;
|
||||
|
||||
tmp = atomic64_dec_return((atomic64_t *)(&sem->count));
|
||||
if (unlikely(tmp < -1L && (tmp & RWSEM_ACTIVE_MASK) == 0L))
|
||||
rwsem_wake(sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* unlock after writing
|
||||
*/
|
||||
static inline void __up_write(struct rw_semaphore *sem)
|
||||
{
|
||||
if (unlikely(atomic64_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
|
||||
(atomic64_t *)(&sem->count)) < 0L))
|
||||
rwsem_wake(sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* implement atomic add functionality
|
||||
*/
|
||||
static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
|
||||
{
|
||||
atomic64_add(delta, (atomic64_t *)(&sem->count));
|
||||
}
|
||||
|
||||
/*
|
||||
* downgrade write lock to read lock
|
||||
*/
|
||||
static inline void __downgrade_write(struct rw_semaphore *sem)
|
||||
{
|
||||
long tmp;
|
||||
|
||||
tmp = atomic64_add_return(-RWSEM_WAITING_BIAS, (atomic64_t *)(&sem->count));
|
||||
if (tmp < 0L)
|
||||
rwsem_downgrade_wake(sem);
|
||||
}
|
||||
|
||||
/*
|
||||
* implement exchange and add functionality
|
||||
*/
|
||||
static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
|
||||
{
|
||||
return atomic64_add_return(delta, (atomic64_t *)(&sem->count));
|
||||
}
|
||||
|
||||
static inline int rwsem_is_locked(struct rw_semaphore *sem)
|
||||
|
|
|
@ -106,6 +106,7 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \
|
|||
*/
|
||||
#define write_pic(__p) \
|
||||
__asm__ __volatile__("ba,pt %%xcc, 99f\n\t" \
|
||||
" nop\n\t" \
|
||||
".align 64\n" \
|
||||
"99:wr %0, 0x0, %%pic\n\t" \
|
||||
"rd %%pic, %%g0" : : "r" (__p))
|
||||
|
|
|
@ -15,7 +15,7 @@ lib-$(CONFIG_SPARC32) += divdi3.o udivdi3.o
|
|||
lib-$(CONFIG_SPARC32) += copy_user.o locks.o
|
||||
lib-y += atomic_$(BITS).o
|
||||
lib-$(CONFIG_SPARC32) += lshrdi3.o ashldi3.o
|
||||
lib-y += rwsem_$(BITS).o
|
||||
lib-$(CONFIG_SPARC32) += rwsem_32.o
|
||||
lib-$(CONFIG_SPARC32) += muldi3.o bitext.o cmpdi2.o
|
||||
|
||||
lib-$(CONFIG_SPARC64) += copy_page.o clear_page.o bzero.o
|
||||
|
|
|
@ -21,7 +21,7 @@ atomic_add: /* %o0 = increment, %o1 = atomic_ptr */
|
|||
add %g1, %o0, %g7
|
||||
cas [%o1], %g1, %g7
|
||||
cmp %g1, %g7
|
||||
bne,pn %icc, 2f
|
||||
bne,pn %icc, BACKOFF_LABEL(2f, 1b)
|
||||
nop
|
||||
retl
|
||||
nop
|
||||
|
@ -36,7 +36,7 @@ atomic_sub: /* %o0 = decrement, %o1 = atomic_ptr */
|
|||
sub %g1, %o0, %g7
|
||||
cas [%o1], %g1, %g7
|
||||
cmp %g1, %g7
|
||||
bne,pn %icc, 2f
|
||||
bne,pn %icc, BACKOFF_LABEL(2f, 1b)
|
||||
nop
|
||||
retl
|
||||
nop
|
||||
|
@ -51,11 +51,10 @@ atomic_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
|
|||
add %g1, %o0, %g7
|
||||
cas [%o1], %g1, %g7
|
||||
cmp %g1, %g7
|
||||
bne,pn %icc, 2f
|
||||
add %g7, %o0, %g7
|
||||
sra %g7, 0, %o0
|
||||
bne,pn %icc, BACKOFF_LABEL(2f, 1b)
|
||||
add %g1, %o0, %g1
|
||||
retl
|
||||
nop
|
||||
sra %g1, 0, %o0
|
||||
2: BACKOFF_SPIN(%o2, %o3, 1b)
|
||||
.size atomic_add_ret, .-atomic_add_ret
|
||||
|
||||
|
@ -67,11 +66,10 @@ atomic_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
|
|||
sub %g1, %o0, %g7
|
||||
cas [%o1], %g1, %g7
|
||||
cmp %g1, %g7
|
||||
bne,pn %icc, 2f
|
||||
sub %g7, %o0, %g7
|
||||
sra %g7, 0, %o0
|
||||
bne,pn %icc, BACKOFF_LABEL(2f, 1b)
|
||||
sub %g1, %o0, %g1
|
||||
retl
|
||||
nop
|
||||
sra %g1, 0, %o0
|
||||
2: BACKOFF_SPIN(%o2, %o3, 1b)
|
||||
.size atomic_sub_ret, .-atomic_sub_ret
|
||||
|
||||
|
@ -83,7 +81,7 @@ atomic64_add: /* %o0 = increment, %o1 = atomic_ptr */
|
|||
add %g1, %o0, %g7
|
||||
casx [%o1], %g1, %g7
|
||||
cmp %g1, %g7
|
||||
bne,pn %xcc, 2f
|
||||
bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
|
||||
nop
|
||||
retl
|
||||
nop
|
||||
|
@ -98,7 +96,7 @@ atomic64_sub: /* %o0 = decrement, %o1 = atomic_ptr */
|
|||
sub %g1, %o0, %g7
|
||||
casx [%o1], %g1, %g7
|
||||
cmp %g1, %g7
|
||||
bne,pn %xcc, 2f
|
||||
bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
|
||||
nop
|
||||
retl
|
||||
nop
|
||||
|
@ -113,11 +111,10 @@ atomic64_add_ret: /* %o0 = increment, %o1 = atomic_ptr */
|
|||
add %g1, %o0, %g7
|
||||
casx [%o1], %g1, %g7
|
||||
cmp %g1, %g7
|
||||
bne,pn %xcc, 2f
|
||||
add %g7, %o0, %g7
|
||||
mov %g7, %o0
|
||||
retl
|
||||
bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
|
||||
nop
|
||||
retl
|
||||
add %g1, %o0, %o0
|
||||
2: BACKOFF_SPIN(%o2, %o3, 1b)
|
||||
.size atomic64_add_ret, .-atomic64_add_ret
|
||||
|
||||
|
@ -129,10 +126,9 @@ atomic64_sub_ret: /* %o0 = decrement, %o1 = atomic_ptr */
|
|||
sub %g1, %o0, %g7
|
||||
casx [%o1], %g1, %g7
|
||||
cmp %g1, %g7
|
||||
bne,pn %xcc, 2f
|
||||
sub %g7, %o0, %g7
|
||||
mov %g7, %o0
|
||||
retl
|
||||
bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
|
||||
nop
|
||||
retl
|
||||
sub %g1, %o0, %o0
|
||||
2: BACKOFF_SPIN(%o2, %o3, 1b)
|
||||
.size atomic64_sub_ret, .-atomic64_sub_ret
|
||||
|
|
|
@ -22,7 +22,7 @@ test_and_set_bit: /* %o0=nr, %o1=addr */
|
|||
or %g7, %o2, %g1
|
||||
casx [%o1], %g7, %g1
|
||||
cmp %g7, %g1
|
||||
bne,pn %xcc, 2f
|
||||
bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
|
||||
and %g7, %o2, %g2
|
||||
clr %o0
|
||||
movrne %g2, 1, %o0
|
||||
|
@ -45,7 +45,7 @@ test_and_clear_bit: /* %o0=nr, %o1=addr */
|
|||
andn %g7, %o2, %g1
|
||||
casx [%o1], %g7, %g1
|
||||
cmp %g7, %g1
|
||||
bne,pn %xcc, 2f
|
||||
bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
|
||||
and %g7, %o2, %g2
|
||||
clr %o0
|
||||
movrne %g2, 1, %o0
|
||||
|
@ -68,7 +68,7 @@ test_and_change_bit: /* %o0=nr, %o1=addr */
|
|||
xor %g7, %o2, %g1
|
||||
casx [%o1], %g7, %g1
|
||||
cmp %g7, %g1
|
||||
bne,pn %xcc, 2f
|
||||
bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
|
||||
and %g7, %o2, %g2
|
||||
clr %o0
|
||||
movrne %g2, 1, %o0
|
||||
|
@ -91,7 +91,7 @@ set_bit: /* %o0=nr, %o1=addr */
|
|||
or %g7, %o2, %g1
|
||||
casx [%o1], %g7, %g1
|
||||
cmp %g7, %g1
|
||||
bne,pn %xcc, 2f
|
||||
bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
|
||||
nop
|
||||
retl
|
||||
nop
|
||||
|
@ -112,7 +112,7 @@ clear_bit: /* %o0=nr, %o1=addr */
|
|||
andn %g7, %o2, %g1
|
||||
casx [%o1], %g7, %g1
|
||||
cmp %g7, %g1
|
||||
bne,pn %xcc, 2f
|
||||
bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
|
||||
nop
|
||||
retl
|
||||
nop
|
||||
|
@ -133,7 +133,7 @@ change_bit: /* %o0=nr, %o1=addr */
|
|||
xor %g7, %o2, %g1
|
||||
casx [%o1], %g7, %g1
|
||||
cmp %g7, %g1
|
||||
bne,pn %xcc, 2f
|
||||
bne,pn %xcc, BACKOFF_LABEL(2f, 1b)
|
||||
nop
|
||||
retl
|
||||
nop
|
||||
|
|
|
@ -1,163 +0,0 @@
|
|||
/* rwsem.S: RW semaphore assembler.
|
||||
*
|
||||
* Written by David S. Miller (davem@redhat.com), 2001.
|
||||
* Derived from asm-i386/rwsem.h
|
||||
*/
|
||||
|
||||
#include <asm/rwsem-const.h>
|
||||
|
||||
.section .sched.text, "ax"
|
||||
|
||||
.globl __down_read
|
||||
__down_read:
|
||||
1: lduw [%o0], %g1
|
||||
add %g1, 1, %g7
|
||||
cas [%o0], %g1, %g7
|
||||
cmp %g1, %g7
|
||||
bne,pn %icc, 1b
|
||||
add %g7, 1, %g7
|
||||
cmp %g7, 0
|
||||
bl,pn %icc, 3f
|
||||
nop
|
||||
2:
|
||||
retl
|
||||
nop
|
||||
3:
|
||||
save %sp, -192, %sp
|
||||
call rwsem_down_read_failed
|
||||
mov %i0, %o0
|
||||
ret
|
||||
restore
|
||||
.size __down_read, .-__down_read
|
||||
|
||||
.globl __down_read_trylock
|
||||
__down_read_trylock:
|
||||
1: lduw [%o0], %g1
|
||||
add %g1, 1, %g7
|
||||
cmp %g7, 0
|
||||
bl,pn %icc, 2f
|
||||
mov 0, %o1
|
||||
cas [%o0], %g1, %g7
|
||||
cmp %g1, %g7
|
||||
bne,pn %icc, 1b
|
||||
mov 1, %o1
|
||||
2: retl
|
||||
mov %o1, %o0
|
||||
.size __down_read_trylock, .-__down_read_trylock
|
||||
|
||||
.globl __down_write
|
||||
__down_write:
|
||||
sethi %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1
|
||||
or %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1
|
||||
1:
|
||||
lduw [%o0], %g3
|
||||
add %g3, %g1, %g7
|
||||
cas [%o0], %g3, %g7
|
||||
cmp %g3, %g7
|
||||
bne,pn %icc, 1b
|
||||
cmp %g7, 0
|
||||
bne,pn %icc, 3f
|
||||
nop
|
||||
2: retl
|
||||
nop
|
||||
3:
|
||||
save %sp, -192, %sp
|
||||
call rwsem_down_write_failed
|
||||
mov %i0, %o0
|
||||
ret
|
||||
restore
|
||||
.size __down_write, .-__down_write
|
||||
|
||||
.globl __down_write_trylock
|
||||
__down_write_trylock:
|
||||
sethi %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1
|
||||
or %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1
|
||||
1:
|
||||
lduw [%o0], %g3
|
||||
cmp %g3, 0
|
||||
bne,pn %icc, 2f
|
||||
mov 0, %o1
|
||||
add %g3, %g1, %g7
|
||||
cas [%o0], %g3, %g7
|
||||
cmp %g3, %g7
|
||||
bne,pn %icc, 1b
|
||||
mov 1, %o1
|
||||
2: retl
|
||||
mov %o1, %o0
|
||||
.size __down_write_trylock, .-__down_write_trylock
|
||||
|
||||
.globl __up_read
|
||||
__up_read:
|
||||
1:
|
||||
lduw [%o0], %g1
|
||||
sub %g1, 1, %g7
|
||||
cas [%o0], %g1, %g7
|
||||
cmp %g1, %g7
|
||||
bne,pn %icc, 1b
|
||||
cmp %g7, 0
|
||||
bl,pn %icc, 3f
|
||||
nop
|
||||
2: retl
|
||||
nop
|
||||
3: sethi %hi(RWSEM_ACTIVE_MASK), %g1
|
||||
sub %g7, 1, %g7
|
||||
or %g1, %lo(RWSEM_ACTIVE_MASK), %g1
|
||||
andcc %g7, %g1, %g0
|
||||
bne,pn %icc, 2b
|
||||
nop
|
||||
save %sp, -192, %sp
|
||||
call rwsem_wake
|
||||
mov %i0, %o0
|
||||
ret
|
||||
restore
|
||||
.size __up_read, .-__up_read
|
||||
|
||||
.globl __up_write
|
||||
__up_write:
|
||||
sethi %hi(RWSEM_ACTIVE_WRITE_BIAS), %g1
|
||||
or %g1, %lo(RWSEM_ACTIVE_WRITE_BIAS), %g1
|
||||
1:
|
||||
lduw [%o0], %g3
|
||||
sub %g3, %g1, %g7
|
||||
cas [%o0], %g3, %g7
|
||||
cmp %g3, %g7
|
||||
bne,pn %icc, 1b
|
||||
sub %g7, %g1, %g7
|
||||
cmp %g7, 0
|
||||
bl,pn %icc, 3f
|
||||
nop
|
||||
2:
|
||||
retl
|
||||
nop
|
||||
3:
|
||||
save %sp, -192, %sp
|
||||
call rwsem_wake
|
||||
mov %i0, %o0
|
||||
ret
|
||||
restore
|
||||
.size __up_write, .-__up_write
|
||||
|
||||
.globl __downgrade_write
|
||||
__downgrade_write:
|
||||
sethi %hi(RWSEM_WAITING_BIAS), %g1
|
||||
or %g1, %lo(RWSEM_WAITING_BIAS), %g1
|
||||
1:
|
||||
lduw [%o0], %g3
|
||||
sub %g3, %g1, %g7
|
||||
cas [%o0], %g3, %g7
|
||||
cmp %g3, %g7
|
||||
bne,pn %icc, 1b
|
||||
sub %g7, %g1, %g7
|
||||
cmp %g7, 0
|
||||
bl,pn %icc, 3f
|
||||
nop
|
||||
2:
|
||||
retl
|
||||
nop
|
||||
3:
|
||||
save %sp, -192, %sp
|
||||
call rwsem_downgrade_wake
|
||||
mov %i0, %o0
|
||||
ret
|
||||
restore
|
||||
.size __downgrade_write, .-__downgrade_write
|
|
@ -9,18 +9,18 @@
|
|||
#include <asm/thread_info.h>
|
||||
|
||||
.text
|
||||
.globl prom_cif_interface
|
||||
prom_cif_interface:
|
||||
sethi %hi(p1275buf), %o0
|
||||
or %o0, %lo(p1275buf), %o0
|
||||
ldx [%o0 + 0x010], %o1 ! prom_cif_stack
|
||||
save %o1, -192, %sp
|
||||
ldx [%i0 + 0x008], %l2 ! prom_cif_handler
|
||||
.globl prom_cif_direct
|
||||
prom_cif_direct:
|
||||
sethi %hi(p1275buf), %o1
|
||||
or %o1, %lo(p1275buf), %o1
|
||||
ldx [%o1 + 0x0010], %o2 ! prom_cif_stack
|
||||
save %o2, -192, %sp
|
||||
ldx [%i1 + 0x0008], %l2 ! prom_cif_handler
|
||||
mov %g4, %l0
|
||||
mov %g5, %l1
|
||||
mov %g6, %l3
|
||||
call %l2
|
||||
add %i0, 0x018, %o0 ! prom_args
|
||||
mov %i0, %o0 ! prom_args
|
||||
mov %l0, %g4
|
||||
mov %l1, %g5
|
||||
mov %l3, %g6
|
||||
|
|
|
@ -21,14 +21,22 @@ extern int prom_stdin, prom_stdout;
|
|||
inline int
|
||||
prom_nbgetchar(void)
|
||||
{
|
||||
unsigned long args[7];
|
||||
char inc;
|
||||
|
||||
if (p1275_cmd("read", P1275_ARG(1,P1275_ARG_OUT_BUF)|
|
||||
P1275_INOUT(3,1),
|
||||
prom_stdin, &inc, P1275_SIZE(1)) == 1)
|
||||
args[0] = (unsigned long) "read";
|
||||
args[1] = 3;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned int) prom_stdin;
|
||||
args[4] = (unsigned long) &inc;
|
||||
args[5] = 1;
|
||||
args[6] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
if (args[6] == 1)
|
||||
return inc;
|
||||
else
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Non blocking put character to console device, returns -1 if
|
||||
|
@ -37,12 +45,22 @@ prom_nbgetchar(void)
|
|||
inline int
|
||||
prom_nbputchar(char c)
|
||||
{
|
||||
unsigned long args[7];
|
||||
char outc;
|
||||
|
||||
outc = c;
|
||||
if (p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
|
||||
P1275_INOUT(3,1),
|
||||
prom_stdout, &outc, P1275_SIZE(1)) == 1)
|
||||
|
||||
args[0] = (unsigned long) "write";
|
||||
args[1] = 3;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned int) prom_stdout;
|
||||
args[4] = (unsigned long) &outc;
|
||||
args[5] = 1;
|
||||
args[6] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
if (args[6] == 1)
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
|
@ -67,7 +85,15 @@ prom_putchar(char c)
|
|||
void
|
||||
prom_puts(const char *s, int len)
|
||||
{
|
||||
p1275_cmd("write", P1275_ARG(1,P1275_ARG_IN_BUF)|
|
||||
P1275_INOUT(3,1),
|
||||
prom_stdout, s, P1275_SIZE(len));
|
||||
unsigned long args[7];
|
||||
|
||||
args[0] = (unsigned long) "write";
|
||||
args[1] = 3;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned int) prom_stdout;
|
||||
args[4] = (unsigned long) s;
|
||||
args[5] = len;
|
||||
args[6] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
|
|
|
@ -18,16 +18,32 @@
|
|||
int
|
||||
prom_devopen(const char *dstr)
|
||||
{
|
||||
return p1275_cmd ("open", P1275_ARG(0,P1275_ARG_IN_STRING)|
|
||||
P1275_INOUT(1,1),
|
||||
dstr);
|
||||
unsigned long args[5];
|
||||
|
||||
args[0] = (unsigned long) "open";
|
||||
args[1] = 1;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned long) dstr;
|
||||
args[4] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return (int) args[4];
|
||||
}
|
||||
|
||||
/* Close the device described by device handle 'dhandle'. */
|
||||
int
|
||||
prom_devclose(int dhandle)
|
||||
{
|
||||
p1275_cmd ("close", P1275_INOUT(1,0), dhandle);
|
||||
unsigned long args[4];
|
||||
|
||||
args[0] = (unsigned long) "close";
|
||||
args[1] = 1;
|
||||
args[2] = 0;
|
||||
args[3] = (unsigned int) dhandle;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -37,5 +53,15 @@ prom_devclose(int dhandle)
|
|||
void
|
||||
prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo)
|
||||
{
|
||||
p1275_cmd ("seek", P1275_INOUT(3,1), dhandle, seekhi, seeklo);
|
||||
unsigned long args[7];
|
||||
|
||||
args[0] = (unsigned long) "seek";
|
||||
args[1] = 3;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned int) dhandle;
|
||||
args[4] = seekhi;
|
||||
args[5] = seeklo;
|
||||
args[6] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
|
|
|
@ -20,10 +20,17 @@
|
|||
|
||||
int prom_service_exists(const char *service_name)
|
||||
{
|
||||
int err = p1275_cmd("test", P1275_ARG(0, P1275_ARG_IN_STRING) |
|
||||
P1275_INOUT(1, 1), service_name);
|
||||
unsigned long args[5];
|
||||
|
||||
if (err)
|
||||
args[0] = (unsigned long) "test";
|
||||
args[1] = 1;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned long) service_name;
|
||||
args[4] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
if (args[4])
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -31,30 +38,47 @@ int prom_service_exists(const char *service_name)
|
|||
void prom_sun4v_guest_soft_state(void)
|
||||
{
|
||||
const char *svc = "SUNW,soft-state-supported";
|
||||
unsigned long args[3];
|
||||
|
||||
if (!prom_service_exists(svc))
|
||||
return;
|
||||
p1275_cmd(svc, P1275_INOUT(0, 0));
|
||||
args[0] = (unsigned long) svc;
|
||||
args[1] = 0;
|
||||
args[2] = 0;
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
|
||||
/* Reset and reboot the machine with the command 'bcommand'. */
|
||||
void prom_reboot(const char *bcommand)
|
||||
{
|
||||
unsigned long args[4];
|
||||
|
||||
#ifdef CONFIG_SUN_LDOMS
|
||||
if (ldom_domaining_enabled)
|
||||
ldom_reboot(bcommand);
|
||||
#endif
|
||||
p1275_cmd("boot", P1275_ARG(0, P1275_ARG_IN_STRING) |
|
||||
P1275_INOUT(1, 0), bcommand);
|
||||
args[0] = (unsigned long) "boot";
|
||||
args[1] = 1;
|
||||
args[2] = 0;
|
||||
args[3] = (unsigned long) bcommand;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
|
||||
/* Forth evaluate the expression contained in 'fstring'. */
|
||||
void prom_feval(const char *fstring)
|
||||
{
|
||||
unsigned long args[5];
|
||||
|
||||
if (!fstring || fstring[0] == 0)
|
||||
return;
|
||||
p1275_cmd("interpret", P1275_ARG(0, P1275_ARG_IN_STRING) |
|
||||
P1275_INOUT(1, 1), fstring);
|
||||
args[0] = (unsigned long) "interpret";
|
||||
args[1] = 1;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned long) fstring;
|
||||
args[4] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
EXPORT_SYMBOL(prom_feval);
|
||||
|
||||
|
@ -68,6 +92,7 @@ extern void smp_release(void);
|
|||
*/
|
||||
void prom_cmdline(void)
|
||||
{
|
||||
unsigned long args[3];
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
@ -76,7 +101,11 @@ void prom_cmdline(void)
|
|||
smp_capture();
|
||||
#endif
|
||||
|
||||
p1275_cmd("enter", P1275_INOUT(0, 0));
|
||||
args[0] = (unsigned long) "enter";
|
||||
args[1] = 0;
|
||||
args[2] = 0;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
smp_release();
|
||||
|
@ -90,22 +119,32 @@ void prom_cmdline(void)
|
|||
*/
|
||||
void notrace prom_halt(void)
|
||||
{
|
||||
unsigned long args[3];
|
||||
|
||||
#ifdef CONFIG_SUN_LDOMS
|
||||
if (ldom_domaining_enabled)
|
||||
ldom_power_off();
|
||||
#endif
|
||||
again:
|
||||
p1275_cmd("exit", P1275_INOUT(0, 0));
|
||||
args[0] = (unsigned long) "exit";
|
||||
args[1] = 0;
|
||||
args[2] = 0;
|
||||
p1275_cmd_direct(args);
|
||||
goto again; /* PROM is out to get me -DaveM */
|
||||
}
|
||||
|
||||
void prom_halt_power_off(void)
|
||||
{
|
||||
unsigned long args[3];
|
||||
|
||||
#ifdef CONFIG_SUN_LDOMS
|
||||
if (ldom_domaining_enabled)
|
||||
ldom_power_off();
|
||||
#endif
|
||||
p1275_cmd("SUNW,power-off", P1275_INOUT(0, 0));
|
||||
args[0] = (unsigned long) "SUNW,power-off";
|
||||
args[1] = 0;
|
||||
args[2] = 0;
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
/* if nothing else helps, we just halt */
|
||||
prom_halt();
|
||||
|
@ -114,10 +153,15 @@ void prom_halt_power_off(void)
|
|||
/* Set prom sync handler to call function 'funcp'. */
|
||||
void prom_setcallback(callback_func_t funcp)
|
||||
{
|
||||
unsigned long args[5];
|
||||
if (!funcp)
|
||||
return;
|
||||
p1275_cmd("set-callback", P1275_ARG(0, P1275_ARG_IN_FUNCTION) |
|
||||
P1275_INOUT(1, 1), funcp);
|
||||
args[0] = (unsigned long) "set-callback";
|
||||
args[1] = 1;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned long) funcp;
|
||||
args[4] = (unsigned long) -1;
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
|
||||
/* Get the idprom and stuff it into buffer 'idbuf'. Returns the
|
||||
|
@ -173,57 +217,61 @@ static int prom_get_memory_ihandle(void)
|
|||
}
|
||||
|
||||
/* Load explicit I/D TLB entries. */
|
||||
static long tlb_load(const char *type, unsigned long index,
|
||||
unsigned long tte_data, unsigned long vaddr)
|
||||
{
|
||||
unsigned long args[9];
|
||||
|
||||
args[0] = (unsigned long) prom_callmethod_name;
|
||||
args[1] = 5;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned long) type;
|
||||
args[4] = (unsigned int) prom_get_mmu_ihandle();
|
||||
args[5] = vaddr;
|
||||
args[6] = tte_data;
|
||||
args[7] = index;
|
||||
args[8] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return (long) args[8];
|
||||
}
|
||||
|
||||
long prom_itlb_load(unsigned long index,
|
||||
unsigned long tte_data,
|
||||
unsigned long vaddr)
|
||||
{
|
||||
return p1275_cmd(prom_callmethod_name,
|
||||
(P1275_ARG(0, P1275_ARG_IN_STRING) |
|
||||
P1275_ARG(2, P1275_ARG_IN_64B) |
|
||||
P1275_ARG(3, P1275_ARG_IN_64B) |
|
||||
P1275_INOUT(5, 1)),
|
||||
"SUNW,itlb-load",
|
||||
prom_get_mmu_ihandle(),
|
||||
/* And then our actual args are pushed backwards. */
|
||||
vaddr,
|
||||
tte_data,
|
||||
index);
|
||||
return tlb_load("SUNW,itlb-load", index, tte_data, vaddr);
|
||||
}
|
||||
|
||||
long prom_dtlb_load(unsigned long index,
|
||||
unsigned long tte_data,
|
||||
unsigned long vaddr)
|
||||
{
|
||||
return p1275_cmd(prom_callmethod_name,
|
||||
(P1275_ARG(0, P1275_ARG_IN_STRING) |
|
||||
P1275_ARG(2, P1275_ARG_IN_64B) |
|
||||
P1275_ARG(3, P1275_ARG_IN_64B) |
|
||||
P1275_INOUT(5, 1)),
|
||||
"SUNW,dtlb-load",
|
||||
prom_get_mmu_ihandle(),
|
||||
/* And then our actual args are pushed backwards. */
|
||||
vaddr,
|
||||
tte_data,
|
||||
index);
|
||||
return tlb_load("SUNW,dtlb-load", index, tte_data, vaddr);
|
||||
}
|
||||
|
||||
int prom_map(int mode, unsigned long size,
|
||||
unsigned long vaddr, unsigned long paddr)
|
||||
{
|
||||
int ret = p1275_cmd(prom_callmethod_name,
|
||||
(P1275_ARG(0, P1275_ARG_IN_STRING) |
|
||||
P1275_ARG(3, P1275_ARG_IN_64B) |
|
||||
P1275_ARG(4, P1275_ARG_IN_64B) |
|
||||
P1275_ARG(6, P1275_ARG_IN_64B) |
|
||||
P1275_INOUT(7, 1)),
|
||||
prom_map_name,
|
||||
prom_get_mmu_ihandle(),
|
||||
mode,
|
||||
size,
|
||||
vaddr,
|
||||
0,
|
||||
paddr);
|
||||
unsigned long args[11];
|
||||
int ret;
|
||||
|
||||
args[0] = (unsigned long) prom_callmethod_name;
|
||||
args[1] = 7;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned long) prom_map_name;
|
||||
args[4] = (unsigned int) prom_get_mmu_ihandle();
|
||||
args[5] = (unsigned int) mode;
|
||||
args[6] = size;
|
||||
args[7] = vaddr;
|
||||
args[8] = 0;
|
||||
args[9] = paddr;
|
||||
args[10] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
ret = (int) args[10];
|
||||
if (ret == 0)
|
||||
ret = -1;
|
||||
return ret;
|
||||
|
@ -231,40 +279,51 @@ int prom_map(int mode, unsigned long size,
|
|||
|
||||
void prom_unmap(unsigned long size, unsigned long vaddr)
|
||||
{
|
||||
p1275_cmd(prom_callmethod_name,
|
||||
(P1275_ARG(0, P1275_ARG_IN_STRING) |
|
||||
P1275_ARG(2, P1275_ARG_IN_64B) |
|
||||
P1275_ARG(3, P1275_ARG_IN_64B) |
|
||||
P1275_INOUT(4, 0)),
|
||||
prom_unmap_name,
|
||||
prom_get_mmu_ihandle(),
|
||||
size,
|
||||
vaddr);
|
||||
unsigned long args[7];
|
||||
|
||||
args[0] = (unsigned long) prom_callmethod_name;
|
||||
args[1] = 4;
|
||||
args[2] = 0;
|
||||
args[3] = (unsigned long) prom_unmap_name;
|
||||
args[4] = (unsigned int) prom_get_mmu_ihandle();
|
||||
args[5] = size;
|
||||
args[6] = vaddr;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
|
||||
/* Set aside physical memory which is not touched or modified
|
||||
* across soft resets.
|
||||
*/
|
||||
unsigned long prom_retain(const char *name,
|
||||
unsigned long pa_low, unsigned long pa_high,
|
||||
long size, long align)
|
||||
int prom_retain(const char *name, unsigned long size,
|
||||
unsigned long align, unsigned long *paddr)
|
||||
{
|
||||
/* XXX I don't think we return multiple values correctly.
|
||||
* XXX OBP supposedly returns pa_low/pa_high here, how does
|
||||
* XXX it work?
|
||||
*/
|
||||
unsigned long args[11];
|
||||
|
||||
/* If align is zero, the pa_low/pa_high args are passed,
|
||||
* else they are not.
|
||||
args[0] = (unsigned long) prom_callmethod_name;
|
||||
args[1] = 5;
|
||||
args[2] = 3;
|
||||
args[3] = (unsigned long) "SUNW,retain";
|
||||
args[4] = (unsigned int) prom_get_memory_ihandle();
|
||||
args[5] = align;
|
||||
args[6] = size;
|
||||
args[7] = (unsigned long) name;
|
||||
args[8] = (unsigned long) -1;
|
||||
args[9] = (unsigned long) -1;
|
||||
args[10] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
if (args[8])
|
||||
return (int) args[8];
|
||||
|
||||
/* Next we get "phys_high" then "phys_low". On 64-bit
|
||||
* the phys_high cell is don't care since the phys_low
|
||||
* cell has the full value.
|
||||
*/
|
||||
if (align == 0)
|
||||
return p1275_cmd("SUNW,retain",
|
||||
(P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(5, 2)),
|
||||
name, pa_low, pa_high, size, align);
|
||||
else
|
||||
return p1275_cmd("SUNW,retain",
|
||||
(P1275_ARG(0, P1275_ARG_IN_BUF) | P1275_INOUT(3, 2)),
|
||||
name, size, align);
|
||||
*paddr = args[10];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get "Unumber" string for the SIMM at the given
|
||||
|
@ -277,62 +336,129 @@ int prom_getunumber(int syndrome_code,
|
|||
unsigned long phys_addr,
|
||||
char *buf, int buflen)
|
||||
{
|
||||
return p1275_cmd(prom_callmethod_name,
|
||||
(P1275_ARG(0, P1275_ARG_IN_STRING) |
|
||||
P1275_ARG(3, P1275_ARG_OUT_BUF) |
|
||||
P1275_ARG(6, P1275_ARG_IN_64B) |
|
||||
P1275_INOUT(8, 2)),
|
||||
"SUNW,get-unumber", prom_get_memory_ihandle(),
|
||||
buflen, buf, P1275_SIZE(buflen),
|
||||
0, phys_addr, syndrome_code);
|
||||
unsigned long args[12];
|
||||
|
||||
args[0] = (unsigned long) prom_callmethod_name;
|
||||
args[1] = 7;
|
||||
args[2] = 2;
|
||||
args[3] = (unsigned long) "SUNW,get-unumber";
|
||||
args[4] = (unsigned int) prom_get_memory_ihandle();
|
||||
args[5] = buflen;
|
||||
args[6] = (unsigned long) buf;
|
||||
args[7] = 0;
|
||||
args[8] = phys_addr;
|
||||
args[9] = (unsigned int) syndrome_code;
|
||||
args[10] = (unsigned long) -1;
|
||||
args[11] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return (int) args[10];
|
||||
}
|
||||
|
||||
/* Power management extensions. */
|
||||
void prom_sleepself(void)
|
||||
{
|
||||
p1275_cmd("SUNW,sleep-self", P1275_INOUT(0, 0));
|
||||
unsigned long args[3];
|
||||
|
||||
args[0] = (unsigned long) "SUNW,sleep-self";
|
||||
args[1] = 0;
|
||||
args[2] = 0;
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
|
||||
int prom_sleepsystem(void)
|
||||
{
|
||||
return p1275_cmd("SUNW,sleep-system", P1275_INOUT(0, 1));
|
||||
unsigned long args[4];
|
||||
|
||||
args[0] = (unsigned long) "SUNW,sleep-system";
|
||||
args[1] = 0;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned long) -1;
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return (int) args[3];
|
||||
}
|
||||
|
||||
int prom_wakeupsystem(void)
|
||||
{
|
||||
return p1275_cmd("SUNW,wakeup-system", P1275_INOUT(0, 1));
|
||||
unsigned long args[4];
|
||||
|
||||
args[0] = (unsigned long) "SUNW,wakeup-system";
|
||||
args[1] = 0;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned long) -1;
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return (int) args[3];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void prom_startcpu(int cpunode, unsigned long pc, unsigned long arg)
|
||||
{
|
||||
p1275_cmd("SUNW,start-cpu", P1275_INOUT(3, 0), cpunode, pc, arg);
|
||||
unsigned long args[6];
|
||||
|
||||
args[0] = (unsigned long) "SUNW,start-cpu";
|
||||
args[1] = 3;
|
||||
args[2] = 0;
|
||||
args[3] = (unsigned int) cpunode;
|
||||
args[4] = pc;
|
||||
args[5] = arg;
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
|
||||
void prom_startcpu_cpuid(int cpuid, unsigned long pc, unsigned long arg)
|
||||
{
|
||||
p1275_cmd("SUNW,start-cpu-by-cpuid", P1275_INOUT(3, 0),
|
||||
cpuid, pc, arg);
|
||||
unsigned long args[6];
|
||||
|
||||
args[0] = (unsigned long) "SUNW,start-cpu-by-cpuid";
|
||||
args[1] = 3;
|
||||
args[2] = 0;
|
||||
args[3] = (unsigned int) cpuid;
|
||||
args[4] = pc;
|
||||
args[5] = arg;
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
|
||||
void prom_stopcpu_cpuid(int cpuid)
|
||||
{
|
||||
p1275_cmd("SUNW,stop-cpu-by-cpuid", P1275_INOUT(1, 0),
|
||||
cpuid);
|
||||
unsigned long args[4];
|
||||
|
||||
args[0] = (unsigned long) "SUNW,stop-cpu-by-cpuid";
|
||||
args[1] = 1;
|
||||
args[2] = 0;
|
||||
args[3] = (unsigned int) cpuid;
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
|
||||
void prom_stopself(void)
|
||||
{
|
||||
p1275_cmd("SUNW,stop-self", P1275_INOUT(0, 0));
|
||||
unsigned long args[3];
|
||||
|
||||
args[0] = (unsigned long) "SUNW,stop-self";
|
||||
args[1] = 0;
|
||||
args[2] = 0;
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
|
||||
void prom_idleself(void)
|
||||
{
|
||||
p1275_cmd("SUNW,idle-self", P1275_INOUT(0, 0));
|
||||
unsigned long args[3];
|
||||
|
||||
args[0] = (unsigned long) "SUNW,idle-self";
|
||||
args[1] = 0;
|
||||
args[2] = 0;
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
|
||||
void prom_resumecpu(int cpunode)
|
||||
{
|
||||
p1275_cmd("SUNW,resume-cpu", P1275_INOUT(1, 0), cpunode);
|
||||
unsigned long args[4];
|
||||
|
||||
args[0] = (unsigned long) "SUNW,resume-cpu";
|
||||
args[1] = 1;
|
||||
args[2] = 0;
|
||||
args[3] = (unsigned int) cpunode;
|
||||
p1275_cmd_direct(args);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -22,13 +22,11 @@ struct {
|
|||
long prom_callback; /* 0x00 */
|
||||
void (*prom_cif_handler)(long *); /* 0x08 */
|
||||
unsigned long prom_cif_stack; /* 0x10 */
|
||||
unsigned long prom_args [23]; /* 0x18 */
|
||||
char prom_buffer [3000];
|
||||
} p1275buf;
|
||||
|
||||
extern void prom_world(int);
|
||||
|
||||
extern void prom_cif_interface(void);
|
||||
extern void prom_cif_direct(unsigned long *args);
|
||||
extern void prom_cif_callback(void);
|
||||
|
||||
/*
|
||||
|
@ -36,114 +34,20 @@ extern void prom_cif_callback(void);
|
|||
*/
|
||||
DEFINE_RAW_SPINLOCK(prom_entry_lock);
|
||||
|
||||
long p1275_cmd(const char *service, long fmt, ...)
|
||||
void p1275_cmd_direct(unsigned long *args)
|
||||
{
|
||||
char *p, *q;
|
||||
unsigned long flags;
|
||||
int nargs, nrets, i;
|
||||
va_list list;
|
||||
long attrs, x;
|
||||
|
||||
p = p1275buf.prom_buffer;
|
||||
|
||||
raw_local_save_flags(flags);
|
||||
raw_local_irq_restore(PIL_NMI);
|
||||
raw_spin_lock(&prom_entry_lock);
|
||||
|
||||
p1275buf.prom_args[0] = (unsigned long)p; /* service */
|
||||
strcpy (p, service);
|
||||
p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
|
||||
p1275buf.prom_args[1] = nargs = (fmt & 0x0f); /* nargs */
|
||||
p1275buf.prom_args[2] = nrets = ((fmt & 0xf0) >> 4); /* nrets */
|
||||
attrs = fmt >> 8;
|
||||
va_start(list, fmt);
|
||||
for (i = 0; i < nargs; i++, attrs >>= 3) {
|
||||
switch (attrs & 0x7) {
|
||||
case P1275_ARG_NUMBER:
|
||||
p1275buf.prom_args[i + 3] =
|
||||
(unsigned)va_arg(list, long);
|
||||
break;
|
||||
case P1275_ARG_IN_64B:
|
||||
p1275buf.prom_args[i + 3] =
|
||||
va_arg(list, unsigned long);
|
||||
break;
|
||||
case P1275_ARG_IN_STRING:
|
||||
strcpy (p, va_arg(list, char *));
|
||||
p1275buf.prom_args[i + 3] = (unsigned long)p;
|
||||
p = (char *)(((long)(strchr (p, 0) + 8)) & ~7);
|
||||
break;
|
||||
case P1275_ARG_OUT_BUF:
|
||||
(void) va_arg(list, char *);
|
||||
p1275buf.prom_args[i + 3] = (unsigned long)p;
|
||||
x = va_arg(list, long);
|
||||
i++; attrs >>= 3;
|
||||
p = (char *)(((long)(p + (int)x + 7)) & ~7);
|
||||
p1275buf.prom_args[i + 3] = x;
|
||||
break;
|
||||
case P1275_ARG_IN_BUF:
|
||||
q = va_arg(list, char *);
|
||||
p1275buf.prom_args[i + 3] = (unsigned long)p;
|
||||
x = va_arg(list, long);
|
||||
i++; attrs >>= 3;
|
||||
memcpy (p, q, (int)x);
|
||||
p = (char *)(((long)(p + (int)x + 7)) & ~7);
|
||||
p1275buf.prom_args[i + 3] = x;
|
||||
break;
|
||||
case P1275_ARG_OUT_32B:
|
||||
(void) va_arg(list, char *);
|
||||
p1275buf.prom_args[i + 3] = (unsigned long)p;
|
||||
p += 32;
|
||||
break;
|
||||
case P1275_ARG_IN_FUNCTION:
|
||||
p1275buf.prom_args[i + 3] =
|
||||
(unsigned long)prom_cif_callback;
|
||||
p1275buf.prom_callback = va_arg(list, long);
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(list);
|
||||
|
||||
prom_world(1);
|
||||
prom_cif_interface();
|
||||
prom_cif_direct(args);
|
||||
prom_world(0);
|
||||
|
||||
attrs = fmt >> 8;
|
||||
va_start(list, fmt);
|
||||
for (i = 0; i < nargs; i++, attrs >>= 3) {
|
||||
switch (attrs & 0x7) {
|
||||
case P1275_ARG_NUMBER:
|
||||
(void) va_arg(list, long);
|
||||
break;
|
||||
case P1275_ARG_IN_STRING:
|
||||
(void) va_arg(list, char *);
|
||||
break;
|
||||
case P1275_ARG_IN_FUNCTION:
|
||||
(void) va_arg(list, long);
|
||||
break;
|
||||
case P1275_ARG_IN_BUF:
|
||||
(void) va_arg(list, char *);
|
||||
(void) va_arg(list, long);
|
||||
i++; attrs >>= 3;
|
||||
break;
|
||||
case P1275_ARG_OUT_BUF:
|
||||
p = va_arg(list, char *);
|
||||
x = va_arg(list, long);
|
||||
memcpy (p, (char *)(p1275buf.prom_args[i + 3]), (int)x);
|
||||
i++; attrs >>= 3;
|
||||
break;
|
||||
case P1275_ARG_OUT_32B:
|
||||
p = va_arg(list, char *);
|
||||
memcpy (p, (char *)(p1275buf.prom_args[i + 3]), 32);
|
||||
break;
|
||||
}
|
||||
}
|
||||
va_end(list);
|
||||
x = p1275buf.prom_args [nargs + 3];
|
||||
|
||||
raw_spin_unlock(&prom_entry_lock);
|
||||
raw_local_irq_restore(flags);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
void prom_cif_init(void *cif_handler, void *cif_stack)
|
||||
|
|
|
@ -16,22 +16,39 @@
|
|||
#include <asm/oplib.h>
|
||||
#include <asm/ldc.h>
|
||||
|
||||
static int prom_node_to_node(const char *type, int node)
|
||||
{
|
||||
unsigned long args[5];
|
||||
|
||||
args[0] = (unsigned long) type;
|
||||
args[1] = 1;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned int) node;
|
||||
args[4] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return (int) args[4];
|
||||
}
|
||||
|
||||
/* Return the child of node 'node' or zero if no this node has no
|
||||
* direct descendent.
|
||||
*/
|
||||
inline int __prom_getchild(int node)
|
||||
{
|
||||
return p1275_cmd ("child", P1275_INOUT(1, 1), node);
|
||||
return prom_node_to_node("child", node);
|
||||
}
|
||||
|
||||
inline int prom_getchild(int node)
|
||||
{
|
||||
int cnode;
|
||||
|
||||
if(node == -1) return 0;
|
||||
if (node == -1)
|
||||
return 0;
|
||||
cnode = __prom_getchild(node);
|
||||
if(cnode == -1) return 0;
|
||||
return (int)cnode;
|
||||
if (cnode == -1)
|
||||
return 0;
|
||||
return cnode;
|
||||
}
|
||||
EXPORT_SYMBOL(prom_getchild);
|
||||
|
||||
|
@ -39,10 +56,12 @@ inline int prom_getparent(int node)
|
|||
{
|
||||
int cnode;
|
||||
|
||||
if(node == -1) return 0;
|
||||
cnode = p1275_cmd ("parent", P1275_INOUT(1, 1), node);
|
||||
if(cnode == -1) return 0;
|
||||
return (int)cnode;
|
||||
if (node == -1)
|
||||
return 0;
|
||||
cnode = prom_node_to_node("parent", node);
|
||||
if (cnode == -1)
|
||||
return 0;
|
||||
return cnode;
|
||||
}
|
||||
|
||||
/* Return the next sibling of node 'node' or zero if no more siblings
|
||||
|
@ -50,7 +69,7 @@ inline int prom_getparent(int node)
|
|||
*/
|
||||
inline int __prom_getsibling(int node)
|
||||
{
|
||||
return p1275_cmd(prom_peer_name, P1275_INOUT(1, 1), node);
|
||||
return prom_node_to_node(prom_peer_name, node);
|
||||
}
|
||||
|
||||
inline int prom_getsibling(int node)
|
||||
|
@ -72,11 +91,21 @@ EXPORT_SYMBOL(prom_getsibling);
|
|||
*/
|
||||
inline int prom_getproplen(int node, const char *prop)
|
||||
{
|
||||
if((!node) || (!prop)) return -1;
|
||||
return p1275_cmd ("getproplen",
|
||||
P1275_ARG(1,P1275_ARG_IN_STRING)|
|
||||
P1275_INOUT(2, 1),
|
||||
node, prop);
|
||||
unsigned long args[6];
|
||||
|
||||
if (!node || !prop)
|
||||
return -1;
|
||||
|
||||
args[0] = (unsigned long) "getproplen";
|
||||
args[1] = 2;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned int) node;
|
||||
args[4] = (unsigned long) prop;
|
||||
args[5] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return (int) args[5];
|
||||
}
|
||||
EXPORT_SYMBOL(prom_getproplen);
|
||||
|
||||
|
@ -87,19 +116,25 @@ EXPORT_SYMBOL(prom_getproplen);
|
|||
inline int prom_getproperty(int node, const char *prop,
|
||||
char *buffer, int bufsize)
|
||||
{
|
||||
unsigned long args[8];
|
||||
int plen;
|
||||
|
||||
plen = prom_getproplen(node, prop);
|
||||
if ((plen > bufsize) || (plen == 0) || (plen == -1)) {
|
||||
if ((plen > bufsize) || (plen == 0) || (plen == -1))
|
||||
return -1;
|
||||
} else {
|
||||
/* Ok, things seem all right. */
|
||||
return p1275_cmd(prom_getprop_name,
|
||||
P1275_ARG(1,P1275_ARG_IN_STRING)|
|
||||
P1275_ARG(2,P1275_ARG_OUT_BUF)|
|
||||
P1275_INOUT(4, 1),
|
||||
node, prop, buffer, P1275_SIZE(plen));
|
||||
}
|
||||
|
||||
args[0] = (unsigned long) prom_getprop_name;
|
||||
args[1] = 4;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned int) node;
|
||||
args[4] = (unsigned long) prop;
|
||||
args[5] = (unsigned long) buffer;
|
||||
args[6] = bufsize;
|
||||
args[7] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return (int) args[7];
|
||||
}
|
||||
EXPORT_SYMBOL(prom_getproperty);
|
||||
|
||||
|
@ -110,7 +145,7 @@ inline int prom_getint(int node, const char *prop)
|
|||
{
|
||||
int intprop;
|
||||
|
||||
if(prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1)
|
||||
if (prom_getproperty(node, prop, (char *) &intprop, sizeof(int)) != -1)
|
||||
return intprop;
|
||||
|
||||
return -1;
|
||||
|
@ -126,7 +161,8 @@ int prom_getintdefault(int node, const char *property, int deflt)
|
|||
int retval;
|
||||
|
||||
retval = prom_getint(node, property);
|
||||
if(retval == -1) return deflt;
|
||||
if (retval == -1)
|
||||
return deflt;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
@ -138,7 +174,8 @@ int prom_getbool(int node, const char *prop)
|
|||
int retval;
|
||||
|
||||
retval = prom_getproplen(node, prop);
|
||||
if(retval == -1) return 0;
|
||||
if (retval == -1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL(prom_getbool);
|
||||
|
@ -152,7 +189,8 @@ void prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size)
|
|||
int len;
|
||||
|
||||
len = prom_getproperty(node, prop, user_buf, ubuf_size);
|
||||
if(len != -1) return;
|
||||
if (len != -1)
|
||||
return;
|
||||
user_buf[0] = 0;
|
||||
}
|
||||
EXPORT_SYMBOL(prom_getstring);
|
||||
|
@ -164,7 +202,8 @@ int prom_nodematch(int node, const char *name)
|
|||
{
|
||||
char namebuf[128];
|
||||
prom_getproperty(node, "name", namebuf, sizeof(namebuf));
|
||||
if(strcmp(namebuf, name) == 0) return 1;
|
||||
if (strcmp(namebuf, name) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -190,16 +229,29 @@ int prom_searchsiblings(int node_start, const char *nodename)
|
|||
}
|
||||
EXPORT_SYMBOL(prom_searchsiblings);
|
||||
|
||||
static const char *prom_nextprop_name = "nextprop";
|
||||
|
||||
/* Return the first property type for node 'node'.
|
||||
* buffer should be at least 32B in length
|
||||
*/
|
||||
inline char *prom_firstprop(int node, char *buffer)
|
||||
{
|
||||
unsigned long args[7];
|
||||
|
||||
*buffer = 0;
|
||||
if(node == -1) return buffer;
|
||||
p1275_cmd ("nextprop", P1275_ARG(2,P1275_ARG_OUT_32B)|
|
||||
P1275_INOUT(3, 0),
|
||||
node, (char *) 0x0, buffer);
|
||||
if (node == -1)
|
||||
return buffer;
|
||||
|
||||
args[0] = (unsigned long) prom_nextprop_name;
|
||||
args[1] = 3;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned int) node;
|
||||
args[4] = 0;
|
||||
args[5] = (unsigned long) buffer;
|
||||
args[6] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
EXPORT_SYMBOL(prom_firstprop);
|
||||
|
@ -210,9 +262,10 @@ EXPORT_SYMBOL(prom_firstprop);
|
|||
*/
|
||||
inline char *prom_nextprop(int node, const char *oprop, char *buffer)
|
||||
{
|
||||
unsigned long args[7];
|
||||
char buf[32];
|
||||
|
||||
if(node == -1) {
|
||||
if (node == -1) {
|
||||
*buffer = 0;
|
||||
return buffer;
|
||||
}
|
||||
|
@ -220,10 +273,17 @@ inline char *prom_nextprop(int node, const char *oprop, char *buffer)
|
|||
strcpy (buf, oprop);
|
||||
oprop = buf;
|
||||
}
|
||||
p1275_cmd ("nextprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
|
||||
P1275_ARG(2,P1275_ARG_OUT_32B)|
|
||||
P1275_INOUT(3, 0),
|
||||
node, oprop, buffer);
|
||||
|
||||
args[0] = (unsigned long) prom_nextprop_name;
|
||||
args[1] = 3;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned int) node;
|
||||
args[4] = (unsigned long) oprop;
|
||||
args[5] = (unsigned long) buffer;
|
||||
args[6] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
EXPORT_SYMBOL(prom_nextprop);
|
||||
|
@ -231,12 +291,19 @@ EXPORT_SYMBOL(prom_nextprop);
|
|||
int
|
||||
prom_finddevice(const char *name)
|
||||
{
|
||||
unsigned long args[5];
|
||||
|
||||
if (!name)
|
||||
return 0;
|
||||
return p1275_cmd(prom_finddev_name,
|
||||
P1275_ARG(0,P1275_ARG_IN_STRING)|
|
||||
P1275_INOUT(1, 1),
|
||||
name);
|
||||
args[0] = (unsigned long) "finddevice";
|
||||
args[1] = 1;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned long) name;
|
||||
args[4] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return (int) args[4];
|
||||
}
|
||||
EXPORT_SYMBOL(prom_finddevice);
|
||||
|
||||
|
@ -247,7 +314,7 @@ int prom_node_has_property(int node, const char *prop)
|
|||
*buf = 0;
|
||||
do {
|
||||
prom_nextprop(node, buf, buf);
|
||||
if(!strcmp(buf, prop))
|
||||
if (!strcmp(buf, prop))
|
||||
return 1;
|
||||
} while (*buf);
|
||||
return 0;
|
||||
|
@ -260,6 +327,8 @@ EXPORT_SYMBOL(prom_node_has_property);
|
|||
int
|
||||
prom_setprop(int node, const char *pname, char *value, int size)
|
||||
{
|
||||
unsigned long args[8];
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
if ((pname == 0) || (value == 0))
|
||||
|
@ -271,19 +340,37 @@ prom_setprop(int node, const char *pname, char *value, int size)
|
|||
return 0;
|
||||
}
|
||||
#endif
|
||||
return p1275_cmd ("setprop", P1275_ARG(1,P1275_ARG_IN_STRING)|
|
||||
P1275_ARG(2,P1275_ARG_IN_BUF)|
|
||||
P1275_INOUT(4, 1),
|
||||
node, pname, value, P1275_SIZE(size));
|
||||
args[0] = (unsigned long) "setprop";
|
||||
args[1] = 4;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned int) node;
|
||||
args[4] = (unsigned long) pname;
|
||||
args[5] = (unsigned long) value;
|
||||
args[6] = size;
|
||||
args[7] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return (int) args[7];
|
||||
}
|
||||
EXPORT_SYMBOL(prom_setprop);
|
||||
|
||||
inline int prom_inst2pkg(int inst)
|
||||
{
|
||||
unsigned long args[5];
|
||||
int node;
|
||||
|
||||
node = p1275_cmd ("instance-to-package", P1275_INOUT(1, 1), inst);
|
||||
if (node == -1) return 0;
|
||||
args[0] = (unsigned long) "instance-to-package";
|
||||
args[1] = 1;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned int) inst;
|
||||
args[4] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
node = (int) args[4];
|
||||
if (node == -1)
|
||||
return 0;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
@ -296,17 +383,28 @@ prom_pathtoinode(const char *path)
|
|||
int node, inst;
|
||||
|
||||
inst = prom_devopen (path);
|
||||
if (inst == 0) return 0;
|
||||
node = prom_inst2pkg (inst);
|
||||
prom_devclose (inst);
|
||||
if (node == -1) return 0;
|
||||
if (inst == 0)
|
||||
return 0;
|
||||
node = prom_inst2pkg(inst);
|
||||
prom_devclose(inst);
|
||||
if (node == -1)
|
||||
return 0;
|
||||
return node;
|
||||
}
|
||||
|
||||
int prom_ihandle2path(int handle, char *buffer, int bufsize)
|
||||
{
|
||||
return p1275_cmd("instance-to-path",
|
||||
P1275_ARG(1,P1275_ARG_OUT_BUF)|
|
||||
P1275_INOUT(3, 1),
|
||||
handle, buffer, P1275_SIZE(bufsize));
|
||||
unsigned long args[7];
|
||||
|
||||
args[0] = (unsigned long) "instance-to-path";
|
||||
args[1] = 3;
|
||||
args[2] = 1;
|
||||
args[3] = (unsigned int) handle;
|
||||
args[4] = (unsigned long) buffer;
|
||||
args[5] = bufsize;
|
||||
args[6] = (unsigned long) -1;
|
||||
|
||||
p1275_cmd_direct(args);
|
||||
|
||||
return (int) args[6];
|
||||
}
|
||||
|
|
|
@ -59,5 +59,7 @@ extern void check_tsc_sync_source(int cpu);
|
|||
extern void check_tsc_sync_target(void);
|
||||
|
||||
extern int notsc_setup(char *);
|
||||
extern void save_sched_clock_state(void);
|
||||
extern void restore_sched_clock_state(void);
|
||||
|
||||
#endif /* _ASM_X86_TSC_H */
|
||||
|
|
|
@ -497,6 +497,8 @@ static int p4_hw_config(struct perf_event *event)
|
|||
event->hw.config |= event->attr.config &
|
||||
(p4_config_pack_escr(P4_ESCR_MASK_HT) |
|
||||
p4_config_pack_cccr(P4_CCCR_MASK_HT | P4_CCCR_RESERVED));
|
||||
|
||||
event->hw.config &= ~P4_CCCR_FORCE_OVF;
|
||||
}
|
||||
|
||||
rc = x86_setup_perfctr(event);
|
||||
|
|
|
@ -626,6 +626,44 @@ static void set_cyc2ns_scale(unsigned long cpu_khz, int cpu)
|
|||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static unsigned long long cyc2ns_suspend;
|
||||
|
||||
void save_sched_clock_state(void)
|
||||
{
|
||||
if (!sched_clock_stable)
|
||||
return;
|
||||
|
||||
cyc2ns_suspend = sched_clock();
|
||||
}
|
||||
|
||||
/*
|
||||
* Even on processors with invariant TSC, TSC gets reset in some the
|
||||
* ACPI system sleep states. And in some systems BIOS seem to reinit TSC to
|
||||
* arbitrary value (still sync'd across cpu's) during resume from such sleep
|
||||
* states. To cope up with this, recompute the cyc2ns_offset for each cpu so
|
||||
* that sched_clock() continues from the point where it was left off during
|
||||
* suspend.
|
||||
*/
|
||||
void restore_sched_clock_state(void)
|
||||
{
|
||||
unsigned long long offset;
|
||||
unsigned long flags;
|
||||
int cpu;
|
||||
|
||||
if (!sched_clock_stable)
|
||||
return;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
get_cpu_var(cyc2ns_offset) = 0;
|
||||
offset = cyc2ns_suspend - sched_clock();
|
||||
|
||||
for_each_possible_cpu(cpu)
|
||||
per_cpu(cyc2ns_offset, cpu) = offset;
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_CPU_FREQ
|
||||
|
||||
/* Frequency scaling support. Adjust the TSC based timer when the cpu frequency
|
||||
|
|
|
@ -113,6 +113,7 @@ static void __save_processor_state(struct saved_context *ctxt)
|
|||
void save_processor_state(void)
|
||||
{
|
||||
__save_processor_state(&saved_context);
|
||||
save_sched_clock_state();
|
||||
}
|
||||
#ifdef CONFIG_X86_32
|
||||
EXPORT_SYMBOL(save_processor_state);
|
||||
|
@ -229,6 +230,7 @@ static void __restore_processor_state(struct saved_context *ctxt)
|
|||
void restore_processor_state(void)
|
||||
{
|
||||
__restore_processor_state(&saved_context);
|
||||
restore_sched_clock_state();
|
||||
}
|
||||
#ifdef CONFIG_X86_32
|
||||
EXPORT_SYMBOL(restore_processor_state);
|
||||
|
|
|
@ -568,7 +568,7 @@ static int _request_firmware(const struct firmware **firmware_p,
|
|||
out:
|
||||
if (retval) {
|
||||
release_firmware(firmware);
|
||||
firmware_p = NULL;
|
||||
*firmware_p = NULL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
|
|
@ -1650,7 +1650,7 @@ ip2_close( PTTY tty, struct file *pFile )
|
|||
/* disable DSS reporting */
|
||||
i2QueueCommands(PTYPE_INLINE, pCh, 100, 4,
|
||||
CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
|
||||
if ( !tty || (tty->termios->c_cflag & HUPCL) ) {
|
||||
if (tty->termios->c_cflag & HUPCL) {
|
||||
i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
|
||||
pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
|
||||
i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
|
||||
|
@ -2930,6 +2930,8 @@ ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
|
|||
if ( pCh )
|
||||
{
|
||||
rc = copy_to_user(argp, pCh, sizeof(i2ChanStr));
|
||||
if (rc)
|
||||
rc = -EFAULT;
|
||||
} else {
|
||||
rc = -ENODEV;
|
||||
}
|
||||
|
|
|
@ -1244,6 +1244,7 @@ static int set_config(struct tty_struct *tty, struct r_port *info,
|
|||
}
|
||||
info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
|
||||
configure_r_port(tty, info, NULL);
|
||||
mutex_unlock(&info->port.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -691,8 +691,10 @@ static int open(struct tty_struct *tty, struct file *filp)
|
|||
if (info->port.count == 1) {
|
||||
/* 1st open on this device, init hardware */
|
||||
retval = startup(info);
|
||||
if (retval < 0)
|
||||
if (retval < 0) {
|
||||
mutex_unlock(&info->port.mutex);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&info->port.mutex);
|
||||
retval = block_til_ready(tty, filp, info);
|
||||
|
|
|
@ -992,7 +992,7 @@ void intel_wait_for_vblank(struct drm_device *dev, int pipe)
|
|||
|
||||
/* Wait for vblank interrupt bit to set */
|
||||
if (wait_for((I915_READ(pipestat_reg) &
|
||||
PIPE_VBLANK_INTERRUPT_STATUS) == 0,
|
||||
PIPE_VBLANK_INTERRUPT_STATUS),
|
||||
50, 0))
|
||||
DRM_DEBUG_KMS("vblank wait timed out\n");
|
||||
}
|
||||
|
|
|
@ -160,30 +160,12 @@ static const struct attribute_group ads7871_group = {
|
|||
|
||||
static int __devinit ads7871_probe(struct spi_device *spi)
|
||||
{
|
||||
int status, ret, err = 0;
|
||||
int ret, err;
|
||||
uint8_t val;
|
||||
struct ads7871_data *pdata;
|
||||
|
||||
dev_dbg(&spi->dev, "probe\n");
|
||||
|
||||
pdata = kzalloc(sizeof(struct ads7871_data), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
status = sysfs_create_group(&spi->dev.kobj, &ads7871_group);
|
||||
if (status < 0)
|
||||
goto error_free;
|
||||
|
||||
pdata->hwmon_dev = hwmon_device_register(&spi->dev);
|
||||
if (IS_ERR(pdata->hwmon_dev)) {
|
||||
err = PTR_ERR(pdata->hwmon_dev);
|
||||
goto error_remove;
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, pdata);
|
||||
|
||||
/* Configure the SPI bus */
|
||||
spi->mode = (SPI_MODE_0);
|
||||
spi->bits_per_word = 8;
|
||||
|
@ -201,6 +183,24 @@ static int __devinit ads7871_probe(struct spi_device *spi)
|
|||
we need to make sure we really have a chip*/
|
||||
if (val != ret) {
|
||||
err = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pdata = kzalloc(sizeof(struct ads7871_data), GFP_KERNEL);
|
||||
if (!pdata) {
|
||||
err = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
err = sysfs_create_group(&spi->dev.kobj, &ads7871_group);
|
||||
if (err < 0)
|
||||
goto error_free;
|
||||
|
||||
spi_set_drvdata(spi, pdata);
|
||||
|
||||
pdata->hwmon_dev = hwmon_device_register(&spi->dev);
|
||||
if (IS_ERR(pdata->hwmon_dev)) {
|
||||
err = PTR_ERR(pdata->hwmon_dev);
|
||||
goto error_remove;
|
||||
}
|
||||
|
||||
|
|
|
@ -518,7 +518,6 @@ static struct notifier_block coretemp_cpu_notifier __refdata = {
|
|||
static int __init coretemp_init(void)
|
||||
{
|
||||
int i, err = -ENODEV;
|
||||
struct pdev_entry *p, *n;
|
||||
|
||||
/* quick check if we run Intel */
|
||||
if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
|
||||
|
|
|
@ -143,6 +143,37 @@ static const struct pci_device_id k8temp_ids[] = {
|
|||
|
||||
MODULE_DEVICE_TABLE(pci, k8temp_ids);
|
||||
|
||||
static int __devinit is_rev_g_desktop(u8 model)
|
||||
{
|
||||
u32 brandidx;
|
||||
|
||||
if (model < 0x69)
|
||||
return 0;
|
||||
|
||||
if (model == 0xc1 || model == 0x6c || model == 0x7c)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Differentiate between AM2 and ASB1.
|
||||
* See "Constructing the processor Name String" in "Revision
|
||||
* Guide for AMD NPT Family 0Fh Processors" (33610).
|
||||
*/
|
||||
brandidx = cpuid_ebx(0x80000001);
|
||||
brandidx = (brandidx >> 9) & 0x1f;
|
||||
|
||||
/* Single core */
|
||||
if ((model == 0x6f || model == 0x7f) &&
|
||||
(brandidx == 0x7 || brandidx == 0x9 || brandidx == 0xc))
|
||||
return 0;
|
||||
|
||||
/* Dual core */
|
||||
if (model == 0x6b &&
|
||||
(brandidx == 0xb || brandidx == 0xc))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __devinit k8temp_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
|
@ -179,9 +210,7 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,
|
|||
"wrong - check erratum #141\n");
|
||||
}
|
||||
|
||||
if ((model >= 0x69) &&
|
||||
!(model == 0xc1 || model == 0x6c || model == 0x7c ||
|
||||
model == 0x6b || model == 0x6f || model == 0x7f)) {
|
||||
if (is_rev_g_desktop(model)) {
|
||||
/*
|
||||
* RevG desktop CPUs (i.e. no socket S1G1 or
|
||||
* ASB1 parts) need additional offset,
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include <linux/syscalls.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/cpu.h>
|
||||
#include <linux/compat.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -2349,11 +2350,52 @@ static long pmu_unlocked_ioctl(struct file *filp,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
#define PMU_IOC_GET_BACKLIGHT32 _IOR('B', 1, compat_size_t)
|
||||
#define PMU_IOC_SET_BACKLIGHT32 _IOW('B', 2, compat_size_t)
|
||||
#define PMU_IOC_GET_MODEL32 _IOR('B', 3, compat_size_t)
|
||||
#define PMU_IOC_HAS_ADB32 _IOR('B', 4, compat_size_t)
|
||||
#define PMU_IOC_CAN_SLEEP32 _IOR('B', 5, compat_size_t)
|
||||
#define PMU_IOC_GRAB_BACKLIGHT32 _IOR('B', 6, compat_size_t)
|
||||
|
||||
static long compat_pmu_ioctl (struct file *filp, u_int cmd, u_long arg)
|
||||
{
|
||||
switch (cmd) {
|
||||
case PMU_IOC_SLEEP:
|
||||
break;
|
||||
case PMU_IOC_GET_BACKLIGHT32:
|
||||
cmd = PMU_IOC_GET_BACKLIGHT;
|
||||
break;
|
||||
case PMU_IOC_SET_BACKLIGHT32:
|
||||
cmd = PMU_IOC_SET_BACKLIGHT;
|
||||
break;
|
||||
case PMU_IOC_GET_MODEL32:
|
||||
cmd = PMU_IOC_GET_MODEL;
|
||||
break;
|
||||
case PMU_IOC_HAS_ADB32:
|
||||
cmd = PMU_IOC_HAS_ADB;
|
||||
break;
|
||||
case PMU_IOC_CAN_SLEEP32:
|
||||
cmd = PMU_IOC_CAN_SLEEP;
|
||||
break;
|
||||
case PMU_IOC_GRAB_BACKLIGHT32:
|
||||
cmd = PMU_IOC_GRAB_BACKLIGHT;
|
||||
break;
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
return pmu_unlocked_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct file_operations pmu_device_fops = {
|
||||
.read = pmu_read,
|
||||
.write = pmu_write,
|
||||
.poll = pmu_fpoll,
|
||||
.unlocked_ioctl = pmu_unlocked_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = compat_pmu_ioctl,
|
||||
#endif
|
||||
.open = pmu_open,
|
||||
.release = pmu_release,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
config MANTIS_CORE
|
||||
tristate "Mantis/Hopper PCI bridge based devices"
|
||||
depends on PCI && I2C && INPUT
|
||||
depends on PCI && I2C && INPUT && IR_CORE
|
||||
|
||||
help
|
||||
Support for PCI cards based on the Mantis and Hopper PCi bridge.
|
||||
|
|
|
@ -145,7 +145,7 @@ static void free_rar_device(struct rar_device *rar)
|
|||
*/
|
||||
static struct rar_device *_rar_to_device(int rar, int *off)
|
||||
{
|
||||
if (rar >= 0 && rar <= 3) {
|
||||
if (rar >= 0 && rar < MRST_NUM_RAR) {
|
||||
*off = rar;
|
||||
return &my_rar_device;
|
||||
}
|
||||
|
|
|
@ -487,7 +487,7 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)
|
|||
mdelay(1);
|
||||
*data = readl(ipcdev.i2c_base + I2C_DATA_ADDR);
|
||||
} else if (cmd == IPC_I2C_WRITE) {
|
||||
writel(addr, ipcdev.i2c_base + I2C_DATA_ADDR);
|
||||
writel(*data, ipcdev.i2c_base + I2C_DATA_ADDR);
|
||||
mdelay(1);
|
||||
writel(addr, ipcdev.i2c_base + IPC_I2C_CNTRL_ADDR);
|
||||
} else {
|
||||
|
|
|
@ -869,7 +869,9 @@ static int get_serial_info(struct m68k_serial * info,
|
|||
tmp.close_delay = info->close_delay;
|
||||
tmp.closing_wait = info->closing_wait;
|
||||
tmp.custom_divisor = info->custom_divisor;
|
||||
copy_to_user(retinfo,&tmp,sizeof(*retinfo));
|
||||
if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -882,7 +884,8 @@ static int set_serial_info(struct m68k_serial * info,
|
|||
|
||||
if (!new_info)
|
||||
return -EFAULT;
|
||||
copy_from_user(&new_serial,new_info,sizeof(new_serial));
|
||||
if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
|
||||
return -EFAULT;
|
||||
old_info = *info;
|
||||
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
|
@ -943,8 +946,7 @@ static int get_lsr_info(struct m68k_serial * info, unsigned int *value)
|
|||
status = 0;
|
||||
#endif
|
||||
local_irq_restore(flags);
|
||||
put_user(status,value);
|
||||
return 0;
|
||||
return put_user(status, value);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -999,27 +1001,18 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
|
|||
send_break(info, arg ? arg*(100) : 250);
|
||||
return 0;
|
||||
case TIOCGSERIAL:
|
||||
if (access_ok(VERIFY_WRITE, (void *) arg,
|
||||
sizeof(struct serial_struct)))
|
||||
return get_serial_info(info,
|
||||
(struct serial_struct *) arg);
|
||||
return -EFAULT;
|
||||
return get_serial_info(info,
|
||||
(struct serial_struct *) arg);
|
||||
case TIOCSSERIAL:
|
||||
return set_serial_info(info,
|
||||
(struct serial_struct *) arg);
|
||||
case TIOCSERGETLSR: /* Get line status register */
|
||||
if (access_ok(VERIFY_WRITE, (void *) arg,
|
||||
sizeof(unsigned int)))
|
||||
return get_lsr_info(info, (unsigned int *) arg);
|
||||
return -EFAULT;
|
||||
return get_lsr_info(info, (unsigned int *) arg);
|
||||
case TIOCSERGSTRUCT:
|
||||
if (!access_ok(VERIFY_WRITE, (void *) arg,
|
||||
sizeof(struct m68k_serial)))
|
||||
if (copy_to_user((struct m68k_serial *) arg,
|
||||
info, sizeof(struct m68k_serial)))
|
||||
return -EFAULT;
|
||||
copy_to_user((struct m68k_serial *) arg,
|
||||
info, sizeof(struct m68k_serial));
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
|
|
@ -203,13 +203,13 @@ static int __init parse_options(struct early_serial8250_device *device,
|
|||
|
||||
if (mmio || mmio32)
|
||||
printk(KERN_INFO
|
||||
"Early serial console at MMIO%s 0x%llu (options '%s')\n",
|
||||
"Early serial console at MMIO%s 0x%llx (options '%s')\n",
|
||||
mmio32 ? "32" : "",
|
||||
(unsigned long long)port->mapbase,
|
||||
device->options);
|
||||
else
|
||||
printk(KERN_INFO
|
||||
"Early serial console at I/O port 0x%lu (options '%s')\n",
|
||||
"Early serial console at I/O port 0x%lx (options '%s')\n",
|
||||
port->iobase,
|
||||
device->options);
|
||||
|
||||
|
|
|
@ -115,8 +115,6 @@ source "drivers/staging/vme/Kconfig"
|
|||
|
||||
source "drivers/staging/memrar/Kconfig"
|
||||
|
||||
source "drivers/staging/sep/Kconfig"
|
||||
|
||||
source "drivers/staging/iio/Kconfig"
|
||||
|
||||
source "drivers/staging/zram/Kconfig"
|
||||
|
|
|
@ -39,7 +39,6 @@ obj-$(CONFIG_FB_UDL) += udlfb/
|
|||
obj-$(CONFIG_HYPERV) += hv/
|
||||
obj-$(CONFIG_VME_BUS) += vme/
|
||||
obj-$(CONFIG_MRST_RAR_HANDLER) += memrar/
|
||||
obj-$(CONFIG_DX_SEP) += sep/
|
||||
obj-$(CONFIG_IIO) += iio/
|
||||
obj-$(CONFIG_ZRAM) += zram/
|
||||
obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/
|
||||
|
|
|
@ -267,6 +267,10 @@ static ssize_t store_log_level(struct kobject *kobj, struct attribute *attr,
|
|||
if (atomic_read(&bat_priv->log_level) == log_level_tmp)
|
||||
return count;
|
||||
|
||||
bat_info(net_dev, "Changing log level from: %i to: %li\n",
|
||||
atomic_read(&bat_priv->log_level),
|
||||
log_level_tmp);
|
||||
|
||||
atomic_set(&bat_priv->log_level, (unsigned)log_level_tmp);
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -129,6 +129,9 @@ static bool hardif_is_iface_up(struct batman_if *batman_if)
|
|||
|
||||
static void update_mac_addresses(struct batman_if *batman_if)
|
||||
{
|
||||
if (!batman_if || !batman_if->packet_buff)
|
||||
return;
|
||||
|
||||
addr_to_string(batman_if->addr_str, batman_if->net_dev->dev_addr);
|
||||
|
||||
memcpy(((struct batman_packet *)(batman_if->packet_buff))->orig,
|
||||
|
@ -194,8 +197,6 @@ static void hardif_activate_interface(struct net_device *net_dev,
|
|||
if (batman_if->if_status != IF_INACTIVE)
|
||||
return;
|
||||
|
||||
dev_hold(batman_if->net_dev);
|
||||
|
||||
update_mac_addresses(batman_if);
|
||||
batman_if->if_status = IF_TO_BE_ACTIVATED;
|
||||
|
||||
|
@ -222,8 +223,6 @@ static void hardif_deactivate_interface(struct net_device *net_dev,
|
|||
(batman_if->if_status != IF_TO_BE_ACTIVATED))
|
||||
return;
|
||||
|
||||
dev_put(batman_if->net_dev);
|
||||
|
||||
batman_if->if_status = IF_INACTIVE;
|
||||
|
||||
bat_info(net_dev, "Interface deactivated: %s\n", batman_if->dev);
|
||||
|
@ -318,11 +317,13 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
|
|||
if (ret != 1)
|
||||
goto out;
|
||||
|
||||
dev_hold(net_dev);
|
||||
|
||||
batman_if = kmalloc(sizeof(struct batman_if), GFP_ATOMIC);
|
||||
if (!batman_if) {
|
||||
pr_err("Can't add interface (%s): out of memory\n",
|
||||
net_dev->name);
|
||||
goto out;
|
||||
goto release_dev;
|
||||
}
|
||||
|
||||
batman_if->dev = kstrdup(net_dev->name, GFP_ATOMIC);
|
||||
|
@ -336,6 +337,7 @@ static struct batman_if *hardif_add_interface(struct net_device *net_dev)
|
|||
batman_if->if_num = -1;
|
||||
batman_if->net_dev = net_dev;
|
||||
batman_if->if_status = IF_NOT_IN_USE;
|
||||
batman_if->packet_buff = NULL;
|
||||
INIT_LIST_HEAD(&batman_if->list);
|
||||
|
||||
check_known_mac_addr(batman_if->net_dev->dev_addr);
|
||||
|
@ -346,6 +348,8 @@ free_dev:
|
|||
kfree(batman_if->dev);
|
||||
free_if:
|
||||
kfree(batman_if);
|
||||
release_dev:
|
||||
dev_put(net_dev);
|
||||
out:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -374,6 +378,7 @@ static void hardif_remove_interface(struct batman_if *batman_if)
|
|||
batman_if->if_status = IF_TO_BE_REMOVED;
|
||||
list_del_rcu(&batman_if->list);
|
||||
sysfs_del_hardif(&batman_if->hardif_obj);
|
||||
dev_put(batman_if->net_dev);
|
||||
call_rcu(&batman_if->rcu, hardif_free_interface);
|
||||
}
|
||||
|
||||
|
@ -393,15 +398,13 @@ static int hard_if_event(struct notifier_block *this,
|
|||
/* FIXME: each batman_if will be attached to a softif */
|
||||
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||
|
||||
if (!batman_if)
|
||||
batman_if = hardif_add_interface(net_dev);
|
||||
if (!batman_if && event == NETDEV_REGISTER)
|
||||
batman_if = hardif_add_interface(net_dev);
|
||||
|
||||
if (!batman_if)
|
||||
goto out;
|
||||
|
||||
switch (event) {
|
||||
case NETDEV_REGISTER:
|
||||
break;
|
||||
case NETDEV_UP:
|
||||
hardif_activate_interface(soft_device, bat_priv, batman_if);
|
||||
break;
|
||||
|
@ -442,8 +445,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
|||
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||
struct batman_packet *batman_packet;
|
||||
struct batman_if *batman_if;
|
||||
struct net_device_stats *stats;
|
||||
struct rtnl_link_stats64 temp;
|
||||
int ret;
|
||||
|
||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
|
@ -479,12 +480,6 @@ int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
|
|||
if (batman_if->if_status != IF_ACTIVE)
|
||||
goto err_free;
|
||||
|
||||
stats = (struct net_device_stats *)dev_get_stats(skb->dev, &temp);
|
||||
if (stats) {
|
||||
stats->rx_packets++;
|
||||
stats->rx_bytes += skb->len;
|
||||
}
|
||||
|
||||
batman_packet = (struct batman_packet *)skb->data;
|
||||
|
||||
if (batman_packet->version != COMPAT_VERSION) {
|
||||
|
|
|
@ -67,6 +67,7 @@ static int bat_socket_open(struct inode *inode, struct file *file)
|
|||
INIT_LIST_HEAD(&socket_client->queue_list);
|
||||
socket_client->queue_len = 0;
|
||||
socket_client->index = i;
|
||||
socket_client->bat_priv = inode->i_private;
|
||||
spin_lock_init(&socket_client->lock);
|
||||
init_waitqueue_head(&socket_client->queue_wait);
|
||||
|
||||
|
@ -151,9 +152,8 @@ static ssize_t bat_socket_read(struct file *file, char __user *buf,
|
|||
static ssize_t bat_socket_write(struct file *file, const char __user *buff,
|
||||
size_t len, loff_t *off)
|
||||
{
|
||||
/* FIXME: each orig_node->batman_if will be attached to a softif */
|
||||
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||
struct socket_client *socket_client = file->private_data;
|
||||
struct bat_priv *bat_priv = socket_client->bat_priv;
|
||||
struct icmp_packet_rr icmp_packet;
|
||||
struct orig_node *orig_node;
|
||||
struct batman_if *batman_if;
|
||||
|
@ -168,6 +168,9 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!bat_priv->primary_if)
|
||||
return -EFAULT;
|
||||
|
||||
if (len >= sizeof(struct icmp_packet_rr))
|
||||
packet_len = sizeof(struct icmp_packet_rr);
|
||||
|
||||
|
@ -223,7 +226,8 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
|
|||
if (batman_if->if_status != IF_ACTIVE)
|
||||
goto dst_unreach;
|
||||
|
||||
memcpy(icmp_packet.orig, batman_if->net_dev->dev_addr, ETH_ALEN);
|
||||
memcpy(icmp_packet.orig,
|
||||
bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
|
||||
|
||||
if (packet_len == sizeof(struct icmp_packet_rr))
|
||||
memcpy(icmp_packet.rr, batman_if->net_dev->dev_addr, ETH_ALEN);
|
||||
|
@ -271,7 +275,7 @@ int bat_socket_setup(struct bat_priv *bat_priv)
|
|||
goto err;
|
||||
|
||||
d = debugfs_create_file(ICMP_SOCKET, S_IFREG | S_IWUSR | S_IRUSR,
|
||||
bat_priv->debug_dir, NULL, &fops);
|
||||
bat_priv->debug_dir, bat_priv, &fops);
|
||||
if (d)
|
||||
goto err;
|
||||
|
||||
|
|
|
@ -250,10 +250,13 @@ int choose_orig(void *data, int32_t size)
|
|||
int is_my_mac(uint8_t *addr)
|
||||
{
|
||||
struct batman_if *batman_if;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(batman_if, &if_list, list) {
|
||||
if ((batman_if->net_dev) &&
|
||||
(compare_orig(batman_if->net_dev->dev_addr, addr))) {
|
||||
if (batman_if->if_status != IF_ACTIVE)
|
||||
continue;
|
||||
|
||||
if (compare_orig(batman_if->net_dev->dev_addr, addr)) {
|
||||
rcu_read_unlock();
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -391,11 +391,12 @@ static int orig_node_add_if(struct orig_node *orig_node, int max_if_num)
|
|||
int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
|
||||
{
|
||||
struct orig_node *orig_node;
|
||||
unsigned long flags;
|
||||
HASHIT(hashit);
|
||||
|
||||
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on
|
||||
* if_num */
|
||||
spin_lock(&orig_hash_lock);
|
||||
spin_lock_irqsave(&orig_hash_lock, flags);
|
||||
|
||||
while (hash_iterate(orig_hash, &hashit)) {
|
||||
orig_node = hashit.bucket->data;
|
||||
|
@ -404,11 +405,11 @@ int orig_hash_add_if(struct batman_if *batman_if, int max_if_num)
|
|||
goto err;
|
||||
}
|
||||
|
||||
spin_unlock(&orig_hash_lock);
|
||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
spin_unlock(&orig_hash_lock);
|
||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -468,12 +469,13 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
|
|||
{
|
||||
struct batman_if *batman_if_tmp;
|
||||
struct orig_node *orig_node;
|
||||
unsigned long flags;
|
||||
HASHIT(hashit);
|
||||
int ret;
|
||||
|
||||
/* resize all orig nodes because orig_node->bcast_own(_sum) depend on
|
||||
* if_num */
|
||||
spin_lock(&orig_hash_lock);
|
||||
spin_lock_irqsave(&orig_hash_lock, flags);
|
||||
|
||||
while (hash_iterate(orig_hash, &hashit)) {
|
||||
orig_node = hashit.bucket->data;
|
||||
|
@ -500,10 +502,10 @@ int orig_hash_del_if(struct batman_if *batman_if, int max_if_num)
|
|||
rcu_read_unlock();
|
||||
|
||||
batman_if->if_num = -1;
|
||||
spin_unlock(&orig_hash_lock);
|
||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
spin_unlock(&orig_hash_lock);
|
||||
spin_unlock_irqrestore(&orig_hash_lock, flags);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
|
@ -783,6 +783,8 @@ int recv_bat_packet(struct sk_buff *skb,
|
|||
|
||||
static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len)
|
||||
{
|
||||
/* FIXME: each batman_if will be attached to a softif */
|
||||
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||
struct orig_node *orig_node;
|
||||
struct icmp_packet_rr *icmp_packet;
|
||||
struct ethhdr *ethhdr;
|
||||
|
@ -801,6 +803,9 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len)
|
|||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
if (!bat_priv->primary_if)
|
||||
return NET_RX_DROP;
|
||||
|
||||
/* answer echo request (ping) */
|
||||
/* get routing information */
|
||||
spin_lock_irqsave(&orig_hash_lock, flags);
|
||||
|
@ -830,7 +835,8 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len)
|
|||
}
|
||||
|
||||
memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
|
||||
memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
|
||||
memcpy(icmp_packet->orig,
|
||||
bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
|
||||
icmp_packet->msg_type = ECHO_REPLY;
|
||||
icmp_packet->ttl = TTL;
|
||||
|
||||
|
@ -845,6 +851,8 @@ static int recv_my_icmp_packet(struct sk_buff *skb, size_t icmp_len)
|
|||
|
||||
static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len)
|
||||
{
|
||||
/* FIXME: each batman_if will be attached to a softif */
|
||||
struct bat_priv *bat_priv = netdev_priv(soft_device);
|
||||
struct orig_node *orig_node;
|
||||
struct icmp_packet *icmp_packet;
|
||||
struct ethhdr *ethhdr;
|
||||
|
@ -865,6 +873,9 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len)
|
|||
return NET_RX_DROP;
|
||||
}
|
||||
|
||||
if (!bat_priv->primary_if)
|
||||
return NET_RX_DROP;
|
||||
|
||||
/* get routing information */
|
||||
spin_lock_irqsave(&orig_hash_lock, flags);
|
||||
orig_node = ((struct orig_node *)
|
||||
|
@ -892,7 +903,8 @@ static int recv_icmp_ttl_exceeded(struct sk_buff *skb, size_t icmp_len)
|
|||
}
|
||||
|
||||
memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN);
|
||||
memcpy(icmp_packet->orig, ethhdr->h_dest, ETH_ALEN);
|
||||
memcpy(icmp_packet->orig,
|
||||
bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
|
||||
icmp_packet->msg_type = TTL_EXCEEDED;
|
||||
icmp_packet->ttl = TTL;
|
||||
|
||||
|
|
|
@ -126,6 +126,7 @@ struct socket_client {
|
|||
unsigned char index;
|
||||
spinlock_t lock;
|
||||
wait_queue_head_t queue_wait;
|
||||
struct bat_priv *bat_priv;
|
||||
};
|
||||
|
||||
struct socket_packet {
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
config DX_SEP
|
||||
tristate "Discretix SEP driver"
|
||||
# depends on MRST
|
||||
depends on RAR_REGISTER && PCI
|
||||
default y
|
||||
help
|
||||
Discretix SEP driver
|
||||
|
||||
If unsure say M. The compiled module will be
|
||||
called sep_driver.ko
|
|
@ -1,2 +0,0 @@
|
|||
obj-$(CONFIG_DX_SEP) := sep_driver.o
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
Todo's so far (from Alan Cox)
|
||||
- Fix firmware loading
|
||||
- Get firmware into firmware git tree
|
||||
- Review and tidy each algorithm function
|
||||
- Check whether it can be plugged into any of the kernel crypto API
|
||||
interfaces
|
||||
- Do something about the magic shared memory interface and replace it
|
||||
with something saner (in Linux terms)
|
|
@ -1,110 +0,0 @@
|
|||
#ifndef __SEP_DEV_H__
|
||||
#define __SEP_DEV_H__
|
||||
|
||||
/*
|
||||
*
|
||||
* sep_dev.h - Security Processor Device Structures
|
||||
*
|
||||
* Copyright(c) 2009 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2009 Discretix. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* CONTACTS:
|
||||
*
|
||||
* Alan Cox alan@linux.intel.com
|
||||
*
|
||||
*/
|
||||
|
||||
struct sep_device {
|
||||
/* pointer to pci dev */
|
||||
struct pci_dev *pdev;
|
||||
|
||||
unsigned long in_use;
|
||||
|
||||
/* address of the shared memory allocated during init for SEP driver
|
||||
(coherent alloc) */
|
||||
void *shared_addr;
|
||||
/* the physical address of the shared area */
|
||||
dma_addr_t shared_bus;
|
||||
|
||||
/* restricted access region (coherent alloc) */
|
||||
dma_addr_t rar_bus;
|
||||
void *rar_addr;
|
||||
/* firmware regions: cache is at rar_addr */
|
||||
unsigned long cache_size;
|
||||
|
||||
/* follows the cache */
|
||||
dma_addr_t resident_bus;
|
||||
unsigned long resident_size;
|
||||
void *resident_addr;
|
||||
|
||||
/* start address of the access to the SEP registers from driver */
|
||||
void __iomem *reg_addr;
|
||||
/* transaction counter that coordinates the transactions between SEP and HOST */
|
||||
unsigned long send_ct;
|
||||
/* counter for the messages from sep */
|
||||
unsigned long reply_ct;
|
||||
/* counter for the number of bytes allocated in the pool for the current
|
||||
transaction */
|
||||
unsigned long data_pool_bytes_allocated;
|
||||
|
||||
/* array of pointers to the pages that represent input data for the synchronic
|
||||
DMA action */
|
||||
struct page **in_page_array;
|
||||
|
||||
/* array of pointers to the pages that represent out data for the synchronic
|
||||
DMA action */
|
||||
struct page **out_page_array;
|
||||
|
||||
/* number of pages in the sep_in_page_array */
|
||||
unsigned long in_num_pages;
|
||||
|
||||
/* number of pages in the sep_out_page_array */
|
||||
unsigned long out_num_pages;
|
||||
|
||||
/* global data for every flow */
|
||||
struct sep_flow_context_t flows[SEP_DRIVER_NUM_FLOWS];
|
||||
|
||||
/* pointer to the workqueue that handles the flow done interrupts */
|
||||
struct workqueue_struct *flow_wq;
|
||||
|
||||
};
|
||||
|
||||
static struct sep_device *sep_dev;
|
||||
|
||||
static inline void sep_write_reg(struct sep_device *dev, int reg, u32 value)
|
||||
{
|
||||
void __iomem *addr = dev->reg_addr + reg;
|
||||
writel(value, addr);
|
||||
}
|
||||
|
||||
static inline u32 sep_read_reg(struct sep_device *dev, int reg)
|
||||
{
|
||||
void __iomem *addr = dev->reg_addr + reg;
|
||||
return readl(addr);
|
||||
}
|
||||
|
||||
/* wait for SRAM write complete(indirect write */
|
||||
static inline void sep_wait_sram_write(struct sep_device *dev)
|
||||
{
|
||||
u32 reg_val;
|
||||
do
|
||||
reg_val = sep_read_reg(dev, HW_SRAM_DATA_READY_REG_ADDR);
|
||||
while (!(reg_val & 1));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,425 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* sep_driver_api.h - Security Processor Driver api definitions
|
||||
*
|
||||
* Copyright(c) 2009 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2009 Discretix. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* CONTACTS:
|
||||
*
|
||||
* Mark Allyn mark.a.allyn@intel.com
|
||||
*
|
||||
* CHANGES:
|
||||
*
|
||||
* 2009.06.26 Initial publish
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SEP_DRIVER_API_H__
|
||||
#define __SEP_DRIVER_API_H__
|
||||
|
||||
|
||||
|
||||
/*----------------------------------------------------------------
|
||||
IOCTL command defines
|
||||
-----------------------------------------------------------------*/
|
||||
|
||||
/* magic number 1 of the sep IOCTL command */
|
||||
#define SEP_IOC_MAGIC_NUMBER 's'
|
||||
|
||||
/* sends interrupt to sep that message is ready */
|
||||
#define SEP_IOCSENDSEPCOMMAND _IO(SEP_IOC_MAGIC_NUMBER , 0)
|
||||
|
||||
/* sends interrupt to sep that message is ready */
|
||||
#define SEP_IOCSENDSEPRPLYCOMMAND _IO(SEP_IOC_MAGIC_NUMBER , 1)
|
||||
|
||||
/* allocate memory in data pool */
|
||||
#define SEP_IOCALLOCDATAPOLL _IO(SEP_IOC_MAGIC_NUMBER , 2)
|
||||
|
||||
/* write to pre-allocated memory in data pool */
|
||||
#define SEP_IOCWRITEDATAPOLL _IO(SEP_IOC_MAGIC_NUMBER , 3)
|
||||
|
||||
/* read from pre-allocated memory in data pool */
|
||||
#define SEP_IOCREADDATAPOLL _IO(SEP_IOC_MAGIC_NUMBER , 4)
|
||||
|
||||
/* create sym dma lli tables */
|
||||
#define SEP_IOCCREATESYMDMATABLE _IO(SEP_IOC_MAGIC_NUMBER , 5)
|
||||
|
||||
/* create flow dma lli tables */
|
||||
#define SEP_IOCCREATEFLOWDMATABLE _IO(SEP_IOC_MAGIC_NUMBER , 6)
|
||||
|
||||
/* free dynamic data aalocated during table creation */
|
||||
#define SEP_IOCFREEDMATABLEDATA _IO(SEP_IOC_MAGIC_NUMBER , 7)
|
||||
|
||||
/* get the static pool area addresses (physical and virtual) */
|
||||
#define SEP_IOCGETSTATICPOOLADDR _IO(SEP_IOC_MAGIC_NUMBER , 8)
|
||||
|
||||
/* set flow id command */
|
||||
#define SEP_IOCSETFLOWID _IO(SEP_IOC_MAGIC_NUMBER , 9)
|
||||
|
||||
/* add tables to the dynamic flow */
|
||||
#define SEP_IOCADDFLOWTABLE _IO(SEP_IOC_MAGIC_NUMBER , 10)
|
||||
|
||||
/* add flow add tables message */
|
||||
#define SEP_IOCADDFLOWMESSAGE _IO(SEP_IOC_MAGIC_NUMBER , 11)
|
||||
|
||||
/* start sep command */
|
||||
#define SEP_IOCSEPSTART _IO(SEP_IOC_MAGIC_NUMBER , 12)
|
||||
|
||||
/* init sep command */
|
||||
#define SEP_IOCSEPINIT _IO(SEP_IOC_MAGIC_NUMBER , 13)
|
||||
|
||||
/* end transaction command */
|
||||
#define SEP_IOCENDTRANSACTION _IO(SEP_IOC_MAGIC_NUMBER , 15)
|
||||
|
||||
/* reallocate cache and resident */
|
||||
#define SEP_IOCREALLOCCACHERES _IO(SEP_IOC_MAGIC_NUMBER , 16)
|
||||
|
||||
/* get the offset of the address starting from the beginnnig of the map area */
|
||||
#define SEP_IOCGETMAPPEDADDROFFSET _IO(SEP_IOC_MAGIC_NUMBER , 17)
|
||||
|
||||
/* get time address and value */
|
||||
#define SEP_IOCGETIME _IO(SEP_IOC_MAGIC_NUMBER , 19)
|
||||
|
||||
/*-------------------------------------------
|
||||
TYPEDEFS
|
||||
----------------------------------------------*/
|
||||
|
||||
/*
|
||||
init command struct
|
||||
*/
|
||||
struct sep_driver_init_t {
|
||||
/* start of the 1G of the host memory address that SEP can access */
|
||||
unsigned long message_addr;
|
||||
|
||||
/* start address of resident */
|
||||
unsigned long message_size_in_words;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
realloc cache resident command
|
||||
*/
|
||||
struct sep_driver_realloc_cache_resident_t {
|
||||
/* new cache address */
|
||||
u64 new_cache_addr;
|
||||
/* new resident address */
|
||||
u64 new_resident_addr;
|
||||
/* new resident address */
|
||||
u64 new_shared_area_addr;
|
||||
/* new base address */
|
||||
u64 new_base_addr;
|
||||
};
|
||||
|
||||
struct sep_driver_alloc_t {
|
||||
/* virtual address of allocated space */
|
||||
unsigned long offset;
|
||||
|
||||
/* physical address of allocated space */
|
||||
unsigned long phys_address;
|
||||
|
||||
/* number of bytes to allocate */
|
||||
unsigned long num_bytes;
|
||||
};
|
||||
|
||||
/*
|
||||
*/
|
||||
struct sep_driver_write_t {
|
||||
/* application space address */
|
||||
unsigned long app_address;
|
||||
|
||||
/* address of the data pool */
|
||||
unsigned long datapool_address;
|
||||
|
||||
/* number of bytes to write */
|
||||
unsigned long num_bytes;
|
||||
};
|
||||
|
||||
/*
|
||||
*/
|
||||
struct sep_driver_read_t {
|
||||
/* application space address */
|
||||
unsigned long app_address;
|
||||
|
||||
/* address of the data pool */
|
||||
unsigned long datapool_address;
|
||||
|
||||
/* number of bytes to read */
|
||||
unsigned long num_bytes;
|
||||
};
|
||||
|
||||
/*
|
||||
*/
|
||||
struct sep_driver_build_sync_table_t {
|
||||
/* address value of the data in */
|
||||
unsigned long app_in_address;
|
||||
|
||||
/* size of data in */
|
||||
unsigned long data_in_size;
|
||||
|
||||
/* address of the data out */
|
||||
unsigned long app_out_address;
|
||||
|
||||
/* the size of the block of the operation - if needed,
|
||||
every table will be modulo this parameter */
|
||||
unsigned long block_size;
|
||||
|
||||
/* the physical address of the first input DMA table */
|
||||
unsigned long in_table_address;
|
||||
|
||||
/* number of entries in the first input DMA table */
|
||||
unsigned long in_table_num_entries;
|
||||
|
||||
/* the physical address of the first output DMA table */
|
||||
unsigned long out_table_address;
|
||||
|
||||
/* number of entries in the first output DMA table */
|
||||
unsigned long out_table_num_entries;
|
||||
|
||||
/* data in the first input table */
|
||||
unsigned long table_data_size;
|
||||
|
||||
/* distinct user/kernel layout */
|
||||
bool isKernelVirtualAddress;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
*/
|
||||
struct sep_driver_build_flow_table_t {
|
||||
/* flow type */
|
||||
unsigned long flow_type;
|
||||
|
||||
/* flag for input output */
|
||||
unsigned long input_output_flag;
|
||||
|
||||
/* address value of the data in */
|
||||
unsigned long virt_buff_data_addr;
|
||||
|
||||
/* size of data in */
|
||||
unsigned long num_virtual_buffers;
|
||||
|
||||
/* the physical address of the first input DMA table */
|
||||
unsigned long first_table_addr;
|
||||
|
||||
/* number of entries in the first input DMA table */
|
||||
unsigned long first_table_num_entries;
|
||||
|
||||
/* data in the first input table */
|
||||
unsigned long first_table_data_size;
|
||||
|
||||
/* distinct user/kernel layout */
|
||||
bool isKernelVirtualAddress;
|
||||
};
|
||||
|
||||
|
||||
struct sep_driver_add_flow_table_t {
|
||||
/* flow id */
|
||||
unsigned long flow_id;
|
||||
|
||||
/* flag for input output */
|
||||
unsigned long inputOutputFlag;
|
||||
|
||||
/* address value of the data in */
|
||||
unsigned long virt_buff_data_addr;
|
||||
|
||||
/* size of data in */
|
||||
unsigned long num_virtual_buffers;
|
||||
|
||||
/* address of the first table */
|
||||
unsigned long first_table_addr;
|
||||
|
||||
/* number of entries in the first table */
|
||||
unsigned long first_table_num_entries;
|
||||
|
||||
/* data size of the first table */
|
||||
unsigned long first_table_data_size;
|
||||
|
||||
/* distinct user/kernel layout */
|
||||
bool isKernelVirtualAddress;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
command struct for set flow id
|
||||
*/
|
||||
struct sep_driver_set_flow_id_t {
|
||||
/* flow id to set */
|
||||
unsigned long flow_id;
|
||||
};
|
||||
|
||||
|
||||
/* command struct for add tables message */
|
||||
struct sep_driver_add_message_t {
|
||||
/* flow id to set */
|
||||
unsigned long flow_id;
|
||||
|
||||
/* message size in bytes */
|
||||
unsigned long message_size_in_bytes;
|
||||
|
||||
/* address of the message */
|
||||
unsigned long message_address;
|
||||
};
|
||||
|
||||
/* command struct for static pool addresses */
|
||||
struct sep_driver_static_pool_addr_t {
|
||||
/* physical address of the static pool */
|
||||
unsigned long physical_static_address;
|
||||
|
||||
/* virtual address of the static pool */
|
||||
unsigned long virtual_static_address;
|
||||
};
|
||||
|
||||
/* command struct for getiing offset of the physical address from
|
||||
the start of the mapped area */
|
||||
struct sep_driver_get_mapped_offset_t {
|
||||
/* physical address of the static pool */
|
||||
unsigned long physical_address;
|
||||
|
||||
/* virtual address of the static pool */
|
||||
unsigned long offset;
|
||||
};
|
||||
|
||||
/* command struct for getting time value and address */
|
||||
struct sep_driver_get_time_t {
|
||||
/* physical address of stored time */
|
||||
unsigned long time_physical_address;
|
||||
|
||||
/* value of the stored time */
|
||||
unsigned long time_value;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
structure that represent one entry in the DMA LLI table
|
||||
*/
|
||||
struct sep_lli_entry_t {
|
||||
/* physical address */
|
||||
unsigned long physical_address;
|
||||
|
||||
/* block size */
|
||||
unsigned long block_size;
|
||||
};
|
||||
|
||||
/*
|
||||
structure that reperesents data needed for lli table construction
|
||||
*/
|
||||
struct sep_lli_prepare_table_data_t {
|
||||
/* pointer to the memory where the first lli entry to be built */
|
||||
struct sep_lli_entry_t *lli_entry_ptr;
|
||||
|
||||
/* pointer to the array of lli entries from which the table is to be built */
|
||||
struct sep_lli_entry_t *lli_array_ptr;
|
||||
|
||||
/* number of elements in lli array */
|
||||
int lli_array_size;
|
||||
|
||||
/* number of entries in the created table */
|
||||
int num_table_entries;
|
||||
|
||||
/* number of array entries processed during table creation */
|
||||
int num_array_entries_processed;
|
||||
|
||||
/* the totatl data size in the created table */
|
||||
int lli_table_total_data_size;
|
||||
};
|
||||
|
||||
/*
|
||||
structure that represent tone table - it is not used in code, jkust
|
||||
to show what table looks like
|
||||
*/
|
||||
struct sep_lli_table_t {
|
||||
/* number of pages mapped in this tables. If 0 - means that the table
|
||||
is not defined (used as a valid flag) */
|
||||
unsigned long num_pages;
|
||||
/*
|
||||
pointer to array of page pointers that represent the mapping of the
|
||||
virtual buffer defined by the table to the physical memory. If this
|
||||
pointer is NULL, it means that the table is not defined
|
||||
(used as a valid flag)
|
||||
*/
|
||||
struct page **table_page_array_ptr;
|
||||
|
||||
/* maximum flow entries in table */
|
||||
struct sep_lli_entry_t lli_entries[SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
structure for keeping the mapping of the virtual buffer into physical pages
|
||||
*/
|
||||
struct sep_flow_buffer_data {
|
||||
/* pointer to the array of page structs pointers to the pages of the
|
||||
virtual buffer */
|
||||
struct page **page_array_ptr;
|
||||
|
||||
/* number of pages taken by the virtual buffer */
|
||||
unsigned long num_pages;
|
||||
|
||||
/* this flag signals if this page_array is the last one among many that were
|
||||
sent in one setting to SEP */
|
||||
unsigned long last_page_array_flag;
|
||||
};
|
||||
|
||||
/*
|
||||
struct that keeps all the data for one flow
|
||||
*/
|
||||
struct sep_flow_context_t {
|
||||
/*
|
||||
work struct for handling the flow done interrupt in the workqueue
|
||||
this structure must be in the first place, since it will be used
|
||||
forcasting to the containing flow context
|
||||
*/
|
||||
struct work_struct flow_wq;
|
||||
|
||||
/* flow id */
|
||||
unsigned long flow_id;
|
||||
|
||||
/* additional input tables exists */
|
||||
unsigned long input_tables_flag;
|
||||
|
||||
/* additional output tables exists */
|
||||
unsigned long output_tables_flag;
|
||||
|
||||
/* data of the first input file */
|
||||
struct sep_lli_entry_t first_input_table;
|
||||
|
||||
/* data of the first output table */
|
||||
struct sep_lli_entry_t first_output_table;
|
||||
|
||||
/* last input table data */
|
||||
struct sep_lli_entry_t last_input_table;
|
||||
|
||||
/* last output table data */
|
||||
struct sep_lli_entry_t last_output_table;
|
||||
|
||||
/* first list of table */
|
||||
struct sep_lli_entry_t input_tables_in_process;
|
||||
|
||||
/* output table in process (in sep) */
|
||||
struct sep_lli_entry_t output_tables_in_process;
|
||||
|
||||
/* size of messages in bytes */
|
||||
unsigned long message_size_in_bytes;
|
||||
|
||||
/* message */
|
||||
unsigned char message[SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES];
|
||||
};
|
||||
|
||||
|
||||
#endif
|
|
@ -1,225 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* sep_driver_config.h - Security Processor Driver configuration
|
||||
*
|
||||
* Copyright(c) 2009 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2009 Discretix. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* CONTACTS:
|
||||
*
|
||||
* Mark Allyn mark.a.allyn@intel.com
|
||||
*
|
||||
* CHANGES:
|
||||
*
|
||||
* 2009.06.26 Initial publish
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __SEP_DRIVER_CONFIG_H__
|
||||
#define __SEP_DRIVER_CONFIG_H__
|
||||
|
||||
|
||||
/*--------------------------------------
|
||||
DRIVER CONFIGURATION FLAGS
|
||||
-------------------------------------*/
|
||||
|
||||
/* if flag is on , then the driver is running in polling and
|
||||
not interrupt mode */
|
||||
#define SEP_DRIVER_POLLING_MODE 1
|
||||
|
||||
/* flag which defines if the shared area address should be
|
||||
reconfiged (send to SEP anew) during init of the driver */
|
||||
#define SEP_DRIVER_RECONFIG_MESSAGE_AREA 0
|
||||
|
||||
/* the mode for running on the ARM1172 Evaluation platform (flag is 1) */
|
||||
#define SEP_DRIVER_ARM_DEBUG_MODE 0
|
||||
|
||||
/*-------------------------------------------
|
||||
INTERNAL DATA CONFIGURATION
|
||||
-------------------------------------------*/
|
||||
|
||||
/* flag for the input array */
|
||||
#define SEP_DRIVER_IN_FLAG 0
|
||||
|
||||
/* flag for output array */
|
||||
#define SEP_DRIVER_OUT_FLAG 1
|
||||
|
||||
/* maximum number of entries in one LLI tables */
|
||||
#define SEP_DRIVER_ENTRIES_PER_TABLE_IN_SEP 8
|
||||
|
||||
|
||||
/*--------------------------------------------------------
|
||||
SHARED AREA memory total size is 36K
|
||||
it is divided is following:
|
||||
|
||||
SHARED_MESSAGE_AREA 8K }
|
||||
}
|
||||
STATIC_POOL_AREA 4K } MAPPED AREA ( 24 K)
|
||||
}
|
||||
DATA_POOL_AREA 12K }
|
||||
|
||||
SYNCHRONIC_DMA_TABLES_AREA 5K
|
||||
|
||||
FLOW_DMA_TABLES_AREA 4K
|
||||
|
||||
SYSTEM_MEMORY_AREA 3k
|
||||
|
||||
SYSTEM_MEMORY total size is 3k
|
||||
it is divided as following:
|
||||
|
||||
TIME_MEMORY_AREA 8B
|
||||
-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
the maximum length of the message - the rest of the message shared
|
||||
area will be dedicated to the dma lli tables
|
||||
*/
|
||||
#define SEP_DRIVER_MAX_MESSAGE_SIZE_IN_BYTES (8 * 1024)
|
||||
|
||||
/* the size of the message shared area in pages */
|
||||
#define SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES (8 * 1024)
|
||||
|
||||
/* the size of the data pool static area in pages */
|
||||
#define SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES (4 * 1024)
|
||||
|
||||
/* the size of the data pool shared area size in pages */
|
||||
#define SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES (12 * 1024)
|
||||
|
||||
/* the size of the message shared area in pages */
|
||||
#define SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES (1024 * 5)
|
||||
|
||||
|
||||
/* the size of the data pool shared area size in pages */
|
||||
#define SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES (1024 * 4)
|
||||
|
||||
/* system data (time, caller id etc') pool */
|
||||
#define SEP_DRIVER_SYSTEM_DATA_MEMORY_SIZE_IN_BYTES 100
|
||||
|
||||
|
||||
/* area size that is mapped - we map the MESSAGE AREA, STATIC POOL and
|
||||
DATA POOL areas. area must be module 4k */
|
||||
#define SEP_DRIVER_MMMAP_AREA_SIZE (1024 * 24)
|
||||
|
||||
|
||||
/*-----------------------------------------------
|
||||
offsets of the areas starting from the shared area start address
|
||||
*/
|
||||
|
||||
/* message area offset */
|
||||
#define SEP_DRIVER_MESSAGE_AREA_OFFSET_IN_BYTES 0
|
||||
|
||||
/* static pool area offset */
|
||||
#define SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES \
|
||||
(SEP_DRIVER_MESSAGE_SHARED_AREA_SIZE_IN_BYTES)
|
||||
|
||||
/* data pool area offset */
|
||||
#define SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES \
|
||||
(SEP_DRIVER_STATIC_AREA_OFFSET_IN_BYTES + \
|
||||
SEP_DRIVER_STATIC_AREA_SIZE_IN_BYTES)
|
||||
|
||||
/* synhronic dma tables area offset */
|
||||
#define SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES \
|
||||
(SEP_DRIVER_DATA_POOL_AREA_OFFSET_IN_BYTES + \
|
||||
SEP_DRIVER_DATA_POOL_SHARED_AREA_SIZE_IN_BYTES)
|
||||
|
||||
/* sep driver flow dma tables area offset */
|
||||
#define SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES \
|
||||
(SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_OFFSET_IN_BYTES + \
|
||||
SEP_DRIVER_SYNCHRONIC_DMA_TABLES_AREA_SIZE_IN_BYTES)
|
||||
|
||||
/* system memory offset in bytes */
|
||||
#define SEP_DRIVER_SYSTEM_DATA_MEMORY_OFFSET_IN_BYTES \
|
||||
(SEP_DRIVER_FLOW_DMA_TABLES_AREA_OFFSET_IN_BYTES + \
|
||||
SEP_DRIVER_FLOW_DMA_TABLES_AREA_SIZE_IN_BYTES)
|
||||
|
||||
/* offset of the time area */
|
||||
#define SEP_DRIVER_SYSTEM_TIME_MEMORY_OFFSET_IN_BYTES \
|
||||
(SEP_DRIVER_SYSTEM_DATA_MEMORY_OFFSET_IN_BYTES)
|
||||
|
||||
|
||||
|
||||
/* start physical address of the SEP registers memory in HOST */
|
||||
#define SEP_IO_MEM_REGION_START_ADDRESS 0x80000000
|
||||
|
||||
/* size of the SEP registers memory region in HOST (for now 100 registers) */
|
||||
#define SEP_IO_MEM_REGION_SIZE (2 * 0x100000)
|
||||
|
||||
/* define the number of IRQ for SEP interrupts */
|
||||
#define SEP_DIRVER_IRQ_NUM 1
|
||||
|
||||
/* maximum number of add buffers */
|
||||
#define SEP_MAX_NUM_ADD_BUFFERS 100
|
||||
|
||||
/* number of flows */
|
||||
#define SEP_DRIVER_NUM_FLOWS 4
|
||||
|
||||
/* maximum number of entries in flow table */
|
||||
#define SEP_DRIVER_MAX_FLOW_NUM_ENTRIES_IN_TABLE 25
|
||||
|
||||
/* offset of the num entries in the block length entry of the LLI */
|
||||
#define SEP_NUM_ENTRIES_OFFSET_IN_BITS 24
|
||||
|
||||
/* offset of the interrupt flag in the block length entry of the LLI */
|
||||
#define SEP_INT_FLAG_OFFSET_IN_BITS 31
|
||||
|
||||
/* mask for extracting data size from LLI */
|
||||
#define SEP_TABLE_DATA_SIZE_MASK 0xFFFFFF
|
||||
|
||||
/* mask for entries after being shifted left */
|
||||
#define SEP_NUM_ENTRIES_MASK 0x7F
|
||||
|
||||
/* default flow id */
|
||||
#define SEP_FREE_FLOW_ID 0xFFFFFFFF
|
||||
|
||||
/* temp flow id used during cretiong of new flow until receiving
|
||||
real flow id from sep */
|
||||
#define SEP_TEMP_FLOW_ID (SEP_DRIVER_NUM_FLOWS + 1)
|
||||
|
||||
/* maximum add buffers message length in bytes */
|
||||
#define SEP_MAX_ADD_MESSAGE_LENGTH_IN_BYTES (7 * 4)
|
||||
|
||||
/* maximum number of concurrent virtual buffers */
|
||||
#define SEP_MAX_VIRT_BUFFERS_CONCURRENT 100
|
||||
|
||||
/* the token that defines the start of time address */
|
||||
#define SEP_TIME_VAL_TOKEN 0x12345678
|
||||
|
||||
/* DEBUG LEVEL MASKS */
|
||||
#define SEP_DEBUG_LEVEL_BASIC 0x1
|
||||
|
||||
#define SEP_DEBUG_LEVEL_EXTENDED 0x4
|
||||
|
||||
|
||||
/* Debug helpers */
|
||||
|
||||
#define dbg(fmt, args...) \
|
||||
do {\
|
||||
if (debug & SEP_DEBUG_LEVEL_BASIC) \
|
||||
printk(KERN_DEBUG fmt, ##args); \
|
||||
} while(0);
|
||||
|
||||
#define edbg(fmt, args...) \
|
||||
do { \
|
||||
if (debug & SEP_DEBUG_LEVEL_EXTENDED) \
|
||||
printk(KERN_DEBUG fmt, ##args); \
|
||||
} while(0);
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -1,232 +0,0 @@
|
|||
/*
|
||||
*
|
||||
* sep_driver_hw_defs.h - Security Processor Driver hardware definitions
|
||||
*
|
||||
* Copyright(c) 2009 Intel Corporation. All rights reserved.
|
||||
* Copyright(c) 2009 Discretix. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program; if not, write to the Free Software Foundation, Inc., 59
|
||||
* Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* CONTACTS:
|
||||
*
|
||||
* Mark Allyn mark.a.allyn@intel.com
|
||||
*
|
||||
* CHANGES:
|
||||
*
|
||||
* 2009.06.26 Initial publish
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SEP_DRIVER_HW_DEFS__H
|
||||
#define SEP_DRIVER_HW_DEFS__H
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* Abstract: HW Registers Defines. */
|
||||
/* */
|
||||
/* Note: This file was automatically created !!! */
|
||||
/* DO NOT EDIT THIS FILE !!! */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/* cf registers */
|
||||
#define HW_R0B_ADDR_0_REG_ADDR 0x0000UL
|
||||
#define HW_R0B_ADDR_1_REG_ADDR 0x0004UL
|
||||
#define HW_R0B_ADDR_2_REG_ADDR 0x0008UL
|
||||
#define HW_R0B_ADDR_3_REG_ADDR 0x000cUL
|
||||
#define HW_R0B_ADDR_4_REG_ADDR 0x0010UL
|
||||
#define HW_R0B_ADDR_5_REG_ADDR 0x0014UL
|
||||
#define HW_R0B_ADDR_6_REG_ADDR 0x0018UL
|
||||
#define HW_R0B_ADDR_7_REG_ADDR 0x001cUL
|
||||
#define HW_R0B_ADDR_8_REG_ADDR 0x0020UL
|
||||
#define HW_R2B_ADDR_0_REG_ADDR 0x0080UL
|
||||
#define HW_R2B_ADDR_1_REG_ADDR 0x0084UL
|
||||
#define HW_R2B_ADDR_2_REG_ADDR 0x0088UL
|
||||
#define HW_R2B_ADDR_3_REG_ADDR 0x008cUL
|
||||
#define HW_R2B_ADDR_4_REG_ADDR 0x0090UL
|
||||
#define HW_R2B_ADDR_5_REG_ADDR 0x0094UL
|
||||
#define HW_R2B_ADDR_6_REG_ADDR 0x0098UL
|
||||
#define HW_R2B_ADDR_7_REG_ADDR 0x009cUL
|
||||
#define HW_R2B_ADDR_8_REG_ADDR 0x00a0UL
|
||||
#define HW_R3B_REG_ADDR 0x00C0UL
|
||||
#define HW_R4B_REG_ADDR 0x0100UL
|
||||
#define HW_CSA_ADDR_0_REG_ADDR 0x0140UL
|
||||
#define HW_CSA_ADDR_1_REG_ADDR 0x0144UL
|
||||
#define HW_CSA_ADDR_2_REG_ADDR 0x0148UL
|
||||
#define HW_CSA_ADDR_3_REG_ADDR 0x014cUL
|
||||
#define HW_CSA_ADDR_4_REG_ADDR 0x0150UL
|
||||
#define HW_CSA_ADDR_5_REG_ADDR 0x0154UL
|
||||
#define HW_CSA_ADDR_6_REG_ADDR 0x0158UL
|
||||
#define HW_CSA_ADDR_7_REG_ADDR 0x015cUL
|
||||
#define HW_CSA_ADDR_8_REG_ADDR 0x0160UL
|
||||
#define HW_CSA_REG_ADDR 0x0140UL
|
||||
#define HW_SINB_REG_ADDR 0x0180UL
|
||||
#define HW_SOUTB_REG_ADDR 0x0184UL
|
||||
#define HW_PKI_CONTROL_REG_ADDR 0x01C0UL
|
||||
#define HW_PKI_STATUS_REG_ADDR 0x01C4UL
|
||||
#define HW_PKI_BUSY_REG_ADDR 0x01C8UL
|
||||
#define HW_PKI_A_1025_REG_ADDR 0x01CCUL
|
||||
#define HW_PKI_SDMA_CTL_REG_ADDR 0x01D0UL
|
||||
#define HW_PKI_SDMA_OFFSET_REG_ADDR 0x01D4UL
|
||||
#define HW_PKI_SDMA_POINTERS_REG_ADDR 0x01D8UL
|
||||
#define HW_PKI_SDMA_DLENG_REG_ADDR 0x01DCUL
|
||||
#define HW_PKI_SDMA_EXP_POINTERS_REG_ADDR 0x01E0UL
|
||||
#define HW_PKI_SDMA_RES_POINTERS_REG_ADDR 0x01E4UL
|
||||
#define HW_PKI_CLR_REG_ADDR 0x01E8UL
|
||||
#define HW_PKI_SDMA_BUSY_REG_ADDR 0x01E8UL
|
||||
#define HW_PKI_SDMA_FIRST_EXP_N_REG_ADDR 0x01ECUL
|
||||
#define HW_PKI_SDMA_MUL_BY1_REG_ADDR 0x01F0UL
|
||||
#define HW_PKI_SDMA_RMUL_SEL_REG_ADDR 0x01F4UL
|
||||
#define HW_DES_KEY_0_REG_ADDR 0x0208UL
|
||||
#define HW_DES_KEY_1_REG_ADDR 0x020CUL
|
||||
#define HW_DES_KEY_2_REG_ADDR 0x0210UL
|
||||
#define HW_DES_KEY_3_REG_ADDR 0x0214UL
|
||||
#define HW_DES_KEY_4_REG_ADDR 0x0218UL
|
||||
#define HW_DES_KEY_5_REG_ADDR 0x021CUL
|
||||
#define HW_DES_CONTROL_0_REG_ADDR 0x0220UL
|
||||
#define HW_DES_CONTROL_1_REG_ADDR 0x0224UL
|
||||
#define HW_DES_IV_0_REG_ADDR 0x0228UL
|
||||
#define HW_DES_IV_1_REG_ADDR 0x022CUL
|
||||
#define HW_AES_KEY_0_ADDR_0_REG_ADDR 0x0400UL
|
||||
#define HW_AES_KEY_0_ADDR_1_REG_ADDR 0x0404UL
|
||||
#define HW_AES_KEY_0_ADDR_2_REG_ADDR 0x0408UL
|
||||
#define HW_AES_KEY_0_ADDR_3_REG_ADDR 0x040cUL
|
||||
#define HW_AES_KEY_0_ADDR_4_REG_ADDR 0x0410UL
|
||||
#define HW_AES_KEY_0_ADDR_5_REG_ADDR 0x0414UL
|
||||
#define HW_AES_KEY_0_ADDR_6_REG_ADDR 0x0418UL
|
||||
#define HW_AES_KEY_0_ADDR_7_REG_ADDR 0x041cUL
|
||||
#define HW_AES_KEY_0_REG_ADDR 0x0400UL
|
||||
#define HW_AES_IV_0_ADDR_0_REG_ADDR 0x0440UL
|
||||
#define HW_AES_IV_0_ADDR_1_REG_ADDR 0x0444UL
|
||||
#define HW_AES_IV_0_ADDR_2_REG_ADDR 0x0448UL
|
||||
#define HW_AES_IV_0_ADDR_3_REG_ADDR 0x044cUL
|
||||
#define HW_AES_IV_0_REG_ADDR 0x0440UL
|
||||
#define HW_AES_CTR1_ADDR_0_REG_ADDR 0x0460UL
|
||||
#define HW_AES_CTR1_ADDR_1_REG_ADDR 0x0464UL
|
||||
#define HW_AES_CTR1_ADDR_2_REG_ADDR 0x0468UL
|
||||
#define HW_AES_CTR1_ADDR_3_REG_ADDR 0x046cUL
|
||||
#define HW_AES_CTR1_REG_ADDR 0x0460UL
|
||||
#define HW_AES_SK_REG_ADDR 0x0478UL
|
||||
#define HW_AES_MAC_OK_REG_ADDR 0x0480UL
|
||||
#define HW_AES_PREV_IV_0_ADDR_0_REG_ADDR 0x0490UL
|
||||
#define HW_AES_PREV_IV_0_ADDR_1_REG_ADDR 0x0494UL
|
||||
#define HW_AES_PREV_IV_0_ADDR_2_REG_ADDR 0x0498UL
|
||||
#define HW_AES_PREV_IV_0_ADDR_3_REG_ADDR 0x049cUL
|
||||
#define HW_AES_PREV_IV_0_REG_ADDR 0x0490UL
|
||||
#define HW_AES_CONTROL_REG_ADDR 0x04C0UL
|
||||
#define HW_HASH_H0_REG_ADDR 0x0640UL
|
||||
#define HW_HASH_H1_REG_ADDR 0x0644UL
|
||||
#define HW_HASH_H2_REG_ADDR 0x0648UL
|
||||
#define HW_HASH_H3_REG_ADDR 0x064CUL
|
||||
#define HW_HASH_H4_REG_ADDR 0x0650UL
|
||||
#define HW_HASH_H5_REG_ADDR 0x0654UL
|
||||
#define HW_HASH_H6_REG_ADDR 0x0658UL
|
||||
#define HW_HASH_H7_REG_ADDR 0x065CUL
|
||||
#define HW_HASH_H8_REG_ADDR 0x0660UL
|
||||
#define HW_HASH_H9_REG_ADDR 0x0664UL
|
||||
#define HW_HASH_H10_REG_ADDR 0x0668UL
|
||||
#define HW_HASH_H11_REG_ADDR 0x066CUL
|
||||
#define HW_HASH_H12_REG_ADDR 0x0670UL
|
||||
#define HW_HASH_H13_REG_ADDR 0x0674UL
|
||||
#define HW_HASH_H14_REG_ADDR 0x0678UL
|
||||
#define HW_HASH_H15_REG_ADDR 0x067CUL
|
||||
#define HW_HASH_CONTROL_REG_ADDR 0x07C0UL
|
||||
#define HW_HASH_PAD_EN_REG_ADDR 0x07C4UL
|
||||
#define HW_HASH_PAD_CFG_REG_ADDR 0x07C8UL
|
||||
#define HW_HASH_CUR_LEN_0_REG_ADDR 0x07CCUL
|
||||
#define HW_HASH_CUR_LEN_1_REG_ADDR 0x07D0UL
|
||||
#define HW_HASH_CUR_LEN_2_REG_ADDR 0x07D4UL
|
||||
#define HW_HASH_CUR_LEN_3_REG_ADDR 0x07D8UL
|
||||
#define HW_HASH_PARAM_REG_ADDR 0x07DCUL
|
||||
#define HW_HASH_INT_BUSY_REG_ADDR 0x07E0UL
|
||||
#define HW_HASH_SW_RESET_REG_ADDR 0x07E4UL
|
||||
#define HW_HASH_ENDIANESS_REG_ADDR 0x07E8UL
|
||||
#define HW_HASH_DATA_REG_ADDR 0x07ECUL
|
||||
#define HW_DRNG_CONTROL_REG_ADDR 0x0800UL
|
||||
#define HW_DRNG_VALID_REG_ADDR 0x0804UL
|
||||
#define HW_DRNG_DATA_REG_ADDR 0x0808UL
|
||||
#define HW_RND_SRC_EN_REG_ADDR 0x080CUL
|
||||
#define HW_AES_CLK_ENABLE_REG_ADDR 0x0810UL
|
||||
#define HW_DES_CLK_ENABLE_REG_ADDR 0x0814UL
|
||||
#define HW_HASH_CLK_ENABLE_REG_ADDR 0x0818UL
|
||||
#define HW_PKI_CLK_ENABLE_REG_ADDR 0x081CUL
|
||||
#define HW_CLK_STATUS_REG_ADDR 0x0824UL
|
||||
#define HW_CLK_ENABLE_REG_ADDR 0x0828UL
|
||||
#define HW_DRNG_SAMPLE_REG_ADDR 0x0850UL
|
||||
#define HW_RND_SRC_CTL_REG_ADDR 0x0858UL
|
||||
#define HW_CRYPTO_CTL_REG_ADDR 0x0900UL
|
||||
#define HW_CRYPTO_STATUS_REG_ADDR 0x090CUL
|
||||
#define HW_CRYPTO_BUSY_REG_ADDR 0x0910UL
|
||||
#define HW_AES_BUSY_REG_ADDR 0x0914UL
|
||||
#define HW_DES_BUSY_REG_ADDR 0x0918UL
|
||||
#define HW_HASH_BUSY_REG_ADDR 0x091CUL
|
||||
#define HW_CONTENT_REG_ADDR 0x0924UL
|
||||
#define HW_VERSION_REG_ADDR 0x0928UL
|
||||
#define HW_CONTEXT_ID_REG_ADDR 0x0930UL
|
||||
#define HW_DIN_BUFFER_REG_ADDR 0x0C00UL
|
||||
#define HW_DIN_MEM_DMA_BUSY_REG_ADDR 0x0c20UL
|
||||
#define HW_SRC_LLI_MEM_ADDR_REG_ADDR 0x0c24UL
|
||||
#define HW_SRC_LLI_WORD0_REG_ADDR 0x0C28UL
|
||||
#define HW_SRC_LLI_WORD1_REG_ADDR 0x0C2CUL
|
||||
#define HW_SRAM_SRC_ADDR_REG_ADDR 0x0c30UL
|
||||
#define HW_DIN_SRAM_BYTES_LEN_REG_ADDR 0x0c34UL
|
||||
#define HW_DIN_SRAM_DMA_BUSY_REG_ADDR 0x0C38UL
|
||||
#define HW_WRITE_ALIGN_REG_ADDR 0x0C3CUL
|
||||
#define HW_OLD_DATA_REG_ADDR 0x0C48UL
|
||||
#define HW_WRITE_ALIGN_LAST_REG_ADDR 0x0C4CUL
|
||||
#define HW_DOUT_BUFFER_REG_ADDR 0x0C00UL
|
||||
#define HW_DST_LLI_WORD0_REG_ADDR 0x0D28UL
|
||||
#define HW_DST_LLI_WORD1_REG_ADDR 0x0D2CUL
|
||||
#define HW_DST_LLI_MEM_ADDR_REG_ADDR 0x0D24UL
|
||||
#define HW_DOUT_MEM_DMA_BUSY_REG_ADDR 0x0D20UL
|
||||
#define HW_SRAM_DEST_ADDR_REG_ADDR 0x0D30UL
|
||||
#define HW_DOUT_SRAM_BYTES_LEN_REG_ADDR 0x0D34UL
|
||||
#define HW_DOUT_SRAM_DMA_BUSY_REG_ADDR 0x0D38UL
|
||||
#define HW_READ_ALIGN_REG_ADDR 0x0D3CUL
|
||||
#define HW_READ_LAST_DATA_REG_ADDR 0x0D44UL
|
||||
#define HW_RC4_THRU_CPU_REG_ADDR 0x0D4CUL
|
||||
#define HW_AHB_SINGLE_REG_ADDR 0x0E00UL
|
||||
#define HW_SRAM_DATA_REG_ADDR 0x0F00UL
|
||||
#define HW_SRAM_ADDR_REG_ADDR 0x0F04UL
|
||||
#define HW_SRAM_DATA_READY_REG_ADDR 0x0F08UL
|
||||
#define HW_HOST_IRR_REG_ADDR 0x0A00UL
|
||||
#define HW_HOST_IMR_REG_ADDR 0x0A04UL
|
||||
#define HW_HOST_ICR_REG_ADDR 0x0A08UL
|
||||
#define HW_HOST_SEP_SRAM_THRESHOLD_REG_ADDR 0x0A10UL
|
||||
#define HW_HOST_SEP_BUSY_REG_ADDR 0x0A14UL
|
||||
#define HW_HOST_SEP_LCS_REG_ADDR 0x0A18UL
|
||||
#define HW_HOST_CC_SW_RST_REG_ADDR 0x0A40UL
|
||||
#define HW_HOST_SEP_SW_RST_REG_ADDR 0x0A44UL
|
||||
#define HW_HOST_FLOW_DMA_SW_INT0_REG_ADDR 0x0A80UL
|
||||
#define HW_HOST_FLOW_DMA_SW_INT1_REG_ADDR 0x0A84UL
|
||||
#define HW_HOST_FLOW_DMA_SW_INT2_REG_ADDR 0x0A88UL
|
||||
#define HW_HOST_FLOW_DMA_SW_INT3_REG_ADDR 0x0A8cUL
|
||||
#define HW_HOST_FLOW_DMA_SW_INT4_REG_ADDR 0x0A90UL
|
||||
#define HW_HOST_FLOW_DMA_SW_INT5_REG_ADDR 0x0A94UL
|
||||
#define HW_HOST_FLOW_DMA_SW_INT6_REG_ADDR 0x0A98UL
|
||||
#define HW_HOST_FLOW_DMA_SW_INT7_REG_ADDR 0x0A9cUL
|
||||
#define HW_HOST_SEP_HOST_GPR0_REG_ADDR 0x0B00UL
|
||||
#define HW_HOST_SEP_HOST_GPR1_REG_ADDR 0x0B04UL
|
||||
#define HW_HOST_SEP_HOST_GPR2_REG_ADDR 0x0B08UL
|
||||
#define HW_HOST_SEP_HOST_GPR3_REG_ADDR 0x0B0CUL
|
||||
#define HW_HOST_HOST_SEP_GPR0_REG_ADDR 0x0B80UL
|
||||
#define HW_HOST_HOST_SEP_GPR1_REG_ADDR 0x0B84UL
|
||||
#define HW_HOST_HOST_SEP_GPR2_REG_ADDR 0x0B88UL
|
||||
#define HW_HOST_HOST_SEP_GPR3_REG_ADDR 0x0B8CUL
|
||||
#define HW_HOST_HOST_ENDIAN_REG_ADDR 0x0B90UL
|
||||
#define HW_HOST_HOST_COMM_CLK_EN_REG_ADDR 0x0B94UL
|
||||
#define HW_CLR_SRAM_BUSY_REG_REG_ADDR 0x0F0CUL
|
||||
#define HW_CC_SRAM_BASE_ADDRESS 0x5800UL
|
||||
|
||||
#endif /* ifndef HW_DEFS */
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/kthread.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/smp_lock.h>
|
||||
|
||||
/**** Helper functions used for Div, Remainder operation on u64 ****/
|
||||
|
||||
|
@ -113,7 +114,6 @@ u64 GLOB_u64_Remainder(u64 addr, u32 divisor_type)
|
|||
|
||||
#define GLOB_SBD_NAME "nd"
|
||||
#define GLOB_SBD_IRQ_NUM (29)
|
||||
#define GLOB_VERSION "driver version 20091110"
|
||||
|
||||
#define GLOB_SBD_IOCTL_GC (0x7701)
|
||||
#define GLOB_SBD_IOCTL_WL (0x7702)
|
||||
|
@ -272,13 +272,6 @@ static int get_res_blk_num_os(void)
|
|||
return res_blks;
|
||||
}
|
||||
|
||||
static void SBD_prepare_flush(struct request_queue *q, struct request *rq)
|
||||
{
|
||||
rq->cmd_type = REQ_TYPE_LINUX_BLOCK;
|
||||
/* rq->timeout = 5 * HZ; */
|
||||
rq->cmd[0] = REQ_LB_OP_FLUSH;
|
||||
}
|
||||
|
||||
/* Transfer a full request. */
|
||||
static int do_transfer(struct spectra_nand_dev *tr, struct request *req)
|
||||
{
|
||||
|
@ -296,8 +289,7 @@ static int do_transfer(struct spectra_nand_dev *tr, struct request *req)
|
|||
IdentifyDeviceData.PagesPerBlock *
|
||||
res_blks_os;
|
||||
|
||||
if (req->cmd_type == REQ_TYPE_LINUX_BLOCK &&
|
||||
req->cmd[0] == REQ_LB_OP_FLUSH) {
|
||||
if (req->cmd_type & REQ_FLUSH) {
|
||||
if (force_flush_cache()) /* Fail to flush cache */
|
||||
return -EIO;
|
||||
else
|
||||
|
@ -597,11 +589,23 @@ int GLOB_SBD_ioctl(struct block_device *bdev, fmode_t mode,
|
|||
return -ENOTTY;
|
||||
}
|
||||
|
||||
int GLOB_SBD_unlocked_ioctl(struct block_device *bdev, fmode_t mode,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lock_kernel();
|
||||
ret = GLOB_SBD_ioctl(bdev, mode, cmd, arg);
|
||||
unlock_kernel();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct block_device_operations GLOB_SBD_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = GLOB_SBD_open,
|
||||
.release = GLOB_SBD_release,
|
||||
.locked_ioctl = GLOB_SBD_ioctl,
|
||||
.ioctl = GLOB_SBD_unlocked_ioctl,
|
||||
.getgeo = GLOB_SBD_getgeo,
|
||||
};
|
||||
|
||||
|
@ -650,8 +654,7 @@ static int SBD_setup_device(struct spectra_nand_dev *dev, int which)
|
|||
/* Here we force report 512 byte hardware sector size to Kernel */
|
||||
blk_queue_logical_block_size(dev->queue, 512);
|
||||
|
||||
blk_queue_ordered(dev->queue, QUEUE_ORDERED_DRAIN_FLUSH,
|
||||
SBD_prepare_flush);
|
||||
blk_queue_ordered(dev->queue, QUEUE_ORDERED_DRAIN_FLUSH);
|
||||
|
||||
dev->thread = kthread_run(spectra_trans_thread, dev, "nand_thd");
|
||||
if (IS_ERR(dev->thread)) {
|
||||
|
|
|
@ -61,7 +61,6 @@ static void FTL_Cache_Read_Page(u8 *pData, u64 dwPageAddr,
|
|||
static void FTL_Cache_Write_Page(u8 *pData, u64 dwPageAddr,
|
||||
u8 cache_blk, u16 flag);
|
||||
static int FTL_Cache_Write(void);
|
||||
static int FTL_Cache_Write_Back(u8 *pData, u64 blk_addr);
|
||||
static void FTL_Calculate_LRU(void);
|
||||
static u32 FTL_Get_Block_Index(u32 wBlockNum);
|
||||
|
||||
|
@ -86,8 +85,6 @@ static u32 FTL_Replace_MWBlock(void);
|
|||
static int FTL_Replace_Block(u64 blk_addr);
|
||||
static int FTL_Adjust_Relative_Erase_Count(u32 Index_of_MAX);
|
||||
|
||||
static int FTL_Flash_Error_Handle(u8 *pData, u64 old_page_addr, u64 blk_addr);
|
||||
|
||||
struct device_info_tag DeviceInfo;
|
||||
struct flash_cache_tag Cache;
|
||||
static struct spectra_l2_cache_info cache_l2;
|
||||
|
@ -775,7 +772,7 @@ static void dump_cache_l2_table(void)
|
|||
{
|
||||
struct list_head *p;
|
||||
struct spectra_l2_cache_list *pnd;
|
||||
int n, i;
|
||||
int n;
|
||||
|
||||
n = 0;
|
||||
list_for_each(p, &cache_l2.table.list) {
|
||||
|
@ -1537,79 +1534,6 @@ static int FTL_Cache_Write_All(u8 *pData, u64 blk_addr)
|
|||
return wResult;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: FTL_Cache_Update_Block
|
||||
* Inputs: pointer to buffer,page address,block address
|
||||
* Outputs: PASS=0 / FAIL=1
|
||||
* Description: It updates the cache
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
static int FTL_Cache_Update_Block(u8 *pData,
|
||||
u64 old_page_addr, u64 blk_addr)
|
||||
{
|
||||
int i, j;
|
||||
u8 *buf = pData;
|
||||
int wResult = PASS;
|
||||
int wFoundInCache;
|
||||
u64 page_addr;
|
||||
u64 addr;
|
||||
u64 old_blk_addr;
|
||||
u16 page_offset;
|
||||
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
old_blk_addr = (u64)(old_page_addr >>
|
||||
DeviceInfo.nBitsInBlockDataSize) * DeviceInfo.wBlockDataSize;
|
||||
page_offset = (u16)(GLOB_u64_Remainder(old_page_addr, 2) >>
|
||||
DeviceInfo.nBitsInPageDataSize);
|
||||
|
||||
for (i = 0; i < DeviceInfo.wPagesPerBlock; i += Cache.pages_per_item) {
|
||||
page_addr = old_blk_addr + i * DeviceInfo.wPageDataSize;
|
||||
if (i != page_offset) {
|
||||
wFoundInCache = FAIL;
|
||||
for (j = 0; j < CACHE_ITEM_NUM; j++) {
|
||||
addr = Cache.array[j].address;
|
||||
addr = FTL_Get_Physical_Block_Addr(addr) +
|
||||
GLOB_u64_Remainder(addr, 2);
|
||||
if ((addr >= page_addr) && addr <
|
||||
(page_addr + Cache.cache_item_size)) {
|
||||
wFoundInCache = PASS;
|
||||
buf = Cache.array[j].buf;
|
||||
Cache.array[j].changed = SET;
|
||||
#if CMD_DMA
|
||||
#if RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE
|
||||
int_cache[ftl_cmd_cnt].item = j;
|
||||
int_cache[ftl_cmd_cnt].cache.address =
|
||||
Cache.array[j].address;
|
||||
int_cache[ftl_cmd_cnt].cache.changed =
|
||||
Cache.array[j].changed;
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (FAIL == wFoundInCache) {
|
||||
if (ERR == FTL_Cache_Read_All(g_pTempBuf,
|
||||
page_addr)) {
|
||||
wResult = FAIL;
|
||||
break;
|
||||
}
|
||||
buf = g_pTempBuf;
|
||||
}
|
||||
} else {
|
||||
buf = pData;
|
||||
}
|
||||
|
||||
if (FAIL == FTL_Cache_Write_All(buf,
|
||||
blk_addr + (page_addr - old_blk_addr))) {
|
||||
wResult = FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return wResult;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: FTL_Copy_Block
|
||||
* Inputs: source block address
|
||||
|
@ -1698,7 +1622,7 @@ static int get_l2_cache_blks(void)
|
|||
static int erase_l2_cache_blocks(void)
|
||||
{
|
||||
int i, ret = PASS;
|
||||
u32 pblk, lblk;
|
||||
u32 pblk, lblk = BAD_BLOCK;
|
||||
u64 addr;
|
||||
u32 *pbt = (u32 *)g_pBlockTable;
|
||||
|
||||
|
@ -2004,87 +1928,6 @@ static int search_l2_cache(u8 *buf, u64 logical_addr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: FTL_Cache_Write_Back
|
||||
* Inputs: pointer to data cached in sys memory
|
||||
* address of free block in flash
|
||||
* Outputs: PASS=0 / FAIL=1
|
||||
* Description: writes all the pages of Cache Block to flash
|
||||
*
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
static int FTL_Cache_Write_Back(u8 *pData, u64 blk_addr)
|
||||
{
|
||||
int i, j, iErase;
|
||||
u64 old_page_addr, addr, phy_addr;
|
||||
u32 *pbt = (u32 *)g_pBlockTable;
|
||||
u32 lba;
|
||||
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
old_page_addr = FTL_Get_Physical_Block_Addr(blk_addr) +
|
||||
GLOB_u64_Remainder(blk_addr, 2);
|
||||
|
||||
iErase = (FAIL == FTL_Replace_Block(blk_addr)) ? PASS : FAIL;
|
||||
|
||||
pbt[BLK_FROM_ADDR(blk_addr)] &= (~SPARE_BLOCK);
|
||||
|
||||
#if CMD_DMA
|
||||
p_BTableChangesDelta = (struct BTableChangesDelta *)g_pBTDelta_Free;
|
||||
g_pBTDelta_Free += sizeof(struct BTableChangesDelta);
|
||||
|
||||
p_BTableChangesDelta->ftl_cmd_cnt = ftl_cmd_cnt;
|
||||
p_BTableChangesDelta->BT_Index = (u32)(blk_addr >>
|
||||
DeviceInfo.nBitsInBlockDataSize);
|
||||
p_BTableChangesDelta->BT_Entry_Value =
|
||||
pbt[(u32)(blk_addr >> DeviceInfo.nBitsInBlockDataSize)];
|
||||
p_BTableChangesDelta->ValidFields = 0x0C;
|
||||
#endif
|
||||
|
||||
if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) {
|
||||
g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
|
||||
FTL_Write_IN_Progress_Block_Table_Page();
|
||||
}
|
||||
|
||||
for (i = 0; i < RETRY_TIMES; i++) {
|
||||
if (PASS == iErase) {
|
||||
phy_addr = FTL_Get_Physical_Block_Addr(blk_addr);
|
||||
if (FAIL == GLOB_FTL_Block_Erase(phy_addr)) {
|
||||
lba = BLK_FROM_ADDR(blk_addr);
|
||||
MARK_BLOCK_AS_BAD(pbt[lba]);
|
||||
i = RETRY_TIMES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < CACHE_ITEM_NUM; j++) {
|
||||
addr = Cache.array[j].address;
|
||||
if ((addr <= blk_addr) &&
|
||||
((addr + Cache.cache_item_size) > blk_addr))
|
||||
cache_block_to_write = j;
|
||||
}
|
||||
|
||||
phy_addr = FTL_Get_Physical_Block_Addr(blk_addr);
|
||||
if (PASS == FTL_Cache_Update_Block(pData,
|
||||
old_page_addr, phy_addr)) {
|
||||
cache_block_to_write = UNHIT_CACHE_ITEM;
|
||||
break;
|
||||
} else {
|
||||
iErase = PASS;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= RETRY_TIMES) {
|
||||
if (ERR == FTL_Flash_Error_Handle(pData,
|
||||
old_page_addr, blk_addr))
|
||||
return ERR;
|
||||
else
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
return PASS;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: FTL_Cache_Write_Page
|
||||
* Inputs: Pointer to buffer, page address, cache block number
|
||||
|
@ -2370,159 +2213,6 @@ static int FTL_Write_Block_Table(int wForce)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* Function: GLOB_FTL_Flash_Format
|
||||
* Inputs: none
|
||||
* Outputs: PASS
|
||||
* Description: The block table stores bad block info, including MDF+
|
||||
* blocks gone bad over the ages. Therefore, if we have a
|
||||
* block table in place, then use it to scan for bad blocks
|
||||
* If not, then scan for MDF.
|
||||
* Now, a block table will only be found if spectra was already
|
||||
* being used. For a fresh flash, we'll go thru scanning for
|
||||
* MDF. If spectra was being used, then there is a chance that
|
||||
* the MDF has been corrupted. Spectra avoids writing to the
|
||||
* first 2 bytes of the spare area to all pages in a block. This
|
||||
* covers all known flash devices. However, since flash
|
||||
* manufacturers have no standard of where the MDF is stored,
|
||||
* this cannot guarantee that the MDF is protected for future
|
||||
* devices too. The initial scanning for the block table assures
|
||||
* this. It is ok even if the block table is outdated, as all
|
||||
* we're looking for are bad block markers.
|
||||
* Use this when mounting a file system or starting a
|
||||
* new flash.
|
||||
*
|
||||
*********************************************************************/
|
||||
static int FTL_Format_Flash(u8 valid_block_table)
|
||||
{
|
||||
u32 i, j;
|
||||
u32 *pbt = (u32 *)g_pBlockTable;
|
||||
u32 tempNode;
|
||||
int ret;
|
||||
|
||||
#if CMD_DMA
|
||||
u32 *pbtStartingCopy = (u32 *)g_pBTStartingCopy;
|
||||
if (ftl_cmd_cnt)
|
||||
return FAIL;
|
||||
#endif
|
||||
|
||||
if (FAIL == FTL_Check_Block_Table(FAIL))
|
||||
valid_block_table = 0;
|
||||
|
||||
if (valid_block_table) {
|
||||
u8 switched = 1;
|
||||
u32 block, k;
|
||||
|
||||
k = DeviceInfo.wSpectraStartBlock;
|
||||
while (switched && (k < DeviceInfo.wSpectraEndBlock)) {
|
||||
switched = 0;
|
||||
k++;
|
||||
for (j = DeviceInfo.wSpectraStartBlock, i = 0;
|
||||
j <= DeviceInfo.wSpectraEndBlock;
|
||||
j++, i++) {
|
||||
block = (pbt[i] & ~BAD_BLOCK) -
|
||||
DeviceInfo.wSpectraStartBlock;
|
||||
if (block != i) {
|
||||
switched = 1;
|
||||
tempNode = pbt[i];
|
||||
pbt[i] = pbt[block];
|
||||
pbt[block] = tempNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((k == DeviceInfo.wSpectraEndBlock) && switched)
|
||||
valid_block_table = 0;
|
||||
}
|
||||
|
||||
if (!valid_block_table) {
|
||||
memset(g_pBlockTable, 0,
|
||||
DeviceInfo.wDataBlockNum * sizeof(u32));
|
||||
memset(g_pWearCounter, 0,
|
||||
DeviceInfo.wDataBlockNum * sizeof(u8));
|
||||
if (DeviceInfo.MLCDevice)
|
||||
memset(g_pReadCounter, 0,
|
||||
DeviceInfo.wDataBlockNum * sizeof(u16));
|
||||
#if CMD_DMA
|
||||
memset(g_pBTStartingCopy, 0,
|
||||
DeviceInfo.wDataBlockNum * sizeof(u32));
|
||||
memset(g_pWearCounterCopy, 0,
|
||||
DeviceInfo.wDataBlockNum * sizeof(u8));
|
||||
if (DeviceInfo.MLCDevice)
|
||||
memset(g_pReadCounterCopy, 0,
|
||||
DeviceInfo.wDataBlockNum * sizeof(u16));
|
||||
#endif
|
||||
for (j = DeviceInfo.wSpectraStartBlock, i = 0;
|
||||
j <= DeviceInfo.wSpectraEndBlock;
|
||||
j++, i++) {
|
||||
if (GLOB_LLD_Get_Bad_Block((u32)j))
|
||||
pbt[i] = (u32)(BAD_BLOCK | j);
|
||||
}
|
||||
}
|
||||
|
||||
nand_dbg_print(NAND_DBG_WARN, "Erasing all blocks in the NAND\n");
|
||||
|
||||
for (j = DeviceInfo.wSpectraStartBlock, i = 0;
|
||||
j <= DeviceInfo.wSpectraEndBlock;
|
||||
j++, i++) {
|
||||
if ((pbt[i] & BAD_BLOCK) != BAD_BLOCK) {
|
||||
ret = GLOB_LLD_Erase_Block(j);
|
||||
if (FAIL == ret) {
|
||||
pbt[i] = (u32)(j);
|
||||
MARK_BLOCK_AS_BAD(pbt[i]);
|
||||
nand_dbg_print(NAND_DBG_WARN,
|
||||
"NAND Program fail in %s, Line %d, "
|
||||
"Function: %s, new Bad Block %d generated!\n",
|
||||
__FILE__, __LINE__, __func__, (int)j);
|
||||
} else {
|
||||
pbt[i] = (u32)(SPARE_BLOCK | j);
|
||||
}
|
||||
}
|
||||
#if CMD_DMA
|
||||
pbtStartingCopy[i] = pbt[i];
|
||||
#endif
|
||||
}
|
||||
|
||||
g_wBlockTableOffset = 0;
|
||||
for (i = 0; (i <= (DeviceInfo.wSpectraEndBlock -
|
||||
DeviceInfo.wSpectraStartBlock))
|
||||
&& ((pbt[i] & BAD_BLOCK) == BAD_BLOCK); i++)
|
||||
;
|
||||
if (i > (DeviceInfo.wSpectraEndBlock - DeviceInfo.wSpectraStartBlock)) {
|
||||
printk(KERN_ERR "All blocks bad!\n");
|
||||
return FAIL;
|
||||
} else {
|
||||
g_wBlockTableIndex = pbt[i] & ~BAD_BLOCK;
|
||||
if (i != BLOCK_TABLE_INDEX) {
|
||||
tempNode = pbt[i];
|
||||
pbt[i] = pbt[BLOCK_TABLE_INDEX];
|
||||
pbt[BLOCK_TABLE_INDEX] = tempNode;
|
||||
}
|
||||
}
|
||||
pbt[BLOCK_TABLE_INDEX] &= (~SPARE_BLOCK);
|
||||
|
||||
#if CMD_DMA
|
||||
pbtStartingCopy[BLOCK_TABLE_INDEX] &= (~SPARE_BLOCK);
|
||||
#endif
|
||||
|
||||
g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
|
||||
memset(g_pBTBlocks, 0xFF,
|
||||
(1 + LAST_BT_ID - FIRST_BT_ID) * sizeof(u32));
|
||||
g_pBTBlocks[FIRST_BT_ID-FIRST_BT_ID] = g_wBlockTableIndex;
|
||||
FTL_Write_Block_Table(FAIL);
|
||||
|
||||
for (i = 0; i < CACHE_ITEM_NUM; i++) {
|
||||
Cache.array[i].address = NAND_CACHE_INIT_ADDR;
|
||||
Cache.array[i].use_cnt = 0;
|
||||
Cache.array[i].changed = CLEAR;
|
||||
}
|
||||
|
||||
#if (RESTORE_CACHE_ON_CDMA_CHAIN_FAILURE && CMD_DMA)
|
||||
memcpy((void *)&cache_start_copy, (void *)&Cache,
|
||||
sizeof(struct flash_cache_tag));
|
||||
#endif
|
||||
return PASS;
|
||||
}
|
||||
|
||||
static int force_format_nand(void)
|
||||
{
|
||||
u32 i;
|
||||
|
@ -3031,112 +2721,6 @@ static int FTL_Read_Block_Table(void)
|
|||
return wResult;
|
||||
}
|
||||
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: FTL_Flash_Error_Handle
|
||||
* Inputs: Pointer to data
|
||||
* Page address
|
||||
* Block address
|
||||
* Outputs: PASS=0 / FAIL=1
|
||||
* Description: It handles any error occured during Spectra operation
|
||||
*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&*/
|
||||
static int FTL_Flash_Error_Handle(u8 *pData, u64 old_page_addr,
|
||||
u64 blk_addr)
|
||||
{
|
||||
u32 i;
|
||||
int j;
|
||||
u32 tmp_node, blk_node = BLK_FROM_ADDR(blk_addr);
|
||||
u64 phy_addr;
|
||||
int wErase = FAIL;
|
||||
int wResult = FAIL;
|
||||
u32 *pbt = (u32 *)g_pBlockTable;
|
||||
|
||||
nand_dbg_print(NAND_DBG_TRACE, "%s, Line %d, Function: %s\n",
|
||||
__FILE__, __LINE__, __func__);
|
||||
|
||||
if (ERR == GLOB_FTL_Garbage_Collection())
|
||||
return ERR;
|
||||
|
||||
do {
|
||||
for (i = DeviceInfo.wSpectraEndBlock -
|
||||
DeviceInfo.wSpectraStartBlock;
|
||||
i > 0; i--) {
|
||||
if (IS_SPARE_BLOCK(i)) {
|
||||
tmp_node = (u32)(BAD_BLOCK |
|
||||
pbt[blk_node]);
|
||||
pbt[blk_node] = (u32)(pbt[i] &
|
||||
(~SPARE_BLOCK));
|
||||
pbt[i] = tmp_node;
|
||||
#if CMD_DMA
|
||||
p_BTableChangesDelta =
|
||||
(struct BTableChangesDelta *)
|
||||
g_pBTDelta_Free;
|
||||
g_pBTDelta_Free +=
|
||||
sizeof(struct BTableChangesDelta);
|
||||
|
||||
p_BTableChangesDelta->ftl_cmd_cnt =
|
||||
ftl_cmd_cnt;
|
||||
p_BTableChangesDelta->BT_Index =
|
||||
blk_node;
|
||||
p_BTableChangesDelta->BT_Entry_Value =
|
||||
pbt[blk_node];
|
||||
p_BTableChangesDelta->ValidFields = 0x0C;
|
||||
|
||||
p_BTableChangesDelta =
|
||||
(struct BTableChangesDelta *)
|
||||
g_pBTDelta_Free;
|
||||
g_pBTDelta_Free +=
|
||||
sizeof(struct BTableChangesDelta);
|
||||
|
||||
p_BTableChangesDelta->ftl_cmd_cnt =
|
||||
ftl_cmd_cnt;
|
||||
p_BTableChangesDelta->BT_Index = i;
|
||||
p_BTableChangesDelta->BT_Entry_Value = pbt[i];
|
||||
p_BTableChangesDelta->ValidFields = 0x0C;
|
||||
#endif
|
||||
wResult = PASS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (FAIL == wResult) {
|
||||
if (FAIL == GLOB_FTL_Garbage_Collection())
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
if (IN_PROGRESS_BLOCK_TABLE != g_cBlockTableStatus) {
|
||||
g_cBlockTableStatus = IN_PROGRESS_BLOCK_TABLE;
|
||||
FTL_Write_IN_Progress_Block_Table_Page();
|
||||
}
|
||||
|
||||
phy_addr = FTL_Get_Physical_Block_Addr(blk_addr);
|
||||
|
||||
for (j = 0; j < RETRY_TIMES; j++) {
|
||||
if (PASS == wErase) {
|
||||
if (FAIL == GLOB_FTL_Block_Erase(phy_addr)) {
|
||||
MARK_BLOCK_AS_BAD(pbt[blk_node]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (PASS == FTL_Cache_Update_Block(pData,
|
||||
old_page_addr,
|
||||
phy_addr)) {
|
||||
wResult = PASS;
|
||||
break;
|
||||
} else {
|
||||
wResult = FAIL;
|
||||
wErase = PASS;
|
||||
}
|
||||
}
|
||||
} while (FAIL == wResult);
|
||||
|
||||
FTL_Write_Block_Table(FAIL);
|
||||
|
||||
return wResult;
|
||||
}
|
||||
|
||||
/*&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
|
||||
* Function: FTL_Get_Page_Num
|
||||
* Inputs: Size in bytes
|
||||
|
|
|
@ -723,12 +723,12 @@ int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str)
|
|||
|
||||
/**
|
||||
* usb_string_ids_n() - allocate unused string IDs in batch
|
||||
* @cdev: the device whose string descriptor IDs are being allocated
|
||||
* @c: the device whose string descriptor IDs are being allocated
|
||||
* @n: number of string IDs to allocate
|
||||
* Context: single threaded during gadget setup
|
||||
*
|
||||
* Returns the first requested ID. This ID and next @n-1 IDs are now
|
||||
* valid IDs. At least providind that @n is non zore because if it
|
||||
* valid IDs. At least provided that @n is non-zero because if it
|
||||
* is, returns last requested ID which is now very useful information.
|
||||
*
|
||||
* @usb_string_ids_n() is called from bind() callbacks to allocate
|
||||
|
|
|
@ -1609,6 +1609,7 @@ static int __init m66592_probe(struct platform_device *pdev)
|
|||
/* initialize ucd */
|
||||
m66592 = kzalloc(sizeof(struct m66592), GFP_KERNEL);
|
||||
if (m66592 == NULL) {
|
||||
ret = -ENOMEM;
|
||||
pr_err("kzalloc error\n");
|
||||
goto clean_up;
|
||||
}
|
||||
|
|
|
@ -1557,6 +1557,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
|
|||
/* initialize ucd */
|
||||
r8a66597 = kzalloc(sizeof(struct r8a66597), GFP_KERNEL);
|
||||
if (r8a66597 == NULL) {
|
||||
ret = -ENOMEM;
|
||||
printk(KERN_ERR "kzalloc error\n");
|
||||
goto clean_up;
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue