[linux-yocto] [PATCH 10/52] arch/arm/mach-axxia: Check Status and Add Locks to NCR Accesses
Daniel Dragomir
daniel.dragomir at windriver.com
Wed Jan 28 09:18:24 PST 2015
From: John Jacques <john.jacques at lsi.com>
When the Preempt-RT patch is applied, and configured for full
preemption, spin_lock* are preemptible. Using the raw variant prevents
preemption in that case.
Signed-off-by: John Jacques <john.jacques at lsi.com>
---
arch/arm/mach-axxia/ncr.c | 73 +++++++++++++++++++++++++++++++++++++++++------
1 file changed, 64 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-axxia/ncr.c b/arch/arm/mach-axxia/ncr.c
index 51fcf66..995e8a0 100644
--- a/arch/arm/mach-axxia/ncr.c
+++ b/arch/arm/mach-axxia/ncr.c
@@ -40,6 +40,9 @@ static void __iomem *apb2ser0_address;
#define WFC_TIMEOUT (400000)
+static DEFINE_RAW_SPINLOCK(ncr_spin_lock);
+static unsigned long flags;
+
#define LOCK_DOMAIN 0
typedef union {
@@ -170,15 +173,48 @@ ncr_lock(int domain)
unsigned long offset;
unsigned long value;
int loops = 10000;
+ command_data_register_0_t cdr0;
+ raw_spin_lock_irqsave(&ncr_spin_lock, flags);
offset = (0xff80 + (domain * 4));
do {
value = ncr_register_read((unsigned *)(nca_address + offset));
} while ((0 != value) && (0 < --loops));
- if (0 == loops)
+ if (0 == loops) {
+ raw_spin_unlock_irqrestore(&ncr_spin_lock, flags);
+ printk(KERN_ERR "ncr_lock() Timeout!\n");
+ BUG();
+
+ return -1;
+ }
+
+ /*
+ Make sure any previous commands completed, and check for errors.
+ */
+
+ loops = 10000;
+
+ do {
+ --loops;
+ cdr0.raw =
+ ncr_register_read((unsigned *)(nca_address + 0xf0));
+ } while ((0x1 == cdr0.bits.status) &&
+ (0 < loops));
+
+ if (0 == loops) {
+ raw_spin_unlock_irqrestore(&ncr_spin_lock, flags);
+ printk(KERN_ERR
+ "ncr_lock() Previous command didn't complete!\n");
+ BUG();
+
return -1;
+ }
+
+ if (0x2 == cdr0.bits.status) {
+ printk(KERN_ERR "Previous ncr access failed!\n");
+ }
return 0;
}
@@ -195,6 +231,7 @@ ncr_unlock(int domain)
offset = (0xff80 + (domain * 4));
ncr_register_write(0, (unsigned *)(nca_address + offset));
+ raw_spin_unlock_irqrestore(&ncr_spin_lock, flags);
return;
}
@@ -264,12 +301,24 @@ ncr_read(unsigned long region, unsigned long address, int number,
do {
--wfc_timeout;
- } while ((0x80000000UL ==
- ncr_register_read((unsigned *)(nca_address + 0xf0))) &&
- 0 < wfc_timeout);
+ cdr0.raw =
+ ncr_register_read((unsigned *)
+ (nca_address + 0xf0));
+ } while (1 == cdr0.bits.start_done && 0 < wfc_timeout);
if (0 == wfc_timeout) {
ncr_unlock(LOCK_DOMAIN);
+ printk(KERN_ERR "ncr_read() Timeout!\n");
+ BUG();
+
+ return -1;
+ }
+
+ if (0x3 != cdr0.bits.status) {
+ ncr_unlock(LOCK_DOMAIN);
+ printk(KERN_ERR "ncr_write() failed: 0x%x\n",
+ cdr0.bits.status);
+
return -1;
}
@@ -459,12 +508,16 @@ ncr_write(unsigned long region, unsigned long address, int number,
do {
--wfc_timeout;
- } while ((0x80000000UL ==
- ncr_register_read((unsigned *)(nca_address + 0xf0))) &&
- 0 < wfc_timeout);
+ cdr0.raw =
+ ncr_register_read((unsigned *)
+ (nca_address + 0xf0));
+ } while (1 == cdr0.bits.start_done && 0 < wfc_timeout);
if (0 == wfc_timeout) {
ncr_unlock(LOCK_DOMAIN);
+ printk(KERN_ERR "ncr_write() Timeout!\n");
+ BUG();
+
return -1;
}
@@ -472,13 +525,15 @@ ncr_write(unsigned long region, unsigned long address, int number,
Check status.
*/
- if (0x3 != ((ncr_register_read((unsigned *) (nca_address + 0xf0)) &
- 0x00c00000) >> 22)) {
+ if ((0x3 != cdr0.bits.status) && (0x00c00000) >> 22) {
unsigned long status;
status = ncr_register_read((unsigned *)(nca_address +
0xe4));
ncr_unlock(LOCK_DOMAIN);
+ printk(KERN_ERR
+ "ncr_write() Error: 0x%x 0x%lx\n",
+ cdr0.bits.status, status);
return status;
}
--
1.8.1.4
More information about the linux-yocto
mailing list