aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */