diff options
author | Ed Nash <enash54@gmail.com> | 2013-07-29 21:01:35 -0400 |
---|---|---|
committer | Ed Nash <enash54@gmail.com> | 2013-07-29 21:01:35 -0400 |
commit | 614660a165ac827ea272c6fa0c59986881309f90 (patch) | |
tree | b745d05e167c8791a4564413c839de00048c3151 | |
parent | 08757351fb4e55f6b8ed0f1a6e9b11329c6daedb (diff) |
add support for spin locks
-rw-r--r-- | arch/arm/mach-mvf/mvf_sema4.c | 72 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-imx.c | 4 | ||||
-rw-r--r-- | include/linux/mvf_sema4.h | 5 |
3 files changed, 45 insertions, 36 deletions
diff --git a/arch/arm/mach-mvf/mvf_sema4.c b/arch/arm/mach-mvf/mvf_sema4.c index aa354c33de4d..31e40f6d02f0 100644 --- a/arch/arm/mach-mvf/mvf_sema4.c +++ b/arch/arm/mach-mvf/mvf_sema4.c @@ -71,12 +71,12 @@ static irqreturn_t sema4_irq_handler(int irq, void *dev_id) // make sure there's a gate assigned if(gates[gate_num]) { - if(gates[gate_num]->use_interrupts) { + //if(gates[gate_num]->use_interrupts) { // wake up whoever was aiting wake_up_interruptible(&(gates[gate_num]->wait_queue)); // bump stats gates[gate_num]->interrupts++; - } + //} } } } @@ -111,7 +111,7 @@ static int initialize(void) return 0; } -int mvf_sema4_assign(int gate_num, bool use_interrupts, MVF_SEMA4** sema4_p) +int mvf_sema4_assign(int gate_num, MVF_SEMA4** sema4_p) { int retval; u32 cp0ine; @@ -140,17 +140,13 @@ int mvf_sema4_assign(int gate_num, bool use_interrupts, MVF_SEMA4** sema4_p) gates[gate_num] = *sema4_p; (*sema4_p)->gate_num = gate_num; - (*sema4_p)->use_interrupts = use_interrupts; - if(use_interrupts) - { - init_waitqueue_head(&((*sema4_p)->wait_queue)); - local_irq_save(irq_flags); - cp0ine = readl(MVF_IO_ADDRESS(SEMA4_CP0INE)); - cp0ine |= MASK_FROM_GATE(gate_num); - writel(cp0ine, MVF_IO_ADDRESS(SEMA4_CP0INE)); - local_irq_restore(irq_flags); - } + init_waitqueue_head(&((*sema4_p)->wait_queue)); + local_irq_save(irq_flags); + cp0ine = readl(MVF_IO_ADDRESS(SEMA4_CP0INE)); + cp0ine |= MASK_FROM_GATE(gate_num); + writel(cp0ine, MVF_IO_ADDRESS(SEMA4_CP0INE)); + local_irq_restore(irq_flags); // debugfs sprintf(debugfs_gatedir_name, "%d", gate_num); @@ -175,14 +171,11 @@ int mvf_sema4_deassign(MVF_SEMA4 *sema4) return -EINVAL; gate_num = sema4->gate_num; - if(sema4->use_interrupts) - { - local_irq_save(irq_flags); - cp0ine = readl(MVF_IO_ADDRESS(SEMA4_CP0INE)); - cp0ine &= ~MASK_FROM_GATE(gate_num); - writel(cp0ine, MVF_IO_ADDRESS(SEMA4_CP0INE)); - local_irq_restore(irq_flags); - } + local_irq_save(irq_flags); + cp0ine = readl(MVF_IO_ADDRESS(SEMA4_CP0INE)); + cp0ine &= ~MASK_FROM_GATE(gate_num); + writel(cp0ine, MVF_IO_ADDRESS(SEMA4_CP0INE)); + local_irq_restore(irq_flags); kfree(sema4); gates[gate_num] = NULL; @@ -191,21 +184,28 @@ int mvf_sema4_deassign(MVF_SEMA4 *sema4) } EXPORT_SYMBOL(mvf_sema4_deassign); -static void add_latency_stat(MVF_SEMA4 *sema4) { +static long delta_time(struct timeval *start) { struct timeval now; - long latency; + long now_us, start_us; do_gettimeofday(&now); - latency = (now.tv_sec * 1000000) + now.tv_usec; - latency -= (sema4->request_time.tv_sec * 1000000) + sema4->request_time.tv_usec; + now_us = (now.tv_sec * 1000000) + now.tv_usec; + start_us = (start->tv_sec * 1000000) + start->tv_usec; + + return now_us > start_us ? now_us - start_us : 0; +} + +static void add_latency_stat(MVF_SEMA4 *sema4) { + + long latency = delta_time(&sema4->request_time); sema4->total_latency_us += latency; sema4->worst_latency_us = sema4->worst_latency_us < latency ? latency : sema4->worst_latency_us; } -int mvf_sema4_lock(MVF_SEMA4 *sema4, unsigned int timeout_us) +int mvf_sema4_lock(MVF_SEMA4 *sema4, unsigned int timeout_us, bool use_interrupts) { int retval; int gate_num; @@ -213,11 +213,6 @@ int mvf_sema4_lock(MVF_SEMA4 *sema4, unsigned int timeout_us) return -EINVAL; gate_num = sema4->gate_num; - // cant use timeouts if not using interruppts - // TODO use spin lock if not using interrupts - if((!sema4->use_interrupts) && timeout_us) - return -EINVAL; - // bump stats gates[gate_num]->attempts++; do_gettimeofday(&gates[gate_num]->request_time); @@ -235,6 +230,21 @@ int mvf_sema4_lock(MVF_SEMA4 *sema4, unsigned int timeout_us) return -EBUSY; } + // spin lock? + if(!use_interrupts) { + while(readb(MVF_IO_ADDRESS(MVF_SEMA4_BASE_ADDR) + gate_num) != LOCK_VALUE) { + + if((timeout_us != 0xffffffff) && (delta_time(&gates[gate_num]->request_time) > timeout_us)) { + gates[gate_num]->failures++; + return -EBUSY; + } + + writeb(LOCK_VALUE, MVF_IO_ADDRESS(MVF_SEMA4_BASE_ADDR) + gate_num); + } + add_latency_stat(gates[gate_num]); + return 0; + } + // wait forever? if(timeout_us == 0xffffffff) { diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index a2e6d2aa16b3..e13e020cab2e 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -439,7 +439,7 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); #ifdef CONFIG_ARCH_MVF - result = mvf_sema4_lock(sema4, 10000000); + result = mvf_sema4_lock(sema4, 10000000, true); if(result) return result; #endif @@ -621,7 +621,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev) #ifdef CONFIG_ARCH_MVF // for makeing sure not in use by MQX concurrently - if(mvf_sema4_assign(MVF_I2C_SEMAPHORE_NUMBER, true, &sema4)) { + if(mvf_sema4_assign(MVF_I2C_SEMAPHORE_NUMBER, &sema4)) { dev_err(&pdev->dev, "could not assign MQX semaphore %d\n", MVF_I2C_SEMAPHORE_NUMBER); goto fail5; } diff --git a/include/linux/mvf_sema4.h b/include/linux/mvf_sema4.h index 7b25996f9417..aa2379a9de05 100644 --- a/include/linux/mvf_sema4.h +++ b/include/linux/mvf_sema4.h @@ -11,7 +11,6 @@ typedef struct mvf_sema4_handle_struct { int gate_num; - int use_interrupts; wait_queue_head_t wait_queue; // stats u32 attempts; @@ -22,9 +21,9 @@ typedef struct mvf_sema4_handle_struct { u32 worst_latency_us; } MVF_SEMA4; -int mvf_sema4_assign(int gate_num, bool use_interrupts, MVF_SEMA4** sema4_p); +int mvf_sema4_assign(int gate_num, MVF_SEMA4** sema4_p); int mvf_sema4_deassign(MVF_SEMA4 *sema4); -int mvf_sema4_lock(MVF_SEMA4 *sema4, unsigned int timeout_us); +int mvf_sema4_lock(MVF_SEMA4 *sema4, unsigned int timeout_us, bool use_interrupts); int mvf_sema4_unlock(MVF_SEMA4 *sema4); #endif |