Commit c4bf98b2 authored by Ilan Elias's avatar Ilan Elias Committed by John W. Linville

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: default avatarIlan Elias <ilane@ti.com>
Acked-by: default avatarSamuel Ortiz <sameo@linux.intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 889cbb91
...@@ -41,6 +41,7 @@ enum { ...@@ -41,6 +41,7 @@ enum {
NCI_DISCOVERY, NCI_DISCOVERY,
NCI_POLL_ACTIVE, NCI_POLL_ACTIVE,
NCI_DATA_EXCHANGE, NCI_DATA_EXCHANGE,
NCI_DATA_EXCHANGE_TO,
}; };
/* NCI timeouts */ /* NCI timeouts */
...@@ -49,6 +50,7 @@ enum { ...@@ -49,6 +50,7 @@ enum {
#define NCI_RF_DISC_TIMEOUT 5000 #define NCI_RF_DISC_TIMEOUT 5000
#define NCI_RF_DEACTIVATE_TIMEOUT 30000 #define NCI_RF_DEACTIVATE_TIMEOUT 30000
#define NCI_CMD_TIMEOUT 5000 #define NCI_CMD_TIMEOUT 5000
#define NCI_DATA_TIMEOUT 700
struct nci_dev; struct nci_dev;
...@@ -74,6 +76,7 @@ struct nci_dev { ...@@ -74,6 +76,7 @@ struct nci_dev {
atomic_t credits_cnt; atomic_t credits_cnt;
struct timer_list cmd_timer; struct timer_list cmd_timer;
struct timer_list data_timer;
struct workqueue_struct *cmd_wq; struct workqueue_struct *cmd_wq;
struct work_struct cmd_work; struct work_struct cmd_work;
......
...@@ -286,6 +286,7 @@ static int nci_close_device(struct nci_dev *ndev) ...@@ -286,6 +286,7 @@ static int nci_close_device(struct nci_dev *ndev)
if (!test_and_clear_bit(NCI_UP, &ndev->flags)) { if (!test_and_clear_bit(NCI_UP, &ndev->flags)) {
del_timer_sync(&ndev->cmd_timer); del_timer_sync(&ndev->cmd_timer);
del_timer_sync(&ndev->data_timer);
mutex_unlock(&ndev->req_lock); mutex_unlock(&ndev->req_lock);
return 0; return 0;
} }
...@@ -331,6 +332,15 @@ static void nci_cmd_timer(unsigned long arg) ...@@ -331,6 +332,15 @@ static void nci_cmd_timer(unsigned long arg)
queue_work(ndev->cmd_wq, &ndev->cmd_work); 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) static int nci_dev_up(struct nfc_dev *nfc_dev)
{ {
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
...@@ -585,6 +595,8 @@ int nci_register_device(struct nci_dev *ndev) ...@@ -585,6 +595,8 @@ int nci_register_device(struct nci_dev *ndev)
setup_timer(&ndev->cmd_timer, nci_cmd_timer, setup_timer(&ndev->cmd_timer, nci_cmd_timer,
(unsigned long) ndev); (unsigned long) ndev);
setup_timer(&ndev->data_timer, nci_data_timer,
(unsigned long) ndev);
mutex_init(&ndev->req_lock); mutex_init(&ndev->req_lock);
...@@ -722,6 +734,9 @@ static void nci_tx_work(struct work_struct *work) ...@@ -722,6 +734,9 @@ static void nci_tx_work(struct work_struct *work)
nci_plen(skb->data)); nci_plen(skb->data));
nci_send_frame(skb); 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) ...@@ -753,6 +768,15 @@ static void nci_rx_work(struct work_struct *work)
break; 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 ----- */ /* ----- NCI TX CMD worker thread ----- */
......
...@@ -44,6 +44,10 @@ void nci_data_exchange_complete(struct nci_dev *ndev, ...@@ -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); 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) { if (cb) {
ndev->data_exchange_cb = NULL; ndev->data_exchange_cb = NULL;
ndev->data_exchange_cb_context = 0; ndev->data_exchange_cb_context = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment