usb: port 7 patches from R2 to R3
authorLi Wenji <wenji.li@intel.com>
Thu, 12 Jan 2012 03:47:01 +0000 (11:47 +0800)
committerbuildbot <buildbot@intel.com>
Wed, 18 Jan 2012 05:31:30 +0000 (21:31 -0800)
BZ: 19817

Patches are from the following BZs:
BZ: 16919
usb/penwell_otg: change all sysfs interface authority to 664
BZ: 11069
usb:langwell_udc:remove the invalid dqh->dqh_current write
BZ: 15754
usb/penwell_otg: retry after charger detection failure
BZ: 14339
usb:langwell_udc: remove controller reset in handle_usb_reset
BZ: 17449 17363 16799
usb: free pending requests before dma_pool_destroy
BZ: 18191
langwell_udc: Turn off the charger when device enters SE0, J, K test mode.
BZ: 18687
usb:gadget: clear string id of rndis and acm when unbinding

Change-Id: I124dfe21f78360a8bb5c00dd4a71ef7e4ac9cbb9
Signed-off-by: Li Wenji <wenji.li@intel.com>
Reviewed-on: http://android.intel.com:8080/31623
Reviewed-by: Tang, Richard <richard.tang@intel.com>
Reviewed-by: Zhuang, Jin Can <jin.can.zhuang@intel.com>
Reviewed-by: Yang, Fei <fei.yang@intel.com>
Tested-by: Sun, Jianhua <jianhua.sun@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
drivers/usb/gadget/f_acm.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/f_rndis.c
drivers/usb/gadget/langwell_udc.c
drivers/usb/otg/penwell_otg.c
include/linux/usb/langwell_udc.h

index dedf5a4..69cadbd 100644 (file)
@@ -717,6 +717,7 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
 {
        struct f_acm            *acm = func_to_acm(f);
 
+       acm_string_defs[ACM_CTRL_IDX].id = 0;
        if (gadget_is_dualspeed(c->cdev->gadget))
                usb_free_descriptors(f->hs_descriptors);
        usb_free_descriptors(f->descriptors);
index 07de190..dccdd2e 100644 (file)
@@ -2442,6 +2442,18 @@ static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 static void fsg_disable(struct usb_function *f)
 {
        struct fsg_dev *fsg = fsg_from_func(f);
+       int    i;
+       struct fsg_buffhd *bh;
+
+       /* free all of pending request */
+       for (i = 0; i < FSG_NUM_BUFFERS; ++i) {
+               bh = &fsg->common->buffhds[i];
+               if (bh->inreq_busy)
+                       usb_ep_dequeue(fsg->bulk_in, bh->inreq);
+               if (bh->outreq_busy)
+                       usb_ep_dequeue(fsg->bulk_out, bh->outreq);
+       }
+
        fsg->common->new_fsg = NULL;
        raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
 }
index 921427b..a327416 100644 (file)
@@ -823,6 +823,7 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f)
 {
        struct f_rndis          *rndis = func_to_rndis(f);
 
+       rndis_string_defs[0].id = 0;
        rndis_deregister(rndis->config);
        rndis_exit();
 
index 8a1cb97..28059bb 100644 (file)
@@ -983,7 +983,7 @@ static int langwell_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
                langwell_ep_fifo_flush(&ep->ep);
 
                /* not the last request in endpoint queue */
-               if (likely(ep->queue.next == &req->queue)) {
+               if (ep->queue.prev != &req->queue) {
                        struct langwell_dqh     *dqh;
                        struct langwell_request *next_req;
 
@@ -992,7 +992,6 @@ static int langwell_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
                                        struct langwell_request, queue);
 
                        /* point the dQH to the first dTD of next request */
-                       writel((u32) next_req->head, &dqh->dqh_current);
                }
        } else {
                struct langwell_request *prev_req;
@@ -1492,6 +1491,7 @@ static int langwell_udc_reset(struct langwell_udc *dev)
        u32             usbcmd, usbmode, devlc, endpointlistaddr;
        u8              devlc_byte0, devlc_byte2;
        unsigned long   timeout;
+       unsigned long   sbuscfg_addr;
 
        if (!dev)
                return -EINVAL;
@@ -1537,6 +1537,10 @@ static int langwell_udc_reset(struct langwell_udc *dev)
        /* Write-Clear setup status */
        writel(0, &dev->op_regs->usbsts);
 
+       /* FIXME: workaround for bug9000364367 */
+       sbuscfg_addr = (unsigned long)dev->cap_regs + SBUSCFG_REG_OFFSET;
+       writel(0x7, sbuscfg_addr);
+
        /* if support USB LPM, ACK all LPM token */
        if (dev->lpm) {
                devlc = readl(&dev->op_regs->devlc);
@@ -1693,12 +1697,6 @@ static void stop_activity(struct langwell_udc *dev,
        struct langwell_ep      *ep;
        dev_dbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-       nuke(&dev->ep[0], -ESHUTDOWN);
-
-       list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
-               nuke(ep, -ESHUTDOWN);
-       }
-
        /* report disconnect; the driver is already quiesced */
        if (driver) {
                spin_unlock(&dev->lock);
@@ -1706,6 +1704,12 @@ static void stop_activity(struct langwell_udc *dev,
                spin_lock(&dev->lock);
        }
 
+       nuke(&dev->ep[0], -ESHUTDOWN);
+
+       list_for_each_entry(ep, &dev->gadget.ep_list, ep.ep_list) {
+               nuke(ep, -ESHUTDOWN);
+       }
+
        dev_dbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
 
@@ -2231,6 +2235,7 @@ static void test_mode_complete(struct usb_ep *ep, struct usb_request *_req)
        case TEST_J:
        case TEST_K:
        case TEST_SE0_NAK:
+               langwell_vbus_draw(&dev->gadget, 0);
        case TEST_PACKET:
        case TEST_FORCE_EN:
                portsc1 = readl(&dev->op_regs->portsc1);
@@ -2981,34 +2986,15 @@ static void handle_usb_reset(struct langwell_udc *dev)
        /* write 1s to endptflush register to clear any primed buffers */
        writel((u32) ~0, &dev->op_regs->endptflush);
 
-       if (readl(&dev->op_regs->portsc1) & PORTS_PR) {
-               dev_vdbg(&dev->pdev->dev, "USB bus reset\n");
-               /* bus is reseting */
-               dev->bus_reset = 1;
-
-               /* reset all the queues, stop all USB activities */
-               stop_activity(dev, dev->driver);
-               dev->usb_state = USB_STATE_DEFAULT;
-       } else {
-               dev_vdbg(&dev->pdev->dev, "device controller reset\n");
-
-               /* add some delay between endpoint flush and controller reset */
-               udelay(200);
+       if (!(readl(&dev->op_regs->portsc1) & PORTS_PR))
+               dev_dbg(&dev->pdev->dev, "Intented to reset device controller?\n");
 
-               /* reset all the queues, stop all USB activities */
-               stop_activity(dev, dev->driver);
+       /* bus is reseting */
+       dev->bus_reset = 1;
 
-               /* controller reset */
-               langwell_udc_reset(dev);
-
-               /* reset ep0 dQH and endptctrl */
-               ep0_reset(dev);
-
-               /* enable interrupt and set controller to run state */
-               langwell_udc_start(dev);
-
-               dev->usb_state = USB_STATE_ATTACHED;
-       }
+       /* reset all the queues, stop all USB activities */
+       stop_activity(dev, dev->driver);
+       dev->usb_state = USB_STATE_DEFAULT;
 
        dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
 }
@@ -3271,8 +3257,10 @@ static void langwell_udc_remove(struct pci_dev *pdev)
        pm_runtime_get_noresume(&pdev->dev);
 
        /* free dTD dma_pool and dQH */
-       if (dev->dtd_pool)
+       if (dev->dtd_pool) {
                dma_pool_destroy(dev->dtd_pool);
+               dev->dtd_pool = NULL;
+       }
 
        if (dev->ep_dqh)
                dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
@@ -3655,8 +3643,10 @@ static int langwell_udc_suspend(struct pci_dev *pdev, pm_message_t state)
        pci_save_state(pdev);
 
        /* free dTD dma_pool and dQH */
-       if (dev->dtd_pool)
+       if (dev->dtd_pool) {
                dma_pool_destroy(dev->dtd_pool);
+               dev->dtd_pool = NULL;
+       }
 
        if (dev->ep_dqh)
                dma_free_coherent(&pdev->dev, dev->ep_dqh_size,
index feb1804..3c77b3e 100644 (file)
@@ -235,6 +235,9 @@ static void _penwell_otg_update_chrg_cap(enum usb_charger_type charger,
                        /* SDP event: enter suspend state */
                        event = USBCHRG_EVENT_SUSPEND;
                        flag = 1;
+               } else if (mA == 0) {
+                       event = USBCHRG_EVENT_DISCONN;
+                       flag = 1;
                } else
                        dev_dbg(pnw->dev, "SDP: no need to update EM\n");
                break;
@@ -1005,7 +1008,7 @@ static int penwell_otg_charger_type_detect(void)
 }
 
 /* manual charger detection by ULPI access */
-static int penwell_otg_manual_charger_detection(void)
+static int penwell_otg_manual_chrg_det(void)
 {
        struct penwell_otg              *pnw = the_transceiver;
        struct intel_mid_otg_xceiv      *iotg;
@@ -1943,8 +1946,18 @@ static void penwell_otg_work(struct work_struct *work)
                        if (!is_clovertrail(pdev)) {
                                mutex_lock(&pnw->msic_mutex);
                                if (pdev->revision >= 0x8) {
-                                       retval =
-                                       penwell_otg_manual_charger_detection();
+                                       retval = penwell_otg_manual_chrg_det();
+                                       if (retval < 0) {
+                                               /* if failed, reset controller
+                                                * and try charger detection
+                                                * flow again */
+                                               dev_warn(pnw->dev,
+                                                               "detection failed, retry");
+                                               set_client_mode();
+                                               msleep(100);
+                                               penwell_otg_phy_low_power(0);
+                                       retval = penwell_otg_manual_chrg_det();
+                                       }
                                } else {
                                        /* Enable data contact detection */
                                        penwell_otg_data_contact_detect();
@@ -3110,7 +3123,7 @@ show_hsm(struct device *_dev, struct device_attribute *attr, char *buf)
 
        return PAGE_SIZE - size;
 }
-static DEVICE_ATTR(hsm, S_IRUGO, show_hsm, NULL);
+static DEVICE_ATTR(hsm, S_IRUGO | S_IWUSR | S_IWGRP, show_hsm, NULL);
 
 static ssize_t
 show_chargers(struct device *_dev, struct device_attribute *attr, char *buf)
@@ -3195,7 +3208,8 @@ set_a_bus_req(struct device *dev, struct device_attribute *attr,
 
        return count;
 }
-static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUGO, get_a_bus_req, set_a_bus_req);
+static DEVICE_ATTR(a_bus_req, S_IRUGO | S_IWUSR | S_IWGRP,
+                                  get_a_bus_req, set_a_bus_req);
 
 static ssize_t
 get_a_bus_drop(struct device *dev, struct device_attribute *attr, char *buf)
@@ -3240,7 +3254,7 @@ set_a_bus_drop(struct device *dev, struct device_attribute *attr,
 
        return count;
 }
-static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(a_bus_drop, S_IRUGO | S_IWUSR | S_IWGRP,
        get_a_bus_drop, set_a_bus_drop);
 
 static ssize_t
@@ -3300,7 +3314,8 @@ set_b_bus_req(struct device *dev, struct device_attribute *attr,
 
        return count;
 }
-static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUGO, get_b_bus_req, set_b_bus_req);
+static DEVICE_ATTR(b_bus_req, S_IRUGO | S_IWUSR | S_IWGRP,
+                                  get_b_bus_req, set_b_bus_req);
 
 static ssize_t
 set_a_clr_err(struct device *dev, struct device_attribute *attr,
@@ -3325,7 +3340,7 @@ set_a_clr_err(struct device *dev, struct device_attribute *attr,
 
        return count;
 }
-static DEVICE_ATTR(a_clr_err, S_IWUGO, NULL, set_a_clr_err);
+static DEVICE_ATTR(a_clr_err, S_IRUGO | S_IWUSR | S_IWGRP, NULL, set_a_clr_err);
 
 static struct attribute *inputs_attrs[] = {
        &dev_attr_a_bus_req.attr,
index 7372415..15ec232 100644 (file)
@@ -25,6 +25,8 @@
 #define        CAP_REG_OFFSET          0x0
 #define        OP_REG_OFFSET           0x28
 
+#define SBUSCFG_REG_OFFSET     0x290
+
 #define        DMA_ADDR_INVALID        (~(dma_addr_t)0)
 
 #define        DQH_ALIGNMENT           2048