From edb4a79b1ef031fbd7f84c66e75e1d906397949f Mon Sep 17 00:00:00 2001 From: Karthik Poosa Date: Thu, 5 Mar 2020 19:42:44 +0530 Subject: [PATCH] NFC: Add timeout when waiting for responses in probe Add timeout of MAX_IBI_WAIT_TIME(ms) when waiting for responses in probe. Without this timeout, device boot can be stuck if there is no response for NFC commands, as nfc probe waiting for responses indefinitely. Change-Id: Iecfb318d72a8d80eba8fa7977007125fa372eaa5 Signed-off-by: Karthik Poosa --- drivers/nfc/qti/nfc_i3c_drv.c | 28 +++++++++++++++++++++++----- drivers/nfc/qti/nfc_i3c_drv.h | 4 ++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/nfc/qti/nfc_i3c_drv.c b/drivers/nfc/qti/nfc_i3c_drv.c index d72e5ad4ab8f..b4fb9e9ac1dc 100644 --- a/drivers/nfc/qti/nfc_i3c_drv.c +++ b/drivers/nfc/qti/nfc_i3c_drv.c @@ -199,11 +199,28 @@ int i3c_nci_kbuf_retrieve(struct nfc_dev *dev, char *buf, break; reinit_completion(&i3c_dev->read_cplt); - ret = wait_for_completion_interruptible(&i3c_dev->read_cplt); - if (ret != 0) { - pr_err("didn't get completion, interrupted!! ret %d\n", - ret); - return ret; + /* + * During probe if there is no response for NCI commands, + * probe shouldn't be blocked, that is why timeout is added. + */ + + if (i3c_dev->is_probe_done) { + ret = wait_for_completion_interruptible( + &i3c_dev->read_cplt); + if (ret != 0) { + pr_err("nfc completion interrupted! ret %d\n", + ret); + return ret; + } + } else { + ret = wait_for_completion_interruptible_timeout( + &i3c_dev->read_cplt, + msecs_to_jiffies(MAX_IBI_WAIT_TIME)); + if (ret <= 0) { + pr_err("nfc completion timedout ret %d\n", + ret); + return ret; + } } } while (available_size < requested_size); @@ -675,6 +692,7 @@ int nfc_i3c_dev_probe(struct i3c_device *device) atomic_set(&nfc_dev->i3c_dev.pm_state, PM_STATE_NORMAL); device_init_wakeup(&device->dev, true); + nfc_dev->i3c_dev.is_probe_done = true; pr_info("%s success\n", __func__); diff --git a/drivers/nfc/qti/nfc_i3c_drv.h b/drivers/nfc/qti/nfc_i3c_drv.h index 78be4a7ff3be..7ef3dfda2990 100644 --- a/drivers/nfc/qti/nfc_i3c_drv.h +++ b/drivers/nfc/qti/nfc_i3c_drv.h @@ -41,6 +41,8 @@ // I3C WorkQueue name #define NFC_I3C_WORKQUEUE "nfc_i3c_workq" +/* Time(in ms) to wait for NCI packet respones */ +#define MAX_IBI_WAIT_TIME (2000) struct nfc_dev; /** @@ -72,6 +74,7 @@ struct nci_buf { * @ibi_enabled: IBI enabled or not. * @pm_state: PM state of NFC I3C device. * @nfc_read_direct Do NFC read bypassing the read buffer. + * @is_probe_done Is NFC I3C probe completed. */ struct i3c_dev { struct i3c_device *device; @@ -87,6 +90,7 @@ struct i3c_dev { atomic_t pm_state; int (*nfc_read_direct)(struct nfc_dev *dev, char *buf, size_t count); + bool is_probe_done; }; int nfc_i3c_dev_probe(struct i3c_device *device);