]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge tag 'usb-ci-v4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/peter...
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Apr 2017 14:52:20 +0000 (16:52 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Apr 2017 14:52:20 +0000 (16:52 +0200)
Peter writes:

Two changes for this v4.12-rc1:
- Add sysfs entry for role switch
- Update gadget state after gadget back from suspend

1  2 
drivers/usb/chipidea/core.c
drivers/usb/chipidea/udc.c

index b4a78b2df2ed2f54a057a5386aae4764abf90f70,05fd2510a620e0fef1633d33e564068d985354f0..9e217b1361ea76af9b9a5bb999b81559643e8e25
@@@ -783,6 -783,9 +783,6 @@@ struct platform_device *ci_hdrc_add_dev
        }
  
        pdev->dev.parent = dev;
 -      pdev->dev.dma_mask = dev->dma_mask;
 -      pdev->dev.dma_parms = dev->dma_parms;
 -      dma_set_coherent_mask(&pdev->dev, dev->coherent_dma_mask);
  
        ret = platform_device_add_resources(pdev, res, nres);
        if (ret)
@@@ -838,6 -841,56 +838,56 @@@ static void ci_get_otg_capable(struct c
        }
  }
  
+ static ssize_t ci_role_show(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+ {
+       struct ci_hdrc *ci = dev_get_drvdata(dev);
+       return sprintf(buf, "%s\n", ci_role(ci)->name);
+ }
+ static ssize_t ci_role_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t n)
+ {
+       struct ci_hdrc *ci = dev_get_drvdata(dev);
+       enum ci_role role;
+       int ret;
+       if (!(ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET])) {
+               dev_warn(dev, "Current configuration is not dual-role, quit\n");
+               return -EPERM;
+       }
+       for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++)
+               if (!strncmp(buf, ci->roles[role]->name,
+                            strlen(ci->roles[role]->name)))
+                       break;
+       if (role == CI_ROLE_END || role == ci->role)
+               return -EINVAL;
+       pm_runtime_get_sync(dev);
+       disable_irq(ci->irq);
+       ci_role_stop(ci);
+       ret = ci_role_start(ci, role);
+       if (!ret && ci->role == CI_ROLE_GADGET)
+               ci_handle_vbus_change(ci);
+       enable_irq(ci->irq);
+       pm_runtime_put_sync(dev);
+       return (ret == 0) ? n : ret;
+ }
+ static DEVICE_ATTR(role, 0644, ci_role_show, ci_role_store);
+ static struct attribute *ci_attrs[] = {
+       &dev_attr_role.attr,
+       NULL,
+ };
+ static struct attribute_group ci_attr_group = {
+       .attrs = ci_attrs,
+ };
  static int ci_hdrc_probe(struct platform_device *pdev)
  {
        struct device   *dev = &pdev->dev;
                ci_hdrc_otg_fsm_start(ci);
  
        device_set_wakeup_capable(&pdev->dev, true);
        ret = dbg_create_files(ci);
-       if (!ret)
-               return 0;
+       if (ret)
+               goto stop;
+       ret = sysfs_create_group(&dev->kobj, &ci_attr_group);
+       if (ret)
+               goto remove_debug;
  
+       return 0;
+ remove_debug:
+       dbg_remove_files(ci);
  stop:
        ci_role_destroy(ci);
  deinit_phy:
@@@ -1030,6 -1090,7 +1087,7 @@@ static int ci_hdrc_remove(struct platfo
        }
  
        dbg_remove_files(ci);
+       sysfs_remove_group(&ci->dev->kobj, &ci_attr_group);
        ci_role_destroy(ci);
        ci_hdrc_enter_lpm(ci, true);
        ci_usb_phy_exit(ci);
index 1fb52359f7b9354a763b9726a85d07d89534e041,c979cecdd6f76497cd2308f216b5b44e3f6aacfb..56d2d32130765dfc655ecbb6e105f8d411070d1d
@@@ -423,8 -423,7 +423,8 @@@ static int _hardware_enqueue(struct ci_
  
        hwreq->req.status = -EALREADY;
  
 -      ret = usb_gadget_map_request(&ci->gadget, &hwreq->req, hwep->dir);
 +      ret = usb_gadget_map_request_by_dev(ci->dev->parent,
 +                                          &hwreq->req, hwep->dir);
        if (ret)
                return ret;
  
@@@ -604,8 -603,7 +604,8 @@@ static int _hardware_dequeue(struct ci_
                list_del_init(&node->td);
        }
  
 -      usb_gadget_unmap_request(&hwep->ci->gadget, &hwreq->req, hwep->dir);
 +      usb_gadget_unmap_request_by_dev(hwep->ci->dev->parent,
 +                                      &hwreq->req, hwep->dir);
  
        hwreq->req.actual += actual;
  
@@@ -1847,27 -1845,32 +1847,32 @@@ static irqreturn_t udc_irq(struct ci_hd
                if (USBi_PCI & intr) {
                        ci->gadget.speed = hw_port_is_high_speed(ci) ?
                                USB_SPEED_HIGH : USB_SPEED_FULL;
-                       if (ci->suspended && ci->driver->resume) {
-                               spin_unlock(&ci->lock);
-                               ci->driver->resume(&ci->gadget);
-                               spin_lock(&ci->lock);
+                       if (ci->suspended) {
+                               if (ci->driver->resume) {
+                                       spin_unlock(&ci->lock);
+                                       ci->driver->resume(&ci->gadget);
+                                       spin_lock(&ci->lock);
+                               }
                                ci->suspended = 0;
+                               usb_gadget_set_state(&ci->gadget,
+                                               ci->resume_state);
                        }
                }
  
                if (USBi_UI  & intr)
                        isr_tr_complete_handler(ci);
  
-               if (USBi_SLI & intr) {
+               if ((USBi_SLI & intr) && !(ci->suspended)) {
+                       ci->suspended = 1;
+                       ci->resume_state = ci->gadget.state;
                        if (ci->gadget.speed != USB_SPEED_UNKNOWN &&
                            ci->driver->suspend) {
-                               ci->suspended = 1;
                                spin_unlock(&ci->lock);
                                ci->driver->suspend(&ci->gadget);
-                               usb_gadget_set_state(&ci->gadget,
-                                               USB_STATE_SUSPENDED);
                                spin_lock(&ci->lock);
                        }
+                       usb_gadget_set_state(&ci->gadget,
+                                       USB_STATE_SUSPENDED);
                }
                retval = IRQ_HANDLED;
        } else {
@@@ -1901,13 -1904,13 +1906,13 @@@ static int udc_start(struct ci_hdrc *ci
        INIT_LIST_HEAD(&ci->gadget.ep_list);
  
        /* alloc resources */
 -      ci->qh_pool = dma_pool_create("ci_hw_qh", dev,
 +      ci->qh_pool = dma_pool_create("ci_hw_qh", dev->parent,
                                       sizeof(struct ci_hw_qh),
                                       64, CI_HDRC_PAGE_SIZE);
        if (ci->qh_pool == NULL)
                return -ENOMEM;
  
 -      ci->td_pool = dma_pool_create("ci_hw_td", dev,
 +      ci->td_pool = dma_pool_create("ci_hw_td", dev->parent,
                                       sizeof(struct ci_hw_td),
                                       64, CI_HDRC_PAGE_SIZE);
        if (ci->td_pool == NULL) {
@@@ -1975,6 -1978,8 +1980,8 @@@ static void udc_id_switch_for_host(stru
         */
        if (ci->is_otg)
                hw_write_otgsc(ci, OTGSC_BSVIE | OTGSC_BSVIS, OTGSC_BSVIS);
+       ci->vbus_active = 0;
  }
  
  /**