Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 289681
b: refs/heads/master
c: 70d4360
h: refs/heads/master
i:
  289679: 68e70c9
v: v3
  • Loading branch information
Andiry Xu authored and Sarah Sharp committed Mar 13, 2012
1 parent 4ad5907 commit d14dcd9
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 35 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b008df60c6369ba0290fa7daa177375407a12e07
refs/heads/master: 70d43601773b9f270b62867a51495846d746b5d4
89 changes: 55 additions & 34 deletions trunk/drivers/usb/host/xhci-mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,20 @@ static void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg)
kfree(seg);
}

static void xhci_free_segments_for_ring(struct xhci_hcd *xhci,
struct xhci_segment *first)
{
struct xhci_segment *seg;

seg = first->next;
while (seg != first) {
struct xhci_segment *next = seg->next;
xhci_segment_free(xhci, seg);
seg = next;
}
xhci_segment_free(xhci, first);
}

/*
* Make the prev segment point to the next segment.
*
Expand Down Expand Up @@ -101,22 +115,12 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
/* XXX: Do we need the hcd structure in all these functions? */
void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
{
struct xhci_segment *seg;
struct xhci_segment *first_seg;

if (!ring)
return;
if (ring->first_seg) {
first_seg = ring->first_seg;
seg = first_seg->next;
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;
}

if (ring->first_seg)
xhci_free_segments_for_ring(xhci, ring->first_seg);

kfree(ring);
}

Expand All @@ -143,6 +147,38 @@ static void xhci_initialize_ring_info(struct xhci_ring *ring)
ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1;
}

/* Allocate segments and link them for a ring */
static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
struct xhci_segment **first, struct xhci_segment **last,
unsigned int num_segs, enum xhci_ring_type type, gfp_t flags)
{
struct xhci_segment *prev;

prev = xhci_segment_alloc(xhci, flags);
if (!prev)
return -ENOMEM;
num_segs--;

*first = prev;
while (num_segs > 0) {
struct xhci_segment *next;

next = xhci_segment_alloc(xhci, flags);
if (!next) {
xhci_free_segments_for_ring(xhci, *first);
return -ENOMEM;
}
xhci_link_segments(xhci, prev, next, type);

prev = next;
num_segs--;
}
xhci_link_segments(xhci, prev, *first, type);
*last = prev;

return 0;
}

/**
* Create a new ring with zero or more segments.
*
Expand All @@ -154,7 +190,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
unsigned int num_segs, enum xhci_ring_type type, gfp_t flags)
{
struct xhci_ring *ring;
struct xhci_segment *prev;
int ret;

ring = kzalloc(sizeof *(ring), flags);
if (!ring)
Expand All @@ -166,30 +202,15 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
if (num_segs == 0)
return ring;

ring->first_seg = xhci_segment_alloc(xhci, flags);
if (!ring->first_seg)
ret = xhci_alloc_segments_for_ring(xhci, &ring->first_seg,
&ring->last_seg, num_segs, type, flags);
if (ret)
goto fail;
num_segs--;

prev = ring->first_seg;
while (num_segs > 0) {
struct xhci_segment *next;

next = xhci_segment_alloc(xhci, flags);
if (!next)
goto fail;
xhci_link_segments(xhci, prev, next, type);

prev = next;
num_segs--;
}
xhci_link_segments(xhci, prev, ring->first_seg, type);
ring->last_seg = prev;

/* Only event ring does not use link TRB */
if (type != TYPE_EVENT) {
/* See section 4.9.2.1 and 6.4.4.1 */
prev->trbs[TRBS_PER_SEGMENT-1].link.control |=
ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |=
cpu_to_le32(LINK_TOGGLE);
}
xhci_initialize_ring_info(ring);
Expand Down

0 comments on commit d14dcd9

Please sign in to comment.