diff --git a/nfc/common.c b/nfc/common.c index 5b47e373c3..5425efa6d3 100644 --- a/nfc/common.c +++ b/nfc/common.c @@ -127,7 +127,7 @@ int configure_gpio(unsigned int gpio, int flag) if (ret) { pr_err("%s: unable to set direction for nfc gpio [%d]\n", - __func__, gpio); + __func__, gpio); gpio_free(gpio); return ret; } @@ -301,10 +301,11 @@ static int nfc_ioctl_power_states(struct nfc_dev *nfc_dev, unsigned long arg) * and error ret code otherwise */ long nfc_dev_compat_ioctl(struct file *pfile, unsigned int cmd, - unsigned long arg) + unsigned long arg) { int ret = 0; - arg = (compat_u64)arg; + + arg = (compat_u64) arg; pr_debug("%s: cmd = %x arg = %zx\n", __func__, cmd, arg); ret = nfc_dev_ioctl(pfile, cmd, arg); return ret; @@ -337,6 +338,19 @@ long nfc_dev_ioctl(struct file *pfile, unsigned int cmd, unsigned long arg) case NFC_SET_PWR: ret = nfc_ioctl_power_states(nfc_dev, arg); break; + case NFC_SET_RESET_READ_PENDING: + if (arg == NFC_SET_READ_PENDING) { + nfc_dev->cold_reset.is_nfc_read_pending = true; + /* Set default NFC state as NCI for Nfc read pending request */ + nfc_dev->nfc_state = NFC_STATE_NCI; + } + else if (arg == NFC_RESET_READ_PENDING){ + nfc_dev->cold_reset.is_nfc_read_pending = false; + } + else { + ret = -EINVAL; + } + break; case ESE_SET_PWR: ret = nfc_ese_pwr(nfc_dev, arg); break; @@ -353,6 +367,7 @@ 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 = NULL; + nfc_dev = container_of(inode->i_cdev, struct nfc_dev, c_dev); if (!nfc_dev) @@ -400,6 +415,7 @@ int nfc_dev_flush(struct file *pfile, fl_owner_t id) int nfc_dev_close(struct inode *inode, struct file *filp) { struct nfc_dev *nfc_dev = NULL; + nfc_dev = container_of(inode->i_cdev, struct nfc_dev, c_dev); if (!nfc_dev) @@ -415,7 +431,9 @@ int nfc_dev_close(struct inode *inode, struct file *filp) * if eSE calls flow is via NFC driver * i.e. direct calls from SPI HAL to NFC driver */ + mutex_unlock(&nfc_dev->dev_ref_mutex); nfc_ese_pwr(nfc_dev, ESE_RST_PROT_DIS_NFC); + mutex_lock(&nfc_dev->dev_ref_mutex); } if (nfc_dev->dev_ref_count > 0) nfc_dev->dev_ref_count = nfc_dev->dev_ref_count - 1; diff --git a/nfc/common.h b/nfc/common.h index bd6759a966..2c82394cc0 100644 --- a/nfc/common.h +++ b/nfc/common.h @@ -51,7 +51,6 @@ #define MAX_DL_BUFFER_SIZE (DL_HDR_LEN + DL_CRC_LEN + \ MAX_DL_PAYLOAD_LEN) - /* Retry count for normal write */ #define NO_RETRY (1) /* Maximum retry count for standby writes */ @@ -72,9 +71,10 @@ /* Ioctls */ /* The type should be aligned with MW HAL definitions */ -#define NFC_SET_PWR _IOW(NFC_MAGIC, 0x01, uint32_t) -#define ESE_SET_PWR _IOW(NFC_MAGIC, 0x02, uint32_t) -#define ESE_GET_PWR _IOR(NFC_MAGIC, 0x03, uint32_t) +#define NFC_SET_PWR _IOW(NFC_MAGIC, 0x01, uint32_t) +#define ESE_SET_PWR _IOW(NFC_MAGIC, 0x02, uint32_t) +#define ESE_GET_PWR _IOR(NFC_MAGIC, 0x03, uint32_t) +#define NFC_SET_RESET_READ_PENDING _IOW(NFC_MAGIC, 0x04, uint32_t) #define DTS_IRQ_GPIO_STR "nxp,sn-irq" #define DTS_VEN_GPIO_STR "nxp,sn-ven-rstn" @@ -97,6 +97,11 @@ enum nfcc_ioctl_request { NFC_FW_DWL_LOW, }; +enum nfc_read_pending { + NFC_RESET_READ_PENDING, + NFC_SET_READ_PENDING, +}; + /* nfc platform interface type */ enum interface_flags { /* I2C physical IF for NFCC */ @@ -154,6 +159,7 @@ struct cold_reset { uint8_t rst_prot_src; /* reset protection source (SPI, NFC) */ struct timer_list timer; wait_queue_head_t read_wq; + bool is_nfc_read_pending; }; /* Device specific structure */ @@ -195,7 +201,7 @@ 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_compat_ioctl(struct file *pfile, unsigned int cmd, - unsigned long arg); + unsigned long arg); 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, uint8_t interface); diff --git a/nfc/common_ese.c b/nfc/common_ese.c index 9be98e2445..b67f93d175 100644 --- a/nfc/common_ese.c +++ b/nfc/common_ese.c @@ -56,11 +56,11 @@ static int send_cold_reset_protection_cmd(struct nfc_dev *nfc_dev, *cmd++ = NCI_PROP_MSG_CMD; - if (requestType) { /* reset protection */ + if (requestType) { /* reset protection */ *cmd++ = RST_PROT_OID; *cmd++ = RST_PROT_PAYLOAD_SIZE; *cmd++ = (!cold_reset->reset_protection) ? 1 : 0; - } else { /* cold reset */ + } else { /* cold reset */ *cmd++ = CLD_RST_OID; *cmd++ = CLD_RST_PAYLOAD_SIZE; } @@ -149,6 +149,7 @@ static int perform_cold_reset_protection(struct nfc_dev *nfc_dev, { int ret = 0; int timeout = 0; + int retry_cnt = 0; char *rsp = nfc_dev->read_kbuf; struct cold_reset *cold_reset = &nfc_dev->cold_reset; @@ -203,41 +204,50 @@ static int perform_cold_reset_protection(struct nfc_dev *nfc_dev, } timeout = NCI_CMD_RSP_TIMEOUT_MS; + mutex_lock(&nfc_dev->dev_ref_mutex); do { - /* call read api directly if reader thread is not blocked */ - if (mutex_trylock(&nfc_dev->read_mutex)) { - pr_debug("%s: reader thread not pending\n", __func__); - ret = nfc_dev->nfc_read(nfc_dev, rsp, 3, - timeout); - mutex_unlock(&nfc_dev->read_mutex); + if (nfc_dev->cold_reset.is_nfc_read_pending) { + if (!wait_event_interruptible_timeout + (cold_reset->read_wq, + cold_reset->rsp_pending == false, + msecs_to_jiffies(timeout))) { + pr_err("%s: cold reset/prot response timeout\n", + __func__); + if (retry_cnt <= 1) { + retry_cnt = retry_cnt + 1; + ret = -EAGAIN; + } else { + pr_debug("%s: Maximum retry reached", + __func__); + ret = -ETIMEDOUT; + } + } + } else { + ret = nfc_dev->nfc_read(nfc_dev, rsp, 3, timeout); if (!ret) break; usleep_range(READ_RETRY_WAIT_TIME_US, - READ_RETRY_WAIT_TIME_US + 500); - /* Read pending response form the HAL service */ - } else if (!wait_event_interruptible_timeout( - cold_reset->read_wq, - cold_reset->rsp_pending == false, - msecs_to_jiffies(timeout))) { - pr_err("%s: cold reset/prot response timeout\n", __func__); - ret = -EAGAIN; + READ_RETRY_WAIT_TIME_US + 500); } - } while (ret == -ERESTARTSYS || ret == -EFAULT); + } while (ret == -ERESTARTSYS || ret == -EFAULT || ret == -EAGAIN); + mutex_unlock(&nfc_dev->dev_ref_mutex); mutex_unlock(&nfc_dev->write_mutex); timeout = ESE_CLD_RST_REBOOT_GUARD_TIME_MS; - if (ret == 0) { /* success case */ + if (ret == 0) { /* success case */ ret = cold_reset->status; if (IS_RST_PROT_REQ(arg)) { cold_reset->reset_protection = IS_RST_PROT_EN_REQ(arg); cold_reset->rst_prot_src = IS_RST_PROT_EN_REQ(arg) ? - GET_SRC(arg) : - SRC_NONE; + GET_SRC(arg) : SRC_NONE; /* wait for reboot guard timer */ - } else if (wait_event_interruptible_timeout( - cold_reset->read_wq, true, - msecs_to_jiffies(timeout)) == 0) { - pr_info("%s: reboot guard timer timeout\n", __func__); + } else { + if (wait_event_interruptible_timeout + (cold_reset->read_wq, true, + msecs_to_jiffies(timeout)) == 0) { + pr_info("%s: reboot guard timer timeout\n", + __func__); + } } } err: