aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nfc
diff options
context:
space:
mode:
authorOlivier Guiter <olivier.guiter@linux.intel.com>2013-06-13 09:43:28 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2013-08-13 18:35:18 -0400
commit963a82e07d4e1f95fc423d53912ac0a7fe643b1c (patch)
tree07cb5859c86cc34c86cefc4e4a0233aac7947bfd /drivers/nfc
parent1575b9d8668f4ecf2648a08751313c826fb6a6e9 (diff)
NFC: pn533: Split large Tx frames in chunks
On sending large frames (size > 262), we split it in multiple chunks and send them asynchronously with MI bit. Signed-off-by: Olivier Guiter <olivier.guiter@linux.intel.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/nfc')
-rw-r--r--drivers/nfc/pn533.c144
1 files changed, 130 insertions, 14 deletions
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c
index ae0fa9ee169d..f06ef7c49f84 100644
--- a/drivers/nfc/pn533.c
+++ b/drivers/nfc/pn533.c
@@ -363,12 +363,14 @@ struct pn533 {
363 struct urb *in_urb; 363 struct urb *in_urb;
364 364
365 struct sk_buff_head resp_q; 365 struct sk_buff_head resp_q;
366 struct sk_buff_head fragment_skb;
366 367
367 struct workqueue_struct *wq; 368 struct workqueue_struct *wq;
368 struct work_struct cmd_work; 369 struct work_struct cmd_work;
369 struct work_struct cmd_complete_work; 370 struct work_struct cmd_complete_work;
370 struct work_struct poll_work; 371 struct work_struct poll_work;
371 struct work_struct mi_work; 372 struct work_struct mi_rx_work;
373 struct work_struct mi_tx_work;
372 struct work_struct tg_work; 374 struct work_struct tg_work;
373 struct work_struct rf_work; 375 struct work_struct rf_work;
374 376
@@ -378,6 +380,7 @@ struct pn533 {
378 struct mutex cmd_lock; /* protects cmd queue */ 380 struct mutex cmd_lock; /* protects cmd queue */
379 381
380 void *cmd_complete_mi_arg; 382 void *cmd_complete_mi_arg;
383 void *cmd_complete_dep_arg;
381 384
382 struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1]; 385 struct pn533_poll_modulations *poll_mod_active[PN533_POLL_MOD_MAX + 1];
383 u8 poll_mod_count; 386 u8 poll_mod_count;
@@ -2328,7 +2331,15 @@ static int pn533_data_exchange_complete(struct pn533 *dev, void *_arg,
2328 2331
2329 if (mi) { 2332 if (mi) {
2330 dev->cmd_complete_mi_arg = arg; 2333 dev->cmd_complete_mi_arg = arg;
2331 queue_work(dev->wq, &dev->mi_work); 2334 queue_work(dev->wq, &dev->mi_rx_work);
2335 return -EINPROGRESS;
2336 }
2337
2338 /* Prepare for the next round */
2339 if (skb_queue_len(&dev->fragment_skb) > 0) {
2340 dev->cmd_complete_dep_arg = arg;
2341 queue_work(dev->wq, &dev->mi_tx_work);
2342
2332 return -EINPROGRESS; 2343 return -EINPROGRESS;
2333 } 2344 }
2334 2345
@@ -2349,6 +2360,50 @@ _error:
2349 return rc; 2360 return rc;
2350} 2361}
2351 2362
2363/* Split the Tx skb into small chunks */
2364static int pn533_fill_fragment_skbs(struct pn533 *dev, struct sk_buff *skb)
2365{
2366 struct sk_buff *frag;
2367 int frag_size;
2368
2369 do {
2370 /* Remaining size */
2371 if (skb->len > PN533_CMD_DATAFRAME_MAXLEN)
2372 frag_size = PN533_CMD_DATAFRAME_MAXLEN;
2373 else
2374 frag_size = skb->len;
2375
2376 /* Allocate and reserve */
2377 frag = pn533_alloc_skb(dev, frag_size);
2378 if (!frag) {
2379 skb_queue_purge(&dev->fragment_skb);
2380 break;
2381 }
2382
2383 /* Reserve the TG/MI byte */
2384 skb_reserve(frag, 1);
2385
2386 /* MI + TG */
2387 if (frag_size == PN533_CMD_DATAFRAME_MAXLEN)
2388 *skb_push(frag, sizeof(u8)) = (PN533_CMD_MI_MASK | 1);
2389 else
2390 *skb_push(frag, sizeof(u8)) = 1; /* TG */
2391
2392 memcpy(skb_put(frag, frag_size), skb->data, frag_size);
2393
2394 /* Reduce the size of incoming buffer */
2395 skb_pull(skb, frag_size);
2396
2397 /* Add this to skb_queue */
2398 skb_queue_tail(&dev->fragment_skb, frag);
2399
2400 } while (skb->len > 0);
2401
2402 dev_kfree_skb(skb);
2403
2404 return skb_queue_len(&dev->fragment_skb);
2405}
2406
2352static int pn533_transceive(struct nfc_dev *nfc_dev, 2407static int pn533_transceive(struct nfc_dev *nfc_dev,
2353 struct nfc_target *target, struct sk_buff *skb, 2408 struct nfc_target *target, struct sk_buff *skb,
2354 data_exchange_cb_t cb, void *cb_context) 2409 data_exchange_cb_t cb, void *cb_context)
@@ -2359,15 +2414,6 @@ static int pn533_transceive(struct nfc_dev *nfc_dev,
2359 2414
2360 nfc_dev_dbg(&dev->interface->dev, "%s", __func__); 2415 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
2361 2416
2362 if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) {
2363 /* TODO: Implement support to multi-part data exchange */
2364 nfc_dev_err(&dev->interface->dev,
2365 "Data length greater than the max allowed: %d",
2366 PN533_CMD_DATAEXCH_DATA_MAXLEN);
2367 rc = -ENOSYS;
2368 goto error;
2369 }
2370
2371 if (!dev->tgt_active_prot) { 2417 if (!dev->tgt_active_prot) {
2372 nfc_dev_err(&dev->interface->dev, 2418 nfc_dev_err(&dev->interface->dev,
2373 "Can't exchange data if there is no active target"); 2419 "Can't exchange data if there is no active target");
@@ -2395,7 +2441,20 @@ static int pn533_transceive(struct nfc_dev *nfc_dev,
2395 break; 2441 break;
2396 } 2442 }
2397 default: 2443 default:
2398 *skb_push(skb, sizeof(u8)) = 1; /*TG*/ 2444 /* jumbo frame ? */
2445 if (skb->len > PN533_CMD_DATAEXCH_DATA_MAXLEN) {
2446 rc = pn533_fill_fragment_skbs(dev, skb);
2447 if (rc <= 0)
2448 goto error;
2449
2450 skb = skb_dequeue(&dev->fragment_skb);
2451 if (!skb) {
2452 rc = -EIO;
2453 goto error;
2454 }
2455 } else {
2456 *skb_push(skb, sizeof(u8)) = 1; /* TG */
2457 }
2399 2458
2400 rc = pn533_send_data_async(dev, PN533_CMD_IN_DATA_EXCHANGE, 2459 rc = pn533_send_data_async(dev, PN533_CMD_IN_DATA_EXCHANGE,
2401 skb, pn533_data_exchange_complete, 2460 skb, pn533_data_exchange_complete,
@@ -2466,7 +2525,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
2466 2525
2467static void pn533_wq_mi_recv(struct work_struct *work) 2526static void pn533_wq_mi_recv(struct work_struct *work)
2468{ 2527{
2469 struct pn533 *dev = container_of(work, struct pn533, mi_work); 2528 struct pn533 *dev = container_of(work, struct pn533, mi_rx_work);
2470 2529
2471 struct sk_buff *skb; 2530 struct sk_buff *skb;
2472 int rc; 2531 int rc;
@@ -2514,6 +2573,61 @@ error:
2514 queue_work(dev->wq, &dev->cmd_work); 2573 queue_work(dev->wq, &dev->cmd_work);
2515} 2574}
2516 2575
2576static void pn533_wq_mi_send(struct work_struct *work)
2577{
2578 struct pn533 *dev = container_of(work, struct pn533, mi_tx_work);
2579 struct sk_buff *skb;
2580 int rc;
2581
2582 nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
2583
2584 /* Grab the first skb in the queue */
2585 skb = skb_dequeue(&dev->fragment_skb);
2586
2587 if (skb == NULL) { /* No more data */
2588 /* Reset the queue for future use */
2589 skb_queue_head_init(&dev->fragment_skb);
2590 goto error;
2591 }
2592
2593 switch (dev->device_type) {
2594 case PN533_DEVICE_PASORI:
2595 if (dev->tgt_active_prot != NFC_PROTO_FELICA) {
2596 rc = -EIO;
2597 break;
2598 }
2599
2600 rc = pn533_send_cmd_direct_async(dev, PN533_CMD_IN_COMM_THRU,
2601 skb,
2602 pn533_data_exchange_complete,
2603 dev->cmd_complete_dep_arg);
2604
2605 break;
2606
2607 default:
2608 /* Still some fragments? */
2609 rc = pn533_send_cmd_direct_async(dev,PN533_CMD_IN_DATA_EXCHANGE,
2610 skb,
2611 pn533_data_exchange_complete,
2612 dev->cmd_complete_dep_arg);
2613
2614 break;
2615 }
2616
2617 if (rc == 0) /* success */
2618 return;
2619
2620 nfc_dev_err(&dev->interface->dev,
2621 "Error %d when trying to perform data_exchange", rc);
2622
2623 dev_kfree_skb(skb);
2624 kfree(dev->cmd_complete_dep_arg);
2625
2626error:
2627 pn533_send_ack(dev, GFP_KERNEL);
2628 queue_work(dev->wq, &dev->cmd_work);
2629}
2630
2517static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata, 2631static int pn533_set_configuration(struct pn533 *dev, u8 cfgitem, u8 *cfgdata,
2518 u8 cfgdata_len) 2632 u8 cfgdata_len)
2519{ 2633{
@@ -2816,7 +2930,8 @@ static int pn533_probe(struct usb_interface *interface,
2816 2930
2817 INIT_WORK(&dev->cmd_work, pn533_wq_cmd); 2931 INIT_WORK(&dev->cmd_work, pn533_wq_cmd);
2818 INIT_WORK(&dev->cmd_complete_work, pn533_wq_cmd_complete); 2932 INIT_WORK(&dev->cmd_complete_work, pn533_wq_cmd_complete);
2819 INIT_WORK(&dev->mi_work, pn533_wq_mi_recv); 2933 INIT_WORK(&dev->mi_rx_work, pn533_wq_mi_recv);
2934 INIT_WORK(&dev->mi_tx_work, pn533_wq_mi_send);
2820 INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data); 2935 INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data);
2821 INIT_WORK(&dev->poll_work, pn533_wq_poll); 2936 INIT_WORK(&dev->poll_work, pn533_wq_poll);
2822 INIT_WORK(&dev->rf_work, pn533_wq_rf); 2937 INIT_WORK(&dev->rf_work, pn533_wq_rf);
@@ -2829,6 +2944,7 @@ static int pn533_probe(struct usb_interface *interface,
2829 dev->listen_timer.function = pn533_listen_mode_timer; 2944 dev->listen_timer.function = pn533_listen_mode_timer;
2830 2945
2831 skb_queue_head_init(&dev->resp_q); 2946 skb_queue_head_init(&dev->resp_q);
2947 skb_queue_head_init(&dev->fragment_skb);
2832 2948
2833 INIT_LIST_HEAD(&dev->cmd_queue); 2949 INIT_LIST_HEAD(&dev->cmd_queue);
2834 2950