aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/process.c
diff options
context:
space:
mode:
authorBernd Schmidt <bernds_cb1@t-online.de>2009-09-23 12:47:16 -0400
committerMike Frysinger <vapier@gentoo.org>2009-12-15 00:13:52 -0500
commit13048f8866390a26a7b657e0ca28100e2660063a (patch)
tree9613b8d038e3e0786ed854ce4f172dc698f8c65d /arch/blackfin/kernel/process.c
parentcb5ae60f7a0b21b936c022a2e7f9303c60665233 (diff)
Blackfin: improve async bank access checking (for cross-banks & XIP)
The access_ok() function did not accept ranges within the async banks which made it impossible to do XIP in flash. Fixing that also showed that the current bfin_mem_access_type() code did not work with accesses that spanned async banks (like a file system). So split out and fix the async bank checks so that all these scenarios work as expected. Signed-off-by: Bernd Schmidt <bernds_cb1@t-online.de> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel/process.c')
-rw-r--r--arch/blackfin/kernel/process.c77
1 files changed, 62 insertions, 15 deletions
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 45876427eb2d..a57723808743 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -332,12 +332,58 @@ int in_mem_const(unsigned long addr, unsigned long size,
332{ 332{
333 return in_mem_const_off(addr, size, 0, const_addr, const_size); 333 return in_mem_const_off(addr, size, 0, const_addr, const_size);
334} 334}
335#define IN_ASYNC(bnum, bctlnum) \ 335#define ASYNC_ENABLED(bnum, bctlnum) \
336({ \ 336({ \
337 (bfin_read_EBIU_AMGCTL() & 0xe) < ((bnum + 1) << 1) ? -EFAULT : \ 337 (bfin_read_EBIU_AMGCTL() & 0xe) < ((bnum + 1) << 1) ? 0 : \
338 bfin_read_EBIU_AMBCTL##bctlnum() & B##bnum##RDYEN ? -EFAULT : \ 338 bfin_read_EBIU_AMBCTL##bctlnum() & B##bnum##RDYEN ? 0 : \
339 BFIN_MEM_ACCESS_CORE; \ 339 1; \
340}) 340})
341/*
342 * We can't read EBIU banks that aren't enabled or we end up hanging
343 * on the access to the async space. Make sure we validate accesses
344 * that cross async banks too.
345 * 0 - found, but unusable
346 * 1 - found & usable
347 * 2 - not found
348 */
349static
350int in_async(unsigned long addr, unsigned long size)
351{
352 if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE) {
353 if (!ASYNC_ENABLED(0, 0))
354 return 0;
355 if (addr + size <= ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE)
356 return 1;
357 size -= ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE - addr;
358 addr = ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE;
359 }
360 if (addr >= ASYNC_BANK1_BASE && addr < ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE) {
361 if (!ASYNC_ENABLED(1, 0))
362 return 0;
363 if (addr + size <= ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE)
364 return 1;
365 size -= ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE - addr;
366 addr = ASYNC_BANK1_BASE + ASYNC_BANK1_SIZE;
367 }
368 if (addr >= ASYNC_BANK2_BASE && addr < ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE) {
369 if (!ASYNC_ENABLED(2, 1))
370 return 0;
371 if (addr + size <= ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE)
372 return 1;
373 size -= ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE - addr;
374 addr = ASYNC_BANK2_BASE + ASYNC_BANK2_SIZE;
375 }
376 if (addr >= ASYNC_BANK3_BASE && addr < ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE) {
377 if (ASYNC_ENABLED(3, 1))
378 return 0;
379 if (addr + size <= ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE)
380 return 1;
381 return 0;
382 }
383
384 /* not within async bounds */
385 return 2;
386}
341 387
342int bfin_mem_access_type(unsigned long addr, unsigned long size) 388int bfin_mem_access_type(unsigned long addr, unsigned long size)
343{ 389{
@@ -374,17 +420,11 @@ int bfin_mem_access_type(unsigned long addr, unsigned long size)
374 if (addr >= SYSMMR_BASE) 420 if (addr >= SYSMMR_BASE)
375 return BFIN_MEM_ACCESS_CORE_ONLY; 421 return BFIN_MEM_ACCESS_CORE_ONLY;
376 422
377 /* We can't read EBIU banks that aren't enabled or we end up hanging 423 switch (in_async(addr, size)) {
378 * on the access to the async space. 424 case 0: return -EFAULT;
379 */ 425 case 1: return BFIN_MEM_ACCESS_CORE;
380 if (in_mem_const(addr, size, ASYNC_BANK0_BASE, ASYNC_BANK0_SIZE)) 426 case 2: /* fall through */;
381 return IN_ASYNC(0, 0); 427 }
382 if (in_mem_const(addr, size, ASYNC_BANK1_BASE, ASYNC_BANK1_SIZE))
383 return IN_ASYNC(1, 0);
384 if (in_mem_const(addr, size, ASYNC_BANK2_BASE, ASYNC_BANK2_SIZE))
385 return IN_ASYNC(2, 1);
386 if (in_mem_const(addr, size, ASYNC_BANK3_BASE, ASYNC_BANK3_SIZE))
387 return IN_ASYNC(3, 1);
388 428
389 if (in_mem_const(addr, size, BOOT_ROM_START, BOOT_ROM_LENGTH)) 429 if (in_mem_const(addr, size, BOOT_ROM_START, BOOT_ROM_LENGTH))
390 return BFIN_MEM_ACCESS_CORE; 430 return BFIN_MEM_ACCESS_CORE;
@@ -401,6 +441,8 @@ __attribute__((l1_text))
401/* Return 1 if access to memory range is OK, 0 otherwise */ 441/* Return 1 if access to memory range is OK, 0 otherwise */
402int _access_ok(unsigned long addr, unsigned long size) 442int _access_ok(unsigned long addr, unsigned long size)
403{ 443{
444 int aret;
445
404 if (size == 0) 446 if (size == 0)
405 return 1; 447 return 1;
406 /* Check that things do not wrap around */ 448 /* Check that things do not wrap around */
@@ -450,6 +492,11 @@ int _access_ok(unsigned long addr, unsigned long size)
450 if (in_mem_const(addr, size, COREB_L1_DATA_B_START, COREB_L1_DATA_B_LENGTH)) 492 if (in_mem_const(addr, size, COREB_L1_DATA_B_START, COREB_L1_DATA_B_LENGTH))
451 return 1; 493 return 1;
452#endif 494#endif
495
496 aret = in_async(addr, size);
497 if (aret < 2)
498 return aret;
499
453 if (in_mem_const_off(addr, size, _ebss_l2 - _stext_l2, L2_START, L2_LENGTH)) 500 if (in_mem_const_off(addr, size, _ebss_l2 - _stext_l2, L2_START, L2_LENGTH))
454 return 1; 501 return 1;
455 502