Commit 3f970bd0 authored by Niklas Neronin's avatar Niklas Neronin Committed by Greg Kroah-Hartman
Browse files

usb: xhci: introduce macro for ring segment list iteration



Add macro to streamline and standardize the iteration over ring
segment list.

xhci_for_each_ring_seg(): Iterates over the entire ring segment list.

The xhci_free_segments_for_ring() function's while loop has not been
updated to use the new macro. This function has some underlying issues,
and as a result, it will be handled separately in a future patch.

Suggested-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: default avatarNiklas Neronin <niklas.neronin@linux.intel.com>
Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20241106101459.775897-11-mathias.nyman@linux.intel.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6d00b614
Loading
Loading
Loading
Loading
+1 −4
Original line number Diff line number Diff line
@@ -214,14 +214,11 @@ static void xhci_ring_dump_segment(struct seq_file *s,

static int xhci_ring_trb_show(struct seq_file *s, void *unused)
{
	int			i;
	struct xhci_ring	*ring = *(struct xhci_ring **)s->private;
	struct xhci_segment	*seg = ring->first_seg;

	for (i = 0; i < ring->num_segs; i++) {
	xhci_for_each_ring_seg(ring->first_seg, seg)
		xhci_ring_dump_segment(s, seg);
		seg = seg->next;
	}

	return 0;
}
+7 −17
Original line number Diff line number Diff line
@@ -224,7 +224,6 @@ static int xhci_update_stream_segment_mapping(
		struct radix_tree_root *trb_address_map,
		struct xhci_ring *ring,
		struct xhci_segment *first_seg,
		struct xhci_segment *last_seg,
		gfp_t mem_flags)
{
	struct xhci_segment *seg;
@@ -234,28 +233,22 @@ static int xhci_update_stream_segment_mapping(
	if (WARN_ON_ONCE(trb_address_map == NULL))
		return 0;

	seg = first_seg;
	do {
	xhci_for_each_ring_seg(first_seg, seg) {
		ret = xhci_insert_segment_mapping(trb_address_map,
				ring, seg, mem_flags);
		if (ret)
			goto remove_streams;
		if (seg == last_seg)
			return 0;
		seg = seg->next;
	} while (seg != first_seg);
	}

	return 0;

remove_streams:
	failed_seg = seg;
	seg = first_seg;
	do {
	xhci_for_each_ring_seg(first_seg, seg) {
		xhci_remove_segment_mapping(trb_address_map, seg);
		if (seg == failed_seg)
			return ret;
		seg = seg->next;
	} while (seg != first_seg);
	}

	return ret;
}
@@ -267,17 +260,14 @@ static void xhci_remove_stream_mapping(struct xhci_ring *ring)
	if (WARN_ON_ONCE(ring->trb_address_map == NULL))
		return;

	seg = ring->first_seg;
	do {
	xhci_for_each_ring_seg(ring->first_seg, seg)
		xhci_remove_segment_mapping(ring->trb_address_map, seg);
		seg = seg->next;
	} while (seg != ring->first_seg);
}

static int xhci_update_stream_mapping(struct xhci_ring *ring, gfp_t mem_flags)
{
	return xhci_update_stream_segment_mapping(ring->trb_address_map, ring,
			ring->first_seg, ring->last_seg, mem_flags);
			ring->first_seg, mem_flags);
}

/* XXX: Do we need the hcd structure in all these functions? */
@@ -438,7 +428,7 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,

	if (ring->type == TYPE_STREAM) {
		ret = xhci_update_stream_segment_mapping(ring->trb_address_map,
						ring, first, last, flags);
						ring, first, flags);
		if (ret)
			goto free_segments;
	}
+8 −12
Original line number Diff line number Diff line
@@ -40,15 +40,15 @@ MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default");

static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
{
	struct xhci_segment *seg = ring->first_seg;
	struct xhci_segment *seg;

	if (!td || !td->start_seg)
		return false;
	do {

	xhci_for_each_ring_seg(ring->first_seg, seg) {
		if (seg == td->start_seg)
			return true;
		seg = seg->next;
	} while (seg && seg != ring->first_seg);
	}

	return false;
}
@@ -785,14 +785,10 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
	struct xhci_segment *seg;

	ring = xhci->cmd_ring;
	seg = ring->deq_seg;
	do {
		memset(seg->trbs, 0,
			sizeof(union xhci_trb) * (TRBS_PER_SEGMENT - 1));
		seg->trbs[TRBS_PER_SEGMENT - 1].link.control &=
			cpu_to_le32(~TRB_CYCLE);
		seg = seg->next;
	} while (seg != ring->deq_seg);
	xhci_for_each_ring_seg(ring->deq_seg, seg) {
		memset(seg->trbs, 0, sizeof(union xhci_trb) * (TRBS_PER_SEGMENT - 1));
		seg->trbs[TRBS_PER_SEGMENT - 1].link.control &= cpu_to_le32(~TRB_CYCLE);
	}

	xhci_initialize_ring_info(ring, 1);
	/*
+3 −0
Original line number Diff line number Diff line
@@ -1263,6 +1263,9 @@ static inline const char *xhci_trb_type_string(u8 type)
#define AVOID_BEI_INTERVAL_MIN	8
#define AVOID_BEI_INTERVAL_MAX	32

#define xhci_for_each_ring_seg(head, seg) \
	for (seg = head; seg != NULL; seg = (seg->next != head ? seg->next : NULL))

struct xhci_segment {
	union xhci_trb		*trbs;
	/* private to HCD */