Commit a5fd3946 authored by Kurt Kanzenbach's avatar Kurt Kanzenbach Committed by Tony Nguyen

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's avatarKurt Kanzenbach <kurt@linutronix.de>
Reviewed-by: default avatarVinicius Costa Gomes <vinicius.gomes@intel.com>
Tested-by: default avatarNaama Meir <naamax.meir@linux.intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 6e693a10
...@@ -5813,9 +5813,10 @@ static bool validate_schedule(struct igc_adapter *adapter, ...@@ -5813,9 +5813,10 @@ static bool validate_schedule(struct igc_adapter *adapter,
return false; return false;
for (n = 0; n < qopt->num_entries; n++) { 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; int i;
prev = n ? &qopt->entries[n - 1] : NULL;
e = &qopt->entries[n]; e = &qopt->entries[n];
/* i225 only supports "global" frame preemption /* i225 only supports "global" frame preemption
...@@ -5828,7 +5829,12 @@ static bool validate_schedule(struct igc_adapter *adapter, ...@@ -5828,7 +5829,12 @@ static bool validate_schedule(struct igc_adapter *adapter,
if (e->gate_mask & BIT(i)) if (e->gate_mask & BIT(i))
queue_uses[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; return false;
} }
} }
...@@ -5872,6 +5878,7 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter) ...@@ -5872,6 +5878,7 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
static int igc_save_qbv_schedule(struct igc_adapter *adapter, static int igc_save_qbv_schedule(struct igc_adapter *adapter,
struct tc_taprio_qopt_offload *qopt) struct tc_taprio_qopt_offload *qopt)
{ {
bool queue_configured[IGC_MAX_TX_QUEUES] = { };
u32 start_time = 0, end_time = 0; u32 start_time = 0, end_time = 0;
size_t n; size_t n;
...@@ -5887,9 +5894,6 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, ...@@ -5887,9 +5894,6 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
adapter->cycle_time = qopt->cycle_time; adapter->cycle_time = qopt->cycle_time;
adapter->base_time = qopt->base_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++) { for (n = 0; n < qopt->num_entries; n++) {
struct tc_taprio_sched_entry *e = &qopt->entries[n]; struct tc_taprio_sched_entry *e = &qopt->entries[n];
int i; int i;
...@@ -5902,8 +5906,15 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, ...@@ -5902,8 +5906,15 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
if (!(e->gate_mask & BIT(i))) if (!(e->gate_mask & BIT(i)))
continue; 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; ring->end_time = end_time;
queue_configured[i] = true;
} }
start_time += e->interval; start_time += e->interval;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment