1 // SPDX-License-Identifier: GPL-2.0-only
3 * Marvell NFC-over-USB driver: USB interface related functions
5 * Copyright (C) 2014, Marvell International Ltd.
8 #include <linux/module.h>
10 #include <linux/nfc.h>
11 #include <net/nfc/nci.h>
12 #include <net/nfc/nci_core.h>
15 static struct usb_device_id nfcmrvl_table
[] = {
16 { USB_DEVICE_AND_INTERFACE_INFO(0x1286, 0x2046,
17 USB_CLASS_VENDOR_SPEC
, 4, 1) },
18 { } /* Terminating entry */
21 MODULE_DEVICE_TABLE(usb
, nfcmrvl_table
);
23 #define NFCMRVL_USB_BULK_RUNNING 1
24 #define NFCMRVL_USB_SUSPENDING 2
26 struct nfcmrvl_usb_drv_data
{
27 struct usb_device
*udev
;
28 struct usb_interface
*intf
;
30 struct work_struct waker
;
31 struct usb_anchor tx_anchor
;
32 struct usb_anchor bulk_anchor
;
33 struct usb_anchor deferred
;
35 /* protects tx_in_flight */
37 struct usb_endpoint_descriptor
*bulk_tx_ep
;
38 struct usb_endpoint_descriptor
*bulk_rx_ep
;
40 struct nfcmrvl_private
*priv
;
43 static int nfcmrvl_inc_tx(struct nfcmrvl_usb_drv_data
*drv_data
)
48 spin_lock_irqsave(&drv_data
->txlock
, flags
);
49 rv
= test_bit(NFCMRVL_USB_SUSPENDING
, &drv_data
->flags
);
51 drv_data
->tx_in_flight
++;
52 spin_unlock_irqrestore(&drv_data
->txlock
, flags
);
57 static void nfcmrvl_bulk_complete(struct urb
*urb
)
59 struct nfcmrvl_usb_drv_data
*drv_data
= urb
->context
;
62 dev_dbg(&drv_data
->udev
->dev
, "urb %p status %d count %d\n",
63 urb
, urb
->status
, urb
->actual_length
);
65 if (!test_bit(NFCMRVL_NCI_RUNNING
, &drv_data
->flags
))
71 skb
= nci_skb_alloc(drv_data
->priv
->ndev
, urb
->actual_length
,
74 nfc_err(&drv_data
->udev
->dev
, "failed to alloc mem\n");
76 skb_put_data(skb
, urb
->transfer_buffer
,
78 if (nfcmrvl_nci_recv_frame(drv_data
->priv
, skb
) < 0)
79 nfc_err(&drv_data
->udev
->dev
,
80 "corrupted Rx packet\n");
84 if (!test_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
))
87 usb_anchor_urb(urb
, &drv_data
->bulk_anchor
);
88 usb_mark_last_busy(drv_data
->udev
);
90 err
= usb_submit_urb(urb
, GFP_ATOMIC
);
92 /* -EPERM: urb is being killed;
93 * -ENODEV: device got disconnected
95 if (err
!= -EPERM
&& err
!= -ENODEV
)
96 nfc_err(&drv_data
->udev
->dev
,
97 "urb %p failed to resubmit (%d)\n", urb
, -err
);
98 usb_unanchor_urb(urb
);
103 nfcmrvl_submit_bulk_urb(struct nfcmrvl_usb_drv_data
*drv_data
, gfp_t mem_flags
)
108 int err
, size
= NFCMRVL_NCI_MAX_EVENT_SIZE
;
110 if (!drv_data
->bulk_rx_ep
)
113 urb
= usb_alloc_urb(0, mem_flags
);
117 buf
= kmalloc(size
, mem_flags
);
123 pipe
= usb_rcvbulkpipe(drv_data
->udev
,
124 drv_data
->bulk_rx_ep
->bEndpointAddress
);
126 usb_fill_bulk_urb(urb
, drv_data
->udev
, pipe
, buf
, size
,
127 nfcmrvl_bulk_complete
, drv_data
);
129 urb
->transfer_flags
|= URB_FREE_BUFFER
;
131 usb_mark_last_busy(drv_data
->udev
);
132 usb_anchor_urb(urb
, &drv_data
->bulk_anchor
);
134 err
= usb_submit_urb(urb
, mem_flags
);
136 if (err
!= -EPERM
&& err
!= -ENODEV
)
137 nfc_err(&drv_data
->udev
->dev
,
138 "urb %p submission failed (%d)\n", urb
, -err
);
139 usb_unanchor_urb(urb
);
147 static void nfcmrvl_tx_complete(struct urb
*urb
)
149 struct sk_buff
*skb
= urb
->context
;
150 struct nci_dev
*ndev
= (struct nci_dev
*)skb
->dev
;
151 struct nfcmrvl_private
*priv
= nci_get_drvdata(ndev
);
152 struct nfcmrvl_usb_drv_data
*drv_data
= priv
->drv_data
;
155 nfc_info(priv
->dev
, "urb %p status %d count %d\n",
156 urb
, urb
->status
, urb
->actual_length
);
158 spin_lock_irqsave(&drv_data
->txlock
, flags
);
159 drv_data
->tx_in_flight
--;
160 spin_unlock_irqrestore(&drv_data
->txlock
, flags
);
162 kfree(urb
->setup_packet
);
166 static int nfcmrvl_usb_nci_open(struct nfcmrvl_private
*priv
)
168 struct nfcmrvl_usb_drv_data
*drv_data
= priv
->drv_data
;
171 err
= usb_autopm_get_interface(drv_data
->intf
);
175 drv_data
->intf
->needs_remote_wakeup
= 1;
177 err
= nfcmrvl_submit_bulk_urb(drv_data
, GFP_KERNEL
);
181 set_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
);
182 nfcmrvl_submit_bulk_urb(drv_data
, GFP_KERNEL
);
184 usb_autopm_put_interface(drv_data
->intf
);
188 usb_autopm_put_interface(drv_data
->intf
);
192 static void nfcmrvl_usb_stop_traffic(struct nfcmrvl_usb_drv_data
*drv_data
)
194 usb_kill_anchored_urbs(&drv_data
->bulk_anchor
);
197 static int nfcmrvl_usb_nci_close(struct nfcmrvl_private
*priv
)
199 struct nfcmrvl_usb_drv_data
*drv_data
= priv
->drv_data
;
202 cancel_work_sync(&drv_data
->waker
);
204 clear_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
);
206 nfcmrvl_usb_stop_traffic(drv_data
);
207 usb_kill_anchored_urbs(&drv_data
->tx_anchor
);
208 err
= usb_autopm_get_interface(drv_data
->intf
);
212 drv_data
->intf
->needs_remote_wakeup
= 0;
213 usb_autopm_put_interface(drv_data
->intf
);
216 usb_scuttle_anchored_urbs(&drv_data
->deferred
);
220 static int nfcmrvl_usb_nci_send(struct nfcmrvl_private
*priv
,
223 struct nfcmrvl_usb_drv_data
*drv_data
= priv
->drv_data
;
228 if (!drv_data
->bulk_tx_ep
)
231 urb
= usb_alloc_urb(0, GFP_ATOMIC
);
235 pipe
= usb_sndbulkpipe(drv_data
->udev
,
236 drv_data
->bulk_tx_ep
->bEndpointAddress
);
238 usb_fill_bulk_urb(urb
, drv_data
->udev
, pipe
, skb
->data
, skb
->len
,
239 nfcmrvl_tx_complete
, skb
);
241 err
= nfcmrvl_inc_tx(drv_data
);
243 usb_anchor_urb(urb
, &drv_data
->deferred
);
244 schedule_work(&drv_data
->waker
);
249 usb_anchor_urb(urb
, &drv_data
->tx_anchor
);
251 err
= usb_submit_urb(urb
, GFP_ATOMIC
);
253 if (err
!= -EPERM
&& err
!= -ENODEV
)
254 nfc_err(&drv_data
->udev
->dev
,
255 "urb %p submission failed (%d)\n", urb
, -err
);
256 kfree(urb
->setup_packet
);
257 usb_unanchor_urb(urb
);
259 usb_mark_last_busy(drv_data
->udev
);
267 static const struct nfcmrvl_if_ops usb_ops
= {
268 .nci_open
= nfcmrvl_usb_nci_open
,
269 .nci_close
= nfcmrvl_usb_nci_close
,
270 .nci_send
= nfcmrvl_usb_nci_send
,
273 static void nfcmrvl_waker(struct work_struct
*work
)
275 struct nfcmrvl_usb_drv_data
*drv_data
=
276 container_of(work
, struct nfcmrvl_usb_drv_data
, waker
);
279 err
= usb_autopm_get_interface(drv_data
->intf
);
283 usb_autopm_put_interface(drv_data
->intf
);
286 static int nfcmrvl_probe(struct usb_interface
*intf
,
287 const struct usb_device_id
*id
)
289 struct nfcmrvl_usb_drv_data
*drv_data
;
290 struct nfcmrvl_private
*priv
;
292 struct usb_device
*udev
= interface_to_usbdev(intf
);
293 struct nfcmrvl_platform_data config
;
295 /* No configuration for USB */
296 memset(&config
, 0, sizeof(config
));
297 config
.reset_n_io
= -EINVAL
;
299 nfc_info(&udev
->dev
, "intf %p id %p\n", intf
, id
);
301 drv_data
= devm_kzalloc(&intf
->dev
, sizeof(*drv_data
), GFP_KERNEL
);
305 for (i
= 0; i
< intf
->cur_altsetting
->desc
.bNumEndpoints
; i
++) {
306 struct usb_endpoint_descriptor
*ep_desc
;
308 ep_desc
= &intf
->cur_altsetting
->endpoint
[i
].desc
;
310 if (!drv_data
->bulk_tx_ep
&&
311 usb_endpoint_is_bulk_out(ep_desc
)) {
312 drv_data
->bulk_tx_ep
= ep_desc
;
313 } else if (!drv_data
->bulk_rx_ep
&&
314 usb_endpoint_is_bulk_in(ep_desc
)) {
315 drv_data
->bulk_rx_ep
= ep_desc
;
319 if (!drv_data
->bulk_tx_ep
|| !drv_data
->bulk_rx_ep
)
322 drv_data
->udev
= udev
;
323 drv_data
->intf
= intf
;
325 INIT_WORK(&drv_data
->waker
, nfcmrvl_waker
);
326 spin_lock_init(&drv_data
->txlock
);
328 init_usb_anchor(&drv_data
->tx_anchor
);
329 init_usb_anchor(&drv_data
->bulk_anchor
);
330 init_usb_anchor(&drv_data
->deferred
);
332 priv
= nfcmrvl_nci_register_dev(NFCMRVL_PHY_USB
, drv_data
, &usb_ops
,
333 &intf
->dev
, &config
);
335 return PTR_ERR(priv
);
337 drv_data
->priv
= priv
;
338 drv_data
->priv
->support_fw_dnld
= false;
340 usb_set_intfdata(intf
, drv_data
);
345 static void nfcmrvl_disconnect(struct usb_interface
*intf
)
347 struct nfcmrvl_usb_drv_data
*drv_data
= usb_get_intfdata(intf
);
352 nfc_info(&drv_data
->udev
->dev
, "intf %p\n", intf
);
354 nfcmrvl_nci_unregister_dev(drv_data
->priv
);
356 usb_set_intfdata(drv_data
->intf
, NULL
);
360 static int nfcmrvl_suspend(struct usb_interface
*intf
, pm_message_t message
)
362 struct nfcmrvl_usb_drv_data
*drv_data
= usb_get_intfdata(intf
);
364 nfc_info(&drv_data
->udev
->dev
, "intf %p\n", intf
);
366 if (drv_data
->suspend_count
++)
369 spin_lock_irq(&drv_data
->txlock
);
370 if (!(PMSG_IS_AUTO(message
) && drv_data
->tx_in_flight
)) {
371 set_bit(NFCMRVL_USB_SUSPENDING
, &drv_data
->flags
);
372 spin_unlock_irq(&drv_data
->txlock
);
374 spin_unlock_irq(&drv_data
->txlock
);
375 drv_data
->suspend_count
--;
379 nfcmrvl_usb_stop_traffic(drv_data
);
380 usb_kill_anchored_urbs(&drv_data
->tx_anchor
);
385 static void nfcmrvl_play_deferred(struct nfcmrvl_usb_drv_data
*drv_data
)
390 while ((urb
= usb_get_from_anchor(&drv_data
->deferred
))) {
391 usb_anchor_urb(urb
, &drv_data
->tx_anchor
);
393 err
= usb_submit_urb(urb
, GFP_ATOMIC
);
395 kfree(urb
->setup_packet
);
396 usb_unanchor_urb(urb
);
401 drv_data
->tx_in_flight
++;
405 /* Cleanup the rest deferred urbs. */
406 while ((urb
= usb_get_from_anchor(&drv_data
->deferred
))) {
407 kfree(urb
->setup_packet
);
412 static int nfcmrvl_resume(struct usb_interface
*intf
)
414 struct nfcmrvl_usb_drv_data
*drv_data
= usb_get_intfdata(intf
);
417 nfc_info(&drv_data
->udev
->dev
, "intf %p\n", intf
);
419 if (--drv_data
->suspend_count
)
422 if (!test_bit(NFCMRVL_NCI_RUNNING
, &drv_data
->flags
))
425 if (test_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
)) {
426 err
= nfcmrvl_submit_bulk_urb(drv_data
, GFP_NOIO
);
428 clear_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
);
432 nfcmrvl_submit_bulk_urb(drv_data
, GFP_NOIO
);
435 spin_lock_irq(&drv_data
->txlock
);
436 nfcmrvl_play_deferred(drv_data
);
437 clear_bit(NFCMRVL_USB_SUSPENDING
, &drv_data
->flags
);
438 spin_unlock_irq(&drv_data
->txlock
);
443 usb_scuttle_anchored_urbs(&drv_data
->deferred
);
445 spin_lock_irq(&drv_data
->txlock
);
446 clear_bit(NFCMRVL_USB_SUSPENDING
, &drv_data
->flags
);
447 spin_unlock_irq(&drv_data
->txlock
);
453 static struct usb_driver nfcmrvl_usb_driver
= {
455 .probe
= nfcmrvl_probe
,
456 .disconnect
= nfcmrvl_disconnect
,
458 .suspend
= nfcmrvl_suspend
,
459 .resume
= nfcmrvl_resume
,
460 .reset_resume
= nfcmrvl_resume
,
462 .id_table
= nfcmrvl_table
,
463 .supports_autosuspend
= 1,
464 .disable_hub_initiated_lpm
= 1,
467 module_usb_driver(nfcmrvl_usb_driver
);
469 MODULE_AUTHOR("Marvell International Ltd.");
470 MODULE_DESCRIPTION("Marvell NFC-over-USB driver");
471 MODULE_LICENSE("GPL v2");