forked from mirrors/linux
		
	igc: Lift TAPRIO schedule restriction
Add support for Qbv schedules where one queue stays open
in consecutive entries. Currently that's not supported.
Example schedule:
|tc qdisc replace dev ${INTERFACE} handle 100 parent root taprio num_tc 3 \
|   map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 \
|   queues 1@0 1@1 2@2 \
|   base-time ${BASETIME} \
|   sched-entry S 0x01 300000 \ # Stream High/Low
|   sched-entry S 0x06 500000 \ # Management and Best Effort
|   sched-entry S 0x04 200000 \ # Best Effort
|   flags 0x02
Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
Reviewed-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
Tested-by: Naama Meir <naamax.meir@linux.intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
			
			
This commit is contained in:
		
							parent
							
								
									6e693a1042
								
							
						
					
					
						commit
						a5fd39464a
					
				
					 1 changed files with 17 additions and 6 deletions
				
			
		| 
						 | 
				
			
			@ -5813,9 +5813,10 @@ static bool validate_schedule(struct igc_adapter *adapter,
 | 
			
		|||
		return false;
 | 
			
		||||
 | 
			
		||||
	for (n = 0; n < qopt->num_entries; n++) {
 | 
			
		||||
		const struct tc_taprio_sched_entry *e;
 | 
			
		||||
		const struct tc_taprio_sched_entry *e, *prev;
 | 
			
		||||
		int i;
 | 
			
		||||
 | 
			
		||||
		prev = n ? &qopt->entries[n - 1] : NULL;
 | 
			
		||||
		e = &qopt->entries[n];
 | 
			
		||||
 | 
			
		||||
		/* i225 only supports "global" frame preemption
 | 
			
		||||
| 
						 | 
				
			
			@ -5828,7 +5829,12 @@ static bool validate_schedule(struct igc_adapter *adapter,
 | 
			
		|||
			if (e->gate_mask & BIT(i))
 | 
			
		||||
				queue_uses[i]++;
 | 
			
		||||
 | 
			
		||||
			if (queue_uses[i] > 1)
 | 
			
		||||
			/* There are limitations: A single queue cannot be
 | 
			
		||||
			 * opened and closed multiple times per cycle unless the
 | 
			
		||||
			 * gate stays open. Check for it.
 | 
			
		||||
			 */
 | 
			
		||||
			if (queue_uses[i] > 1 &&
 | 
			
		||||
			    !(prev->gate_mask & BIT(i)))
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -5872,6 +5878,7 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
 | 
			
		|||
static int igc_save_qbv_schedule(struct igc_adapter *adapter,
 | 
			
		||||
				 struct tc_taprio_qopt_offload *qopt)
 | 
			
		||||
{
 | 
			
		||||
	bool queue_configured[IGC_MAX_TX_QUEUES] = { };
 | 
			
		||||
	u32 start_time = 0, end_time = 0;
 | 
			
		||||
	size_t n;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -5887,9 +5894,6 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
 | 
			
		|||
	adapter->cycle_time = qopt->cycle_time;
 | 
			
		||||
	adapter->base_time = qopt->base_time;
 | 
			
		||||
 | 
			
		||||
	/* FIXME: be a little smarter about cases when the gate for a
 | 
			
		||||
	 * queue stays open for more than one entry.
 | 
			
		||||
	 */
 | 
			
		||||
	for (n = 0; n < qopt->num_entries; n++) {
 | 
			
		||||
		struct tc_taprio_sched_entry *e = &qopt->entries[n];
 | 
			
		||||
		int i;
 | 
			
		||||
| 
						 | 
				
			
			@ -5902,8 +5906,15 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
 | 
			
		|||
			if (!(e->gate_mask & BIT(i)))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			ring->start_time = start_time;
 | 
			
		||||
			/* Check whether a queue stays open for more than one
 | 
			
		||||
			 * entry. If so, keep the start and advance the end
 | 
			
		||||
			 * time.
 | 
			
		||||
			 */
 | 
			
		||||
			if (!queue_configured[i])
 | 
			
		||||
				ring->start_time = start_time;
 | 
			
		||||
			ring->end_time = end_time;
 | 
			
		||||
 | 
			
		||||
			queue_configured[i] = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		start_time += e->interval;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue