Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Marvell NFC-over-USB driver: USB interface related functions
0004  *
0005  * Copyright (C) 2014, Marvell International Ltd.
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/usb.h>
0010 #include <linux/nfc.h>
0011 #include <net/nfc/nci.h>
0012 #include <net/nfc/nci_core.h>
0013 #include "nfcmrvl.h"
0014 
0015 static struct usb_device_id nfcmrvl_table[] = {
0016     { USB_DEVICE_AND_INTERFACE_INFO(0x1286, 0x2046,
0017                     USB_CLASS_VENDOR_SPEC, 4, 1) },
0018     { } /* Terminating entry */
0019 };
0020 
0021 MODULE_DEVICE_TABLE(usb, nfcmrvl_table);
0022 
0023 #define NFCMRVL_USB_BULK_RUNNING    1
0024 #define NFCMRVL_USB_SUSPENDING      2
0025 
0026 struct nfcmrvl_usb_drv_data {
0027     struct usb_device *udev;
0028     struct usb_interface *intf;
0029     unsigned long flags;
0030     struct work_struct waker;
0031     struct usb_anchor tx_anchor;
0032     struct usb_anchor bulk_anchor;
0033     struct usb_anchor deferred;
0034     int tx_in_flight;
0035     /* protects tx_in_flight */
0036     spinlock_t txlock;
0037     struct usb_endpoint_descriptor *bulk_tx_ep;
0038     struct usb_endpoint_descriptor *bulk_rx_ep;
0039     int suspend_count;
0040     struct nfcmrvl_private *priv;
0041 };
0042 
0043 static int nfcmrvl_inc_tx(struct nfcmrvl_usb_drv_data *drv_data)
0044 {
0045     unsigned long flags;
0046     int rv;
0047 
0048     spin_lock_irqsave(&drv_data->txlock, flags);
0049     rv = test_bit(NFCMRVL_USB_SUSPENDING, &drv_data->flags);
0050     if (!rv)
0051         drv_data->tx_in_flight++;
0052     spin_unlock_irqrestore(&drv_data->txlock, flags);
0053 
0054     return rv;
0055 }
0056 
0057 static void nfcmrvl_bulk_complete(struct urb *urb)
0058 {
0059     struct nfcmrvl_usb_drv_data *drv_data = urb->context;
0060     int err;
0061 
0062     dev_dbg(&drv_data->udev->dev, "urb %p status %d count %d\n",
0063         urb, urb->status, urb->actual_length);
0064 
0065     if (!test_bit(NFCMRVL_NCI_RUNNING, &drv_data->flags))
0066         return;
0067 
0068     if (!urb->status) {
0069         struct sk_buff *skb;
0070 
0071         skb = nci_skb_alloc(drv_data->priv->ndev, urb->actual_length,
0072                     GFP_ATOMIC);
0073         if (!skb) {
0074             nfc_err(&drv_data->udev->dev, "failed to alloc mem\n");
0075         } else {
0076             skb_put_data(skb, urb->transfer_buffer,
0077                      urb->actual_length);
0078             if (nfcmrvl_nci_recv_frame(drv_data->priv, skb) < 0)
0079                 nfc_err(&drv_data->udev->dev,
0080                     "corrupted Rx packet\n");
0081         }
0082     }
0083 
0084     if (!test_bit(NFCMRVL_USB_BULK_RUNNING, &drv_data->flags))
0085         return;
0086 
0087     usb_anchor_urb(urb, &drv_data->bulk_anchor);
0088     usb_mark_last_busy(drv_data->udev);
0089 
0090     err = usb_submit_urb(urb, GFP_ATOMIC);
0091     if (err) {
0092         /* -EPERM: urb is being killed;
0093          * -ENODEV: device got disconnected
0094          */
0095         if (err != -EPERM && err != -ENODEV)
0096             nfc_err(&drv_data->udev->dev,
0097                 "urb %p failed to resubmit (%d)\n", urb, -err);
0098         usb_unanchor_urb(urb);
0099     }
0100 }
0101 
0102 static int
0103 nfcmrvl_submit_bulk_urb(struct nfcmrvl_usb_drv_data *drv_data, gfp_t mem_flags)
0104 {
0105     struct urb *urb;
0106     unsigned char *buf;
0107     unsigned int pipe;
0108     int err, size = NFCMRVL_NCI_MAX_EVENT_SIZE;
0109 
0110     if (!drv_data->bulk_rx_ep)
0111         return -ENODEV;
0112 
0113     urb = usb_alloc_urb(0, mem_flags);
0114     if (!urb)
0115         return -ENOMEM;
0116 
0117     buf = kmalloc(size, mem_flags);
0118     if (!buf) {
0119         usb_free_urb(urb);
0120         return -ENOMEM;
0121     }
0122 
0123     pipe = usb_rcvbulkpipe(drv_data->udev,
0124                    drv_data->bulk_rx_ep->bEndpointAddress);
0125 
0126     usb_fill_bulk_urb(urb, drv_data->udev, pipe, buf, size,
0127               nfcmrvl_bulk_complete, drv_data);
0128 
0129     urb->transfer_flags |= URB_FREE_BUFFER;
0130 
0131     usb_mark_last_busy(drv_data->udev);
0132     usb_anchor_urb(urb, &drv_data->bulk_anchor);
0133 
0134     err = usb_submit_urb(urb, mem_flags);
0135     if (err) {
0136         if (err != -EPERM && err != -ENODEV)
0137             nfc_err(&drv_data->udev->dev,
0138                 "urb %p submission failed (%d)\n", urb, -err);
0139         usb_unanchor_urb(urb);
0140     }
0141 
0142     usb_free_urb(urb);
0143 
0144     return err;
0145 }
0146 
0147 static void nfcmrvl_tx_complete(struct urb *urb)
0148 {
0149     struct sk_buff *skb = urb->context;
0150     struct nci_dev *ndev = (struct nci_dev *)skb->dev;
0151     struct nfcmrvl_private *priv = nci_get_drvdata(ndev);
0152     struct nfcmrvl_usb_drv_data *drv_data = priv->drv_data;
0153     unsigned long flags;
0154 
0155     nfc_info(priv->dev, "urb %p status %d count %d\n",
0156          urb, urb->status, urb->actual_length);
0157 
0158     spin_lock_irqsave(&drv_data->txlock, flags);
0159     drv_data->tx_in_flight--;
0160     spin_unlock_irqrestore(&drv_data->txlock, flags);
0161 
0162     kfree(urb->setup_packet);
0163     kfree_skb(skb);
0164 }
0165 
0166 static int nfcmrvl_usb_nci_open(struct nfcmrvl_private *priv)
0167 {
0168     struct nfcmrvl_usb_drv_data *drv_data = priv->drv_data;
0169     int err;
0170 
0171     err = usb_autopm_get_interface(drv_data->intf);
0172     if (err)
0173         return err;
0174 
0175     drv_data->intf->needs_remote_wakeup = 1;
0176 
0177     err = nfcmrvl_submit_bulk_urb(drv_data, GFP_KERNEL);
0178     if (err)
0179         goto failed;
0180 
0181     set_bit(NFCMRVL_USB_BULK_RUNNING, &drv_data->flags);
0182     nfcmrvl_submit_bulk_urb(drv_data, GFP_KERNEL);
0183 
0184     usb_autopm_put_interface(drv_data->intf);
0185     return 0;
0186 
0187 failed:
0188     usb_autopm_put_interface(drv_data->intf);
0189     return err;
0190 }
0191 
0192 static void nfcmrvl_usb_stop_traffic(struct nfcmrvl_usb_drv_data *drv_data)
0193 {
0194     usb_kill_anchored_urbs(&drv_data->bulk_anchor);
0195 }
0196 
0197 static int nfcmrvl_usb_nci_close(struct nfcmrvl_private *priv)
0198 {
0199     struct nfcmrvl_usb_drv_data *drv_data = priv->drv_data;
0200     int err;
0201 
0202     cancel_work_sync(&drv_data->waker);
0203 
0204     clear_bit(NFCMRVL_USB_BULK_RUNNING, &drv_data->flags);
0205 
0206     nfcmrvl_usb_stop_traffic(drv_data);
0207     usb_kill_anchored_urbs(&drv_data->tx_anchor);
0208     err = usb_autopm_get_interface(drv_data->intf);
0209     if (err)
0210         goto failed;
0211 
0212     drv_data->intf->needs_remote_wakeup = 0;
0213     usb_autopm_put_interface(drv_data->intf);
0214 
0215 failed:
0216     usb_scuttle_anchored_urbs(&drv_data->deferred);
0217     return 0;
0218 }
0219 
0220 static int nfcmrvl_usb_nci_send(struct nfcmrvl_private *priv,
0221                 struct sk_buff *skb)
0222 {
0223     struct nfcmrvl_usb_drv_data *drv_data = priv->drv_data;
0224     struct urb *urb;
0225     unsigned int pipe;
0226     int err;
0227 
0228     if (!drv_data->bulk_tx_ep)
0229         return -ENODEV;
0230 
0231     urb = usb_alloc_urb(0, GFP_ATOMIC);
0232     if (!urb)
0233         return -ENOMEM;
0234 
0235     pipe = usb_sndbulkpipe(drv_data->udev,
0236                 drv_data->bulk_tx_ep->bEndpointAddress);
0237 
0238     usb_fill_bulk_urb(urb, drv_data->udev, pipe, skb->data, skb->len,
0239               nfcmrvl_tx_complete, skb);
0240 
0241     err = nfcmrvl_inc_tx(drv_data);
0242     if (err) {
0243         usb_anchor_urb(urb, &drv_data->deferred);
0244         schedule_work(&drv_data->waker);
0245         err = 0;
0246         goto done;
0247     }
0248 
0249     usb_anchor_urb(urb, &drv_data->tx_anchor);
0250 
0251     err = usb_submit_urb(urb, GFP_ATOMIC);
0252     if (err) {
0253         if (err != -EPERM && err != -ENODEV)
0254             nfc_err(&drv_data->udev->dev,
0255                 "urb %p submission failed (%d)\n", urb, -err);
0256         kfree(urb->setup_packet);
0257         usb_unanchor_urb(urb);
0258     } else {
0259         usb_mark_last_busy(drv_data->udev);
0260     }
0261 
0262 done:
0263     usb_free_urb(urb);
0264     return err;
0265 }
0266 
0267 static const struct nfcmrvl_if_ops usb_ops = {
0268     .nci_open = nfcmrvl_usb_nci_open,
0269     .nci_close = nfcmrvl_usb_nci_close,
0270     .nci_send = nfcmrvl_usb_nci_send,
0271 };
0272 
0273 static void nfcmrvl_waker(struct work_struct *work)
0274 {
0275     struct nfcmrvl_usb_drv_data *drv_data =
0276             container_of(work, struct nfcmrvl_usb_drv_data, waker);
0277     int err;
0278 
0279     err = usb_autopm_get_interface(drv_data->intf);
0280     if (err)
0281         return;
0282 
0283     usb_autopm_put_interface(drv_data->intf);
0284 }
0285 
0286 static int nfcmrvl_probe(struct usb_interface *intf,
0287              const struct usb_device_id *id)
0288 {
0289     struct nfcmrvl_usb_drv_data *drv_data;
0290     struct nfcmrvl_private *priv;
0291     int i;
0292     struct usb_device *udev = interface_to_usbdev(intf);
0293     struct nfcmrvl_platform_data config;
0294 
0295     /* No configuration for USB */
0296     memset(&config, 0, sizeof(config));
0297     config.reset_n_io = -EINVAL;
0298 
0299     nfc_info(&udev->dev, "intf %p id %p\n", intf, id);
0300 
0301     drv_data = devm_kzalloc(&intf->dev, sizeof(*drv_data), GFP_KERNEL);
0302     if (!drv_data)
0303         return -ENOMEM;
0304 
0305     for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
0306         struct usb_endpoint_descriptor *ep_desc;
0307 
0308         ep_desc = &intf->cur_altsetting->endpoint[i].desc;
0309 
0310         if (!drv_data->bulk_tx_ep &&
0311             usb_endpoint_is_bulk_out(ep_desc)) {
0312             drv_data->bulk_tx_ep = ep_desc;
0313         } else if (!drv_data->bulk_rx_ep &&
0314                usb_endpoint_is_bulk_in(ep_desc)) {
0315             drv_data->bulk_rx_ep = ep_desc;
0316         }
0317     }
0318 
0319     if (!drv_data->bulk_tx_ep || !drv_data->bulk_rx_ep)
0320         return -ENODEV;
0321 
0322     drv_data->udev = udev;
0323     drv_data->intf = intf;
0324 
0325     INIT_WORK(&drv_data->waker, nfcmrvl_waker);
0326     spin_lock_init(&drv_data->txlock);
0327 
0328     init_usb_anchor(&drv_data->tx_anchor);
0329     init_usb_anchor(&drv_data->bulk_anchor);
0330     init_usb_anchor(&drv_data->deferred);
0331 
0332     priv = nfcmrvl_nci_register_dev(NFCMRVL_PHY_USB, drv_data, &usb_ops,
0333                     &intf->dev, &config);
0334     if (IS_ERR(priv))
0335         return PTR_ERR(priv);
0336 
0337     drv_data->priv = priv;
0338     drv_data->priv->support_fw_dnld = false;
0339 
0340     usb_set_intfdata(intf, drv_data);
0341 
0342     return 0;
0343 }
0344 
0345 static void nfcmrvl_disconnect(struct usb_interface *intf)
0346 {
0347     struct nfcmrvl_usb_drv_data *drv_data = usb_get_intfdata(intf);
0348 
0349     if (!drv_data)
0350         return;
0351 
0352     nfc_info(&drv_data->udev->dev, "intf %p\n", intf);
0353 
0354     nfcmrvl_nci_unregister_dev(drv_data->priv);
0355 
0356     usb_set_intfdata(drv_data->intf, NULL);
0357 }
0358 
0359 #ifdef CONFIG_PM
0360 static int nfcmrvl_suspend(struct usb_interface *intf, pm_message_t message)
0361 {
0362     struct nfcmrvl_usb_drv_data *drv_data = usb_get_intfdata(intf);
0363 
0364     nfc_info(&drv_data->udev->dev, "intf %p\n", intf);
0365 
0366     if (drv_data->suspend_count++)
0367         return 0;
0368 
0369     spin_lock_irq(&drv_data->txlock);
0370     if (!(PMSG_IS_AUTO(message) && drv_data->tx_in_flight)) {
0371         set_bit(NFCMRVL_USB_SUSPENDING, &drv_data->flags);
0372         spin_unlock_irq(&drv_data->txlock);
0373     } else {
0374         spin_unlock_irq(&drv_data->txlock);
0375         drv_data->suspend_count--;
0376         return -EBUSY;
0377     }
0378 
0379     nfcmrvl_usb_stop_traffic(drv_data);
0380     usb_kill_anchored_urbs(&drv_data->tx_anchor);
0381 
0382     return 0;
0383 }
0384 
0385 static void nfcmrvl_play_deferred(struct nfcmrvl_usb_drv_data *drv_data)
0386 {
0387     struct urb *urb;
0388     int err;
0389 
0390     while ((urb = usb_get_from_anchor(&drv_data->deferred))) {
0391         usb_anchor_urb(urb, &drv_data->tx_anchor);
0392 
0393         err = usb_submit_urb(urb, GFP_ATOMIC);
0394         if (err) {
0395             kfree(urb->setup_packet);
0396             usb_unanchor_urb(urb);
0397             usb_free_urb(urb);
0398             break;
0399         }
0400 
0401         drv_data->tx_in_flight++;
0402         usb_free_urb(urb);
0403     }
0404 
0405     /* Cleanup the rest deferred urbs. */
0406     while ((urb = usb_get_from_anchor(&drv_data->deferred))) {
0407         kfree(urb->setup_packet);
0408         usb_free_urb(urb);
0409     }
0410 }
0411 
0412 static int nfcmrvl_resume(struct usb_interface *intf)
0413 {
0414     struct nfcmrvl_usb_drv_data *drv_data = usb_get_intfdata(intf);
0415     int err = 0;
0416 
0417     nfc_info(&drv_data->udev->dev, "intf %p\n", intf);
0418 
0419     if (--drv_data->suspend_count)
0420         return 0;
0421 
0422     if (!test_bit(NFCMRVL_NCI_RUNNING, &drv_data->flags))
0423         goto done;
0424 
0425     if (test_bit(NFCMRVL_USB_BULK_RUNNING, &drv_data->flags)) {
0426         err = nfcmrvl_submit_bulk_urb(drv_data, GFP_NOIO);
0427         if (err) {
0428             clear_bit(NFCMRVL_USB_BULK_RUNNING, &drv_data->flags);
0429             goto failed;
0430         }
0431 
0432         nfcmrvl_submit_bulk_urb(drv_data, GFP_NOIO);
0433     }
0434 
0435     spin_lock_irq(&drv_data->txlock);
0436     nfcmrvl_play_deferred(drv_data);
0437     clear_bit(NFCMRVL_USB_SUSPENDING, &drv_data->flags);
0438     spin_unlock_irq(&drv_data->txlock);
0439 
0440     return 0;
0441 
0442 failed:
0443     usb_scuttle_anchored_urbs(&drv_data->deferred);
0444 done:
0445     spin_lock_irq(&drv_data->txlock);
0446     clear_bit(NFCMRVL_USB_SUSPENDING, &drv_data->flags);
0447     spin_unlock_irq(&drv_data->txlock);
0448 
0449     return err;
0450 }
0451 #endif
0452 
0453 static struct usb_driver nfcmrvl_usb_driver = {
0454     .name       = "nfcmrvl",
0455     .probe      = nfcmrvl_probe,
0456     .disconnect = nfcmrvl_disconnect,
0457 #ifdef CONFIG_PM
0458     .suspend    = nfcmrvl_suspend,
0459     .resume     = nfcmrvl_resume,
0460     .reset_resume   = nfcmrvl_resume,
0461 #endif
0462     .id_table   = nfcmrvl_table,
0463     .supports_autosuspend = 1,
0464     .disable_hub_initiated_lpm = 1,
0465     .soft_unbind = 1,
0466 };
0467 module_usb_driver(nfcmrvl_usb_driver);
0468 
0469 MODULE_AUTHOR("Marvell International Ltd.");
0470 MODULE_DESCRIPTION("Marvell NFC-over-USB driver");
0471 MODULE_LICENSE("GPL v2");