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