diff --git a/nfc/common.c b/nfc/common.c index 30231f8c37..094eb40c81 100644 --- a/nfc/common.c +++ b/nfc/common.c @@ -224,7 +224,8 @@ int nfc_misc_register(struct nfc_dev *nfc_dev, * Device power control. Depending on the arg value, device moves to * different states, refer common.h for args * - * Return: -ENOIOCTLCMD if arg is not supported, 0 in any other case + * Return: -ENOIOCTLCMD if arg is not supported, 0 if Success(or no issue) + * and error ret code otherwise */ static int nfc_ioctl_power_states(struct nfc_dev *nfc_dev, unsigned long arg) { @@ -293,7 +294,10 @@ static int nfc_ioctl_power_states(struct nfc_dev *nfc_dev, unsigned long arg) * * NFC and ESE Device power control, based on the argument value * - * Return: -ENOIOCTLCMD if arg is not supported, 0 or other in any other case + * Return: -ENOIOCTLCMD if arg is not supported + * 0 if Success(or no issue) + * 0 or 1 in case of arg is ESE_GET_PWR/ESE_POWER_STATE + * and error ret code otherwise */ long nfc_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg) { @@ -323,8 +327,8 @@ long nfc_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg) int nfc_dev_open(struct inode *inode, struct file *filp) { - struct nfc_dev *nfc_dev = - container_of(inode->i_cdev, struct nfc_dev, c_dev); + struct nfc_dev *nfc_dev = NULL; + nfc_dev = container_of(inode->i_cdev, struct nfc_dev, c_dev); if (!nfc_dev) return -ENODEV; @@ -345,10 +349,33 @@ int nfc_dev_open(struct inode *inode, struct file *filp) return 0; } +int nfc_dev_flush(struct file *pfile, fl_owner_t id) +{ + struct nfc_dev *nfc_dev = pfile->private_data; + + if (!nfc_dev) + return -ENODEV; + /* + * release blocked user thread waiting for pending read during close + */ + if (!mutex_trylock(&nfc_dev->read_mutex)) { + nfc_dev->release_read = true; + nfc_dev->nfc_disable_intr(nfc_dev); + wake_up(&nfc_dev->read_wq); + pr_debug("%s: waiting for release of blocked read\n", __func__); + mutex_lock(&nfc_dev->read_mutex); + nfc_dev->release_read = false; + } else { + pr_debug("%s: read thread already released\n", __func__); + } + mutex_unlock(&nfc_dev->read_mutex); + return 0; +} + int nfc_dev_close(struct inode *inode, struct file *filp) { - struct nfc_dev *nfc_dev = - container_of(inode->i_cdev, struct nfc_dev, c_dev); + struct nfc_dev *nfc_dev = NULL; + nfc_dev = container_of(inode->i_cdev, struct nfc_dev, c_dev); if (!nfc_dev) return -ENODEV; diff --git a/nfc/common.h b/nfc/common.h index c96958fe3a..c4f3388ad7 100644 --- a/nfc/common.h +++ b/nfc/common.h @@ -177,6 +177,7 @@ struct nfc_dev { uint8_t nfc_state; /* NFC VEN pin state */ bool nfc_ven_enabled; + bool release_read; union { struct i2c_dev i2c_dev; }; @@ -193,6 +194,7 @@ struct nfc_dev { }; int nfc_dev_open(struct inode *inode, struct file *filp); +int nfc_dev_flush(struct file *pfile, fl_owner_t id); int nfc_dev_close(struct inode *inode, struct file *filp); long nfc_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg); int nfc_parse_dt(struct device *dev, struct platform_configs *nfc_configs, diff --git a/nfc/common_ese.c b/nfc/common_ese.c index 18b3d34e1f..0abfc1a0c1 100644 --- a/nfc/common_ese.c +++ b/nfc/common_ese.c @@ -261,7 +261,10 @@ err: * Device power control. Depending on the arg value, device moves to * different states, refer common_ese.h for args * - * Return: -ENOIOCTLCMD if arg is not supported, 0 in any other case + * Return: -ENOIOCTLCMD if arg is not supported + * 0 if Success(or no issue) + * 0 or 1 in case of arg is ESE_POWER_STATE + * and error ret code otherwise */ int nfc_ese_pwr(struct nfc_dev *nfc_dev, unsigned long arg) { diff --git a/nfc/i2c_drv.c b/nfc/i2c_drv.c index 83a1ed5d9e..381ae3811b 100644 --- a/nfc/i2c_drv.c +++ b/nfc/i2c_drv.c @@ -128,7 +128,6 @@ int i2c_read(struct nfc_dev *nfc_dev, char *buf, size_t count, int timeout) nfc_dev->read_wq, !i2c_dev->irq_enabled, msecs_to_jiffies(timeout)); - if (ret <= 0) { pr_err("%s: timeout error\n", __func__); @@ -154,6 +153,18 @@ int i2c_read(struct nfc_dev *nfc_dev, char *buf, size_t count, int timeout) ret = -EIO; goto err; } + /* + * NFC service wanted to close the driver so, + * release the calling reader thread asap. + * + * This can happen in case of nfc node close call from + * eSE HAL in that case the NFC HAL reader thread + * will again call read system call + */ + if (nfc_dev->release_read) { + pr_debug("%s: releasing read\n", __func__); + return 0; + } pr_warn("%s: spurious interrupt detected\n", __func__); } } @@ -218,7 +229,7 @@ int i2c_write(struct nfc_dev *nfc_dev, const char *buf, size_t count, break; } if (retry_cnt == MAX_WRITE_IRQ_COUNT && - gpio_get_value(nfc_gpio->irq)) { + gpio_get_value(nfc_gpio->irq)) { pr_warn("%s: allow after maximum wait\n", __func__); } } @@ -287,6 +298,7 @@ static const struct file_operations nfc_i2c_dev_fops = { .read = nfc_i2c_dev_read, .write = nfc_i2c_dev_write, .open = nfc_dev_open, + .flush = nfc_dev_flush, .release = nfc_dev_close, .unlocked_ioctl = nfc_dev_ioctl, };