2 * Marvell NFC-over-USB driver: USB interface related functions
4 * Copyright (C) 2014, Marvell International Ltd.
6 * This software file (the "File") is distributed by Marvell International
7 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
8 * (the "License"). You may use, redistribute and/or modify this File in
9 * accordance with the terms and conditions of the License, a copy of which
10 * is available on the worldwide web at
11 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
13 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
14 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
15 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
16 * this warranty disclaimer.
19 #include <linux/module.h>
20 #include <linux/usb.h>
21 #include <linux/nfc.h>
22 #include <net/nfc/nci.h>
23 #include <net/nfc/nci_core.h>
28 static struct usb_device_id nfcmrvl_table
[] = {
29 { USB_DEVICE_INTERFACE_CLASS(0x1286, 0x2046, 0xff) },
30 { } /* Terminating entry */
33 MODULE_DEVICE_TABLE(usb
, nfcmrvl_table
);
35 #define NFCMRVL_USB_BULK_RUNNING 1
36 #define NFCMRVL_USB_SUSPENDING 2
38 struct nfcmrvl_usb_drv_data
{
39 struct usb_device
*udev
;
40 struct usb_interface
*intf
;
42 struct work_struct waker
;
43 struct usb_anchor tx_anchor
;
44 struct usb_anchor bulk_anchor
;
45 struct usb_anchor deferred
;
47 /* protects tx_in_flight */
49 struct usb_endpoint_descriptor
*bulk_tx_ep
;
50 struct usb_endpoint_descriptor
*bulk_rx_ep
;
52 struct nfcmrvl_private
*priv
;
55 static int nfcmrvl_inc_tx(struct nfcmrvl_usb_drv_data
*drv_data
)
60 spin_lock_irqsave(&drv_data
->txlock
, flags
);
61 rv
= test_bit(NFCMRVL_USB_SUSPENDING
, &drv_data
->flags
);
63 drv_data
->tx_in_flight
++;
64 spin_unlock_irqrestore(&drv_data
->txlock
, flags
);
69 static void nfcmrvl_bulk_complete(struct urb
*urb
)
71 struct nfcmrvl_usb_drv_data
*drv_data
= urb
->context
;
74 dev_dbg(&drv_data
->udev
->dev
, "urb %p status %d count %d",
75 urb
, urb
->status
, urb
->actual_length
);
77 if (!test_bit(NFCMRVL_NCI_RUNNING
, &drv_data
->flags
))
81 if (nfcmrvl_nci_recv_frame(drv_data
->priv
, urb
->transfer_buffer
,
82 urb
->actual_length
) < 0)
83 nfc_err(&drv_data
->udev
->dev
, "corrupted Rx packet");
86 if (!test_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
))
89 usb_anchor_urb(urb
, &drv_data
->bulk_anchor
);
90 usb_mark_last_busy(drv_data
->udev
);
92 err
= usb_submit_urb(urb
, GFP_ATOMIC
);
94 /* -EPERM: urb is being killed;
95 * -ENODEV: device got disconnected
97 if (err
!= -EPERM
&& err
!= -ENODEV
)
98 nfc_err(&drv_data
->udev
->dev
,
99 "urb %p failed to resubmit (%d)", urb
, -err
);
100 usb_unanchor_urb(urb
);
105 nfcmrvl_submit_bulk_urb(struct nfcmrvl_usb_drv_data
*drv_data
, gfp_t mem_flags
)
110 int err
, size
= NFCMRVL_NCI_MAX_EVENT_SIZE
;
112 if (!drv_data
->bulk_rx_ep
)
115 urb
= usb_alloc_urb(0, mem_flags
);
119 buf
= kmalloc(size
, mem_flags
);
125 pipe
= usb_rcvbulkpipe(drv_data
->udev
,
126 drv_data
->bulk_rx_ep
->bEndpointAddress
);
128 usb_fill_bulk_urb(urb
, drv_data
->udev
, pipe
, buf
, size
,
129 nfcmrvl_bulk_complete
, drv_data
);
131 urb
->transfer_flags
|= URB_FREE_BUFFER
;
133 usb_mark_last_busy(drv_data
->udev
);
134 usb_anchor_urb(urb
, &drv_data
->bulk_anchor
);
136 err
= usb_submit_urb(urb
, mem_flags
);
138 if (err
!= -EPERM
&& err
!= -ENODEV
)
139 nfc_err(&drv_data
->udev
->dev
,
140 "urb %p submission failed (%d)", urb
, -err
);
141 usb_unanchor_urb(urb
);
149 static void nfcmrvl_tx_complete(struct urb
*urb
)
151 struct sk_buff
*skb
= urb
->context
;
152 struct nci_dev
*ndev
= (struct nci_dev
*)skb
->dev
;
153 struct nfcmrvl_private
*priv
= nci_get_drvdata(ndev
);
154 struct nfcmrvl_usb_drv_data
*drv_data
= priv
->drv_data
;
156 nfc_info(priv
->dev
, "urb %p status %d count %d",
157 urb
, urb
->status
, urb
->actual_length
);
159 spin_lock(&drv_data
->txlock
);
160 drv_data
->tx_in_flight
--;
161 spin_unlock(&drv_data
->txlock
);
163 kfree(urb
->setup_packet
);
167 static int nfcmrvl_usb_nci_open(struct nfcmrvl_private
*priv
)
169 struct nfcmrvl_usb_drv_data
*drv_data
= priv
->drv_data
;
172 err
= usb_autopm_get_interface(drv_data
->intf
);
176 drv_data
->intf
->needs_remote_wakeup
= 1;
178 err
= nfcmrvl_submit_bulk_urb(drv_data
, GFP_KERNEL
);
182 set_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
);
183 nfcmrvl_submit_bulk_urb(drv_data
, GFP_KERNEL
);
185 usb_autopm_put_interface(drv_data
->intf
);
189 usb_autopm_put_interface(drv_data
->intf
);
193 static void nfcmrvl_usb_stop_traffic(struct nfcmrvl_usb_drv_data
*drv_data
)
195 usb_kill_anchored_urbs(&drv_data
->bulk_anchor
);
198 static int nfcmrvl_usb_nci_close(struct nfcmrvl_private
*priv
)
200 struct nfcmrvl_usb_drv_data
*drv_data
= priv
->drv_data
;
203 cancel_work_sync(&drv_data
->waker
);
205 clear_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
);
207 nfcmrvl_usb_stop_traffic(drv_data
);
208 usb_kill_anchored_urbs(&drv_data
->tx_anchor
);
209 err
= usb_autopm_get_interface(drv_data
->intf
);
213 drv_data
->intf
->needs_remote_wakeup
= 0;
214 usb_autopm_put_interface(drv_data
->intf
);
217 usb_scuttle_anchored_urbs(&drv_data
->deferred
);
221 static int nfcmrvl_usb_nci_send(struct nfcmrvl_private
*priv
,
224 struct nfcmrvl_usb_drv_data
*drv_data
= priv
->drv_data
;
229 if (!drv_data
->bulk_tx_ep
)
232 urb
= usb_alloc_urb(0, GFP_ATOMIC
);
236 pipe
= usb_sndbulkpipe(drv_data
->udev
,
237 drv_data
->bulk_tx_ep
->bEndpointAddress
);
239 usb_fill_bulk_urb(urb
, drv_data
->udev
, pipe
, skb
->data
, skb
->len
,
240 nfcmrvl_tx_complete
, skb
);
242 err
= nfcmrvl_inc_tx(drv_data
);
244 usb_anchor_urb(urb
, &drv_data
->deferred
);
245 schedule_work(&drv_data
->waker
);
250 usb_anchor_urb(urb
, &drv_data
->tx_anchor
);
252 err
= usb_submit_urb(urb
, GFP_ATOMIC
);
254 if (err
!= -EPERM
&& err
!= -ENODEV
)
255 nfc_err(&drv_data
->udev
->dev
,
256 "urb %p submission failed (%d)", urb
, -err
);
257 kfree(urb
->setup_packet
);
258 usb_unanchor_urb(urb
);
260 usb_mark_last_busy(drv_data
->udev
);
268 static struct nfcmrvl_if_ops usb_ops
= {
269 .nci_open
= nfcmrvl_usb_nci_open
,
270 .nci_close
= nfcmrvl_usb_nci_close
,
271 .nci_send
= nfcmrvl_usb_nci_send
,
274 static void nfcmrvl_waker(struct work_struct
*work
)
276 struct nfcmrvl_usb_drv_data
*drv_data
=
277 container_of(work
, struct nfcmrvl_usb_drv_data
, waker
);
280 err
= usb_autopm_get_interface(drv_data
->intf
);
284 usb_autopm_put_interface(drv_data
->intf
);
287 static int nfcmrvl_probe(struct usb_interface
*intf
,
288 const struct usb_device_id
*id
)
290 struct usb_endpoint_descriptor
*ep_desc
;
291 struct nfcmrvl_usb_drv_data
*drv_data
;
292 struct nfcmrvl_private
*priv
;
294 struct usb_device
*udev
= interface_to_usbdev(intf
);
296 nfc_info(&udev
->dev
, "intf %p id %p", intf
, id
);
298 drv_data
= devm_kzalloc(&intf
->dev
, sizeof(*drv_data
), GFP_KERNEL
);
302 for (i
= 0; i
< intf
->cur_altsetting
->desc
.bNumEndpoints
; i
++) {
303 ep_desc
= &intf
->cur_altsetting
->endpoint
[i
].desc
;
305 if (!drv_data
->bulk_tx_ep
&&
306 usb_endpoint_is_bulk_out(ep_desc
)) {
307 drv_data
->bulk_tx_ep
= ep_desc
;
311 if (!drv_data
->bulk_rx_ep
&&
312 usb_endpoint_is_bulk_in(ep_desc
)) {
313 drv_data
->bulk_rx_ep
= ep_desc
;
318 if (!drv_data
->bulk_tx_ep
|| !drv_data
->bulk_rx_ep
)
321 drv_data
->udev
= udev
;
322 drv_data
->intf
= intf
;
324 INIT_WORK(&drv_data
->waker
, nfcmrvl_waker
);
325 spin_lock_init(&drv_data
->txlock
);
327 init_usb_anchor(&drv_data
->tx_anchor
);
328 init_usb_anchor(&drv_data
->bulk_anchor
);
329 init_usb_anchor(&drv_data
->deferred
);
331 priv
= nfcmrvl_nci_register_dev(drv_data
, &usb_ops
,
332 &drv_data
->udev
->dev
);
334 return PTR_ERR(priv
);
336 drv_data
->priv
= priv
;
337 priv
->dev
= &drv_data
->udev
->dev
;
339 usb_set_intfdata(intf
, drv_data
);
344 static void nfcmrvl_disconnect(struct usb_interface
*intf
)
346 struct nfcmrvl_usb_drv_data
*drv_data
= usb_get_intfdata(intf
);
351 nfc_info(&drv_data
->udev
->dev
, "intf %p", intf
);
353 nfcmrvl_nci_unregister_dev(drv_data
->priv
);
355 usb_set_intfdata(drv_data
->intf
, NULL
);
359 static int nfcmrvl_suspend(struct usb_interface
*intf
, pm_message_t message
)
361 struct nfcmrvl_usb_drv_data
*drv_data
= usb_get_intfdata(intf
);
363 nfc_info(&drv_data
->udev
->dev
, "intf %p", intf
);
365 if (drv_data
->suspend_count
++)
368 spin_lock_irq(&drv_data
->txlock
);
369 if (!(PMSG_IS_AUTO(message
) && drv_data
->tx_in_flight
)) {
370 set_bit(NFCMRVL_USB_SUSPENDING
, &drv_data
->flags
);
371 spin_unlock_irq(&drv_data
->txlock
);
373 spin_unlock_irq(&drv_data
->txlock
);
374 drv_data
->suspend_count
--;
378 nfcmrvl_usb_stop_traffic(drv_data
);
379 usb_kill_anchored_urbs(&drv_data
->tx_anchor
);
384 static void nfcmrvl_play_deferred(struct nfcmrvl_usb_drv_data
*drv_data
)
389 while ((urb
= usb_get_from_anchor(&drv_data
->deferred
))) {
390 err
= usb_submit_urb(urb
, GFP_ATOMIC
);
394 drv_data
->tx_in_flight
++;
396 usb_scuttle_anchored_urbs(&drv_data
->deferred
);
399 static int nfcmrvl_resume(struct usb_interface
*intf
)
401 struct nfcmrvl_usb_drv_data
*drv_data
= usb_get_intfdata(intf
);
404 nfc_info(&drv_data
->udev
->dev
, "intf %p", intf
);
406 if (--drv_data
->suspend_count
)
409 if (!test_bit(NFCMRVL_NCI_RUNNING
, &drv_data
->flags
))
412 if (test_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
)) {
413 err
= nfcmrvl_submit_bulk_urb(drv_data
, GFP_NOIO
);
415 clear_bit(NFCMRVL_USB_BULK_RUNNING
, &drv_data
->flags
);
419 nfcmrvl_submit_bulk_urb(drv_data
, GFP_NOIO
);
422 spin_lock_irq(&drv_data
->txlock
);
423 nfcmrvl_play_deferred(drv_data
);
424 clear_bit(NFCMRVL_USB_SUSPENDING
, &drv_data
->flags
);
425 spin_unlock_irq(&drv_data
->txlock
);
430 usb_scuttle_anchored_urbs(&drv_data
->deferred
);
432 spin_lock_irq(&drv_data
->txlock
);
433 clear_bit(NFCMRVL_USB_SUSPENDING
, &drv_data
->flags
);
434 spin_unlock_irq(&drv_data
->txlock
);
440 static struct usb_driver nfcmrvl_usb_driver
= {
442 .probe
= nfcmrvl_probe
,
443 .disconnect
= nfcmrvl_disconnect
,
445 .suspend
= nfcmrvl_suspend
,
446 .resume
= nfcmrvl_resume
,
447 .reset_resume
= nfcmrvl_resume
,
449 .id_table
= nfcmrvl_table
,
450 .supports_autosuspend
= 1,
451 .disable_hub_initiated_lpm
= 1,
454 module_usb_driver(nfcmrvl_usb_driver
);
456 MODULE_AUTHOR("Marvell International Ltd.");
457 MODULE_DESCRIPTION("Marvell NFC-over-USB driver ver " VERSION
);
458 MODULE_VERSION(VERSION
);
459 MODULE_LICENSE("GPL v2");