xhci-mem.c: xhci_segment_free: No need for checking seg argument
[pandora-kernel.git] / drivers / usb / host / xhci-mem.c
index 9451d94..bc6ec0c 100644 (file)
@@ -61,8 +61,6 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci, gfp_t flag
 
 static void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg)
 {
-       if (!seg)
-               return;
        if (seg->trbs) {
                xhci_dbg(xhci, "Freeing DMA segment at %p (virtual) 0x%llx (DMA)\n",
                                seg->trbs, (unsigned long long)seg->dma);
@@ -112,18 +110,20 @@ void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
        struct xhci_segment *seg;
        struct xhci_segment *first_seg;
 
-       if (!ring || !ring->first_seg)
+       if (!ring)
                return;
-       first_seg = ring->first_seg;
-       seg = first_seg->next;
-       xhci_dbg(xhci, "Freeing ring at %p\n", ring);
-       while (seg != first_seg) {
-               struct xhci_segment *next = seg->next;
-               xhci_segment_free(xhci, seg);
-               seg = next;
+       if (ring->first_seg) {
+               first_seg = ring->first_seg;
+               seg = first_seg->next;
+               xhci_dbg(xhci, "Freeing ring at %p\n", ring);
+               while (seg != first_seg) {
+                       struct xhci_segment *next = seg->next;
+                       xhci_segment_free(xhci, seg);
+                       seg = next;
+               }
+               xhci_segment_free(xhci, first_seg);
+               ring->first_seg = NULL;
        }
-       xhci_segment_free(xhci, first_seg);
-       ring->first_seg = NULL;
        kfree(ring);
 }
 
@@ -783,6 +783,7 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
 {
        struct xhci_virt_device *dev;
        int i;
+       int old_active_eps = 0;
 
        /* Slot ID 0 is reserved */
        if (slot_id == 0 || !xhci->devs[slot_id])
@@ -793,15 +794,29 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id)
        if (!dev)
                return;
 
+       if (dev->tt_info)
+               old_active_eps = dev->tt_info->active_eps;
+
        for (i = 0; i < 31; ++i) {
                if (dev->eps[i].ring)
                        xhci_ring_free(xhci, dev->eps[i].ring);
                if (dev->eps[i].stream_info)
                        xhci_free_stream_info(xhci,
                                        dev->eps[i].stream_info);
+               /* Endpoints on the TT/root port lists should have been removed
+                * when usb_disable_device() was called for the device.
+                * We can't drop them anyway, because the udev might have gone
+                * away by this point, and we can't tell what speed it was.
+                */
+               if (!list_empty(&dev->eps[i].bw_endpoint_list))
+                       xhci_warn(xhci, "Slot %u endpoint %u "
+                                       "not removed from BW list!\n",
+                                       slot_id, i);
        }
        /* If this is a hub, free the TT(s) from the TT list */
        xhci_free_tt_info(xhci, dev, slot_id);
+       /* If necessary, update the number of active TTs on this root port */
+       xhci_update_tt_active_eps(xhci, dev, old_active_eps);
 
        if (dev->ring_cache) {
                for (i = 0; i < dev->num_rings_cached; i++)
@@ -855,6 +870,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
        for (i = 0; i < 31; i++) {
                xhci_init_endpoint_timer(xhci, &dev->eps[i]);
                INIT_LIST_HEAD(&dev->eps[i].cancelled_td_list);
+               INIT_LIST_HEAD(&dev->eps[i].bw_endpoint_list);
        }
 
        /* Allocate endpoint 0 ring */
@@ -1457,11 +1473,12 @@ void xhci_update_bw_info(struct xhci_hcd *xhci,
                        /* Added or changed endpoint */
                        bw_info->ep_interval = CTX_TO_EP_INTERVAL(
                                        le32_to_cpu(ep_ctx->ep_info));
-                       bw_info->mult = CTX_TO_EP_MULT(
-                                       le32_to_cpu(ep_ctx->ep_info));
-                       /* Number of packets is zero-based in the input context,
-                        * but we want one-based for the interval table.
+                       /* Number of packets and mult are zero-based in the
+                        * input context, but we want one-based for the
+                        * interval table.
                         */
+                       bw_info->mult = CTX_TO_EP_MULT(
+                                       le32_to_cpu(ep_ctx->ep_info)) + 1;
                        bw_info->num_packets = CTX_TO_MAX_BURST(
                                        le32_to_cpu(ep_ctx->ep_info2)) + 1;
                        bw_info->max_packet_size = MAX_PACKET_DECODED(
@@ -1650,18 +1667,10 @@ struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci,
 
 void xhci_urb_free_priv(struct xhci_hcd *xhci, struct urb_priv *urb_priv)
 {
-       int last;
-
-       if (!urb_priv)
-               return;
-
-       last = urb_priv->length - 1;
-       if (last >= 0) {
-               int     i;
-               for (i = 0; i <= last; i++)
-                       kfree(urb_priv->td[i]);
+       if (urb_priv) {
+               kfree(urb_priv->td[0]);
+               kfree(urb_priv);
        }
-       kfree(urb_priv);
 }
 
 void xhci_free_command(struct xhci_hcd *xhci,
@@ -1994,7 +2003,7 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
        __le32 __iomem *addr;
        u32 offset;
        unsigned int num_ports;
-       int i, port_index;
+       int i, j, port_index;
 
        addr = &xhci->cap_regs->hcc_params;
        offset = XHCI_HCC_EXT_CAPS(xhci_readl(xhci, addr));
@@ -2012,8 +2021,14 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
        xhci->rh_bw = kzalloc(sizeof(*xhci->rh_bw)*num_ports, flags);
        if (!xhci->rh_bw)
                return -ENOMEM;
-       for (i = 0; i < num_ports; i++)
+       for (i = 0; i < num_ports; i++) {
+               struct xhci_interval_bw_table *bw_table;
+
                INIT_LIST_HEAD(&xhci->rh_bw[i].tts);
+               bw_table = &xhci->rh_bw[i].bw_table;
+               for (j = 0; j < XHCI_MAX_INTERVAL; j++)
+                       INIT_LIST_HEAD(&bw_table->interval_bw[j].endpoints);
+       }
 
        /*
         * For whatever reason, the first capability offset is from the