mirror of
				https://github.com/Ysurac/openmptcprouter.git
				synced 2025-03-09 15:40:20 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			268 lines
		
	
	
	
		
			9.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			268 lines
		
	
	
	
		
			9.9 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| From faa6b820eac2b7c5ebb0632a6201b4eb54bd028c Mon Sep 17 00:00:00 2001
 | |
| From: Jonathan Bell <jonathan@raspberrypi.com>
 | |
| Date: Mon, 13 Dec 2021 15:05:56 +0000
 | |
| Subject: [PATCH 370/726] xhci: refactor out TRBS_PER_SEGMENT define in runtime
 | |
|  code
 | |
| 
 | |
| In anticipation of adjusting the number of utilised TRBs in a ring
 | |
| segment, add trbs_per_seg to struct xhci_ring and use this instead
 | |
| of a compile-time define.
 | |
| 
 | |
| Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
 | |
| ---
 | |
|  drivers/usb/host/xhci-mem.c  | 48 +++++++++++++++++++-----------------
 | |
|  drivers/usb/host/xhci-ring.c | 20 +++++++++------
 | |
|  drivers/usb/host/xhci.c      |  6 ++---
 | |
|  drivers/usb/host/xhci.h      |  1 +
 | |
|  4 files changed, 42 insertions(+), 33 deletions(-)
 | |
| 
 | |
| diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
 | |
| index 2221aba82579..ac6e8957c894 100644
 | |
| --- a/drivers/usb/host/xhci-mem.c
 | |
| +++ b/drivers/usb/host/xhci-mem.c
 | |
| @@ -98,6 +98,7 @@ static void xhci_free_segments_for_ring(struct xhci_hcd *xhci,
 | |
|   */
 | |
|  static void xhci_link_segments(struct xhci_segment *prev,
 | |
|  			       struct xhci_segment *next,
 | |
| +			       unsigned int trbs_per_seg,
 | |
|  			       enum xhci_ring_type type, bool chain_links)
 | |
|  {
 | |
|  	u32 val;
 | |
| @@ -106,16 +107,16 @@ static void xhci_link_segments(struct xhci_segment *prev,
 | |
|  		return;
 | |
|  	prev->next = next;
 | |
|  	if (type != TYPE_EVENT) {
 | |
| -		prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
 | |
| +		prev->trbs[trbs_per_seg - 1].link.segment_ptr =
 | |
|  			cpu_to_le64(next->dma);
 | |
|  
 | |
|  		/* Set the last TRB in the segment to have a TRB type ID of Link TRB */
 | |
| -		val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control);
 | |
| +		val = le32_to_cpu(prev->trbs[trbs_per_seg - 1].link.control);
 | |
|  		val &= ~TRB_TYPE_BITMASK;
 | |
|  		val |= TRB_TYPE(TRB_LINK);
 | |
|  		if (chain_links)
 | |
|  			val |= TRB_CHAIN;
 | |
| -		prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val);
 | |
| +		prev->trbs[trbs_per_seg - 1].link.control = cpu_to_le32(val);
 | |
|  	}
 | |
|  }
 | |
|  
 | |
| @@ -139,15 +140,17 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring,
 | |
|  			  (xhci->quirks & XHCI_AMD_0x96_HOST)));
 | |
|  
 | |
|  	next = ring->enq_seg->next;
 | |
| -	xhci_link_segments(ring->enq_seg, first, ring->type, chain_links);
 | |
| -	xhci_link_segments(last, next, ring->type, chain_links);
 | |
| +	xhci_link_segments(ring->enq_seg, first, ring->trbs_per_seg,
 | |
| +			   ring->type, chain_links);
 | |
| +	xhci_link_segments(last, next, ring->trbs_per_seg,
 | |
| +			   ring->type, chain_links);
 | |
|  	ring->num_segs += num_segs;
 | |
| -	ring->num_trbs_free += (TRBS_PER_SEGMENT - 1) * num_segs;
 | |
| +	ring->num_trbs_free += (ring->trbs_per_seg - 1) * num_segs;
 | |
|  
 | |
|  	if (ring->type != TYPE_EVENT && ring->enq_seg == ring->last_seg) {
 | |
| -		ring->last_seg->trbs[TRBS_PER_SEGMENT-1].link.control
 | |
| +		ring->last_seg->trbs[ring->trbs_per_seg - 1].link.control
 | |
|  			&= ~cpu_to_le32(LINK_TOGGLE);
 | |
| -		last->trbs[TRBS_PER_SEGMENT-1].link.control
 | |
| +		last->trbs[ring->trbs_per_seg - 1].link.control
 | |
|  			|= cpu_to_le32(LINK_TOGGLE);
 | |
|  		ring->last_seg = last;
 | |
|  	}
 | |
| @@ -314,14 +317,15 @@ void xhci_initialize_ring_info(struct xhci_ring *ring,
 | |
|  	 * Each segment has a link TRB, and leave an extra TRB for SW
 | |
|  	 * accounting purpose
 | |
|  	 */
 | |
| -	ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1;
 | |
| +	ring->num_trbs_free = ring->num_segs * (ring->trbs_per_seg - 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, unsigned int cycle_state,
 | |
| -		enum xhci_ring_type type, unsigned int max_packet, gfp_t flags)
 | |
| +		unsigned int num_segs, unsigned int trbs_per_seg,
 | |
| +		unsigned int cycle_state, enum xhci_ring_type type,
 | |
| +		unsigned int max_packet, gfp_t flags)
 | |
|  {
 | |
|  	struct xhci_segment *prev;
 | |
|  	bool chain_links;
 | |
| @@ -350,12 +354,12 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
 | |
|  			}
 | |
|  			return -ENOMEM;
 | |
|  		}
 | |
| -		xhci_link_segments(prev, next, type, chain_links);
 | |
| +		xhci_link_segments(prev, next, trbs_per_seg, type, chain_links);
 | |
|  
 | |
|  		prev = next;
 | |
|  		num_segs--;
 | |
|  	}
 | |
| -	xhci_link_segments(prev, *first, type, chain_links);
 | |
| +	xhci_link_segments(prev, *first, trbs_per_seg, type, chain_links);
 | |
|  	*last = prev;
 | |
|  
 | |
|  	return 0;
 | |
| @@ -387,16 +391,17 @@ struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
 | |
|  	if (num_segs == 0)
 | |
|  		return ring;
 | |
|  
 | |
| +	ring->trbs_per_seg = TRBS_PER_SEGMENT;
 | |
|  	ret = xhci_alloc_segments_for_ring(xhci, &ring->first_seg,
 | |
| -			&ring->last_seg, num_segs, cycle_state, type,
 | |
| -			max_packet, flags);
 | |
| +			&ring->last_seg, num_segs, ring->trbs_per_seg,
 | |
| +			cycle_state, type, max_packet, flags);
 | |
|  	if (ret)
 | |
|  		goto fail;
 | |
|  
 | |
|  	/* Only event ring does not use link TRB */
 | |
|  	if (type != TYPE_EVENT) {
 | |
|  		/* See section 4.9.2.1 and 6.4.4.1 */
 | |
| -		ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |=
 | |
| +		ring->last_seg->trbs[ring->trbs_per_seg - 1].link.control |=
 | |
|  			cpu_to_le32(LINK_TOGGLE);
 | |
|  	}
 | |
|  	xhci_initialize_ring_info(ring, cycle_state);
 | |
| @@ -429,15 +434,14 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
 | |
|  	unsigned int		num_segs_needed;
 | |
|  	int			ret;
 | |
|  
 | |
| -	num_segs_needed = (num_trbs + (TRBS_PER_SEGMENT - 1) - 1) /
 | |
| -				(TRBS_PER_SEGMENT - 1);
 | |
| -
 | |
| +	num_segs_needed = (num_trbs + (ring->trbs_per_seg - 1) - 1) /
 | |
| +				(ring->trbs_per_seg - 1);
 | |
|  	/* Allocate number of segments we needed, or double the ring size */
 | |
|  	num_segs = max(ring->num_segs, num_segs_needed);
 | |
|  
 | |
|  	ret = xhci_alloc_segments_for_ring(xhci, &first, &last,
 | |
| -			num_segs, ring->cycle_state, ring->type,
 | |
| -			ring->bounce_buf_len, flags);
 | |
| +			num_segs, ring->trbs_per_seg, ring->cycle_state,
 | |
| +			ring->type, ring->bounce_buf_len, flags);
 | |
|  	if (ret)
 | |
|  		return -ENOMEM;
 | |
|  
 | |
| @@ -1811,7 +1815,7 @@ int xhci_alloc_erst(struct xhci_hcd *xhci,
 | |
|  	for (val = 0; val < evt_ring->num_segs; val++) {
 | |
|  		entry = &erst->entries[val];
 | |
|  		entry->seg_addr = cpu_to_le64(seg->dma);
 | |
| -		entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT);
 | |
| +		entry->seg_size = cpu_to_le32(evt_ring->trbs_per_seg);
 | |
|  		entry->rsvd = 0;
 | |
|  		seg = seg->next;
 | |
|  	}
 | |
| diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
 | |
| index c2ba570a98b6..323ca0dba61d 100644
 | |
| --- a/drivers/usb/host/xhci-ring.c
 | |
| +++ b/drivers/usb/host/xhci-ring.c
 | |
| @@ -90,15 +90,16 @@ static bool trb_is_link(union xhci_trb *trb)
 | |
|  	return TRB_TYPE_LINK_LE32(trb->link.control);
 | |
|  }
 | |
|  
 | |
| -static bool last_trb_on_seg(struct xhci_segment *seg, union xhci_trb *trb)
 | |
| +static bool last_trb_on_seg(struct xhci_segment *seg,
 | |
| +			    unsigned int trbs_per_seg, union xhci_trb *trb)
 | |
|  {
 | |
| -	return trb == &seg->trbs[TRBS_PER_SEGMENT - 1];
 | |
| +	return trb == &seg->trbs[trbs_per_seg - 1];
 | |
|  }
 | |
|  
 | |
|  static bool last_trb_on_ring(struct xhci_ring *ring,
 | |
|  			struct xhci_segment *seg, union xhci_trb *trb)
 | |
|  {
 | |
| -	return last_trb_on_seg(seg, trb) && (seg->next == ring->first_seg);
 | |
| +	return last_trb_on_seg(seg, ring->trbs_per_seg, trb) && (seg->next == ring->first_seg);
 | |
|  }
 | |
|  
 | |
|  static bool link_trb_toggles_cycle(union xhci_trb *trb)
 | |
| @@ -161,7 +162,8 @@ void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
 | |
|  
 | |
|  	/* event ring doesn't have link trbs, check for last trb */
 | |
|  	if (ring->type == TYPE_EVENT) {
 | |
| -		if (!last_trb_on_seg(ring->deq_seg, ring->dequeue)) {
 | |
| +		if (!last_trb_on_seg(ring->deq_seg, ring->trbs_per_seg,
 | |
| +				     ring->dequeue)) {
 | |
|  			ring->dequeue++;
 | |
|  			goto out;
 | |
|  		}
 | |
| @@ -174,7 +176,8 @@ void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
 | |
|  
 | |
|  	/* All other rings have link trbs */
 | |
|  	if (!trb_is_link(ring->dequeue)) {
 | |
| -		if (last_trb_on_seg(ring->deq_seg, ring->dequeue)) {
 | |
| +		if (last_trb_on_seg(ring->deq_seg, ring->trbs_per_seg,
 | |
| +		    ring->dequeue)) {
 | |
|  			xhci_warn(xhci, "Missing link TRB at end of segment\n");
 | |
|  		} else {
 | |
|  			ring->dequeue++;
 | |
| @@ -225,7 +228,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
 | |
|  	if (!trb_is_link(ring->enqueue))
 | |
|  		ring->num_trbs_free--;
 | |
|  
 | |
| -	if (last_trb_on_seg(ring->enq_seg, ring->enqueue)) {
 | |
| +	if (last_trb_on_seg(ring->enq_seg, ring->trbs_per_seg, ring->enqueue)) {
 | |
|  		xhci_err(xhci, "Tried to move enqueue past ring segment\n");
 | |
|  		return;
 | |
|  	}
 | |
| @@ -3096,7 +3099,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
 | |
|  	 * that clears the EHB.
 | |
|  	 */
 | |
|  	while (xhci_handle_event(xhci) > 0) {
 | |
| -		if (event_loop++ < TRBS_PER_SEGMENT / 2)
 | |
| +		if (event_loop++ < xhci->event_ring->trbs_per_seg / 2)
 | |
|  			continue;
 | |
|  		xhci_update_erst_dequeue(xhci, event_ring_deq);
 | |
|  		event_ring_deq = xhci->event_ring->dequeue;
 | |
| @@ -3238,7 +3241,8 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
 | |
|  		}
 | |
|  	}
 | |
|  
 | |
| -	if (last_trb_on_seg(ep_ring->enq_seg, ep_ring->enqueue)) {
 | |
| +	if (last_trb_on_seg(ep_ring->enq_seg, ep_ring->trbs_per_seg,
 | |
| +	    ep_ring->enqueue)) {
 | |
|  		xhci_warn(xhci, "Missing link TRB at end of ring segment\n");
 | |
|  		return -EINVAL;
 | |
|  	}
 | |
| diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
 | |
| index c7aaba91062d..3e7ca9058df3 100644
 | |
| --- a/drivers/usb/host/xhci.c
 | |
| +++ b/drivers/usb/host/xhci.c
 | |
| @@ -891,8 +891,8 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
 | |
|  	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 &=
 | |
| +			sizeof(union xhci_trb) * (ring->trbs_per_seg - 1));
 | |
| +		seg->trbs[ring->trbs_per_seg - 1].link.control &=
 | |
|  			cpu_to_le32(~TRB_CYCLE);
 | |
|  		seg = seg->next;
 | |
|  	} while (seg != ring->deq_seg);
 | |
| @@ -903,7 +903,7 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
 | |
|  	ring->enq_seg = ring->deq_seg;
 | |
|  	ring->enqueue = ring->dequeue;
 | |
|  
 | |
| -	ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1;
 | |
| +	ring->num_trbs_free = ring->num_segs * (ring->trbs_per_seg - 1) - 1;
 | |
|  	/*
 | |
|  	 * Ring is now zeroed, so the HW should look for change of ownership
 | |
|  	 * when the cycle bit is set to 1.
 | |
| diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
 | |
| index 829a40b063e1..4b6700b8e2ce 100644
 | |
| --- a/drivers/usb/host/xhci.h
 | |
| +++ b/drivers/usb/host/xhci.h
 | |
| @@ -1633,6 +1633,7 @@ struct xhci_ring {
 | |
|  	unsigned int		num_trbs_free;
 | |
|  	unsigned int		num_trbs_free_temp;
 | |
|  	unsigned int		bounce_buf_len;
 | |
| +	unsigned int		trbs_per_seg;
 | |
|  	enum xhci_ring_type	type;
 | |
|  	bool			last_td_was_short;
 | |
|  	struct radix_tree_root	*trb_address_map;
 | |
| -- 
 | |
| 2.33.1
 | |
| 
 |