Hey,
I'm sitting at the airport, I have seen the latest attachment to #1597 and the
below patch compiles and makes sense. Keep in mind that I'm hungry, can not
think, and that no restaurant is insight until I land in Frankfurt...
comments welcome
z.
From e58348b75db2060bf7079d007cc34d25aa3e35e8 Mon Sep 17 00:00:00 2001
From: Holger Freyther <[EMAIL PROTECTED]>
Date: Fri, 10 Oct 2008 15:43:15 +0200
Subject: [PATCH] [lis302dl] Switch from mutex to spinlock because we have to
https://docs.openmoko.org/trac/attachment/ticket/1597/dmesg-removing-from-wall-charger-pluging-into-desktop-usb
shows a nice mutex message that we might sleep in a mutex which is
forbidden. Switch everything to a spinlock... and as irq's are disabled
everything should be fine. We have done so in the led and vibrator driver
as wel.
Signed-Off-By: Holger Hans Peter Freyther <[EMAIL PROTECTED]>
---
drivers/input/misc/lis302dl.c | 56 +++++++++++++++++++---------------------
include/linux/lis302dl.h | 2 +-
2 files changed, 28 insertions(+), 30 deletions(-)
diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c
index b01ca04..10f6035 100644
--- a/drivers/input/misc/lis302dl.c
+++ b/drivers/input/misc/lis302dl.c
@@ -62,10 +62,11 @@ static u_int8_t __reg_read(struct lis302dl_info *lis, u_int8_t reg)
static u_int8_t reg_read(struct lis302dl_info *lis, u_int8_t reg)
{
u_int8_t ret;
+ unsigned long flags;
- mutex_lock(&lis->lock);
+ spin_lock_irqsave(&lis->lock, flags);
ret = __reg_read(lis, reg);
- mutex_unlock(&lis->lock);
+ spin_unlock_irqrestore(&lis->lock, flags);
return ret;
}
@@ -85,10 +86,11 @@ static int __reg_write(struct lis302dl_info *lis, u_int8_t reg, u_int8_t val)
static int reg_write(struct lis302dl_info *lis, u_int8_t reg, u_int8_t val)
{
int ret;
+ unsigned long flags;
- mutex_lock(&lis->lock);
+ spin_lock_irqsave(&lis->lock, flags);
ret = __reg_write(lis, reg, val);
- mutex_unlock(&lis->lock);
+ spin_unlock_irqrestore(&lis->lock, flags);
return ret;
}
@@ -98,17 +100,18 @@ static int reg_set_bit_mask(struct lis302dl_info *lis,
{
int ret;
u_int8_t tmp;
+ unsigned long flags;
val &= mask;
- mutex_lock(&lis->lock);
+ spin_lock_irqsave(&lis->lock, flags);
tmp = __reg_read(lis, reg);
tmp &= ~mask;
tmp |= val;
ret = __reg_write(lis, reg, tmp);
- mutex_unlock(&lis->lock);
+ spin_unlock_irqrestore(&lis->lock, flags);
return ret;
}
@@ -230,12 +233,12 @@ static ssize_t lis302dl_dump(struct device *dev, struct device_attribute *attr,
char *end = buf;
unsigned long flags;
- local_irq_save(flags);
+ spin_lock_irqsave(&lis->lock, flags);
for (n = 0; n < sizeof(reg); n++)
reg[n] = reg_read(lis, n);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&lis->lock, flags);
for (n = 0; n < sizeof(reg); n += 16) {
hex_dump_to_buffer(reg + n, 16, 16, 1, end, 128, 0);
@@ -312,7 +315,7 @@ static ssize_t set_freefall_common(int which, struct device *dev,
/* Parse the input */
if (strcmp(buf, "0\n") == 0) {
/* Turn off the interrupt */
- local_irq_save(flags);
+ spin_lock_irqsave(&lis->lock, flags);
if (lis->flags & LIS302DL_F_IRQ_WAKE)
disable_irq_wake(lis->spi_dev->irq);
lis302dl_int_mode(lis->spi_dev, which,
@@ -328,7 +331,7 @@ static ssize_t set_freefall_common(int which, struct device *dev,
reg_set_bit_mask(lis, LIS302DL_REG_CTRL1,
LIS302DL_CTRL1_PD, 0);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&lis->lock, flags);
return count;
}
@@ -354,7 +357,7 @@ static ssize_t set_freefall_common(int which, struct device *dev,
z_hi = z > 0 ? LIS302DL_FFWUCFG_ZHIE : 0;
/* Setup the configuration registers */
- local_irq_save(flags);
+ spin_lock_irqsave(&lis->lock, flags);
reg_write(lis, r_cfg, 0); /* First zero to get to a known state */
reg_write(lis, r_cfg,
(and_events ? LIS302DL_FFWUCFG_AOI : 0) |
@@ -373,7 +376,7 @@ static ssize_t set_freefall_common(int which, struct device *dev,
lis->flags |= flag_mask | LIS302DL_F_IRQ_WAKE;
reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD,
LIS302DL_CTRL1_PD);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&lis->lock, flags);
return count;
}
@@ -476,13 +479,9 @@ static int lis302dl_input_open(struct input_dev *inp)
struct lis302dl_info *lis = inp->private;
u_int8_t ctrl1 = LIS302DL_CTRL1_PD | LIS302DL_CTRL1_Xen |
LIS302DL_CTRL1_Yen | LIS302DL_CTRL1_Zen;
- unsigned long flags;
- local_irq_save(flags);
/* make sure we're powered up and generate data ready */
reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, ctrl1);
- local_irq_restore(flags);
-
lis->flags |= LIS302DL_F_INPUT_OPEN;
/* kick it off -- since we are edge triggered, if we missed the edge
@@ -499,7 +498,7 @@ static void lis302dl_input_close(struct input_dev *inp)
LIS302DL_CTRL1_Zen;
unsigned long flags;
- local_irq_save(flags);
+ spin_lock_irqsave(&lis->lock, flags);
/* since the input core already serializes access and makes sure we
* only see close() for the close of the last user, we can safely
@@ -513,7 +512,7 @@ static void lis302dl_input_close(struct input_dev *inp)
reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD,
0x00);
}
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&lis->lock, flags);
}
/* get the device to reload its coefficients from EEPROM and wait for it
@@ -546,9 +545,8 @@ static int __devinit lis302dl_probe(struct spi_device *spi)
if (!lis)
return -ENOMEM;
- local_irq_save(flags);
-
- mutex_init(&lis->lock);
+ spin_lock_init(&lis->lock);
+ spin_lock_irqsave(&lis->lock, flags);
lis->spi_dev = spi;
spi_set_drvdata(spi, lis);
@@ -654,7 +652,7 @@ static int __devinit lis302dl_probe(struct spi_device *spi)
lis->spi_dev->irq);
goto bail_inp_reg;
}
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&lis->lock, flags);
return 0;
bail_inp_reg:
@@ -665,7 +663,7 @@ bail_sysfs:
sysfs_remove_group(&spi->dev.kobj, &lis302dl_attr_group);
bail_free_lis:
kfree(lis);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&lis->lock, flags);
return rc;
}
@@ -675,11 +673,11 @@ static int __devexit lis302dl_remove(struct spi_device *spi)
unsigned long flags;
/* Reset and power down the device */
- local_irq_save(flags);
+ spin_lock_irqsave(&lis->lock, flags);
reg_write(lis, LIS302DL_REG_CTRL3, 0x00);
reg_write(lis, LIS302DL_REG_CTRL2, 0x00);
reg_write(lis, LIS302DL_REG_CTRL1, 0x00);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&lis->lock, flags);
/* Cleanup resources */
free_irq(lis->spi_dev->irq, lis);
@@ -706,7 +704,7 @@ static int lis302dl_suspend(struct spi_device *spi, pm_message_t state)
return 0;
disable_irq(lis->spi_dev->irq);
- local_irq_save(flags);
+ spin_lock_irqsave(&lis->lock, flags);
/*
* When we share SPI over multiple sensors, there is a race here
@@ -754,7 +752,7 @@ static int lis302dl_suspend(struct spi_device *spi, pm_message_t state)
/* place our IO to the device in sleep-compatible states */
(lis->pdata->lis302dl_suspend_io)(lis, 0);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&lis->lock, flags);
return 0;
}
@@ -768,7 +766,7 @@ static int lis302dl_resume(struct spi_device *spi)
lis->flags & LIS302DL_F_WUP_CLICK)
return 0;
- local_irq_save(flags);
+ spin_lock_irqsave(&lis->lock, flags);
/* get our IO to the device back in operational states */
(lis->pdata->lis302dl_suspend_io)(lis, 1);
@@ -816,7 +814,7 @@ static int lis302dl_resume(struct spi_device *spi)
reg_write(lis, LIS302DL_REG_CLICK_WINDOW,
lis->regs[LIS302DL_REG_CLICK_WINDOW]);
- local_irq_restore(flags);
+ spin_unlock_irqrestore(&lis->lock, flags);
enable_irq(lis->spi_dev->irq);
return 0;
diff --git a/include/linux/lis302dl.h b/include/linux/lis302dl.h
index 7daa8b3..c3ecbb7 100644
--- a/include/linux/lis302dl.h
+++ b/include/linux/lis302dl.h
@@ -23,7 +23,7 @@ struct lis302dl_info {
struct lis302dl_platform_data *pdata;
struct spi_device *spi_dev;
struct input_dev *input_dev;
- struct mutex lock;
+ spinlock_t lock;
unsigned int flags;
u_int8_t regs[0x40];
};
--
1.5.4.3