tools: edimax_fw_header: fix suspicious memset usage
[openwrt/svn-archive/archive.git] / target / linux / adm5120 / files / drivers / usb / host / adm5120-q.c
index 632140b75e848cc779ddfd1882acffad2896f237..cd9c8920afc9235c17a3cd76f2fc516d97939681 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ADM5120 HCD (Host Controller Driver) for USB
  *
- * Copyright (C) 2007,2008 Gabor Juhos <juhosg at openwrt.org>
+ * Copyright (C) 2007-2008 Gabor Juhos <juhosg@openwrt.org>
  *
  * This file was derived from: drivers/usb/host/ohci-q.c
  *   (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
@@ -14,6 +14,7 @@
  */
 
 #include <linux/irq.h>
+#include <linux/slab.h>
 
 /*-------------------------------------------------------------------------*/
 
@@ -42,7 +43,7 @@ __acquires(ahcd->lock)
        }
 
 #ifdef ADMHC_VERBOSE_DEBUG
-       urb_print(ahcd, urb, "RET", usb_pipeout (urb->pipe), status);
+       urb_print(ahcd, urb, "RET", usb_pipeout(urb->pipe), status);
 #endif
 
        /* urb->complete() can reenter this HCD */
@@ -73,12 +74,12 @@ static int balance(struct admhcd *ahcd, int interval, int load)
         * that has enough bandwidth left unreserved.
         */
        for (i = 0; i < interval ; i++) {
-               if (branch < 0 || ahcd->load [branch] > ahcd->load [i]) {
+               if (branch < 0 || ahcd->load[branch] > ahcd->load[i]) {
                        int     j;
 
                        /* usb 1.1 says 90% of one frame */
                        for (j = i; j < NUM_INTS; j += interval) {
-                               if ((ahcd->load [j] + load) > 900)
+                               if ((ahcd->load[j] + load) > 900)
                                        break;
                        }
                        if (j < NUM_INTS)
@@ -97,17 +98,17 @@ static int balance(struct admhcd *ahcd, int interval, int load)
  * into the schedule tree in the apppropriate place.  most iso devices use
  * 1msec periods, but that's not required.
  */
-static void periodic_link (struct admhcd *ahcd, struct ed *ed)
+static void periodic_link(struct admhcd *ahcd, struct ed *ed)
 {
        unsigned        i;
 
-       admhc_vdbg (ahcd, "link %sed %p branch %d [%dus.], interval %d\n",
+       admhc_vdbg(ahcd, "link %sed %p branch %d [%dus.], interval %d\n",
                (ed->hwINFO & cpu_to_hc32(ahcd, ED_ISO)) ? "iso " : "",
                ed, ed->branch, ed->load, ed->interval);
 
        for (i = ed->branch; i < NUM_INTS; i += ed->interval) {
-               struct ed       **prev = &ahcd->periodic [i];
-               __hc32          *prev_p = &ahcd->hcca->int_table [i];
+               struct ed       **prev = &ahcd->periodic[i];
+               __hc32          *prev_p = &ahcd->hcca->int_table[i];
                struct ed       *here = *prev;
 
                /* sorting each branch by period (slow before fast)
@@ -125,12 +126,12 @@ static void periodic_link (struct admhcd *ahcd, struct ed *ed)
                        ed->ed_next = here;
                        if (here)
                                ed->hwNextED = *prev_p;
-                       wmb ();
+                       wmb();
                        *prev = ed;
                        *prev_p = cpu_to_hc32(ahcd, ed->dma);
                        wmb();
                }
-               ahcd->load [i] += ed->load;
+               ahcd->load[i] += ed->load;
        }
        admhcd_to_hcd(ahcd)->self.bandwidth_allocated += ed->load / ed->interval;
 }
@@ -170,14 +171,14 @@ static int ed_schedule(struct admhcd *ahcd, struct ed *ed)
 
 #if 0  /* FIXME */
 /* scan the periodic table to find and unlink this ED */
-static void periodic_unlink (struct admhcd *ahcd, struct ed *ed)
+static void periodic_unlink(struct admhcd *ahcd, struct ed *ed)
 {
        int     i;
 
        for (i = ed->branch; i < NUM_INTS; i += ed->interval) {
                struct ed       *temp;
-               struct ed       **prev = &ahcd->periodic [i];
-               __hc32          *prev_p = &ahcd->hcca->int_table [i];
+               struct ed       **prev = &ahcd->periodic[i];
+               __hc32          *prev_p = &ahcd->hcca->int_table[i];
 
                while (*prev && (temp = *prev) != ed) {
                        prev_p = &temp->hwNextED;
@@ -187,11 +188,11 @@ static void periodic_unlink (struct admhcd *ahcd, struct ed *ed)
                        *prev_p = ed->hwNextED;
                        *prev = ed->ed_next;
                }
-               ahcd->load [i] -= ed->load;
+               ahcd->load[i] -= ed->load;
        }
 
        admhcd_to_hcd(ahcd)->self.bandwidth_allocated -= ed->load / ed->interval;
-       admhc_vdbg (ahcd, "unlink %sed %p branch %d [%dus.], interval %d\n",
+       admhc_vdbg(ahcd, "unlink %sed %p branch %d [%dus.], interval %d\n",
                (ed->hwINFO & cpu_to_hc32(ahcd, ED_ISO)) ? "iso " : "",
                ed, ed->branch, ed->load, ed->interval);
 }
@@ -300,7 +301,7 @@ static struct ed *ed_get(struct admhcd *ahcd,       struct usb_host_endpoint *ep,
                u32             info;
 
                /* FIXME: usbcore changes dev->devnum before SET_ADDRESS
-                * suceeds ... otherwise we wouldn't need "pipe".
+                * succeeds ... otherwise we wouldn't need "pipe".
                 */
                info = usb_pipedevice(pipe);
                info |= (ep->desc.bEndpointAddress & ~USB_DIR_IN) << ED_EN_SHIFT;
@@ -596,7 +597,7 @@ static int td_done(struct admhcd *ahcd, struct urb *urb, struct td *td)
                urb->iso_frame_desc[td->index].status = cc_to_error[cc];
 
                if (cc != TD_CC_NOERROR)
-                       admhc_vdbg (ahcd,
+                       admhc_vdbg(ahcd,
                                "urb %p iso td %p (%d) len %d cc %d\n",
                                urb, td, 1 + td->index, dlen, cc);
 
@@ -615,9 +616,8 @@ static int td_done(struct admhcd *ahcd, struct urb *urb, struct td *td)
 
 
                /* count all non-empty packets except control SETUP packet */
-               if ((type != PIPE_CONTROL || td->index != 0) && tdDBP != 0) {
+               if ((type != PIPE_CONTROL || td->index != 0) && tdDBP != 0)
                        urb->actual_length += tdDBP - td->data_dma + bl;
-               }
 
                if (cc != TD_CC_NOERROR && cc < TD_CC_HCD0)
                        admhc_vdbg(ahcd,
@@ -635,8 +635,7 @@ static int td_done(struct admhcd *ahcd, struct urb *urb, struct td *td)
 
 /*-------------------------------------------------------------------------*/
 
-static inline void
-ed_halted(struct admhcd *ahcd, struct td *td, int cc, struct td *rev)
+static void ed_halted(struct admhcd *ahcd, struct td *td, int cc)
 {
        struct urb              *urb = td->urb;
        struct urb_priv         *urb_priv = urb->hcpriv;
@@ -691,13 +690,13 @@ ed_halted(struct admhcd *ahcd, struct td *td, int cc, struct td *rev)
                        break;
                /* fallthrough */
        default:
-               admhc_dbg (ahcd,
+               admhc_dbg(ahcd,
                        "urb %p path %s ep%d%s %08x cc %d --> status %d\n",
                        urb, urb->dev->devpath,
                        usb_pipeendpoint (urb->pipe),
-                       usb_pipein (urb->pipe) ? "in" : "out",
+                       usb_pipein(urb->pipe) ? "in" : "out",
                        hc32_to_cpu(ahcd, td->hwINFO),
-                       cc, cc_to_error [cc]);
+                       cc, cc_to_error[cc]);
        }
 }
 
@@ -719,7 +718,7 @@ rescan_all:
                 * frame counter wraps and EDs with partially retired TDs
                 */
                if (likely(HC_IS_RUNNING(admhcd_to_hcd(ahcd)->state))) {
-                       if (tick_before (tick, ed->tick)) {
+                       if (tick_before(tick, ed->tick)) {
 skip_ed:
                                last = &ed->ed_rm_next;
                                continue;
@@ -765,6 +764,7 @@ rescan_this:
                        struct urb      *urb;
                        struct urb_priv *urb_priv;
                        __hc32          savebits;
+                       u32             tdINFO;
                        int             status;
 
                        td = list_entry(entry, struct td, td_list);
@@ -782,6 +782,16 @@ rescan_this:
                        /* patch pointer hc uses */
                        savebits = *prev & ~cpu_to_hc32(ahcd, TD_MASK);
                        *prev = td->hwNextTD | savebits;
+                       /* If this was unlinked, the TD may not have been
+                        * retired ... so manually save dhe data toggle.
+                        * The controller ignores the value we save for
+                        * control and ISO endpoints.
+                        */
+                       tdINFO = hc32_to_cpup(ahcd, &td->hwINFO);
+                       if ((tdINFO & TD_T) == TD_T_DATA0)
+                               ed->hwHeadP &= ~cpu_to_hc32(ahcd, ED_C);
+                       else if ((tdINFO & TD_T) == TD_T_DATA1)
+                               ed->hwHeadP |= cpu_to_hc32(ahcd, ED_C);
 
                        /* HC may have partly processed this TD */
 #ifdef ADMHC_VERBOSE_DEBUG
@@ -817,18 +827,17 @@ rescan_this:
 }
 
 /*-------------------------------------------------------------------------*/
-
 /*
  * Process normal completions (error or success) and clean the schedules.
  *
  * This is the main path for handing urbs back to drivers.  The only other
- * path is finish_unlinks(), which unlinks URBs using ed_rm_list, instead of
- * scanning the (re-reversed) donelist as this does.
+ * normal path is finish_unlinks(), which unlinks URBs using ed_rm_list,
+ * instead of scanning the (re-reversed) donelist as this does.
  */
 
 static void ed_unhalt(struct admhcd *ahcd, struct ed *ed, struct urb *urb)
 {
-       struct list_head *entry,*tmp;
+       struct list_head *entry, *tmp;
        __hc32 toggle = ed->hwHeadP & cpu_to_hc32(ahcd, ED_C);
 
 #ifdef ADMHC_VERBOSE_DEBUG
@@ -880,7 +889,7 @@ static inline int is_td_halted(struct admhcd *ahcd, struct ed *ed,
 
 static void ed_update(struct admhcd *ahcd, struct ed *ed)
 {
-       struct list_head *entry,*tmp;
+       struct list_head *entry, *tmp;
 
 #ifdef ADMHC_VERBOSE_DEBUG
        admhc_dump_ed(ahcd, "UPDATE", ed, 1);
@@ -901,7 +910,7 @@ static void ed_update(struct admhcd *ahcd, struct ed *ed)
                        ed_unhalt(ahcd, ed, urb);
 
                if (ed->type == PIPE_INTERRUPT)
-                       ed_intr_refill(ahcd,ed);
+                       ed_intr_refill(ahcd, ed);
 
                /* If all this urb's TDs are done, call complete() */
                if (urb_priv->td_idx == urb_priv->td_cnt)
@@ -923,11 +932,11 @@ static void ed_update(struct admhcd *ahcd, struct ed *ed)
                                /* ... hc may need waking-up */
                                switch (ed->type) {
                                case PIPE_CONTROL:
-                                       admhc_writel (ahcd, OHCI_CLF,
+                                       admhc_writel(ahcd, OHCI_CLF,
                                                &ahcd->regs->cmdstatus);
                                        break;
                                case PIPE_BULK:
-                                       admhc_writel (ahcd, OHCI_BLF,
+                                       admhc_writel(ahcd, OHCI_BLF,
                                                &ahcd->regs->cmdstatus);
                                        break;
                                }