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

Reply via email to