diff options
author | David S. Miller <davem@davemloft.net> | 2016-07-21 02:39:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-07-21 02:39:36 -0400 |
commit | 276b8c77c3e4838f574d37e25ec8ba52d0418475 (patch) | |
tree | 99bf7313765ca10e40d5a1edde2a5db44143bfb7 /drivers/nfc | |
parent | 0f06a6787e0516352117f0720e3052f46bc13523 (diff) | |
parent | 2a0fe4fe5bf2a6e2277354e7e8f369a20d881891 (diff) |
Merge tag 'nfc-next-4.8-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sameo/nfc-next
Samuel Ortiz says:
====================
NFC 4.8 pull request
This is the first NFC pull request for 4.8. We have:
- A fairly large NFC digital stack patchset:
* RTOX fixes.
* Proper DEP RWT support.
* ACK and NACK PDUs handling fixes, in both initiator
and target modes.
* A few memory leak fixes.
- A conversion of the nfcsim driver to use the digital stack.
The driver supports the DEP protocol in both NFC-A and NFC-F.
- Error injection through debugfs for the nfcsim driver.
- Improvements to the port100 driver for the Sony USB chipset, in
particular to the command abort and cancellation code paths.
- A few minor fixes for the pn533, trf7970a and fdp drivers.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/nfc')
-rw-r--r-- | drivers/nfc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/nfc/fdp/fdp.c | 6 | ||||
-rw-r--r-- | drivers/nfc/nfcsim.c | 643 | ||||
-rw-r--r-- | drivers/nfc/pn533/usb.c | 9 | ||||
-rw-r--r-- | drivers/nfc/port100.c | 82 | ||||
-rw-r--r-- | drivers/nfc/trf7970a.c | 4 |
6 files changed, 392 insertions, 353 deletions
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index ea8321a483f9..9d2369269abf 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig | |||
@@ -40,6 +40,7 @@ config NFC_MEI_PHY | |||
40 | 40 | ||
41 | config NFC_SIM | 41 | config NFC_SIM |
42 | tristate "NFC hardware simulator driver" | 42 | tristate "NFC hardware simulator driver" |
43 | depends on NFC_DIGITAL | ||
43 | help | 44 | help |
44 | This driver declares two virtual NFC devices supporting NFC-DEP | 45 | This driver declares two virtual NFC devices supporting NFC-DEP |
45 | protocol. An LLCP connection can be established between them and | 46 | protocol. An LLCP connection can be established between them and |
diff --git a/drivers/nfc/fdp/fdp.c b/drivers/nfc/fdp/fdp.c index e44a7a2f4061..7c1eaea3b685 100644 --- a/drivers/nfc/fdp/fdp.c +++ b/drivers/nfc/fdp/fdp.c | |||
@@ -345,7 +345,7 @@ static void fdp_nci_release_firmware(struct nci_dev *ndev) | |||
345 | 345 | ||
346 | if (info->ram_patch) { | 346 | if (info->ram_patch) { |
347 | release_firmware(info->ram_patch); | 347 | release_firmware(info->ram_patch); |
348 | info->otp_patch = NULL; | 348 | info->ram_patch = NULL; |
349 | } | 349 | } |
350 | } | 350 | } |
351 | 351 | ||
@@ -353,7 +353,7 @@ static int fdp_nci_patch_otp(struct nci_dev *ndev) | |||
353 | { | 353 | { |
354 | struct fdp_nci_info *info = nci_get_drvdata(ndev); | 354 | struct fdp_nci_info *info = nci_get_drvdata(ndev); |
355 | struct device *dev = &info->phy->i2c_dev->dev; | 355 | struct device *dev = &info->phy->i2c_dev->dev; |
356 | u8 conn_id; | 356 | int conn_id; |
357 | int r = 0; | 357 | int r = 0; |
358 | 358 | ||
359 | if (info->otp_version >= info->otp_patch_version) | 359 | if (info->otp_version >= info->otp_patch_version) |
@@ -424,7 +424,7 @@ static int fdp_nci_patch_ram(struct nci_dev *ndev) | |||
424 | { | 424 | { |
425 | struct fdp_nci_info *info = nci_get_drvdata(ndev); | 425 | struct fdp_nci_info *info = nci_get_drvdata(ndev); |
426 | struct device *dev = &info->phy->i2c_dev->dev; | 426 | struct device *dev = &info->phy->i2c_dev->dev; |
427 | u8 conn_id; | 427 | int conn_id; |
428 | int r = 0; | 428 | int r = 0; |
429 | 429 | ||
430 | if (info->ram_version >= info->ram_patch_version) | 430 | if (info->ram_version >= info->ram_patch_version) |
diff --git a/drivers/nfc/nfcsim.c b/drivers/nfc/nfcsim.c index 93aaca586858..a466e7978466 100644 --- a/drivers/nfc/nfcsim.c +++ b/drivers/nfc/nfcsim.c | |||
@@ -16,525 +16,492 @@ | |||
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/ctype.h> | ||
20 | #include <linux/debugfs.h> | ||
19 | #include <linux/nfc.h> | 21 | #include <linux/nfc.h> |
20 | #include <net/nfc/nfc.h> | 22 | #include <net/nfc/nfc.h> |
23 | #include <net/nfc/digital.h> | ||
21 | 24 | ||
22 | #define DEV_ERR(_dev, fmt, args...) nfc_err(&_dev->nfc_dev->dev, \ | 25 | #define NFCSIM_ERR(d, fmt, args...) nfc_err(&d->nfc_digital_dev->nfc_dev->dev, \ |
23 | "%s: " fmt, __func__, ## args) | 26 | "%s: " fmt, __func__, ## args) |
24 | 27 | ||
25 | #define DEV_DBG(_dev, fmt, args...) dev_dbg(&_dev->nfc_dev->dev, \ | 28 | #define NFCSIM_DBG(d, fmt, args...) dev_dbg(&d->nfc_digital_dev->nfc_dev->dev, \ |
26 | "%s: " fmt, __func__, ## args) | 29 | "%s: " fmt, __func__, ## args) |
27 | 30 | ||
28 | #define NFCSIM_VERSION "0.1" | 31 | #define NFCSIM_VERSION "0.2" |
29 | 32 | ||
30 | #define NFCSIM_POLL_NONE 0 | 33 | #define NFCSIM_MODE_NONE 0 |
31 | #define NFCSIM_POLL_INITIATOR 1 | 34 | #define NFCSIM_MODE_INITIATOR 1 |
32 | #define NFCSIM_POLL_TARGET 2 | 35 | #define NFCSIM_MODE_TARGET 2 |
33 | #define NFCSIM_POLL_DUAL (NFCSIM_POLL_INITIATOR | NFCSIM_POLL_TARGET) | ||
34 | 36 | ||
35 | #define RX_DEFAULT_DELAY 5 | 37 | #define NFCSIM_CAPABILITIES (NFC_DIGITAL_DRV_CAPS_IN_CRC | \ |
38 | NFC_DIGITAL_DRV_CAPS_TG_CRC) | ||
36 | 39 | ||
37 | struct nfcsim { | 40 | struct nfcsim { |
38 | struct nfc_dev *nfc_dev; | 41 | struct nfc_digital_dev *nfc_digital_dev; |
39 | 42 | ||
40 | struct mutex lock; | 43 | struct work_struct recv_work; |
44 | struct delayed_work send_work; | ||
41 | 45 | ||
42 | struct delayed_work recv_work; | 46 | struct nfcsim_link *link_in; |
47 | struct nfcsim_link *link_out; | ||
43 | 48 | ||
44 | struct sk_buff *clone_skb; | 49 | bool up; |
50 | u8 mode; | ||
51 | u8 rf_tech; | ||
45 | 52 | ||
46 | struct delayed_work poll_work; | 53 | u16 recv_timeout; |
47 | u8 polling_mode; | ||
48 | u8 curr_polling_mode; | ||
49 | 54 | ||
50 | u8 shutting_down; | 55 | nfc_digital_cmd_complete_t cb; |
56 | void *arg; | ||
51 | 57 | ||
52 | u8 up; | 58 | u8 dropframe; |
59 | }; | ||
53 | 60 | ||
54 | u8 initiator; | 61 | struct nfcsim_link { |
62 | struct mutex lock; | ||
55 | 63 | ||
56 | u32 rx_delay; | 64 | u8 rf_tech; |
65 | u8 mode; | ||
57 | 66 | ||
58 | data_exchange_cb_t cb; | 67 | u8 shutdown; |
59 | void *cb_context; | ||
60 | 68 | ||
61 | struct nfcsim *peer_dev; | 69 | struct sk_buff *skb; |
70 | wait_queue_head_t recv_wait; | ||
71 | u8 cond; | ||
62 | }; | 72 | }; |
63 | 73 | ||
64 | static struct nfcsim *dev0; | 74 | static struct nfcsim_link *nfcsim_link_new(void) |
65 | static struct nfcsim *dev1; | ||
66 | |||
67 | static struct workqueue_struct *wq; | ||
68 | |||
69 | static void nfcsim_cleanup_dev(struct nfcsim *dev, u8 shutdown) | ||
70 | { | 75 | { |
71 | DEV_DBG(dev, "shutdown=%d\n", shutdown); | 76 | struct nfcsim_link *link; |
72 | 77 | ||
73 | mutex_lock(&dev->lock); | 78 | link = kzalloc(sizeof(struct nfcsim_link), GFP_KERNEL); |
79 | if (!link) | ||
80 | return NULL; | ||
74 | 81 | ||
75 | dev->polling_mode = NFCSIM_POLL_NONE; | 82 | mutex_init(&link->lock); |
76 | dev->shutting_down = shutdown; | 83 | init_waitqueue_head(&link->recv_wait); |
77 | dev->cb = NULL; | ||
78 | dev_kfree_skb(dev->clone_skb); | ||
79 | dev->clone_skb = NULL; | ||
80 | 84 | ||
81 | mutex_unlock(&dev->lock); | 85 | return link; |
82 | |||
83 | cancel_delayed_work_sync(&dev->poll_work); | ||
84 | cancel_delayed_work_sync(&dev->recv_work); | ||
85 | } | 86 | } |
86 | 87 | ||
87 | static int nfcsim_target_found(struct nfcsim *dev) | 88 | static void nfcsim_link_free(struct nfcsim_link *link) |
88 | { | 89 | { |
89 | struct nfc_target nfc_tgt; | 90 | dev_kfree_skb(link->skb); |
91 | kfree(link); | ||
92 | } | ||
90 | 93 | ||
91 | DEV_DBG(dev, "\n"); | 94 | static void nfcsim_link_recv_wake(struct nfcsim_link *link) |
95 | { | ||
96 | link->cond = 1; | ||
97 | wake_up_interruptible(&link->recv_wait); | ||
98 | } | ||
92 | 99 | ||
93 | memset(&nfc_tgt, 0, sizeof(struct nfc_target)); | 100 | static void nfcsim_link_set_skb(struct nfcsim_link *link, struct sk_buff *skb, |
101 | u8 rf_tech, u8 mode) | ||
102 | { | ||
103 | mutex_lock(&link->lock); | ||
94 | 104 | ||
95 | nfc_tgt.supported_protocols = NFC_PROTO_NFC_DEP_MASK; | 105 | dev_kfree_skb(link->skb); |
96 | nfc_targets_found(dev->nfc_dev, &nfc_tgt, 1); | 106 | link->skb = skb; |
107 | link->rf_tech = rf_tech; | ||
108 | link->mode = mode; | ||
97 | 109 | ||
98 | return 0; | 110 | mutex_unlock(&link->lock); |
99 | } | 111 | } |
100 | 112 | ||
101 | static int nfcsim_dev_up(struct nfc_dev *nfc_dev) | 113 | static void nfcsim_link_recv_cancel(struct nfcsim_link *link) |
102 | { | 114 | { |
103 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 115 | mutex_lock(&link->lock); |
104 | 116 | ||
105 | DEV_DBG(dev, "\n"); | 117 | link->mode = NFCSIM_MODE_NONE; |
106 | 118 | ||
107 | mutex_lock(&dev->lock); | 119 | mutex_unlock(&link->lock); |
108 | 120 | ||
109 | dev->up = 1; | 121 | nfcsim_link_recv_wake(link); |
110 | |||
111 | mutex_unlock(&dev->lock); | ||
112 | |||
113 | return 0; | ||
114 | } | 122 | } |
115 | 123 | ||
116 | static int nfcsim_dev_down(struct nfc_dev *nfc_dev) | 124 | static void nfcsim_link_shutdown(struct nfcsim_link *link) |
117 | { | 125 | { |
118 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 126 | mutex_lock(&link->lock); |
119 | |||
120 | DEV_DBG(dev, "\n"); | ||
121 | 127 | ||
122 | mutex_lock(&dev->lock); | 128 | link->shutdown = 1; |
129 | link->mode = NFCSIM_MODE_NONE; | ||
123 | 130 | ||
124 | dev->up = 0; | 131 | mutex_unlock(&link->lock); |
125 | 132 | ||
126 | mutex_unlock(&dev->lock); | 133 | nfcsim_link_recv_wake(link); |
127 | |||
128 | return 0; | ||
129 | } | 134 | } |
130 | 135 | ||
131 | static int nfcsim_dep_link_up(struct nfc_dev *nfc_dev, | 136 | static struct sk_buff *nfcsim_link_recv_skb(struct nfcsim_link *link, |
132 | struct nfc_target *target, | 137 | int timeout, u8 rf_tech, u8 mode) |
133 | u8 comm_mode, u8 *gb, size_t gb_len) | ||
134 | { | 138 | { |
135 | int rc; | 139 | int rc; |
136 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 140 | struct sk_buff *skb; |
137 | struct nfcsim *peer = dev->peer_dev; | ||
138 | u8 *remote_gb; | ||
139 | size_t remote_gb_len; | ||
140 | 141 | ||
141 | DEV_DBG(dev, "target_idx: %d, comm_mode: %d\n", target->idx, comm_mode); | 142 | rc = wait_event_interruptible_timeout(link->recv_wait, |
143 | link->cond, | ||
144 | msecs_to_jiffies(timeout)); | ||
142 | 145 | ||
143 | mutex_lock(&peer->lock); | 146 | mutex_lock(&link->lock); |
144 | 147 | ||
145 | nfc_tm_activated(peer->nfc_dev, NFC_PROTO_NFC_DEP_MASK, | 148 | skb = link->skb; |
146 | NFC_COMM_ACTIVE, gb, gb_len); | 149 | link->skb = NULL; |
147 | 150 | ||
148 | remote_gb = nfc_get_local_general_bytes(peer->nfc_dev, &remote_gb_len); | 151 | if (!rc) { |
149 | if (!remote_gb) { | 152 | rc = -ETIMEDOUT; |
150 | DEV_ERR(peer, "Can't get remote general bytes\n"); | 153 | goto done; |
154 | } | ||
151 | 155 | ||
152 | mutex_unlock(&peer->lock); | 156 | if (!skb || link->rf_tech != rf_tech || link->mode == mode) { |
153 | return -EINVAL; | 157 | rc = -EINVAL; |
158 | goto done; | ||
154 | } | 159 | } |
155 | 160 | ||
156 | mutex_unlock(&peer->lock); | 161 | if (link->shutdown) { |
162 | rc = -ENODEV; | ||
163 | goto done; | ||
164 | } | ||
157 | 165 | ||
158 | mutex_lock(&dev->lock); | 166 | done: |
167 | mutex_unlock(&link->lock); | ||
159 | 168 | ||
160 | rc = nfc_set_remote_general_bytes(nfc_dev, remote_gb, remote_gb_len); | 169 | if (rc < 0) { |
161 | if (rc) { | 170 | dev_kfree_skb(skb); |
162 | DEV_ERR(dev, "Can't set remote general bytes\n"); | 171 | skb = ERR_PTR(rc); |
163 | mutex_unlock(&dev->lock); | ||
164 | return rc; | ||
165 | } | 172 | } |
166 | 173 | ||
167 | rc = nfc_dep_link_is_up(nfc_dev, target->idx, NFC_COMM_ACTIVE, | 174 | link->cond = 0; |
168 | NFC_RF_INITIATOR); | ||
169 | |||
170 | mutex_unlock(&dev->lock); | ||
171 | 175 | ||
172 | return rc; | 176 | return skb; |
173 | } | 177 | } |
174 | 178 | ||
175 | static int nfcsim_dep_link_down(struct nfc_dev *nfc_dev) | 179 | static void nfcsim_send_wq(struct work_struct *work) |
176 | { | 180 | { |
177 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 181 | struct nfcsim *dev = container_of(work, struct nfcsim, send_work.work); |
178 | 182 | ||
179 | DEV_DBG(dev, "\n"); | 183 | /* |
180 | 184 | * To effectively send data, the device just wake up its link_out which | |
181 | nfcsim_cleanup_dev(dev, 0); | 185 | * is the link_in of the peer device. The exchanged skb has already been |
182 | 186 | * stored in the dev->link_out through nfcsim_link_set_skb(). | |
183 | return 0; | 187 | */ |
188 | nfcsim_link_recv_wake(dev->link_out); | ||
184 | } | 189 | } |
185 | 190 | ||
186 | static int nfcsim_start_poll(struct nfc_dev *nfc_dev, | 191 | static void nfcsim_recv_wq(struct work_struct *work) |
187 | u32 im_protocols, u32 tm_protocols) | ||
188 | { | 192 | { |
189 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 193 | struct nfcsim *dev = container_of(work, struct nfcsim, recv_work); |
190 | int rc; | 194 | struct sk_buff *skb; |
191 | |||
192 | mutex_lock(&dev->lock); | ||
193 | 195 | ||
194 | if (dev->polling_mode != NFCSIM_POLL_NONE) { | 196 | skb = nfcsim_link_recv_skb(dev->link_in, dev->recv_timeout, |
195 | DEV_ERR(dev, "Already in polling mode\n"); | 197 | dev->rf_tech, dev->mode); |
196 | rc = -EBUSY; | ||
197 | goto exit; | ||
198 | } | ||
199 | 198 | ||
200 | if (im_protocols & NFC_PROTO_NFC_DEP_MASK) | 199 | if (!dev->up) { |
201 | dev->polling_mode |= NFCSIM_POLL_INITIATOR; | 200 | NFCSIM_ERR(dev, "Device is down\n"); |
202 | 201 | ||
203 | if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) | 202 | if (!IS_ERR(skb)) |
204 | dev->polling_mode |= NFCSIM_POLL_TARGET; | 203 | dev_kfree_skb(skb); |
205 | 204 | ||
206 | if (dev->polling_mode == NFCSIM_POLL_NONE) { | 205 | skb = ERR_PTR(-ENODEV); |
207 | DEV_ERR(dev, "Unsupported polling mode\n"); | ||
208 | rc = -EINVAL; | ||
209 | goto exit; | ||
210 | } | 206 | } |
211 | 207 | ||
212 | dev->initiator = 0; | 208 | dev->cb(dev->nfc_digital_dev, dev->arg, skb); |
213 | dev->curr_polling_mode = NFCSIM_POLL_NONE; | 209 | } |
214 | 210 | ||
215 | queue_delayed_work(wq, &dev->poll_work, 0); | 211 | static int nfcsim_send(struct nfc_digital_dev *ddev, struct sk_buff *skb, |
212 | u16 timeout, nfc_digital_cmd_complete_t cb, void *arg) | ||
213 | { | ||
214 | struct nfcsim *dev = nfc_digital_get_drvdata(ddev); | ||
215 | u8 delay; | ||
216 | 216 | ||
217 | DEV_DBG(dev, "Start polling: im: 0x%X, tm: 0x%X\n", im_protocols, | 217 | if (!dev->up) { |
218 | tm_protocols); | 218 | NFCSIM_ERR(dev, "Device is down\n"); |
219 | return -ENODEV; | ||
220 | } | ||
219 | 221 | ||
220 | rc = 0; | 222 | dev->recv_timeout = timeout; |
221 | exit: | 223 | dev->cb = cb; |
222 | mutex_unlock(&dev->lock); | 224 | dev->arg = arg; |
223 | 225 | ||
224 | return rc; | 226 | schedule_work(&dev->recv_work); |
225 | } | ||
226 | 227 | ||
227 | static void nfcsim_stop_poll(struct nfc_dev *nfc_dev) | 228 | if (dev->dropframe) { |
228 | { | 229 | NFCSIM_DBG(dev, "dropping frame (out of %d)\n", dev->dropframe); |
229 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 230 | dev_kfree_skb(skb); |
231 | dev->dropframe--; | ||
230 | 232 | ||
231 | DEV_DBG(dev, "Stop poll\n"); | 233 | return 0; |
234 | } | ||
232 | 235 | ||
233 | mutex_lock(&dev->lock); | 236 | if (skb) { |
237 | nfcsim_link_set_skb(dev->link_out, skb, dev->rf_tech, | ||
238 | dev->mode); | ||
234 | 239 | ||
235 | dev->polling_mode = NFCSIM_POLL_NONE; | 240 | /* Add random delay (between 3 and 10 ms) before sending data */ |
241 | get_random_bytes(&delay, 1); | ||
242 | delay = 3 + (delay & 0x07); | ||
236 | 243 | ||
237 | mutex_unlock(&dev->lock); | 244 | schedule_delayed_work(&dev->send_work, msecs_to_jiffies(delay)); |
245 | } | ||
238 | 246 | ||
239 | cancel_delayed_work_sync(&dev->poll_work); | 247 | return 0; |
240 | } | 248 | } |
241 | 249 | ||
242 | static int nfcsim_activate_target(struct nfc_dev *nfc_dev, | 250 | static void nfcsim_abort_cmd(struct nfc_digital_dev *ddev) |
243 | struct nfc_target *target, u32 protocol) | ||
244 | { | 251 | { |
245 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 252 | struct nfcsim *dev = nfc_digital_get_drvdata(ddev); |
246 | |||
247 | DEV_DBG(dev, "\n"); | ||
248 | 253 | ||
249 | return -ENOTSUPP; | 254 | nfcsim_link_recv_cancel(dev->link_in); |
250 | } | 255 | } |
251 | 256 | ||
252 | static void nfcsim_deactivate_target(struct nfc_dev *nfc_dev, | 257 | static int nfcsim_switch_rf(struct nfc_digital_dev *ddev, bool on) |
253 | struct nfc_target *target, u8 mode) | ||
254 | { | 258 | { |
255 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 259 | struct nfcsim *dev = nfc_digital_get_drvdata(ddev); |
260 | |||
261 | dev->up = on; | ||
256 | 262 | ||
257 | DEV_DBG(dev, "\n"); | 263 | return 0; |
258 | } | 264 | } |
259 | 265 | ||
260 | static void nfcsim_wq_recv(struct work_struct *work) | 266 | static int nfcsim_in_configure_hw(struct nfc_digital_dev *ddev, |
267 | int type, int param) | ||
261 | { | 268 | { |
262 | struct nfcsim *dev = container_of(work, struct nfcsim, | 269 | struct nfcsim *dev = nfc_digital_get_drvdata(ddev); |
263 | recv_work.work); | ||
264 | 270 | ||
265 | mutex_lock(&dev->lock); | 271 | switch (type) { |
272 | case NFC_DIGITAL_CONFIG_RF_TECH: | ||
273 | dev->up = true; | ||
274 | dev->mode = NFCSIM_MODE_INITIATOR; | ||
275 | dev->rf_tech = param; | ||
276 | break; | ||
266 | 277 | ||
267 | if (dev->shutting_down || !dev->up || !dev->clone_skb) { | 278 | case NFC_DIGITAL_CONFIG_FRAMING: |
268 | dev_kfree_skb(dev->clone_skb); | 279 | break; |
269 | goto exit; | ||
270 | } | ||
271 | 280 | ||
272 | if (dev->initiator) { | 281 | default: |
273 | if (!dev->cb) { | 282 | NFCSIM_ERR(dev, "Invalid configuration type: %d\n", type); |
274 | DEV_ERR(dev, "Null recv callback\n"); | 283 | return -EINVAL; |
275 | dev_kfree_skb(dev->clone_skb); | ||
276 | goto exit; | ||
277 | } | ||
278 | |||
279 | dev->cb(dev->cb_context, dev->clone_skb, 0); | ||
280 | dev->cb = NULL; | ||
281 | } else { | ||
282 | nfc_tm_data_received(dev->nfc_dev, dev->clone_skb); | ||
283 | } | 284 | } |
284 | 285 | ||
285 | exit: | 286 | return 0; |
286 | dev->clone_skb = NULL; | 287 | } |
287 | 288 | ||
288 | mutex_unlock(&dev->lock); | 289 | static int nfcsim_in_send_cmd(struct nfc_digital_dev *ddev, |
290 | struct sk_buff *skb, u16 timeout, | ||
291 | nfc_digital_cmd_complete_t cb, void *arg) | ||
292 | { | ||
293 | return nfcsim_send(ddev, skb, timeout, cb, arg); | ||
289 | } | 294 | } |
290 | 295 | ||
291 | static int nfcsim_tx(struct nfc_dev *nfc_dev, struct nfc_target *target, | 296 | static int nfcsim_tg_configure_hw(struct nfc_digital_dev *ddev, |
292 | struct sk_buff *skb, data_exchange_cb_t cb, | 297 | int type, int param) |
293 | void *cb_context) | ||
294 | { | 298 | { |
295 | struct nfcsim *dev = nfc_get_drvdata(nfc_dev); | 299 | struct nfcsim *dev = nfc_digital_get_drvdata(ddev); |
296 | struct nfcsim *peer = dev->peer_dev; | ||
297 | int err; | ||
298 | 300 | ||
299 | mutex_lock(&dev->lock); | 301 | switch (type) { |
302 | case NFC_DIGITAL_CONFIG_RF_TECH: | ||
303 | dev->up = true; | ||
304 | dev->mode = NFCSIM_MODE_TARGET; | ||
305 | dev->rf_tech = param; | ||
306 | break; | ||
300 | 307 | ||
301 | if (dev->shutting_down || !dev->up) { | 308 | case NFC_DIGITAL_CONFIG_FRAMING: |
302 | mutex_unlock(&dev->lock); | 309 | break; |
303 | err = -ENODEV; | 310 | |
304 | goto exit; | 311 | default: |
312 | NFCSIM_ERR(dev, "Invalid configuration type: %d\n", type); | ||
313 | return -EINVAL; | ||
305 | } | 314 | } |
306 | 315 | ||
307 | dev->cb = cb; | 316 | return 0; |
308 | dev->cb_context = cb_context; | 317 | } |
309 | 318 | ||
310 | mutex_unlock(&dev->lock); | 319 | static int nfcsim_tg_send_cmd(struct nfc_digital_dev *ddev, |
320 | struct sk_buff *skb, u16 timeout, | ||
321 | nfc_digital_cmd_complete_t cb, void *arg) | ||
322 | { | ||
323 | return nfcsim_send(ddev, skb, timeout, cb, arg); | ||
324 | } | ||
311 | 325 | ||
312 | mutex_lock(&peer->lock); | 326 | static int nfcsim_tg_listen(struct nfc_digital_dev *ddev, u16 timeout, |
327 | nfc_digital_cmd_complete_t cb, void *arg) | ||
328 | { | ||
329 | return nfcsim_send(ddev, NULL, timeout, cb, arg); | ||
330 | } | ||
313 | 331 | ||
314 | peer->clone_skb = skb_clone(skb, GFP_KERNEL); | 332 | static struct nfc_digital_ops nfcsim_digital_ops = { |
333 | .in_configure_hw = nfcsim_in_configure_hw, | ||
334 | .in_send_cmd = nfcsim_in_send_cmd, | ||
315 | 335 | ||
316 | if (!peer->clone_skb) { | 336 | .tg_listen = nfcsim_tg_listen, |
317 | DEV_ERR(dev, "skb_clone failed\n"); | 337 | .tg_configure_hw = nfcsim_tg_configure_hw, |
318 | mutex_unlock(&peer->lock); | 338 | .tg_send_cmd = nfcsim_tg_send_cmd, |
319 | err = -ENOMEM; | ||
320 | goto exit; | ||
321 | } | ||
322 | 339 | ||
323 | /* This simulates an arbitrary transmission delay between the 2 devices. | 340 | .abort_cmd = nfcsim_abort_cmd, |
324 | * If packet transmission occurs immediately between them, we have a | 341 | .switch_rf = nfcsim_switch_rf, |
325 | * non-stop flow of several tens of thousands SYMM packets per second | 342 | }; |
326 | * and a burning cpu. | 343 | |
327 | */ | 344 | static struct dentry *nfcsim_debugfs_root; |
328 | queue_delayed_work(wq, &peer->recv_work, | ||
329 | msecs_to_jiffies(dev->rx_delay)); | ||
330 | 345 | ||
331 | mutex_unlock(&peer->lock); | 346 | static void nfcsim_debugfs_init(void) |
347 | { | ||
348 | nfcsim_debugfs_root = debugfs_create_dir("nfcsim", NULL); | ||
332 | 349 | ||
333 | err = 0; | 350 | if (!nfcsim_debugfs_root) |
334 | exit: | 351 | pr_err("Could not create debugfs entry\n"); |
335 | dev_kfree_skb(skb); | ||
336 | 352 | ||
337 | return err; | ||
338 | } | 353 | } |
339 | 354 | ||
340 | static int nfcsim_im_transceive(struct nfc_dev *nfc_dev, | 355 | static void nfcsim_debugfs_remove(void) |
341 | struct nfc_target *target, struct sk_buff *skb, | ||
342 | data_exchange_cb_t cb, void *cb_context) | ||
343 | { | 356 | { |
344 | return nfcsim_tx(nfc_dev, target, skb, cb, cb_context); | 357 | debugfs_remove_recursive(nfcsim_debugfs_root); |
345 | } | 358 | } |
346 | 359 | ||
347 | static int nfcsim_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) | 360 | static void nfcsim_debugfs_init_dev(struct nfcsim *dev) |
348 | { | 361 | { |
349 | return nfcsim_tx(nfc_dev, NULL, skb, NULL, NULL); | 362 | struct dentry *dev_dir; |
350 | } | 363 | char devname[5]; /* nfcX\0 */ |
351 | 364 | u32 idx; | |
352 | static struct nfc_ops nfcsim_nfc_ops = { | 365 | int n; |
353 | .dev_up = nfcsim_dev_up, | ||
354 | .dev_down = nfcsim_dev_down, | ||
355 | .dep_link_up = nfcsim_dep_link_up, | ||
356 | .dep_link_down = nfcsim_dep_link_down, | ||
357 | .start_poll = nfcsim_start_poll, | ||
358 | .stop_poll = nfcsim_stop_poll, | ||
359 | .activate_target = nfcsim_activate_target, | ||
360 | .deactivate_target = nfcsim_deactivate_target, | ||
361 | .im_transceive = nfcsim_im_transceive, | ||
362 | .tm_send = nfcsim_tm_send, | ||
363 | }; | ||
364 | 366 | ||
365 | static void nfcsim_set_polling_mode(struct nfcsim *dev) | 367 | if (!nfcsim_debugfs_root) { |
366 | { | 368 | NFCSIM_ERR(dev, "nfcsim debugfs not initialized\n"); |
367 | if (dev->polling_mode == NFCSIM_POLL_NONE) { | ||
368 | dev->curr_polling_mode = NFCSIM_POLL_NONE; | ||
369 | return; | 369 | return; |
370 | } | 370 | } |
371 | 371 | ||
372 | if (dev->curr_polling_mode == NFCSIM_POLL_NONE) { | 372 | idx = dev->nfc_digital_dev->nfc_dev->idx; |
373 | if (dev->polling_mode & NFCSIM_POLL_INITIATOR) | 373 | n = snprintf(devname, sizeof(devname), "nfc%d", idx); |
374 | dev->curr_polling_mode = NFCSIM_POLL_INITIATOR; | 374 | if (n >= sizeof(devname)) { |
375 | else | 375 | NFCSIM_ERR(dev, "Could not compute dev name for dev %d\n", idx); |
376 | dev->curr_polling_mode = NFCSIM_POLL_TARGET; | ||
377 | |||
378 | return; | 376 | return; |
379 | } | 377 | } |
380 | 378 | ||
381 | if (dev->polling_mode == NFCSIM_POLL_DUAL) { | 379 | dev_dir = debugfs_create_dir(devname, nfcsim_debugfs_root); |
382 | if (dev->curr_polling_mode == NFCSIM_POLL_TARGET) | 380 | if (!dev_dir) { |
383 | dev->curr_polling_mode = NFCSIM_POLL_INITIATOR; | 381 | NFCSIM_ERR(dev, "Could not create debugfs entries for nfc%d\n", |
384 | else | 382 | idx); |
385 | dev->curr_polling_mode = NFCSIM_POLL_TARGET; | 383 | return; |
386 | } | 384 | } |
385 | |||
386 | debugfs_create_u8("dropframe", 0664, dev_dir, &dev->dropframe); | ||
387 | } | 387 | } |
388 | 388 | ||
389 | static void nfcsim_wq_poll(struct work_struct *work) | 389 | static struct nfcsim *nfcsim_device_new(struct nfcsim_link *link_in, |
390 | struct nfcsim_link *link_out) | ||
390 | { | 391 | { |
391 | struct nfcsim *dev = container_of(work, struct nfcsim, poll_work.work); | 392 | struct nfcsim *dev; |
392 | struct nfcsim *peer = dev->peer_dev; | 393 | int rc; |
393 | 394 | ||
394 | /* These work items run on an ordered workqueue and are therefore | 395 | dev = kzalloc(sizeof(struct nfcsim), GFP_KERNEL); |
395 | * serialized. So we can take both mutexes without being dead locked. | 396 | if (!dev) |
396 | */ | 397 | return ERR_PTR(-ENOMEM); |
397 | mutex_lock(&dev->lock); | ||
398 | mutex_lock(&peer->lock); | ||
399 | 398 | ||
400 | nfcsim_set_polling_mode(dev); | 399 | INIT_DELAYED_WORK(&dev->send_work, nfcsim_send_wq); |
400 | INIT_WORK(&dev->recv_work, nfcsim_recv_wq); | ||
401 | 401 | ||
402 | if (dev->curr_polling_mode == NFCSIM_POLL_NONE) { | 402 | dev->nfc_digital_dev = |
403 | DEV_DBG(dev, "Not polling\n"); | 403 | nfc_digital_allocate_device(&nfcsim_digital_ops, |
404 | goto unlock; | 404 | NFC_PROTO_NFC_DEP_MASK, |
405 | NFCSIM_CAPABILITIES, | ||
406 | 0, 0); | ||
407 | if (!dev->nfc_digital_dev) { | ||
408 | kfree(dev); | ||
409 | return ERR_PTR(-ENOMEM); | ||
405 | } | 410 | } |
406 | 411 | ||
407 | DEV_DBG(dev, "Polling as %s", | 412 | nfc_digital_set_drvdata(dev->nfc_digital_dev, dev); |
408 | dev->curr_polling_mode == NFCSIM_POLL_INITIATOR ? | ||
409 | "initiator\n" : "target\n"); | ||
410 | 413 | ||
411 | if (dev->curr_polling_mode == NFCSIM_POLL_TARGET) | 414 | dev->link_in = link_in; |
412 | goto sched_work; | 415 | dev->link_out = link_out; |
413 | 416 | ||
414 | if (peer->curr_polling_mode == NFCSIM_POLL_TARGET) { | 417 | rc = nfc_digital_register_device(dev->nfc_digital_dev); |
415 | peer->polling_mode = NFCSIM_POLL_NONE; | 418 | if (rc) { |
416 | dev->polling_mode = NFCSIM_POLL_NONE; | 419 | pr_err("Could not register digital device (%d)\n", rc); |
417 | 420 | nfc_digital_free_device(dev->nfc_digital_dev); | |
418 | dev->initiator = 1; | 421 | kfree(dev); |
419 | |||
420 | nfcsim_target_found(dev); | ||
421 | 422 | ||
422 | goto unlock; | 423 | return ERR_PTR(rc); |
423 | } | 424 | } |
424 | 425 | ||
425 | sched_work: | 426 | nfcsim_debugfs_init_dev(dev); |
426 | /* This defines the delay for an initiator to check if the other device | ||
427 | * is polling in target mode. | ||
428 | * If the device starts in dual mode polling, it switches between | ||
429 | * initiator and target at every round. | ||
430 | * Because the wq is ordered and only 1 work item is executed at a time, | ||
431 | * we'll always have one device polling as initiator and the other as | ||
432 | * target at some point, even if both are started in dual mode. | ||
433 | */ | ||
434 | queue_delayed_work(wq, &dev->poll_work, msecs_to_jiffies(200)); | ||
435 | 427 | ||
436 | unlock: | 428 | return dev; |
437 | mutex_unlock(&peer->lock); | ||
438 | mutex_unlock(&dev->lock); | ||
439 | } | 429 | } |
440 | 430 | ||
441 | static struct nfcsim *nfcsim_init_dev(void) | 431 | static void nfcsim_device_free(struct nfcsim *dev) |
442 | { | 432 | { |
443 | struct nfcsim *dev; | 433 | nfc_digital_unregister_device(dev->nfc_digital_dev); |
444 | int rc = -ENOMEM; | ||
445 | 434 | ||
446 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 435 | dev->up = false; |
447 | if (dev == NULL) | ||
448 | return ERR_PTR(-ENOMEM); | ||
449 | 436 | ||
450 | mutex_init(&dev->lock); | 437 | nfcsim_link_shutdown(dev->link_in); |
451 | 438 | ||
452 | INIT_DELAYED_WORK(&dev->recv_work, nfcsim_wq_recv); | 439 | cancel_delayed_work_sync(&dev->send_work); |
453 | INIT_DELAYED_WORK(&dev->poll_work, nfcsim_wq_poll); | 440 | cancel_work_sync(&dev->recv_work); |
454 | 441 | ||
455 | dev->nfc_dev = nfc_allocate_device(&nfcsim_nfc_ops, | 442 | nfc_digital_free_device(dev->nfc_digital_dev); |
456 | NFC_PROTO_NFC_DEP_MASK, | ||
457 | 0, 0); | ||
458 | if (!dev->nfc_dev) | ||
459 | goto error; | ||
460 | 443 | ||
461 | nfc_set_drvdata(dev->nfc_dev, dev); | ||
462 | |||
463 | rc = nfc_register_device(dev->nfc_dev); | ||
464 | if (rc) | ||
465 | goto free_nfc_dev; | ||
466 | |||
467 | dev->rx_delay = RX_DEFAULT_DELAY; | ||
468 | return dev; | ||
469 | |||
470 | free_nfc_dev: | ||
471 | nfc_free_device(dev->nfc_dev); | ||
472 | |||
473 | error: | ||
474 | kfree(dev); | 444 | kfree(dev); |
475 | |||
476 | return ERR_PTR(rc); | ||
477 | } | 445 | } |
478 | 446 | ||
479 | static void nfcsim_free_device(struct nfcsim *dev) | 447 | static struct nfcsim *dev0; |
480 | { | 448 | static struct nfcsim *dev1; |
481 | nfc_unregister_device(dev->nfc_dev); | ||
482 | |||
483 | nfc_free_device(dev->nfc_dev); | ||
484 | |||
485 | kfree(dev); | ||
486 | } | ||
487 | 449 | ||
488 | static int __init nfcsim_init(void) | 450 | static int __init nfcsim_init(void) |
489 | { | 451 | { |
452 | struct nfcsim_link *link0, *link1; | ||
490 | int rc; | 453 | int rc; |
491 | 454 | ||
492 | /* We need an ordered wq to ensure that poll_work items are executed | 455 | link0 = nfcsim_link_new(); |
493 | * one at a time. | 456 | link1 = nfcsim_link_new(); |
494 | */ | 457 | if (!link0 || !link1) { |
495 | wq = alloc_ordered_workqueue("nfcsim", 0); | ||
496 | if (!wq) { | ||
497 | rc = -ENOMEM; | 458 | rc = -ENOMEM; |
498 | goto exit; | 459 | goto exit_err; |
499 | } | 460 | } |
500 | 461 | ||
501 | dev0 = nfcsim_init_dev(); | 462 | nfcsim_debugfs_init(); |
463 | |||
464 | dev0 = nfcsim_device_new(link0, link1); | ||
502 | if (IS_ERR(dev0)) { | 465 | if (IS_ERR(dev0)) { |
503 | rc = PTR_ERR(dev0); | 466 | rc = PTR_ERR(dev0); |
504 | goto exit; | 467 | goto exit_err; |
505 | } | 468 | } |
506 | 469 | ||
507 | dev1 = nfcsim_init_dev(); | 470 | dev1 = nfcsim_device_new(link1, link0); |
508 | if (IS_ERR(dev1)) { | 471 | if (IS_ERR(dev1)) { |
509 | kfree(dev0); | 472 | nfcsim_device_free(dev0); |
510 | 473 | ||
511 | rc = PTR_ERR(dev1); | 474 | rc = PTR_ERR(dev1); |
512 | goto exit; | 475 | goto exit_err; |
513 | } | 476 | } |
514 | 477 | ||
515 | dev0->peer_dev = dev1; | 478 | pr_info("nfcsim " NFCSIM_VERSION " initialized\n"); |
516 | dev1->peer_dev = dev0; | 479 | |
480 | return 0; | ||
517 | 481 | ||
518 | pr_debug("NFCsim " NFCSIM_VERSION " initialized\n"); | 482 | exit_err: |
483 | pr_err("Failed to initialize nfcsim driver (%d)\n", rc); | ||
519 | 484 | ||
520 | rc = 0; | 485 | nfcsim_link_free(link0); |
521 | exit: | 486 | nfcsim_link_free(link1); |
522 | if (rc) | ||
523 | pr_err("Failed to initialize nfcsim driver (%d)\n", | ||
524 | rc); | ||
525 | 487 | ||
526 | return rc; | 488 | return rc; |
527 | } | 489 | } |
528 | 490 | ||
529 | static void __exit nfcsim_exit(void) | 491 | static void __exit nfcsim_exit(void) |
530 | { | 492 | { |
531 | nfcsim_cleanup_dev(dev0, 1); | 493 | struct nfcsim_link *link0, *link1; |
532 | nfcsim_cleanup_dev(dev1, 1); | 494 | |
495 | link0 = dev0->link_in; | ||
496 | link1 = dev0->link_out; | ||
497 | |||
498 | nfcsim_device_free(dev0); | ||
499 | nfcsim_device_free(dev1); | ||
533 | 500 | ||
534 | nfcsim_free_device(dev0); | 501 | nfcsim_link_free(link0); |
535 | nfcsim_free_device(dev1); | 502 | nfcsim_link_free(link1); |
536 | 503 | ||
537 | destroy_workqueue(wq); | 504 | nfcsim_debugfs_remove(); |
538 | } | 505 | } |
539 | 506 | ||
540 | module_init(nfcsim_init); | 507 | module_init(nfcsim_init); |
diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c index 8ca060324b6a..33ed78be2750 100644 --- a/drivers/nfc/pn533/usb.c +++ b/drivers/nfc/pn533/usb.c | |||
@@ -464,10 +464,8 @@ static int pn533_usb_probe(struct usb_interface *interface, | |||
464 | return -ENOMEM; | 464 | return -ENOMEM; |
465 | 465 | ||
466 | in_buf = kzalloc(in_buf_len, GFP_KERNEL); | 466 | in_buf = kzalloc(in_buf_len, GFP_KERNEL); |
467 | if (!in_buf) { | 467 | if (!in_buf) |
468 | rc = -ENOMEM; | 468 | return -ENOMEM; |
469 | goto out_free_phy; | ||
470 | } | ||
471 | 469 | ||
472 | phy->udev = usb_get_dev(interface_to_usbdev(interface)); | 470 | phy->udev = usb_get_dev(interface_to_usbdev(interface)); |
473 | phy->interface = interface; | 471 | phy->interface = interface; |
@@ -554,8 +552,7 @@ error: | |||
554 | usb_free_urb(phy->out_urb); | 552 | usb_free_urb(phy->out_urb); |
555 | usb_put_dev(phy->udev); | 553 | usb_put_dev(phy->udev); |
556 | kfree(in_buf); | 554 | kfree(in_buf); |
557 | out_free_phy: | 555 | |
558 | kfree(phy); | ||
559 | return rc; | 556 | return rc; |
560 | } | 557 | } |
561 | 558 | ||
diff --git a/drivers/nfc/port100.c b/drivers/nfc/port100.c index 87d509996704..2b2330b235e6 100644 --- a/drivers/nfc/port100.c +++ b/drivers/nfc/port100.c | |||
@@ -343,7 +343,26 @@ in_protocols[][PORT100_IN_MAX_NUM_PROTOCOLS + 1] = { | |||
343 | }, | 343 | }, |
344 | [NFC_DIGITAL_FRAMING_NFCF_NFC_DEP] = { | 344 | [NFC_DIGITAL_FRAMING_NFCF_NFC_DEP] = { |
345 | /* nfc_digital_framing_nfcf */ | 345 | /* nfc_digital_framing_nfcf */ |
346 | { PORT100_IN_PROT_END, 0 }, | 346 | { PORT100_IN_PROT_INITIAL_GUARD_TIME, 18 }, |
347 | { PORT100_IN_PROT_ADD_CRC, 1 }, | ||
348 | { PORT100_IN_PROT_CHECK_CRC, 1 }, | ||
349 | { PORT100_IN_PROT_MULTI_CARD, 0 }, | ||
350 | { PORT100_IN_PROT_ADD_PARITY, 0 }, | ||
351 | { PORT100_IN_PROT_CHECK_PARITY, 0 }, | ||
352 | { PORT100_IN_PROT_BITWISE_AC_RECV_MODE, 0 }, | ||
353 | { PORT100_IN_PROT_VALID_BIT_NUMBER, 8 }, | ||
354 | { PORT100_IN_PROT_CRYPTO1, 0 }, | ||
355 | { PORT100_IN_PROT_ADD_SOF, 0 }, | ||
356 | { PORT100_IN_PROT_CHECK_SOF, 0 }, | ||
357 | { PORT100_IN_PROT_ADD_EOF, 0 }, | ||
358 | { PORT100_IN_PROT_CHECK_EOF, 0 }, | ||
359 | { PORT100_IN_PROT_DEAF_TIME, 4 }, | ||
360 | { PORT100_IN_PROT_CRM, 0 }, | ||
361 | { PORT100_IN_PROT_CRM_MIN_LEN, 0 }, | ||
362 | { PORT100_IN_PROT_T1_TAG_FRAME, 0 }, | ||
363 | { PORT100_IN_PROT_RFCA, 0 }, | ||
364 | { PORT100_IN_PROT_GUARD_TIME_AT_INITIATOR, 6 }, | ||
365 | { PORT100_IN_PROT_END, 0 }, | ||
347 | }, | 366 | }, |
348 | [NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED] = { | 367 | [NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED] = { |
349 | { PORT100_IN_PROT_END, 0 }, | 368 | { PORT100_IN_PROT_END, 0 }, |
@@ -437,6 +456,12 @@ struct port100 { | |||
437 | struct urb *out_urb; | 456 | struct urb *out_urb; |
438 | struct urb *in_urb; | 457 | struct urb *in_urb; |
439 | 458 | ||
459 | /* This mutex protects the out_urb and avoids to submit a new command | ||
460 | * through port100_send_frame_async() while the previous one is being | ||
461 | * canceled through port100_abort_cmd(). | ||
462 | */ | ||
463 | struct mutex out_urb_lock; | ||
464 | |||
440 | struct work_struct cmd_complete_work; | 465 | struct work_struct cmd_complete_work; |
441 | 466 | ||
442 | u8 cmd_type; | 467 | u8 cmd_type; |
@@ -445,6 +470,9 @@ struct port100 { | |||
445 | * for any queuing/locking mechanism at driver level. | 470 | * for any queuing/locking mechanism at driver level. |
446 | */ | 471 | */ |
447 | struct port100_cmd *cmd; | 472 | struct port100_cmd *cmd; |
473 | |||
474 | bool cmd_cancel; | ||
475 | struct completion cmd_cancel_done; | ||
448 | }; | 476 | }; |
449 | 477 | ||
450 | struct port100_cmd { | 478 | struct port100_cmd { |
@@ -699,10 +727,27 @@ static int port100_send_ack(struct port100 *dev) | |||
699 | { | 727 | { |
700 | int rc; | 728 | int rc; |
701 | 729 | ||
730 | mutex_lock(&dev->out_urb_lock); | ||
731 | |||
732 | init_completion(&dev->cmd_cancel_done); | ||
733 | |||
734 | usb_kill_urb(dev->out_urb); | ||
735 | |||
702 | dev->out_urb->transfer_buffer = ack_frame; | 736 | dev->out_urb->transfer_buffer = ack_frame; |
703 | dev->out_urb->transfer_buffer_length = sizeof(ack_frame); | 737 | dev->out_urb->transfer_buffer_length = sizeof(ack_frame); |
704 | rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); | 738 | rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); |
705 | 739 | ||
740 | /* Set the cmd_cancel flag only if the URB has been successfully | ||
741 | * submitted. It will be reset by the out URB completion callback | ||
742 | * port100_send_complete(). | ||
743 | */ | ||
744 | dev->cmd_cancel = !rc; | ||
745 | |||
746 | mutex_unlock(&dev->out_urb_lock); | ||
747 | |||
748 | if (!rc) | ||
749 | wait_for_completion(&dev->cmd_cancel_done); | ||
750 | |||
706 | return rc; | 751 | return rc; |
707 | } | 752 | } |
708 | 753 | ||
@@ -711,6 +756,16 @@ static int port100_send_frame_async(struct port100 *dev, struct sk_buff *out, | |||
711 | { | 756 | { |
712 | int rc; | 757 | int rc; |
713 | 758 | ||
759 | mutex_lock(&dev->out_urb_lock); | ||
760 | |||
761 | /* A command cancel frame as been sent through dev->out_urb. Don't try | ||
762 | * to submit a new one. | ||
763 | */ | ||
764 | if (dev->cmd_cancel) { | ||
765 | rc = -EAGAIN; | ||
766 | goto exit; | ||
767 | } | ||
768 | |||
714 | dev->out_urb->transfer_buffer = out->data; | 769 | dev->out_urb->transfer_buffer = out->data; |
715 | dev->out_urb->transfer_buffer_length = out->len; | 770 | dev->out_urb->transfer_buffer_length = out->len; |
716 | 771 | ||
@@ -722,16 +777,15 @@ static int port100_send_frame_async(struct port100 *dev, struct sk_buff *out, | |||
722 | 777 | ||
723 | rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); | 778 | rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); |
724 | if (rc) | 779 | if (rc) |
725 | return rc; | 780 | goto exit; |
726 | 781 | ||
727 | rc = port100_submit_urb_for_ack(dev, GFP_KERNEL); | 782 | rc = port100_submit_urb_for_ack(dev, GFP_KERNEL); |
728 | if (rc) | 783 | if (rc) |
729 | goto error; | 784 | usb_unlink_urb(dev->out_urb); |
730 | 785 | ||
731 | return 0; | 786 | exit: |
787 | mutex_unlock(&dev->out_urb_lock); | ||
732 | 788 | ||
733 | error: | ||
734 | usb_unlink_urb(dev->out_urb); | ||
735 | return rc; | 789 | return rc; |
736 | } | 790 | } |
737 | 791 | ||
@@ -790,6 +844,12 @@ static int port100_send_cmd_async(struct port100 *dev, u8 cmd_code, | |||
790 | PORT100_FRAME_MAX_PAYLOAD_LEN + | 844 | PORT100_FRAME_MAX_PAYLOAD_LEN + |
791 | PORT100_FRAME_TAIL_LEN; | 845 | PORT100_FRAME_TAIL_LEN; |
792 | 846 | ||
847 | if (dev->cmd) { | ||
848 | nfc_err(&dev->interface->dev, | ||
849 | "A command is still in process\n"); | ||
850 | return -EBUSY; | ||
851 | } | ||
852 | |||
793 | resp = alloc_skb(resp_len, GFP_KERNEL); | 853 | resp = alloc_skb(resp_len, GFP_KERNEL); |
794 | if (!resp) | 854 | if (!resp) |
795 | return -ENOMEM; | 855 | return -ENOMEM; |
@@ -867,6 +927,11 @@ static void port100_send_complete(struct urb *urb) | |||
867 | { | 927 | { |
868 | struct port100 *dev = urb->context; | 928 | struct port100 *dev = urb->context; |
869 | 929 | ||
930 | if (dev->cmd_cancel) { | ||
931 | dev->cmd_cancel = false; | ||
932 | complete(&dev->cmd_cancel_done); | ||
933 | } | ||
934 | |||
870 | switch (urb->status) { | 935 | switch (urb->status) { |
871 | case 0: | 936 | case 0: |
872 | break; /* success */ | 937 | break; /* success */ |
@@ -985,6 +1050,10 @@ static int port100_switch_rf(struct nfc_digital_dev *ddev, bool on) | |||
985 | 1050 | ||
986 | *skb_put(skb, 1) = on ? 1 : 0; | 1051 | *skb_put(skb, 1) = on ? 1 : 0; |
987 | 1052 | ||
1053 | /* Cancel the last command if the device is being switched off */ | ||
1054 | if (!on) | ||
1055 | port100_abort_cmd(ddev); | ||
1056 | |||
988 | resp = port100_send_cmd_sync(dev, PORT100_CMD_SWITCH_RF, skb); | 1057 | resp = port100_send_cmd_sync(dev, PORT100_CMD_SWITCH_RF, skb); |
989 | 1058 | ||
990 | if (IS_ERR(resp)) | 1059 | if (IS_ERR(resp)) |
@@ -1430,6 +1499,7 @@ static int port100_probe(struct usb_interface *interface, | |||
1430 | if (!dev) | 1499 | if (!dev) |
1431 | return -ENOMEM; | 1500 | return -ENOMEM; |
1432 | 1501 | ||
1502 | mutex_init(&dev->out_urb_lock); | ||
1433 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); | 1503 | dev->udev = usb_get_dev(interface_to_usbdev(interface)); |
1434 | dev->interface = interface; | 1504 | dev->interface = interface; |
1435 | usb_set_intfdata(interface, dev); | 1505 | usb_set_intfdata(interface, dev); |
diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c index 10842b7051b3..26c9dbbccb0c 100644 --- a/drivers/nfc/trf7970a.c +++ b/drivers/nfc/trf7970a.c | |||
@@ -1048,6 +1048,10 @@ static int trf7970a_init(struct trf7970a *trf) | |||
1048 | if (ret) | 1048 | if (ret) |
1049 | goto err_out; | 1049 | goto err_out; |
1050 | 1050 | ||
1051 | ret = trf7970a_write(trf, TRF7970A_NFC_TARGET_LEVEL, 0); | ||
1052 | if (ret) | ||
1053 | goto err_out; | ||
1054 | |||
1051 | usleep_range(1000, 2000); | 1055 | usleep_range(1000, 2000); |
1052 | 1056 | ||
1053 | trf->chip_status_ctrl &= ~TRF7970A_CHIP_STATUS_RF_ON; | 1057 | trf->chip_status_ctrl &= ~TRF7970A_CHIP_STATUS_RF_ON; |