From: Mark Brown <broonie@opensource.wolfsonmicro.com>
To: Samuel Ortiz <sameo@linux.intel.com>
Cc: patches@opensource.wolfsonmicro.com,
linux-kernel@vger.kernel.org,
Mark Brown <broonie@opensource.wolfsonmicro.com>
Subject: [PATCH 1/9] mfd: Fix bus lock interaction for WM831x IRQ set_type() operation
Date: Thu, 2 Jun 2011 19:18:47 +0100 [thread overview]
Message-ID: <1307038735-18788-1-git-send-email-broonie@opensource.wolfsonmicro.com> (raw)
In-Reply-To: <20110602181808.GA18726@opensource.wolfsonmicro.com>
The WM831x IRQ set_type() operation is doing a direct register write when
called but since set_type() is called with the bus lock held this isn't
legal and could cause deadlocks in the IRQ core.
Fix this by posting the updates into an array and syncing in the
bus_sync_unlock() callback.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
---
drivers/mfd/wm831x-irq.c | 24 ++++++++++++++++++------
include/linux/mfd/wm831x/core.h | 4 ++++
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c
index 42b928e..b23d8d5 100644
--- a/drivers/mfd/wm831x-irq.c
+++ b/drivers/mfd/wm831x-irq.c
@@ -348,6 +348,15 @@ static void wm831x_irq_sync_unlock(struct irq_data *data)
struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
int i;
+ for (i = 0; i < ARRAY_SIZE(wm831x->gpio_update); i++) {
+ if (wm831x->gpio_update[i]) {
+ wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + i,
+ WM831X_GPN_INT_MODE | WM831X_GPN_POL,
+ wm831x->gpio_update[i]);
+ wm831x->gpio_update[i] = 0;
+ }
+ }
+
for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) {
/* If there's been a change in the mask write it back
* to the hardware. */
@@ -387,7 +396,7 @@ static void wm831x_irq_disable(struct irq_data *data)
static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
{
struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
- int val, irq;
+ int irq;
irq = data->irq - wm831x->irq_base;
@@ -399,22 +408,25 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
return -EINVAL;
}
+ /* We set the high bit to flag that we need an update; don't
+ * do the update here as we can be called with the bus lock
+ * held.
+ */
switch (type) {
case IRQ_TYPE_EDGE_BOTH:
- val = WM831X_GPN_INT_MODE;
+ wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_INT_MODE;
break;
case IRQ_TYPE_EDGE_RISING:
- val = WM831X_GPN_POL;
+ wm831x->gpio_update[irq] = 0x10000 | WM831X_GPN_POL;
break;
case IRQ_TYPE_EDGE_FALLING:
- val = 0;
+ wm831x->gpio_update[irq] = 0x10000;
break;
default:
return -EINVAL;
}
- return wm831x_set_bits(wm831x, WM831X_GPIO1_CONTROL + irq,
- WM831X_GPN_INT_MODE | WM831X_GPN_POL, val);
+ return 0;
}
static struct irq_chip wm831x_irq_chip = {
diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h
index 0d515ee..ebead1c 100644
--- a/include/linux/mfd/wm831x/core.h
+++ b/include/linux/mfd/wm831x/core.h
@@ -237,6 +237,7 @@
struct regulator_dev;
#define WM831X_NUM_IRQ_REGS 5
+#define WM831X_NUM_GPIO_REGS 16
enum wm831x_parent {
WM8310 = 0x8310,
@@ -272,6 +273,9 @@ struct wm831x {
int num_gpio;
+ /* Used by the interrupt controller code to post writes */
+ int gpio_update[WM831X_NUM_GPIO_REGS];
+
struct mutex auxadc_lock;
struct completion auxadc_done;
--
1.7.5.3
next prev parent reply other threads:[~2011-06-02 18:20 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-02 18:18 [PATCH 0/9] Pending Wolfson patches Mark Brown
2011-06-02 18:18 ` Mark Brown [this message]
2011-06-02 18:18 ` [PATCH 2/9] mfd: Implement support for multiple WM831x devices Mark Brown
2011-06-02 18:18 ` [PATCH 3/9] mfd: Allow touchscreen to be disabled on wm831x devices Mark Brown
2011-06-02 18:18 ` [PATCH 4/9] mfd: Only register wm831x RTC device if the 32.768kHz crystal is enabled Mark Brown
2011-06-02 18:18 ` [PATCH 5/9] mfd: Support dynamic allocation of IRQ range for wm831x Mark Brown
2011-06-02 18:18 ` [PATCH 6/9] mfd: Read wm831x AUXADC conversion results before acknowledging interrupt Mark Brown
2011-06-02 18:18 ` [PATCH 7/9] mfd: Refactor wm831x AUXADC handling into a separate file Mark Brown
2011-06-02 18:18 ` [PATCH 8/9] mfd: Allocate wm835x irq descs dynamically Mark Brown
2011-06-02 18:18 ` [PATCH 9/9] mfd: Restructure wm8994-core device revision handling Mark Brown
2011-06-20 10:13 ` [PATCH 0/9] Pending Wolfson patches Samuel Ortiz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1307038735-18788-1-git-send-email-broonie@opensource.wolfsonmicro.com \
--to=broonie@opensource.wolfsonmicro.com \
--cc=linux-kernel@vger.kernel.org \
--cc=patches@opensource.wolfsonmicro.com \
--cc=sameo@linux.intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome