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