Why not treat all four banks as one contiguous area? All banks are equally sized and contiguous.
-Michael ________________________________________ From: [email protected] [mailto:[email protected]] On Behalf Of [email protected] Sent: Wednesday, September 23, 2009 7:19 PM To: [email protected] Subject: [Linux-kernel-commits] [7434] trunk/arch/blackfin/kernel/process.c:Bug[#4090] Revision 7434 Author bernds Date 2009-09-23 13:18:38 -0400 (Wed, 23 Sep 2009) Log Message Bug[#4090] A more elaborate version of the previous patch, changing both bfin_mem_access_type and _access_ok to handle the case where accesses cross async bank boundaries. Modified Paths * trunk/arch/blackfin/kernel/process.c Diff Modified: trunk/arch/blackfin/kernel/process.c (7433 => 7434) --- trunk/arch/blackfin/kernel/process.c 2009-09-23 16:47:16 UTC (rev 7433) +++ trunk/arch/blackfin/kernel/process.c 2009-09-23 17:18:38 UTC (rev 7434) @@ -367,6 +367,7 @@ int bfin_mem_access_type(unsigned long addr, unsigned long size) { int cpu = raw_smp_processor_id(); + int async_type; /* Check that things do not wrap around */ if (addr > ULONG_MAX - size) @@ -401,7 +402,45 @@ /* We can't read EBIU banks that aren't enabled or we end up hanging * on the access to the async space. + * For accesses that cross async banks, keep track of the type and + * return -EFAULT if we have different ones. */ + async_type = -1; + if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE) { + async_type = IN_ASYNC(0, 0); + if (addr + size <= ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE) + return async_type; + size -= ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE - addr; + addr = ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE; + } + if (addr >= ASYNC_BANK1_BASE && addr < ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE) { + int t = IN_ASYNC(1, 0); + if (t != async_type && async_type != -1) + return -EFAULT; + async_type = t; + if (addr + size <= ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE) + return t; + size -= ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE - addr; + addr = ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE; + } + if (addr >= ASYNC_BANK2_BASE && addr < ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE) { + int t = IN_ASYNC(2, 1); + if (t != async_type && async_type != -1) + return -EFAULT; + async_type = t; + if (addr + size <= ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE) + return t; + size -= ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE - addr; + addr = ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE; + } + if (addr >= ASYNC_BANK3_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) { + int t = IN_ASYNC(2, 1); + if (t != async_type && async_type != -1) + return -EFAULT; + if (addr + size <= ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) + return t; + return -EFAULT; + } if (in_mem_const(addr, size, ASYNC_BANK0_BASE, ASYNC_BANK0_SIZE)) return IN_ASYNC(0, 0); if (in_mem_const(addr, size, ASYNC_BANK1_BASE, ASYNC_BANK1_SIZE)) @@ -479,14 +518,41 @@ /* We can't read EBIU banks that aren't enabled or we end up hanging * on the access to the async space. */ - if (in_mem_const(addr, size, ASYNC_BANK0_BASE, ASYNC_BANK0_SIZE)) - return IN_ASYNC(0, 0) != -EFAULT; - if (in_mem_const(addr, size, ASYNC_BANK1_BASE, ASYNC_BANK1_SIZE)) - return IN_ASYNC(1, 0) != -EFAULT; - if (in_mem_const(addr, size, ASYNC_BANK2_BASE, ASYNC_BANK2_SIZE)) - return IN_ASYNC(2, 1) != -EFAULT; - if (in_mem_const(addr, size, ASYNC_BANK3_BASE, ASYNC_BANK3_SIZE)) - return IN_ASYNC(3, 1) != -EFAULT; + if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE) { + int t = IN_ASYNC(0, 0); + if (t != BFIN_MEM_ACCESS_CORE && t != BFIN_MEM_ACCESS_CORE_ONLY) + return 0; + if (addr + size <= ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE) + return 1; + size -= ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE - addr; + addr = ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE; + } + if (addr >= ASYNC_BANK1_BASE && addr < ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE) { + int t = IN_ASYNC(1, 0); + if (t != BFIN_MEM_ACCESS_CORE && t != BFIN_MEM_ACCESS_CORE_ONLY) + return 0; + if (addr + size <= ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE) + return 1; + size -= ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE - addr; + addr = ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE; + } + if (addr >= ASYNC_BANK2_BASE && addr < ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE) { + int t = IN_ASYNC(2, 1); + if (t != BFIN_MEM_ACCESS_CORE && t != BFIN_MEM_ACCESS_CORE_ONLY) + return 0; + if (addr + size <= ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE) + return 1; + size -= ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE - addr; + addr = ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE; + } + if (addr >= ASYNC_BANK3_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) { + int t = IN_ASYNC(3, 1); + if (t != BFIN_MEM_ACCESS_CORE && t != BFIN_MEM_ACCESS_CORE_ONLY) + return 0; + if (addr + size <= ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) + return 1; + return 0; + } if (in_mem_const_off(addr, size, _ebss_l2 - _stext_l2, L2_START, L2_LENGTH)) return 1; _______________________________________________ Linux-kernel-commits mailing list [email protected] https://blackfin.uclinux.org/mailman/listinfo/linux-kernel-commits
