aboutsummaryrefslogtreecommitdiffstats
path: root/net/nfc
diff options
context:
space:
mode:
authorThierry Escande <thierry.escande@linux.intel.com>2013-03-04 09:43:32 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2013-03-10 18:16:41 -0400
commit40213fa8513c2a92e7390f25571f7c17c7955e2b (patch)
tree06e02361b9563018bacd648991997aa864af904c /net/nfc
parentd9b8d8e19b073096d3609bbd60f82148d128b555 (diff)
NFC: llcp: Add cleanup support for unreplied SNL requests
If the remote LLC doesn't reply in time to our SNL requests we remove them from the list of pending requests. The timeout is fixed to an arbitrary value of 3 times remote_lto. When not replied, the local LLC broadcasts NFC_EVENT_LLC_SDRES nl events for the concerned uris with sap values set to LLCP_SDP_UNBOUND (which is 65). Signed-off-by: Thierry Escande <thierry.escande@linux.intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'net/nfc')
-rw-r--r--net/nfc/llcp/commands.c6
-rw-r--r--net/nfc/llcp/llcp.c47
-rw-r--r--net/nfc/llcp/llcp.h4
3 files changed, 57 insertions, 0 deletions
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c
index c943edb07b72..b75a9b3f9e89 100644
--- a/net/nfc/llcp/commands.c
+++ b/net/nfc/llcp/commands.c
@@ -174,6 +174,8 @@ struct nfc_llcp_sdp_tlv *nfc_llcp_build_sdreq_tlv(u8 tid, char *uri,
174 sdreq->uri = sdreq->tlv + 3; 174 sdreq->uri = sdreq->tlv + 3;
175 memcpy(sdreq->uri, uri, uri_len); 175 memcpy(sdreq->uri, uri, uri_len);
176 176
177 sdreq->time = jiffies;
178
177 INIT_HLIST_NODE(&sdreq->node); 179 INIT_HLIST_NODE(&sdreq->node);
178 180
179 return sdreq; 181 return sdreq;
@@ -571,6 +573,10 @@ int nfc_llcp_send_snl_sdreq(struct nfc_llcp_local *local,
571 573
572 mutex_lock(&local->sdreq_lock); 574 mutex_lock(&local->sdreq_lock);
573 575
576 if (hlist_empty(&local->pending_sdreqs))
577 mod_timer(&local->sdreq_timer,
578 jiffies + msecs_to_jiffies(3 * local->remote_lto));
579
574 hlist_for_each_entry_safe(sdreq, n, tlv_list, node) { 580 hlist_for_each_entry_safe(sdreq, n, tlv_list, node) {
575 pr_debug("tid %d for %s\n", sdreq->tid, sdreq->uri); 581 pr_debug("tid %d for %s\n", sdreq->tid, sdreq->uri);
576 582
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index 99e911060422..3361170cb262 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -156,6 +156,8 @@ static void local_release(struct kref *ref)
156 cancel_work_sync(&local->rx_work); 156 cancel_work_sync(&local->rx_work);
157 cancel_work_sync(&local->timeout_work); 157 cancel_work_sync(&local->timeout_work);
158 kfree_skb(local->rx_pending); 158 kfree_skb(local->rx_pending);
159 del_timer_sync(&local->sdreq_timer);
160 cancel_work_sync(&local->sdreq_timeout_work);
159 nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs); 161 nfc_llcp_free_sdp_tlv_list(&local->pending_sdreqs);
160 kfree(local); 162 kfree(local);
161} 163}
@@ -224,6 +226,47 @@ static void nfc_llcp_symm_timer(unsigned long data)
224 schedule_work(&local->timeout_work); 226 schedule_work(&local->timeout_work);
225} 227}
226 228
229static void nfc_llcp_sdreq_timeout_work(struct work_struct *work)
230{
231 unsigned long time;
232 HLIST_HEAD(nl_sdres_list);
233 struct hlist_node *n;
234 struct nfc_llcp_sdp_tlv *sdp;
235 struct nfc_llcp_local *local = container_of(work, struct nfc_llcp_local,
236 sdreq_timeout_work);
237
238 mutex_lock(&local->sdreq_lock);
239
240 time = jiffies - msecs_to_jiffies(3 * local->remote_lto);
241
242 hlist_for_each_entry_safe(sdp, n, &local->pending_sdreqs, node) {
243 if (time_after(sdp->time, time))
244 continue;
245
246 sdp->sap = LLCP_SDP_UNBOUND;
247
248 hlist_del(&sdp->node);
249
250 hlist_add_head(&sdp->node, &nl_sdres_list);
251 }
252
253 if (!hlist_empty(&local->pending_sdreqs))
254 mod_timer(&local->sdreq_timer,
255 jiffies + msecs_to_jiffies(3 * local->remote_lto));
256
257 mutex_unlock(&local->sdreq_lock);
258
259 if (!hlist_empty(&nl_sdres_list))
260 nfc_genl_llc_send_sdres(local->dev, &nl_sdres_list);
261}
262
263static void nfc_llcp_sdreq_timer(unsigned long data)
264{
265 struct nfc_llcp_local *local = (struct nfc_llcp_local *) data;
266
267 schedule_work(&local->sdreq_timeout_work);
268}
269
227struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) 270struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
228{ 271{
229 struct nfc_llcp_local *local, *n; 272 struct nfc_llcp_local *local, *n;
@@ -1457,6 +1500,10 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
1457 1500
1458 mutex_init(&local->sdreq_lock); 1501 mutex_init(&local->sdreq_lock);
1459 INIT_HLIST_HEAD(&local->pending_sdreqs); 1502 INIT_HLIST_HEAD(&local->pending_sdreqs);
1503 init_timer(&local->sdreq_timer);
1504 local->sdreq_timer.data = (unsigned long) local;
1505 local->sdreq_timer.function = nfc_llcp_sdreq_timer;
1506 INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work);
1460 1507
1461 list_add(&local->list, &llcp_devices); 1508 list_add(&local->list, &llcp_devices);
1462 1509
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h
index ca8c6d94ab85..7e87a66b02ec 100644
--- a/net/nfc/llcp/llcp.h
+++ b/net/nfc/llcp/llcp.h
@@ -54,6 +54,8 @@ struct nfc_llcp_sdp_tlv {
54 u8 tid; 54 u8 tid;
55 u8 sap; 55 u8 sap;
56 56
57 unsigned long time;
58
57 struct hlist_node node; 59 struct hlist_node node;
58}; 60};
59 61
@@ -99,6 +101,8 @@ struct nfc_llcp_local {
99 101
100 struct mutex sdreq_lock; 102 struct mutex sdreq_lock;
101 struct hlist_head pending_sdreqs; 103 struct hlist_head pending_sdreqs;
104 struct timer_list sdreq_timer;
105 struct work_struct sdreq_timeout_work;
102 u8 sdreq_next_tid; 106 u8 sdreq_next_tid;
103 107
104 /* sockets array */ 108 /* sockets array */