mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-21 16:29:59 +00:00
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>
This commit is contained in:
parent
cb5ae60f7a
commit
13048f8866
1 changed files with 62 additions and 15 deletions
|
@ -332,12 +332,58 @@ int in_mem_const(unsigned long addr, unsigned long size,
|
|||
{
|
||||
return in_mem_const_off(addr, size, 0, const_addr, const_size);
|
||||
}
|
||||
#define IN_ASYNC(bnum, bctlnum) \
|
||||
#define ASYNC_ENABLED(bnum, bctlnum) \
|
||||
({ \
|
||||
(bfin_read_EBIU_AMGCTL() & 0xe) < ((bnum + 1) << 1) ? -EFAULT : \
|
||||
bfin_read_EBIU_AMBCTL##bctlnum() & B##bnum##RDYEN ? -EFAULT : \
|
||||
BFIN_MEM_ACCESS_CORE; \
|
||||
(bfin_read_EBIU_AMGCTL() & 0xe) < ((bnum + 1) << 1) ? 0 : \
|
||||
bfin_read_EBIU_AMBCTL##bctlnum() & B##bnum##RDYEN ? 0 : \
|
||||
1; \
|
||||
})
|
||||
/*
|
||||
* We can't read EBIU banks that aren't enabled or we end up hanging
|
||||
* on the access to the async space. Make sure we validate accesses
|
||||
* that cross async banks too.
|
||||
* 0 - found, but unusable
|
||||
* 1 - found & usable
|
||||
* 2 - not found
|
||||
*/
|
||||
static
|
||||
int in_async(unsigned long addr, unsigned long size)
|
||||
{
|
||||
if (addr >= ASYNC_BANK0_BASE && addr < ASYNC_BANK0_BASE + ASYNC_BANK0_SIZE) {
|
||||
if (!ASYNC_ENABLED(0, 0))
|
||||
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) {
|
||||
if (!ASYNC_ENABLED(1, 0))
|
||||
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) {
|
||||
if (!ASYNC_ENABLED(2, 1))
|
||||
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) {
|
||||
if (ASYNC_ENABLED(3, 1))
|
||||
return 0;
|
||||
if (addr + size <= ASYNC_BANK3_BASE + ASYNC_BANK3_SIZE)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* not within async bounds */
|
||||
return 2;
|
||||
}
|
||||
|
||||
int bfin_mem_access_type(unsigned long addr, unsigned long size)
|
||||
{
|
||||
|
@ -374,17 +420,11 @@ int bfin_mem_access_type(unsigned long addr, unsigned long size)
|
|||
if (addr >= SYSMMR_BASE)
|
||||
return BFIN_MEM_ACCESS_CORE_ONLY;
|
||||
|
||||
/* 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);
|
||||
if (in_mem_const(addr, size, ASYNC_BANK1_BASE, ASYNC_BANK1_SIZE))
|
||||
return IN_ASYNC(1, 0);
|
||||
if (in_mem_const(addr, size, ASYNC_BANK2_BASE, ASYNC_BANK2_SIZE))
|
||||
return IN_ASYNC(2, 1);
|
||||
if (in_mem_const(addr, size, ASYNC_BANK3_BASE, ASYNC_BANK3_SIZE))
|
||||
return IN_ASYNC(3, 1);
|
||||
switch (in_async(addr, size)) {
|
||||
case 0: return -EFAULT;
|
||||
case 1: return BFIN_MEM_ACCESS_CORE;
|
||||
case 2: /* fall through */;
|
||||
}
|
||||
|
||||
if (in_mem_const(addr, size, BOOT_ROM_START, BOOT_ROM_LENGTH))
|
||||
return BFIN_MEM_ACCESS_CORE;
|
||||
|
@ -401,6 +441,8 @@ __attribute__((l1_text))
|
|||
/* Return 1 if access to memory range is OK, 0 otherwise */
|
||||
int _access_ok(unsigned long addr, unsigned long size)
|
||||
{
|
||||
int aret;
|
||||
|
||||
if (size == 0)
|
||||
return 1;
|
||||
/* Check that things do not wrap around */
|
||||
|
@ -450,6 +492,11 @@ int _access_ok(unsigned long addr, unsigned long size)
|
|||
if (in_mem_const(addr, size, COREB_L1_DATA_B_START, COREB_L1_DATA_B_LENGTH))
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
aret = in_async(addr, size);
|
||||
if (aret < 2)
|
||||
return aret;
|
||||
|
||||
if (in_mem_const_off(addr, size, _ebss_l2 - _stext_l2, L2_START, L2_LENGTH))
|
||||
return 1;
|
||||
|
||||
|
|
Loading…
Reference in a new issue