summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-08-18 04:59:14 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-08-18 04:59:14 -0700
commitb2397d388fe2ae309be1782dbe9759d634a3e2a3 (patch)
tree18d6364ac37f1f635b32f911ddd01431184bd786
parent559e948c14bc8f1aae8a9e9a845e7fc653f8c3c7 (diff)
parent6f13460739a5815ae437a00e628758d365300b98 (diff)
Merge "NFC: Fix unbalanced irq warning stack trace"
-rw-r--r--drivers/nfc/nq-nci.c46
1 files changed, 32 insertions, 14 deletions
diff --git a/drivers/nfc/nq-nci.c b/drivers/nfc/nq-nci.c
index 9b962a63c3d8..154310020997 100644
--- a/drivers/nfc/nq-nci.c
+++ b/drivers/nfc/nq-nci.c
@@ -63,6 +63,8 @@ struct nqx_dev {
bool nfc_ven_enabled;
/* NFC_IRQ state */
bool irq_enabled;
+ /* NFC_IRQ wake-up state */
+ bool irq_wake_up;
spinlock_t irq_enabled_lock;
unsigned int count_irq;
/* Initial CORE RESET notification */
@@ -372,6 +374,9 @@ int nfc_ioctl_power_states(struct file *filp, unsigned long arg)
} else {
dev_dbg(&nqx_dev->client->dev, "keeping en_gpio high\n");
}
+ } else {
+ dev_dbg(&nqx_dev->client->dev, "ese_gpio invalid, set en_gpio to low\n");
+ gpio_set_value(nqx_dev->en_gpio, 0);
}
r = nqx_clock_deselect(nqx_dev);
if (r < 0)
@@ -777,21 +782,29 @@ static int nqx_probe(struct i2c_client *client,
r = gpio_request(platform_data->ese_gpio,
"nfc-ese_pwr");
if (r) {
+ nqx_dev->ese_gpio = -EINVAL;
dev_err(&client->dev,
"%s: unable to request nfc ese gpio [%d]\n",
__func__, platform_data->ese_gpio);
/* ese gpio optional so we should continue */
} else {
nqx_dev->ese_gpio = platform_data->ese_gpio;
- }
- r = gpio_direction_output(platform_data->ese_gpio, 0);
- if (r) {
- dev_err(&client->dev,
- "%s: cannot set direction for nfc ese gpio [%d]\n",
- __func__, platform_data->ese_gpio);
- /* ese gpio optional so we should continue */
+ r = gpio_direction_output(platform_data->ese_gpio, 0);
+ if (r) {
+ /*
+ * free ese gpio and set invalid
+ * to avoid further use
+ */
+ gpio_free(platform_data->ese_gpio);
+ nqx_dev->ese_gpio = -EINVAL;
+ dev_err(&client->dev,
+ "%s: cannot set direction for nfc ese gpio [%d]\n",
+ __func__, platform_data->ese_gpio);
+ /* ese gpio optional so we should continue */
+ }
}
} else {
+ nqx_dev->ese_gpio = -EINVAL;
dev_err(&client->dev,
"%s: ese gpio not provided\n", __func__);
/* ese gpio optional so we should continue */
@@ -821,7 +834,6 @@ static int nqx_probe(struct i2c_client *client,
nqx_dev->en_gpio = platform_data->en_gpio;
nqx_dev->irq_gpio = platform_data->irq_gpio;
nqx_dev->firm_gpio = platform_data->firm_gpio;
- nqx_dev->ese_gpio = platform_data->ese_gpio;
nqx_dev->clkreq_gpio = platform_data->clkreq_gpio;
nqx_dev->pdata = platform_data;
@@ -889,6 +901,7 @@ static int nqx_probe(struct i2c_client *client,
device_init_wakeup(&client->dev, true);
device_set_wakeup_capable(&client->dev, true);
i2c_set_clientdata(client, nqx_dev);
+ nqx_dev->irq_wake_up = false;
dev_err(&client->dev,
"%s: probing NFCC NQxxx exited successfully\n",
@@ -909,7 +922,7 @@ err_clkreq_gpio:
gpio_free(platform_data->clkreq_gpio);
err_ese_gpio:
/* optional gpio, not sure was configured in probe */
- if (nqx_dev->ese_gpio)
+ if (nqx_dev->ese_gpio > 0)
gpio_free(platform_data->ese_gpio);
err_firm_gpio:
gpio_free(platform_data->firm_gpio);
@@ -950,7 +963,7 @@ static int nqx_remove(struct i2c_client *client)
mutex_destroy(&nqx_dev->read_mutex);
gpio_free(nqx_dev->clkreq_gpio);
/* optional gpio, not sure was configured in probe */
- if (nqx_dev->ese_gpio)
+ if (nqx_dev->ese_gpio > 0)
gpio_free(nqx_dev->ese_gpio);
gpio_free(nqx_dev->firm_gpio);
gpio_free(nqx_dev->irq_gpio);
@@ -969,17 +982,22 @@ static int nqx_suspend(struct device *device)
struct i2c_client *client = to_i2c_client(device);
struct nqx_dev *nqx_dev = i2c_get_clientdata(client);
- if (device_may_wakeup(&client->dev) && nqx_dev->irq_enabled)
- enable_irq_wake(client->irq);
+ if (device_may_wakeup(&client->dev) && nqx_dev->irq_enabled) {
+ if (!enable_irq_wake(client->irq))
+ nqx_dev->irq_wake_up = true;
+ }
return 0;
}
static int nqx_resume(struct device *device)
{
struct i2c_client *client = to_i2c_client(device);
+ struct nqx_dev *nqx_dev = i2c_get_clientdata(client);
- if (device_may_wakeup(&client->dev))
- disable_irq_wake(client->irq);
+ if (device_may_wakeup(&client->dev) && nqx_dev->irq_wake_up) {
+ if (!disable_irq_wake(client->irq))
+ nqx_dev->irq_wake_up = false;
+ }
return 0;
}