diff options
-rw-r--r-- | arch/mips/kernel/traps.c | 41 |
1 files changed, 18 insertions, 23 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 61efc61c45e2..081e6ed5bb62 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -961,15 +961,19 @@ void *set_except_vector(int n, void *addr) | |||
961 | 961 | ||
962 | #ifdef CONFIG_CPU_MIPSR2 | 962 | #ifdef CONFIG_CPU_MIPSR2 |
963 | /* | 963 | /* |
964 | * Shadow register allocation | 964 | * MIPSR2 shadow register set allocation |
965 | * FIXME: SMP... | 965 | * FIXME: SMP... |
966 | */ | 966 | */ |
967 | 967 | ||
968 | /* MIPSR2 shadow register sets */ | 968 | static struct shadow_registers { |
969 | struct shadow_registers { | 969 | /* |
970 | spinlock_t sr_lock; /* */ | 970 | * Number of shadow register sets supported |
971 | int sr_supported; /* Number of shadow register sets supported */ | 971 | */ |
972 | int sr_allocated; /* Bitmap of allocated shadow registers */ | 972 | unsigned long sr_supported; |
973 | /* | ||
974 | * Bitmap of allocated shadow registers | ||
975 | */ | ||
976 | unsigned long sr_allocated; | ||
973 | } shadow_registers; | 977 | } shadow_registers; |
974 | 978 | ||
975 | void mips_srs_init(void) | 979 | void mips_srs_init(void) |
@@ -980,7 +984,6 @@ void mips_srs_init(void) | |||
980 | shadow_registers.sr_supported); | 984 | shadow_registers.sr_supported); |
981 | #endif | 985 | #endif |
982 | shadow_registers.sr_allocated = 1; /* Set 0 used by kernel */ | 986 | shadow_registers.sr_allocated = 1; /* Set 0 used by kernel */ |
983 | spin_lock_init(&shadow_registers.sr_lock); | ||
984 | } | 987 | } |
985 | 988 | ||
986 | int mips_srs_max(void) | 989 | int mips_srs_max(void) |
@@ -991,32 +994,24 @@ int mips_srs_max(void) | |||
991 | int mips_srs_alloc(void) | 994 | int mips_srs_alloc(void) |
992 | { | 995 | { |
993 | struct shadow_registers *sr = &shadow_registers; | 996 | struct shadow_registers *sr = &shadow_registers; |
994 | unsigned long flags; | ||
995 | int set; | 997 | int set; |
996 | 998 | ||
997 | spin_lock_irqsave(&sr->sr_lock, flags); | 999 | again: |
1000 | set = find_first_zero_bit(&sr->sr_allocated, sr->sr_supported); | ||
1001 | if (set >= sr->sr_supported) | ||
1002 | return -1; | ||
998 | 1003 | ||
999 | for (set = 0; set < sr->sr_supported; set++) { | 1004 | if (test_and_set_bit(set, &sr->sr_allocated)) |
1000 | if ((sr->sr_allocated & (1 << set)) == 0) { | 1005 | goto again; |
1001 | sr->sr_allocated |= 1 << set; | ||
1002 | spin_unlock_irqrestore(&sr->sr_lock, flags); | ||
1003 | return set; | ||
1004 | } | ||
1005 | } | ||
1006 | 1006 | ||
1007 | /* None available */ | 1007 | return set; |
1008 | spin_unlock_irqrestore(&sr->sr_lock, flags); | ||
1009 | return -1; | ||
1010 | } | 1008 | } |
1011 | 1009 | ||
1012 | void mips_srs_free (int set) | 1010 | void mips_srs_free (int set) |
1013 | { | 1011 | { |
1014 | struct shadow_registers *sr = &shadow_registers; | 1012 | struct shadow_registers *sr = &shadow_registers; |
1015 | unsigned long flags; | ||
1016 | 1013 | ||
1017 | spin_lock_irqsave(&sr->sr_lock, flags); | 1014 | clear_bit(set, &sr->sr_allocated); |
1018 | sr->sr_allocated &= ~(1 << set); | ||
1019 | spin_unlock_irqrestore(&sr->sr_lock, flags); | ||
1020 | } | 1015 | } |
1021 | 1016 | ||
1022 | static void *set_vi_srs_handler(int n, void *addr, int srs) | 1017 | static void *set_vi_srs_handler(int n, void *addr, int srs) |