sparc: Move of_set_property_mutex acquisition outside of devtree_lock grab.
[safe/jmp/linux-2.6] / arch / blackfin / kernel / kgdb.c
index 1c5afae..cce79d0 100644 (file)
@@ -34,10 +34,6 @@ int gdb_bfin_vector = -1;
 #error change the definition of slavecpulocks
 #endif
 
-#ifdef CONFIG_BFIN_WDT
-# error "Please unselect blackfin watchdog driver before build KGDB."
-#endif
-
 void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
 {
        gdb_regs[BFIN_R0] = regs->r0;
@@ -219,6 +215,7 @@ int bfin_set_hw_break(unsigned long addr, int len, enum kgdb_bptype type)
                if (bfin_type == breakinfo[breakno].type
                        && !breakinfo[breakno].occupied) {
                        breakinfo[breakno].occupied = 1;
+                       breakinfo[breakno].skip = 0;
                        breakinfo[breakno].enabled = 1;
                        breakinfo[breakno].addr = addr;
                        breakinfo[breakno].dataacc = dataacc;
@@ -363,12 +360,12 @@ void kgdb_passive_cpu_callback(void *info)
 
 void kgdb_roundup_cpus(unsigned long flags)
 {
-       smp_call_function(kgdb_passive_cpu_callback, NULL, 0, 0);
+       smp_call_function(kgdb_passive_cpu_callback, NULL, 0);
 }
 
 void kgdb_roundup_cpu(int cpu, unsigned long flags)
 {
-       smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0, 0);
+       smp_call_function_single(cpu, kgdb_passive_cpu_callback, NULL, 0);
 }
 #endif
 
@@ -385,10 +382,8 @@ int kgdb_arch_handle_exception(int vector, int signo,
                               struct pt_regs *regs)
 {
        long addr;
-       long breakno;
        char *ptr;
        int newPC;
-       int wp_status;
        int i;
 
        switch (remcom_in_buffer[0]) {
@@ -426,17 +421,6 @@ int kgdb_arch_handle_exception(int vector, int signo,
                        kgdb_single_step = i + 1;
                }
 
-               if (vector == VEC_WATCH) {
-                       wp_status = bfin_read_WPSTAT();
-                       for (breakno = 0; breakno < HW_WATCHPOINT_NUM; breakno++) {
-                               if (wp_status & (1 << breakno)) {
-                                       breakinfo->skip = 1;
-                                       break;
-                               }
-                       }
-                       bfin_write_WPSTAT(0);
-               }
-
                bfin_correct_hw_break();
 
                return 0;
@@ -470,67 +454,89 @@ static int hex(char ch)
 
 static int validate_memory_access_address(unsigned long addr, int size)
 {
-       int cpu = raw_smp_processor_id();
+       if (size < 0 || addr == 0)
+               return -EFAULT;
+       return bfin_mem_access_type(addr, size);
+}
 
-       if (size < 0)
-               return EFAULT;
-       if (addr >= 0x1000 && (addr + size) <= physical_mem_end)
-               return 0;
-       if (addr >= SYSMMR_BASE)
-               return 0;
-       if (addr >= ASYNC_BANK0_BASE
-          && addr + size <= ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE)
-               return 0;
-       if (cpu == 0) {
-               if (addr >= L1_SCRATCH_START
-                  && (addr + size <= L1_SCRATCH_START + L1_SCRATCH_LENGTH))
-                       return 0;
-#if L1_CODE_LENGTH != 0
-               if (addr >= L1_CODE_START
-                  && (addr + size <= L1_CODE_START + L1_CODE_LENGTH))
-                       return 0;
-#endif
-#if L1_DATA_A_LENGTH != 0
-               if (addr >= L1_DATA_A_START
-                  && (addr + size <= L1_DATA_A_START + L1_DATA_A_LENGTH))
-                       return 0;
-#endif
-#if L1_DATA_B_LENGTH != 0
-               if (addr >= L1_DATA_B_START
-                  && (addr + size <= L1_DATA_B_START + L1_DATA_B_LENGTH))
-                       return 0;
-#endif
-#ifdef CONFIG_SMP
-       } else if (cpu == 1) {
-               if (addr >= COREB_L1_SCRATCH_START
-                  && (addr + size <= COREB_L1_SCRATCH_START
-                  + L1_SCRATCH_LENGTH))
+static int bfin_probe_kernel_read(char *dst, char *src, int size)
+{
+       unsigned long lsrc = (unsigned long)src;
+       int mem_type;
+
+       mem_type = validate_memory_access_address(lsrc, size);
+       if (mem_type < 0)
+               return mem_type;
+
+       if (lsrc >= SYSMMR_BASE) {
+               if (size == 2 && lsrc % 2 == 0) {
+                       u16 mmr = bfin_read16(src);
+                       memcpy(dst, &mmr, sizeof(mmr));
                        return 0;
-# if L1_CODE_LENGTH != 0
-               if (addr >= COREB_L1_CODE_START
-                  && (addr + size <= COREB_L1_CODE_START + L1_CODE_LENGTH))
+               } else if (size == 4 && lsrc % 4 == 0) {
+                       u32 mmr = bfin_read32(src);
+                       memcpy(dst, &mmr, sizeof(mmr));
                        return 0;
-# endif
-# if L1_DATA_A_LENGTH != 0
-               if (addr >= COREB_L1_DATA_A_START
-                  && (addr + size <= COREB_L1_DATA_A_START + L1_DATA_A_LENGTH))
+               }
+       } else {
+               switch (mem_type) {
+                       case BFIN_MEM_ACCESS_CORE:
+                       case BFIN_MEM_ACCESS_CORE_ONLY:
+                               return probe_kernel_read(dst, src, size);
+                       /* XXX: should support IDMA here with SMP */
+                       case BFIN_MEM_ACCESS_DMA:
+                               if (dma_memcpy(dst, src, size))
+                                       return 0;
+                               break;
+                       case BFIN_MEM_ACCESS_ITEST:
+                               if (isram_memcpy(dst, src, size))
+                                       return 0;
+                               break;
+               }
+       }
+
+       return -EFAULT;
+}
+
+static int bfin_probe_kernel_write(char *dst, char *src, int size)
+{
+       unsigned long ldst = (unsigned long)dst;
+       int mem_type;
+
+       mem_type = validate_memory_access_address(ldst, size);
+       if (mem_type < 0)
+               return mem_type;
+
+       if (ldst >= SYSMMR_BASE) {
+               if (size == 2 && ldst % 2 == 0) {
+                       u16 mmr;
+                       memcpy(&mmr, src, sizeof(mmr));
+                       bfin_write16(dst, mmr);
                        return 0;
-# endif
-# if L1_DATA_B_LENGTH != 0
-               if (addr >= COREB_L1_DATA_B_START
-                  && (addr + size <= COREB_L1_DATA_B_START + L1_DATA_B_LENGTH))
+               } else if (size == 4 && ldst % 4 == 0) {
+                       u32 mmr;
+                       memcpy(&mmr, src, sizeof(mmr));
+                       bfin_write32(dst, mmr);
                        return 0;
-# endif
-#endif
+               }
+       } else {
+               switch (mem_type) {
+                       case BFIN_MEM_ACCESS_CORE:
+                       case BFIN_MEM_ACCESS_CORE_ONLY:
+                               return probe_kernel_write(dst, src, size);
+                       /* XXX: should support IDMA here with SMP */
+                       case BFIN_MEM_ACCESS_DMA:
+                               if (dma_memcpy(dst, src, size))
+                                       return 0;
+                               break;
+                       case BFIN_MEM_ACCESS_ITEST:
+                               if (isram_memcpy(dst, src, size))
+                                       return 0;
+                               break;
+               }
        }
 
-#if L2_LENGTH != 0
-       if (addr >= L2_START
-          && addr + size <= L2_START + L2_LENGTH)
-               return 0;
-#endif
-
-       return EFAULT;
+       return -EFAULT;
 }
 
 /*
@@ -540,14 +546,7 @@ static int validate_memory_access_address(unsigned long addr, int size)
 int kgdb_mem2hex(char *mem, char *buf, int count)
 {
        char *tmp;
-       int err = 0;
-       unsigned char *pch;
-       unsigned short mmr16;
-       unsigned long mmr32;
-       int cpu = raw_smp_processor_id();
-
-       if (validate_memory_access_address((unsigned long)mem, count))
-               return EFAULT;
+       int err;
 
        /*
         * We use the upper half of buf as an intermediate buffer for the
@@ -555,47 +554,7 @@ int kgdb_mem2hex(char *mem, char *buf, int count)
         */
        tmp = buf + count;
 
-       if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/
-               switch (count) {
-               case 2:
-                       if ((unsigned int)mem % 2 == 0) {
-                               mmr16 = *(unsigned short *)mem;
-                               pch = (unsigned char *)&mmr16;
-                               *tmp++ = *pch++;
-                               *tmp++ = *pch++;
-                               tmp -= 2;
-                       } else
-                               err = EFAULT;
-                       break;
-               case 4:
-                       if ((unsigned int)mem % 4 == 0) {
-                               mmr32 = *(unsigned long *)mem;
-                               pch = (unsigned char *)&mmr32;
-                               *tmp++ = *pch++;
-                               *tmp++ = *pch++;
-                               *tmp++ = *pch++;
-                               *tmp++ = *pch++;
-                               tmp -= 4;
-                       } else
-                               err = EFAULT;
-                       break;
-               default:
-                       err = EFAULT;
-               }
-       } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START &&
-               (unsigned int)(mem + count) <= L1_CODE_START + L1_CODE_LENGTH
-#ifdef CONFIG_SMP
-               || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START &&
-               (unsigned int)(mem + count) <=
-               COREB_L1_CODE_START + L1_CODE_LENGTH
-#endif
-               ) {
-               /* access L1 instruction SRAM*/
-               if (dma_memcpy(tmp, mem, count) == NULL)
-                       err = EFAULT;
-       } else
-               err = probe_kernel_read(tmp, mem, count);
-
+       err = bfin_probe_kernel_read(tmp, mem, count);
        if (!err) {
                while (count > 0) {
                        buf = pack_hex_byte(buf, *tmp);
@@ -616,63 +575,21 @@ int kgdb_mem2hex(char *mem, char *buf, int count)
  */
 int kgdb_ebin2mem(char *buf, char *mem, int count)
 {
-       char *tmp_old;
-       char *tmp_new;
-       unsigned short *mmr16;
-       unsigned long *mmr32;
-       int err = 0;
-       int size = 0;
-       int cpu = raw_smp_processor_id();
+       char *tmp_old, *tmp_new;
+       int size;
 
        tmp_old = tmp_new = buf;
 
-       while (count-- > 0) {
+       for (size = 0; size < count; ++size) {
                if (*tmp_old == 0x7d)
                        *tmp_new = *(++tmp_old) ^ 0x20;
                else
                        *tmp_new = *tmp_old;
                tmp_new++;
                tmp_old++;
-               size++;
        }
 
-       if (validate_memory_access_address((unsigned long)mem, size))
-               return EFAULT;
-
-       if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/
-               switch (size) {
-               case 2:
-                       if ((unsigned int)mem % 2 == 0) {
-                               mmr16 = (unsigned short *)buf;
-                               *(unsigned short *)mem = *mmr16;
-                       } else
-                               return EFAULT;
-                       break;
-               case 4:
-                       if ((unsigned int)mem % 4 == 0) {
-                               mmr32 = (unsigned long *)buf;
-                               *(unsigned long *)mem = *mmr32;
-                       } else
-                               return EFAULT;
-                       break;
-               default:
-                       return EFAULT;
-               }
-       } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START &&
-               (unsigned int)(mem + count) < L1_CODE_START + L1_CODE_LENGTH
-#ifdef CONFIG_SMP
-               || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START &&
-               (unsigned int)(mem + count) <=
-               COREB_L1_CODE_START + L1_CODE_LENGTH
-#endif
-               ) {
-               /* access L1 instruction SRAM */
-               if (dma_memcpy(mem, buf, size) == NULL)
-                       err = EFAULT;
-       } else
-               err = probe_kernel_write(mem, buf, size);
-
-       return err;
+       return bfin_probe_kernel_write(mem, buf, count);
 }
 
 /*
@@ -682,14 +599,7 @@ int kgdb_ebin2mem(char *buf, char *mem, int count)
  */
 int kgdb_hex2mem(char *buf, char *mem, int count)
 {
-       char *tmp_raw;
-       char *tmp_hex;
-       unsigned short *mmr16;
-       unsigned long *mmr32;
-       int cpu = raw_smp_processor_id();
-
-       if (validate_memory_access_address((unsigned long)mem, count))
-               return EFAULT;
+       char *tmp_raw, *tmp_hex;
 
        /*
         * We use the upper half of buf as an intermediate buffer for the
@@ -704,117 +614,51 @@ int kgdb_hex2mem(char *buf, char *mem, int count)
                *tmp_raw |= hex(*tmp_hex--) << 4;
        }
 
-       if ((unsigned int)mem >= SYSMMR_BASE) { /*access MMR registers*/
-               switch (count) {
-               case 2:
-                       if ((unsigned int)mem % 2 == 0) {
-                               mmr16 = (unsigned short *)tmp_raw;
-                               *(unsigned short *)mem = *mmr16;
-                       } else
-                               return EFAULT;
-                       break;
-               case 4:
-                       if ((unsigned int)mem % 4 == 0) {
-                               mmr32 = (unsigned long *)tmp_raw;
-                               *(unsigned long *)mem = *mmr32;
-                       } else
-                               return EFAULT;
-                       break;
-               default:
-                       return EFAULT;
-               }
-       } else if (cpu == 0 && (unsigned int)mem >= L1_CODE_START &&
-               (unsigned int)(mem + count) <= L1_CODE_START + L1_CODE_LENGTH
-#ifdef CONFIG_SMP
-               || cpu == 1 && (unsigned int)mem >= COREB_L1_CODE_START &&
-               (unsigned int)(mem + count) <=
-               COREB_L1_CODE_START + L1_CODE_LENGTH
-#endif
-               ) {
-               /* access L1 instruction SRAM */
-               if (dma_memcpy(mem, tmp_raw, count) == NULL)
-                       return EFAULT;
-       } else
-               return probe_kernel_write(mem, tmp_raw, count);
-       return 0;
+       return bfin_probe_kernel_write(mem, tmp_raw, count);
 }
 
+#define IN_MEM(addr, size, l1_addr, l1_size) \
+({ \
+       unsigned long __addr = (unsigned long)(addr); \
+       (l1_size && __addr >= l1_addr && __addr + (size) <= l1_addr + l1_size); \
+})
+#define ASYNC_BANK_SIZE \
+       (ASYNC_BANK0_SIZE + ASYNC_BANK1_SIZE + \
+        ASYNC_BANK2_SIZE + ASYNC_BANK3_SIZE)
+
 int kgdb_validate_break_address(unsigned long addr)
 {
        int cpu = raw_smp_processor_id();
 
        if (addr >= 0x1000 && (addr + BREAK_INSTR_SIZE) <= physical_mem_end)
                return 0;
-       if (addr >= ASYNC_BANK0_BASE
-          && addr + BREAK_INSTR_SIZE <= ASYNC_BANK3_BASE + ASYNC_BANK3_BASE)
+       if (IN_MEM(addr, BREAK_INSTR_SIZE, ASYNC_BANK0_BASE, ASYNC_BANK_SIZE))
                return 0;
-#if L1_CODE_LENGTH != 0
-       if (cpu == 0 && addr >= L1_CODE_START
-          && addr + BREAK_INSTR_SIZE <= L1_CODE_START + L1_CODE_LENGTH)
+       if (cpu == 0 && IN_MEM(addr, BREAK_INSTR_SIZE, L1_CODE_START, L1_CODE_LENGTH))
                return 0;
-# ifdef CONFIG_SMP
-       else if (cpu == 1 && addr >= COREB_L1_CODE_START
-          && addr + BREAK_INSTR_SIZE <= COREB_L1_CODE_START + L1_CODE_LENGTH)
+#ifdef CONFIG_SMP
+       else if (cpu == 1 && IN_MEM(addr, BREAK_INSTR_SIZE, COREB_L1_CODE_START, L1_CODE_LENGTH))
                return 0;
-# endif
 #endif
-#if L2_LENGTH != 0
-       if (addr >= L2_START
-          && addr + BREAK_INSTR_SIZE <= L2_START + L2_LENGTH)
+       if (IN_MEM(addr, BREAK_INSTR_SIZE, L2_START, L2_LENGTH))
                return 0;
-#endif
 
-       return EFAULT;
+       return -EFAULT;
 }
 
 int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr)
 {
-       int err;
-       int cpu = raw_smp_processor_id();
-
-       if ((cpu == 0 && (unsigned int)addr >= L1_CODE_START
-               && (unsigned int)(addr + BREAK_INSTR_SIZE)
-               < L1_CODE_START + L1_CODE_LENGTH)
-#ifdef CONFIG_SMP
-               || (cpu == 1 && (unsigned int)addr >= COREB_L1_CODE_START
-               && (unsigned int)(addr + BREAK_INSTR_SIZE)
-               < COREB_L1_CODE_START + L1_CODE_LENGTH)
-#endif
-               ) {
-               /* access L1 instruction SRAM */
-               if (dma_memcpy(saved_instr, (void *)addr, BREAK_INSTR_SIZE)
-                       == NULL)
-                       return -EFAULT;
-
-               if (dma_memcpy((void *)addr, arch_kgdb_ops.gdb_bpt_instr,
-                       BREAK_INSTR_SIZE) == NULL)
-                       return -EFAULT;
-
-               return 0;
-       } else {
-               err = probe_kernel_read(saved_instr, (char *)addr,
-                       BREAK_INSTR_SIZE);
-               if (err)
-                       return err;
-
-               return probe_kernel_write((char *)addr,
-                       arch_kgdb_ops.gdb_bpt_instr, BREAK_INSTR_SIZE);
-       }
+       int err = bfin_probe_kernel_read(saved_instr, (char *)addr,
+                                        BREAK_INSTR_SIZE);
+       if (err)
+               return err;
+       return bfin_probe_kernel_write((char *)addr, arch_kgdb_ops.gdb_bpt_instr,
+                                      BREAK_INSTR_SIZE);
 }
 
 int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle)
 {
-       if ((unsigned int)addr >= L1_CODE_START &&
-               (unsigned int)(addr + BREAK_INSTR_SIZE) <
-                       L1_CODE_START + L1_CODE_LENGTH) {
-               /* access L1 instruction SRAM */
-               if (dma_memcpy((void *)addr, bundle, BREAK_INSTR_SIZE) == NULL)
-                       return -EFAULT;
-
-               return 0;
-       } else
-               return probe_kernel_write((char *)addr,
-                               (char *)bundle, BREAK_INSTR_SIZE);
+       return bfin_probe_kernel_write((char *)addr, bundle, BREAK_INSTR_SIZE);
 }
 
 int kgdb_arch_init(void)