From: John Jacques <john.jacq...@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.jacq...@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 -- _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto