1/** 2 * Marvell NFC-over-USB driver: USB interface related functions 3 * 4 * Copyright (C) 2014, Marvell International Ltd. 5 * 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. 12 * 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. 17 **/ 18 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> 24#include "nfcmrvl.h" 25 26#define VERSION "1.0" 27 28static struct usb_device_id nfcmrvl_table[] = { 29 { USB_DEVICE_INTERFACE_CLASS(0x1286, 0x2046, 0xff) }, 30 { } /* Terminating entry */ 31}; 32 33MODULE_DEVICE_TABLE(usb, nfcmrvl_table); 34 35#define NFCMRVL_USB_BULK_RUNNING 1 36#define NFCMRVL_USB_SUSPENDING 2 37 38struct nfcmrvl_usb_drv_data { 39 struct usb_device *udev; 40 struct usb_interface *intf; 41 unsigned long flags; 42 struct work_struct waker; 43 struct usb_anchor tx_anchor; 44 struct usb_anchor bulk_anchor; 45 struct usb_anchor deferred; 46 int tx_in_flight; 47 /* protects tx_in_flight */ 48 spinlock_t txlock; 49 struct usb_endpoint_descriptor *bulk_tx_ep; 50 struct usb_endpoint_descriptor *bulk_rx_ep; 51 int suspend_count; 52 struct nfcmrvl_private *priv; 53}; 54 55static int nfcmrvl_inc_tx(struct nfcmrvl_usb_drv_data *drv_data) 56{ 57 unsigned long flags; 58 int rv; 59 60 spin_lock_irqsave(&drv_data->txlock, flags); 61 rv = test_bit(NFCMRVL_USB_SUSPENDING, &drv_data->flags); 62 if (!rv) 63 drv_data->tx_in_flight++; 64 spin_unlock_irqrestore(&drv_data->txlock, flags); 65 66 return rv; 67} 68 69static void nfcmrvl_bulk_complete(struct urb *urb) 70{ 71 struct nfcmrvl_usb_drv_data *drv_data = urb->context; 72 int err; 73 74 dev_dbg(&drv_data->udev->dev, "urb %p status %d count %d", 75 urb, urb->status, urb->actual_length); 76 77 if (!test_bit(NFCMRVL_NCI_RUNNING, &drv_data->flags)) 78 return; 79 80 if (!urb->status) { 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\n"); 84 } 85 86 if (!test_bit(NFCMRVL_USB_BULK_RUNNING, &drv_data->flags)) 87 return; 88 89 usb_anchor_urb(urb, &drv_data->bulk_anchor); 90 usb_mark_last_busy(drv_data->udev); 91 92 err = usb_submit_urb(urb, GFP_ATOMIC); 93 if (err) { 94 /* -EPERM: urb is being killed; 95 * -ENODEV: device got disconnected 96 */ 97 if (err != -EPERM && err != -ENODEV) 98 nfc_err(&drv_data->udev->dev, 99 "urb %p failed to resubmit (%d)\n", urb, -err); 100 usb_unanchor_urb(urb); 101 } 102} 103 104static int 105nfcmrvl_submit_bulk_urb(struct nfcmrvl_usb_drv_data *drv_data, gfp_t mem_flags) 106{ 107 struct urb *urb; 108 unsigned char *buf; 109 unsigned int pipe; 110 int err, size = NFCMRVL_NCI_MAX_EVENT_SIZE; 111 112 if (!drv_data->bulk_rx_ep) 113 return -ENODEV; 114 115 urb = usb_alloc_urb(0, mem_flags); 116 if (!urb) 117 return -ENOMEM; 118 119 buf = kmalloc(size, mem_flags); 120 if (!buf) { 121 usb_free_urb(urb); 122 return -ENOMEM; 123 } 124 125 pipe = usb_rcvbulkpipe(drv_data->udev, 126 drv_data->bulk_rx_ep->bEndpointAddress); 127 128 usb_fill_bulk_urb(urb, drv_data->udev, pipe, buf, size, 129 nfcmrvl_bulk_complete, drv_data); 130 131 urb->transfer_flags |= URB_FREE_BUFFER; 132 133 usb_mark_last_busy(drv_data->udev); 134 usb_anchor_urb(urb, &drv_data->bulk_anchor); 135 136 err = usb_submit_urb(urb, mem_flags); 137 if (err) { 138 if (err != -EPERM && err != -ENODEV) 139 nfc_err(&drv_data->udev->dev, 140 "urb %p submission failed (%d)\n", urb, -err); 141 usb_unanchor_urb(urb); 142 } 143 144 usb_free_urb(urb); 145 146 return err; 147} 148 149static void nfcmrvl_tx_complete(struct urb *urb) 150{ 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; 155 156 nfc_info(priv->dev, "urb %p status %d count %d\n", 157 urb, urb->status, urb->actual_length); 158 159 spin_lock(&drv_data->txlock); 160 drv_data->tx_in_flight--; 161 spin_unlock(&drv_data->txlock); 162 163 kfree(urb->setup_packet); 164 kfree_skb(skb); 165} 166 167static int nfcmrvl_usb_nci_open(struct nfcmrvl_private *priv) 168{ 169 struct nfcmrvl_usb_drv_data *drv_data = priv->drv_data; 170 int err; 171 172 err = usb_autopm_get_interface(drv_data->intf); 173 if (err) 174 return err; 175 176 drv_data->intf->needs_remote_wakeup = 1; 177 178 err = nfcmrvl_submit_bulk_urb(drv_data, GFP_KERNEL); 179 if (err) 180 goto failed; 181 182 set_bit(NFCMRVL_USB_BULK_RUNNING, &drv_data->flags); 183 nfcmrvl_submit_bulk_urb(drv_data, GFP_KERNEL); 184 185 usb_autopm_put_interface(drv_data->intf); 186 return 0; 187 188failed: 189 usb_autopm_put_interface(drv_data->intf); 190 return err; 191} 192 193static void nfcmrvl_usb_stop_traffic(struct nfcmrvl_usb_drv_data *drv_data) 194{ 195 usb_kill_anchored_urbs(&drv_data->bulk_anchor); 196} 197 198static int nfcmrvl_usb_nci_close(struct nfcmrvl_private *priv) 199{ 200 struct nfcmrvl_usb_drv_data *drv_data = priv->drv_data; 201 int err; 202 203 cancel_work_sync(&drv_data->waker); 204 205 clear_bit(NFCMRVL_USB_BULK_RUNNING, &drv_data->flags); 206 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); 210 if (err) 211 goto failed; 212 213 drv_data->intf->needs_remote_wakeup = 0; 214 usb_autopm_put_interface(drv_data->intf); 215 216failed: 217 usb_scuttle_anchored_urbs(&drv_data->deferred); 218 return 0; 219} 220 221static int nfcmrvl_usb_nci_send(struct nfcmrvl_private *priv, 222 struct sk_buff *skb) 223{ 224 struct nfcmrvl_usb_drv_data *drv_data = priv->drv_data; 225 struct urb *urb; 226 unsigned int pipe; 227 int err; 228 229 if (!drv_data->bulk_tx_ep) 230 return -ENODEV; 231 232 urb = usb_alloc_urb(0, GFP_ATOMIC); 233 if (!urb) 234 return -ENOMEM; 235 236 pipe = usb_sndbulkpipe(drv_data->udev, 237 drv_data->bulk_tx_ep->bEndpointAddress); 238 239 usb_fill_bulk_urb(urb, drv_data->udev, pipe, skb->data, skb->len, 240 nfcmrvl_tx_complete, skb); 241 242 err = nfcmrvl_inc_tx(drv_data); 243 if (err) { 244 usb_anchor_urb(urb, &drv_data->deferred); 245 schedule_work(&drv_data->waker); 246 err = 0; 247 goto done; 248 } 249 250 usb_anchor_urb(urb, &drv_data->tx_anchor); 251 252 err = usb_submit_urb(urb, GFP_ATOMIC); 253 if (err) { 254 if (err != -EPERM && err != -ENODEV) 255 nfc_err(&drv_data->udev->dev, 256 "urb %p submission failed (%d)\n", urb, -err); 257 kfree(urb->setup_packet); 258 usb_unanchor_urb(urb); 259 } else { 260 usb_mark_last_busy(drv_data->udev); 261 } 262 263done: 264 usb_free_urb(urb); 265 return err; 266} 267 268static 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, 272}; 273 274static void nfcmrvl_waker(struct work_struct *work) 275{ 276 struct nfcmrvl_usb_drv_data *drv_data = 277 container_of(work, struct nfcmrvl_usb_drv_data, waker); 278 int err; 279 280 err = usb_autopm_get_interface(drv_data->intf); 281 if (err) 282 return; 283 284 usb_autopm_put_interface(drv_data->intf); 285} 286 287static int nfcmrvl_probe(struct usb_interface *intf, 288 const struct usb_device_id *id) 289{ 290 struct usb_endpoint_descriptor *ep_desc; 291 struct nfcmrvl_usb_drv_data *drv_data; 292 struct nfcmrvl_private *priv; 293 int i; 294 struct usb_device *udev = interface_to_usbdev(intf); 295 296 nfc_info(&udev->dev, "intf %p id %p\n", intf, id); 297 298 drv_data = devm_kzalloc(&intf->dev, sizeof(*drv_data), GFP_KERNEL); 299 if (!drv_data) 300 return -ENOMEM; 301 302 for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { 303 ep_desc = &intf->cur_altsetting->endpoint[i].desc; 304 305 if (!drv_data->bulk_tx_ep && 306 usb_endpoint_is_bulk_out(ep_desc)) { 307 drv_data->bulk_tx_ep = ep_desc; 308 continue; 309 } 310 311 if (!drv_data->bulk_rx_ep && 312 usb_endpoint_is_bulk_in(ep_desc)) { 313 drv_data->bulk_rx_ep = ep_desc; 314 continue; 315 } 316 } 317 318 if (!drv_data->bulk_tx_ep || !drv_data->bulk_rx_ep) 319 return -ENODEV; 320 321 drv_data->udev = udev; 322 drv_data->intf = intf; 323 324 INIT_WORK(&drv_data->waker, nfcmrvl_waker); 325 spin_lock_init(&drv_data->txlock); 326 327 init_usb_anchor(&drv_data->tx_anchor); 328 init_usb_anchor(&drv_data->bulk_anchor); 329 init_usb_anchor(&drv_data->deferred); 330 331 priv = nfcmrvl_nci_register_dev(drv_data, &usb_ops, 332 &drv_data->udev->dev); 333 if (IS_ERR(priv)) 334 return PTR_ERR(priv); 335 336 drv_data->priv = priv; 337 priv->dev = &drv_data->udev->dev; 338 339 usb_set_intfdata(intf, drv_data); 340 341 return 0; 342} 343 344static void nfcmrvl_disconnect(struct usb_interface *intf) 345{ 346 struct nfcmrvl_usb_drv_data *drv_data = usb_get_intfdata(intf); 347 348 if (!drv_data) 349 return; 350 351 nfc_info(&drv_data->udev->dev, "intf %p\n", intf); 352 353 nfcmrvl_nci_unregister_dev(drv_data->priv); 354 355 usb_set_intfdata(drv_data->intf, NULL); 356} 357 358#ifdef CONFIG_PM 359static int nfcmrvl_suspend(struct usb_interface *intf, pm_message_t message) 360{ 361 struct nfcmrvl_usb_drv_data *drv_data = usb_get_intfdata(intf); 362 363 nfc_info(&drv_data->udev->dev, "intf %p\n", intf); 364 365 if (drv_data->suspend_count++) 366 return 0; 367 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); 372 } else { 373 spin_unlock_irq(&drv_data->txlock); 374 drv_data->suspend_count--; 375 return -EBUSY; 376 } 377 378 nfcmrvl_usb_stop_traffic(drv_data); 379 usb_kill_anchored_urbs(&drv_data->tx_anchor); 380 381 return 0; 382} 383 384static void nfcmrvl_play_deferred(struct nfcmrvl_usb_drv_data *drv_data) 385{ 386 struct urb *urb; 387 int err; 388 389 while ((urb = usb_get_from_anchor(&drv_data->deferred))) { 390 err = usb_submit_urb(urb, GFP_ATOMIC); 391 if (err) 392 break; 393 394 drv_data->tx_in_flight++; 395 } 396 usb_scuttle_anchored_urbs(&drv_data->deferred); 397} 398 399static int nfcmrvl_resume(struct usb_interface *intf) 400{ 401 struct nfcmrvl_usb_drv_data *drv_data = usb_get_intfdata(intf); 402 int err = 0; 403 404 nfc_info(&drv_data->udev->dev, "intf %p\n", intf); 405 406 if (--drv_data->suspend_count) 407 return 0; 408 409 if (!test_bit(NFCMRVL_NCI_RUNNING, &drv_data->flags)) 410 goto done; 411 412 if (test_bit(NFCMRVL_USB_BULK_RUNNING, &drv_data->flags)) { 413 err = nfcmrvl_submit_bulk_urb(drv_data, GFP_NOIO); 414 if (err) { 415 clear_bit(NFCMRVL_USB_BULK_RUNNING, &drv_data->flags); 416 goto failed; 417 } 418 419 nfcmrvl_submit_bulk_urb(drv_data, GFP_NOIO); 420 } 421 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); 426 427 return 0; 428 429failed: 430 usb_scuttle_anchored_urbs(&drv_data->deferred); 431done: 432 spin_lock_irq(&drv_data->txlock); 433 clear_bit(NFCMRVL_USB_SUSPENDING, &drv_data->flags); 434 spin_unlock_irq(&drv_data->txlock); 435 436 return err; 437} 438#endif 439 440static struct usb_driver nfcmrvl_usb_driver = { 441 .name = "nfcmrvl", 442 .probe = nfcmrvl_probe, 443 .disconnect = nfcmrvl_disconnect, 444#ifdef CONFIG_PM 445 .suspend = nfcmrvl_suspend, 446 .resume = nfcmrvl_resume, 447 .reset_resume = nfcmrvl_resume, 448#endif 449 .id_table = nfcmrvl_table, 450 .supports_autosuspend = 1, 451 .disable_hub_initiated_lpm = 1, 452 .soft_unbind = 1, 453}; 454module_usb_driver(nfcmrvl_usb_driver); 455 456MODULE_AUTHOR("Marvell International Ltd."); 457MODULE_DESCRIPTION("Marvell NFC-over-USB driver ver " VERSION); 458MODULE_VERSION(VERSION); 459MODULE_LICENSE("GPL v2"); 460