aboutsummaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorIlan Elias2012-01-17 12:03:50 +0200
committerJohn W. Linville2012-01-24 14:21:55 -0500
commitc4bf98b220cba7a8618405261d69ee53a265110e (patch)
tree2710efffaefc519f0d08f116ba669b1648aaab4a /net
parent889cbb911a195b832745f77240f547cb2a2885bc (diff)
NFC: Add NCI data exchange timer
Add NCI data exchange timer to catch timeouts, and call the data exchange callback with an error. Signed-off-by: Ilan Elias <ilane@ti.com> Acked-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/nfc/nci/core.c24
-rw-r--r--net/nfc/nci/data.c4
2 files changed, 28 insertions, 0 deletions
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 7650139a1a05..815d28a0ed9d 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -286,6 +286,7 @@ static int nci_close_device(struct nci_dev *ndev)
if (!test_and_clear_bit(NCI_UP, &ndev->flags)) {
del_timer_sync(&ndev->cmd_timer);
+ del_timer_sync(&ndev->data_timer);
mutex_unlock(&ndev->req_lock);
return 0;
}
@@ -331,6 +332,15 @@ static void nci_cmd_timer(unsigned long arg)
queue_work(ndev->cmd_wq, &ndev->cmd_work);
}
+/* NCI data exchange timer function */
+static void nci_data_timer(unsigned long arg)
+{
+ struct nci_dev *ndev = (void *) arg;
+
+ set_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags);
+ queue_work(ndev->rx_wq, &ndev->rx_work);
+}
+
static int nci_dev_up(struct nfc_dev *nfc_dev)
{
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
@@ -585,6 +595,8 @@ int nci_register_device(struct nci_dev *ndev)
setup_timer(&ndev->cmd_timer, nci_cmd_timer,
(unsigned long) ndev);
+ setup_timer(&ndev->data_timer, nci_data_timer,
+ (unsigned long) ndev);
mutex_init(&ndev->req_lock);
@@ -722,6 +734,9 @@ static void nci_tx_work(struct work_struct *work)
nci_plen(skb->data));
nci_send_frame(skb);
+
+ mod_timer(&ndev->data_timer,
+ jiffies + msecs_to_jiffies(NCI_DATA_TIMEOUT));
}
}
@@ -753,6 +768,15 @@ static void nci_rx_work(struct work_struct *work)
break;
}
}
+
+ /* check if a data exchange timout has occurred */
+ if (test_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags)) {
+ /* complete the data exchange transaction, if exists */
+ if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags))
+ nci_data_exchange_complete(ndev, NULL, -ETIMEDOUT);
+
+ clear_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags);
+ }
}
/* ----- NCI TX CMD worker thread ----- */
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c
index e5756b30e602..7880ae924d5e 100644
--- a/net/nfc/nci/data.c
+++ b/net/nfc/nci/data.c
@@ -44,6 +44,10 @@ void nci_data_exchange_complete(struct nci_dev *ndev,
pr_debug("len %d, err %d\n", skb ? skb->len : 0, err);
+ /* data exchange is complete, stop the data timer */
+ del_timer_sync(&ndev->data_timer);
+ clear_bit(NCI_DATA_EXCHANGE_TO, &ndev->flags);
+
if (cb) {
ndev->data_exchange_cb = NULL;
ndev->data_exchange_cb_context = 0;