summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEd Nash <enash54@gmail.com>2013-07-29 21:01:35 -0400
committerEd Nash <enash54@gmail.com>2013-07-29 21:01:35 -0400
commit614660a165ac827ea272c6fa0c59986881309f90 (patch)
treeb745d05e167c8791a4564413c839de00048c3151
parent08757351fb4e55f6b8ed0f1a6e9b11329c6daedb (diff)
add support for spin locks
-rw-r--r--arch/arm/mach-mvf/mvf_sema4.c72
-rw-r--r--drivers/i2c/busses/i2c-imx.c4
-rw-r--r--include/linux/mvf_sema4.h5
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