Commit 17e9d9d437d1bb52077e562fae9457236dbaa76f
1 parent
f1abed171f
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
NFC: pn533: Fix the pn533 polling loop
By turning the radio off after each failed polling try, we dramatically improve the pn533 polling loop efficiency. Without this fix, all Android phones running the broadcom NFC stack are almost never detected. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Showing 1 changed file with 54 additions and 1 deletions Side-by-side Diff
drivers/nfc/pn533.c
... | ... | @@ -359,6 +359,7 @@ |
359 | 359 | struct work_struct poll_work; |
360 | 360 | struct work_struct mi_work; |
361 | 361 | struct work_struct tg_work; |
362 | + struct work_struct rf_work; | |
362 | 363 | |
363 | 364 | struct list_head cmd_queue; |
364 | 365 | struct pn533_cmd *cmd; |
... | ... | @@ -1660,6 +1661,53 @@ |
1660 | 1661 | queue_work(dev->wq, &dev->poll_work); |
1661 | 1662 | } |
1662 | 1663 | |
1664 | +static int pn533_rf_complete(struct pn533 *dev, void *arg, | |
1665 | + struct sk_buff *resp) | |
1666 | +{ | |
1667 | + int rc = 0; | |
1668 | + | |
1669 | + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | |
1670 | + | |
1671 | + if (IS_ERR(resp)) { | |
1672 | + rc = PTR_ERR(resp); | |
1673 | + | |
1674 | + nfc_dev_err(&dev->interface->dev, "%s RF setting error %d", | |
1675 | + __func__, rc); | |
1676 | + | |
1677 | + return rc; | |
1678 | + } | |
1679 | + | |
1680 | + queue_work(dev->wq, &dev->poll_work); | |
1681 | + | |
1682 | + dev_kfree_skb(resp); | |
1683 | + return rc; | |
1684 | +} | |
1685 | + | |
1686 | +static void pn533_wq_rf(struct work_struct *work) | |
1687 | +{ | |
1688 | + struct pn533 *dev = container_of(work, struct pn533, rf_work); | |
1689 | + struct sk_buff *skb; | |
1690 | + int rc; | |
1691 | + | |
1692 | + nfc_dev_dbg(&dev->interface->dev, "%s", __func__); | |
1693 | + | |
1694 | + skb = pn533_alloc_skb(dev, 2); | |
1695 | + if (!skb) | |
1696 | + return; | |
1697 | + | |
1698 | + *skb_put(skb, 1) = PN533_CFGITEM_RF_FIELD; | |
1699 | + *skb_put(skb, 1) = 0; | |
1700 | + | |
1701 | + rc = pn533_send_cmd_async(dev, PN533_CMD_RF_CONFIGURATION, skb, | |
1702 | + pn533_rf_complete, NULL); | |
1703 | + if (rc < 0) { | |
1704 | + dev_kfree_skb(skb); | |
1705 | + nfc_dev_err(&dev->interface->dev, "RF setting error %d", rc); | |
1706 | + } | |
1707 | + | |
1708 | + return; | |
1709 | +} | |
1710 | + | |
1663 | 1711 | static int pn533_poll_complete(struct pn533 *dev, void *arg, |
1664 | 1712 | struct sk_buff *resp) |
1665 | 1713 | { |
... | ... | @@ -1705,7 +1753,8 @@ |
1705 | 1753 | } |
1706 | 1754 | |
1707 | 1755 | pn533_poll_next_mod(dev); |
1708 | - queue_work(dev->wq, &dev->poll_work); | |
1756 | + /* Not target found, turn radio off */ | |
1757 | + queue_work(dev->wq, &dev->rf_work); | |
1709 | 1758 | |
1710 | 1759 | done: |
1711 | 1760 | dev_kfree_skb(resp); |
... | ... | @@ -2051,6 +2100,7 @@ |
2051 | 2100 | } |
2052 | 2101 | } |
2053 | 2102 | |
2103 | +static int pn533_rf_field(struct nfc_dev *nfc_dev, u8 rf); | |
2054 | 2104 | #define PASSIVE_DATA_LEN 5 |
2055 | 2105 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, |
2056 | 2106 | u8 comm_mode, u8 *gb, size_t gb_len) |
... | ... | @@ -2127,6 +2177,8 @@ |
2127 | 2177 | |
2128 | 2178 | *arg = !comm_mode; |
2129 | 2179 | |
2180 | + pn533_rf_field(dev->nfc_dev, 0); | |
2181 | + | |
2130 | 2182 | rc = pn533_send_cmd_async(dev, PN533_CMD_IN_JUMP_FOR_DEP, skb, |
2131 | 2183 | pn533_in_dep_link_up_complete, arg); |
2132 | 2184 | |
... | ... | @@ -2721,6 +2773,7 @@ |
2721 | 2773 | INIT_WORK(&dev->mi_work, pn533_wq_mi_recv); |
2722 | 2774 | INIT_WORK(&dev->tg_work, pn533_wq_tg_get_data); |
2723 | 2775 | INIT_WORK(&dev->poll_work, pn533_wq_poll); |
2776 | + INIT_WORK(&dev->rf_work, pn533_wq_rf); | |
2724 | 2777 | dev->wq = alloc_ordered_workqueue("pn533", 0); |
2725 | 2778 | if (dev->wq == NULL) |
2726 | 2779 | goto error; |