NFC: Add NCI data exchange timer
authorIlan Elias <ilane@ti.com>
Tue, 17 Jan 2012 10:03:50 +0000 (12:03 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 24 Jan 2012 19:21:55 +0000 (14:21 -0500)
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>
include/net/nfc/nci_core.h
net/nfc/nci/core.c
net/nfc/nci/data.c

index f4963ea77947b7410c4924abe516641f87d12040..9154663b606b9a3877c3b759e68137f6cf2eed32 100644 (file)
@@ -41,6 +41,7 @@ enum {
        NCI_DISCOVERY,
        NCI_POLL_ACTIVE,
        NCI_DATA_EXCHANGE,
+       NCI_DATA_EXCHANGE_TO,
 };
 
 /* NCI timeouts */
@@ -49,6 +50,7 @@ enum {
 #define NCI_RF_DISC_TIMEOUT                    5000
 #define NCI_RF_DEACTIVATE_TIMEOUT              30000
 #define NCI_CMD_TIMEOUT                                5000
+#define NCI_DATA_TIMEOUT                       700
 
 struct nci_dev;
 
@@ -74,6 +76,7 @@ struct nci_dev {
        atomic_t                credits_cnt;
 
        struct timer_list       cmd_timer;
+       struct timer_list       data_timer;
 
        struct workqueue_struct *cmd_wq;
        struct work_struct      cmd_work;
index 7650139a1a0538da0a6857b21e4460e8f2f47a01..815d28a0ed9d2eb86c40eeaf1867d6c9ff803b18 100644 (file)
@@ -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 ----- */
index e5756b30e6025ff6e90a6419824c6e9c378131bd..7880ae924d5e623db609df4feaf260ad2406535a 100644 (file)
@@ -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;