diff options
-rw-r--r-- | net/nfc/llcp/commands.c | 6 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.c | 47 | ||||
-rw-r--r-- | net/nfc/llcp/llcp.h | 4 |
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 | ||
229 | static 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 | |||
263 | static 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 | |||
227 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) | 270 | struct 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 */ |