Commit 56d205cc authored by David S. Miller's avatar David S. Miller
Browse files

sparc: Use popc when possible for ffs/__ffs/ffz.

parent ea5e7447
Loading
Loading
Loading
Loading
+4 −3
Original line number Original line Diff line number Diff line
@@ -26,16 +26,17 @@ extern void change_bit(unsigned long nr, volatile unsigned long *addr);
#define smp_mb__before_clear_bit()	barrier()
#define smp_mb__before_clear_bit()	barrier()
#define smp_mb__after_clear_bit()	barrier()
#define smp_mb__after_clear_bit()	barrier()


#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/__ffs.h>
#include <asm-generic/bitops/fls.h>
#include <asm-generic/bitops/fls.h>
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/__fls.h>
#include <asm-generic/bitops/fls64.h>
#include <asm-generic/bitops/fls64.h>


#ifdef __KERNEL__
#ifdef __KERNEL__


extern int ffs(int x);
extern unsigned long __ffs(unsigned long);

#include <asm-generic/bitops/ffz.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/sched.h>
#include <asm-generic/bitops/ffs.h>


/*
/*
 * hweightN: returns the hamming weight (i.e. the number
 * hweightN: returns the hamming weight (i.e. the number
+7 −0
Original line number Original line Diff line number Diff line
@@ -49,6 +49,13 @@ struct popc_3insn_patch_entry {
extern struct popc_3insn_patch_entry __popc_3insn_patch,
extern struct popc_3insn_patch_entry __popc_3insn_patch,
	__popc_3insn_patch_end;
	__popc_3insn_patch_end;


struct popc_6insn_patch_entry {
	unsigned int	addr;
	unsigned int	insns[6];
};
extern struct popc_6insn_patch_entry __popc_6insn_patch,
	__popc_6insn_patch_end;

extern void __init per_cpu_patch(void);
extern void __init per_cpu_patch(void);
extern void __init sun4v_patch(void);
extern void __init sun4v_patch(void);
extern void __init boot_cpu_id_too_large(int cpu);
extern void __init boot_cpu_id_too_large(int cpu);
+21 −11
Original line number Original line Diff line number Diff line
@@ -275,24 +275,34 @@ void __init sun4v_patch(void)
static void __init popc_patch(void)
static void __init popc_patch(void)
{
{
	struct popc_3insn_patch_entry *p3;
	struct popc_3insn_patch_entry *p3;
	struct popc_6insn_patch_entry *p6;


	p3 = &__popc_3insn_patch;
	p3 = &__popc_3insn_patch;
	while (p3 < &__popc_3insn_patch_end) {
	while (p3 < &__popc_3insn_patch_end) {
		unsigned long addr = p3->addr;
		unsigned long i, addr = p3->addr;


		*(unsigned int *) (addr +  0) = p3->insns[0];
		for (i = 0; i < 3; i++) {
			*(unsigned int *) (addr +  (i * 4)) = p3->insns[i];
			wmb();
			wmb();
		__asm__ __volatile__("flush	%0" : : "r" (addr +  0));
			__asm__ __volatile__("flush	%0"
					     : : "r" (addr +  (i * 4)));
		}


		*(unsigned int *) (addr +  4) = p3->insns[1];
		p3++;
		wmb();
	}
		__asm__ __volatile__("flush	%0" : : "r" (addr +  4));

	p6 = &__popc_6insn_patch;
	while (p6 < &__popc_6insn_patch_end) {
		unsigned long i, addr = p6->addr;


		*(unsigned int *) (addr +  8) = p3->insns[2];
		for (i = 0; i < 6; i++) {
			*(unsigned int *) (addr +  (i * 4)) = p6->insns[i];
			wmb();
			wmb();
		__asm__ __volatile__("flush	%0" : : "r" (addr +  4));
			__asm__ __volatile__("flush	%0"
					     : : "r" (addr +  (i * 4)));
		}


		p3++;
		p6++;
	}
	}
}
}


+4 −0
Original line number Original line Diff line number Diff line
@@ -45,5 +45,9 @@ EXPORT_SYMBOL(__arch_hweight16);
EXPORT_SYMBOL(__arch_hweight32);
EXPORT_SYMBOL(__arch_hweight32);
EXPORT_SYMBOL(__arch_hweight64);
EXPORT_SYMBOL(__arch_hweight64);


/* from ffs_ffz.S */
EXPORT_SYMBOL(ffs);
EXPORT_SYMBOL(__ffs);

/* Exporting a symbol from /init/main.c */
/* Exporting a symbol from /init/main.c */
EXPORT_SYMBOL(saved_command_line);
EXPORT_SYMBOL(saved_command_line);
+5 −0
Original line number Original line Diff line number Diff line
@@ -112,6 +112,11 @@ SECTIONS
		*(.popc_3insn_patch)
		*(.popc_3insn_patch)
		__popc_3insn_patch_end = .;
		__popc_3insn_patch_end = .;
	}
	}
	.popc_6insn_patch : {
		__popc_6insn_patch = .;
		*(.popc_6insn_patch)
		__popc_6insn_patch_end = .;
	}
	PERCPU_SECTION(SMP_CACHE_BYTES)
	PERCPU_SECTION(SMP_CACHE_BYTES)


	. = ALIGN(PAGE_SIZE);
	. = ALIGN(PAGE_SIZE);
Loading