1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright 2020, NXP Semiconductors
4 #include <net/tc_act/tc_gate.h>
5 #include <linux/dsa/8021q.h>
6 #include "sja1105_vl.h"
8 #define SJA1105_SIZE_VL_STATUS 8
10 /* Insert into the global gate list, sorted by gate action time. */
11 static int sja1105_insert_gate_entry(struct sja1105_gating_config *gating_cfg,
12 struct sja1105_rule *rule,
13 u8 gate_state, s64 entry_time,
14 struct netlink_ext_ack *extack)
16 struct sja1105_gate_entry *e;
19 e = kzalloc(sizeof(*e), GFP_KERNEL);
24 e->gate_state = gate_state;
25 e->interval = entry_time;
27 if (list_empty(&gating_cfg->entries)) {
28 list_add(&e->list, &gating_cfg->entries);
30 struct sja1105_gate_entry *p;
32 list_for_each_entry(p, &gating_cfg->entries, list) {
33 if (p->interval == e->interval) {
34 NL_SET_ERR_MSG_MOD(extack,
40 if (e->interval < p->interval)
43 list_add(&e->list, p->list.prev);
46 gating_cfg->num_entries++;
54 /* The gate entries contain absolute times in their e->interval field. Convert
55 * that to proper intervals (i.e. "0, 5, 10, 15" to "5, 5, 5, 5").
58 sja1105_gating_cfg_time_to_interval(struct sja1105_gating_config *gating_cfg,
61 struct sja1105_gate_entry *last_e;
62 struct sja1105_gate_entry *e;
63 struct list_head *prev;
65 list_for_each_entry(e, &gating_cfg->entries, list) {
66 struct sja1105_gate_entry *p;
70 if (prev == &gating_cfg->entries)
73 p = list_entry(prev, struct sja1105_gate_entry, list);
74 p->interval = e->interval - p->interval;
76 last_e = list_last_entry(&gating_cfg->entries,
77 struct sja1105_gate_entry, list);
78 last_e->interval = cycle_time - last_e->interval;
81 static void sja1105_free_gating_config(struct sja1105_gating_config *gating_cfg)
83 struct sja1105_gate_entry *e, *n;
85 list_for_each_entry_safe(e, n, &gating_cfg->entries, list) {
91 static int sja1105_compose_gating_subschedule(struct sja1105_private *priv,
92 struct netlink_ext_ack *extack)
94 struct sja1105_gating_config *gating_cfg = &priv->tas_data.gating_cfg;
95 struct sja1105_rule *rule;
96 s64 max_cycle_time = 0;
97 s64 its_base_time = 0;
100 sja1105_free_gating_config(gating_cfg);
102 list_for_each_entry(rule, &priv->flow_block.rules, list) {
103 if (rule->type != SJA1105_RULE_VL)
105 if (rule->vl.type != SJA1105_VL_TIME_TRIGGERED)
108 if (max_cycle_time < rule->vl.cycle_time) {
109 max_cycle_time = rule->vl.cycle_time;
110 its_base_time = rule->vl.base_time;
117 dev_dbg(priv->ds->dev, "max_cycle_time %lld its_base_time %lld\n",
118 max_cycle_time, its_base_time);
120 gating_cfg->base_time = its_base_time;
121 gating_cfg->cycle_time = max_cycle_time;
122 gating_cfg->num_entries = 0;
124 list_for_each_entry(rule, &priv->flow_block.rules, list) {
128 if (rule->type != SJA1105_RULE_VL)
130 if (rule->vl.type != SJA1105_VL_TIME_TRIGGERED)
133 /* Calculate the difference between this gating schedule's
134 * base time, and the base time of the gating schedule with the
135 * longest cycle time. We call it the relative base time (rbt).
137 rbt = future_base_time(rule->vl.base_time, rule->vl.cycle_time,
139 rbt -= its_base_time;
143 for (i = 0; i < rule->vl.num_entries; i++) {
144 u8 gate_state = rule->vl.entries[i].gate_state;
145 s64 entry_time = time;
147 while (entry_time < max_cycle_time) {
148 rc = sja1105_insert_gate_entry(gating_cfg, rule,
155 entry_time += rule->vl.cycle_time;
157 time += rule->vl.entries[i].interval;
161 sja1105_gating_cfg_time_to_interval(gating_cfg, max_cycle_time);
165 sja1105_free_gating_config(gating_cfg);
169 /* The switch flow classification core implements TTEthernet, which 'thinks' in
170 * terms of Virtual Links (VL), a concept borrowed from ARINC 664 part 7.
171 * However it also has one other operating mode (VLLUPFORMAT=0) where it acts
172 * somewhat closer to a pre-standard implementation of IEEE 802.1Qci
173 * (Per-Stream Filtering and Policing), which is what the driver is going to be
177 * Key = {DMAC && VLANID +---------+ Key = { (DMAC[47:16] & VLMASK ==
178 * && VLAN PCP | | VLMARKER)
179 * && INGRESS PORT} +---------+ (both fixed)
180 * (exact match, | && DMAC[15:0] == VLID
181 * all specified in rule) | (specified in rule)
182 * v && INGRESS PORT }
184 * 0 (PSFP) / \ 1 (ARINC664)
185 * +-----------/ VLLUPFORMAT \----------+
188 * 0 (forwarding) v ------------ |
190 * / \ 1 (QoS classification) |
191 * +---/ ISCRITICAL \-----------+ |
192 * | \ (per rule) / | |
193 * | \ / VLID taken from VLID taken from
194 * v ------------ index of rule contents of rule
195 * select that matched that matched
197 * | +---------+--------+
201 * | (indexed by VLID)
203 * | +--------------| |
204 * | | select TYPE +---------+
206 * | 0 (rate ------------ 1 (time
207 * | constrained) / \ triggered)
208 * | +------/ TYPE \------------+
209 * | | \ (per VLID) / |
211 * | VL Policing ------------ VL Policing
212 * | (indexed by VLID) (indexed by VLID)
213 * | +---------+ +---------+
214 * | | TYPE=0 | | TYPE=1 |
215 * | +---------+ +---------+
216 * | select SHARINDX select SHARINDX to
217 * | to rate-limit re-enter VL Forwarding
218 * | groups of VL's with new VLID for egress
221 * | select MAXLEN -> exceed => drop select MAXLEN -> exceed => drop
224 * | VL Forwarding VL Forwarding
225 * | (indexed by SHARINDX) (indexed by SHARINDX)
226 * | +---------+ +---------+
227 * | | TYPE=0 | | TYPE=1 |
228 * | +---------+ +---------+
229 * | select PRIORITY, select PRIORITY,
230 * | PARTITION, DESTPORTS PARTITION, DESTPORTS
233 * | VL Policing VL Policing
234 * | (indexed by SHARINDX) (indexed by SHARINDX)
235 * | +---------+ +---------+
236 * | | TYPE=0 | | TYPE=1 |
237 * | +---------+ +---------+
240 * | select BAG, -> exceed => drop |
242 * | | ----------------------------------------------
243 * | | / Reception Window is open for this VL \
244 * | | / (the Schedule Table executes an entry i \
245 * | | / M <= i < N, for which these conditions hold): \ no
247 * | | |yes \ WINST[M] == 1 && WINSTINDEX[M] == VLID / |
248 * | | | \ WINEND[N] == 1 && WINSTINDEX[N] == VLID / |
250 * | | | \ (the VL window has opened and not yet closed)/ |
251 * | | | ---------------------------------------------- |
253 * | | dispatch to DESTPORTS when the Schedule Table drop
254 * | | executes an entry i with TXEN == 1 && VLINDEX == i
256 * dispatch immediately to DESTPORTS
258 * The per-port classification key is always composed of {DMAC, VID, PCP} and
259 * is non-maskable. This 'looks like' the NULL stream identification function
260 * from IEEE 802.1CB clause 6, except for the extra VLAN PCP. When the switch
261 * ports operate as VLAN-unaware, we do allow the user to not specify the VLAN
262 * ID and PCP, and then the port-based defaults will be used.
264 * In TTEthernet, routing is something that needs to be done manually for each
265 * Virtual Link. So the flow action must always include one of:
266 * a. 'redirect', 'trap' or 'drop': select the egress port list
267 * Additionally, the following actions may be applied on a Virtual Link,
268 * turning it into 'critical' traffic:
269 * b. 'police': turn it into a rate-constrained VL, with bandwidth limitation
270 * given by the maximum frame length, bandwidth allocation gap (BAG) and
272 * c. 'gate': turn it into a time-triggered VL, which can be only be received
273 * and forwarded according to a given schedule.
276 static bool sja1105_vl_key_lower(struct sja1105_vl_lookup_entry *a,
277 struct sja1105_vl_lookup_entry *b)
279 if (a->macaddr < b->macaddr)
281 if (a->macaddr > b->macaddr)
283 if (a->vlanid < b->vlanid)
285 if (a->vlanid > b->vlanid)
287 if (a->port < b->port)
289 if (a->port > b->port)
291 if (a->vlanprior < b->vlanprior)
293 if (a->vlanprior > b->vlanprior)
299 static int sja1105_init_virtual_links(struct sja1105_private *priv,
300 struct netlink_ext_ack *extack)
302 struct sja1105_vl_policing_entry *vl_policing;
303 struct sja1105_vl_forwarding_entry *vl_fwd;
304 struct sja1105_vl_lookup_entry *vl_lookup;
305 bool have_critical_virtual_links = false;
306 struct sja1105_table *table;
307 struct sja1105_rule *rule;
308 int num_virtual_links = 0;
309 int max_sharindx = 0;
312 /* Figure out the dimensioning of the problem */
313 list_for_each_entry(rule, &priv->flow_block.rules, list) {
314 if (rule->type != SJA1105_RULE_VL)
316 /* Each VL lookup entry matches on a single ingress port */
317 num_virtual_links += hweight_long(rule->port_mask);
319 if (rule->vl.type != SJA1105_VL_NONCRITICAL)
320 have_critical_virtual_links = true;
321 if (max_sharindx < rule->vl.sharindx)
322 max_sharindx = rule->vl.sharindx;
325 if (num_virtual_links > SJA1105_MAX_VL_LOOKUP_COUNT) {
326 NL_SET_ERR_MSG_MOD(extack, "Not enough VL entries available");
330 if (max_sharindx + 1 > SJA1105_MAX_VL_LOOKUP_COUNT) {
331 NL_SET_ERR_MSG_MOD(extack, "Policer index out of range");
335 max_sharindx = max_t(int, num_virtual_links, max_sharindx) + 1;
337 /* Discard previous VL Lookup Table */
338 table = &priv->static_config.tables[BLK_IDX_VL_LOOKUP];
339 if (table->entry_count) {
340 kfree(table->entries);
341 table->entry_count = 0;
344 /* Discard previous VL Policing Table */
345 table = &priv->static_config.tables[BLK_IDX_VL_POLICING];
346 if (table->entry_count) {
347 kfree(table->entries);
348 table->entry_count = 0;
351 /* Discard previous VL Forwarding Table */
352 table = &priv->static_config.tables[BLK_IDX_VL_FORWARDING];
353 if (table->entry_count) {
354 kfree(table->entries);
355 table->entry_count = 0;
358 /* Discard previous VL Forwarding Parameters Table */
359 table = &priv->static_config.tables[BLK_IDX_VL_FORWARDING_PARAMS];
360 if (table->entry_count) {
361 kfree(table->entries);
362 table->entry_count = 0;
366 if (!num_virtual_links)
369 /* Pre-allocate space in the static config tables */
371 /* VL Lookup Table */
372 table = &priv->static_config.tables[BLK_IDX_VL_LOOKUP];
373 table->entries = kcalloc(num_virtual_links,
374 table->ops->unpacked_entry_size,
378 table->entry_count = num_virtual_links;
379 vl_lookup = table->entries;
383 list_for_each_entry(rule, &priv->flow_block.rules, list) {
386 if (rule->type != SJA1105_RULE_VL)
389 for_each_set_bit(port, &rule->port_mask, SJA1105_NUM_PORTS) {
390 vl_lookup[k].format = SJA1105_VL_FORMAT_PSFP;
391 vl_lookup[k].port = port;
392 vl_lookup[k].macaddr = rule->key.vl.dmac;
393 if (rule->key.type == SJA1105_KEY_VLAN_AWARE_VL) {
394 vl_lookup[k].vlanid = rule->key.vl.vid;
395 vl_lookup[k].vlanprior = rule->key.vl.pcp;
397 u16 vid = dsa_8021q_rx_vid(priv->ds, port);
399 vl_lookup[k].vlanid = vid;
400 vl_lookup[k].vlanprior = 0;
402 /* For critical VLs, the DESTPORTS mask is taken from
403 * the VL Forwarding Table, so no point in putting it
404 * in the VL Lookup Table
406 if (rule->vl.type == SJA1105_VL_NONCRITICAL)
407 vl_lookup[k].destports = rule->vl.destports;
409 vl_lookup[k].iscritical = true;
410 vl_lookup[k].flow_cookie = rule->cookie;
415 /* UM10944.pdf chapter 4.2.3 VL Lookup table:
416 * "the entries in the VL Lookup table must be sorted in ascending
417 * order (i.e. the smallest value must be loaded first) according to
418 * the following sort order: MACADDR, VLANID, PORT, VLANPRIOR."
420 for (i = 0; i < num_virtual_links; i++) {
421 struct sja1105_vl_lookup_entry *a = &vl_lookup[i];
423 for (j = i + 1; j < num_virtual_links; j++) {
424 struct sja1105_vl_lookup_entry *b = &vl_lookup[j];
426 if (sja1105_vl_key_lower(b, a)) {
427 struct sja1105_vl_lookup_entry tmp = *a;
435 if (!have_critical_virtual_links)
438 /* VL Policing Table */
439 table = &priv->static_config.tables[BLK_IDX_VL_POLICING];
440 table->entries = kcalloc(max_sharindx, table->ops->unpacked_entry_size,
444 table->entry_count = max_sharindx;
445 vl_policing = table->entries;
447 /* VL Forwarding Table */
448 table = &priv->static_config.tables[BLK_IDX_VL_FORWARDING];
449 table->entries = kcalloc(max_sharindx, table->ops->unpacked_entry_size,
453 table->entry_count = max_sharindx;
454 vl_fwd = table->entries;
456 /* VL Forwarding Parameters Table */
457 table = &priv->static_config.tables[BLK_IDX_VL_FORWARDING_PARAMS];
458 table->entries = kcalloc(1, table->ops->unpacked_entry_size,
462 table->entry_count = 1;
464 for (i = 0; i < num_virtual_links; i++) {
465 unsigned long cookie = vl_lookup[i].flow_cookie;
466 struct sja1105_rule *rule = sja1105_rule_find(priv, cookie);
468 if (rule->vl.type == SJA1105_VL_NONCRITICAL)
470 if (rule->vl.type == SJA1105_VL_TIME_TRIGGERED) {
471 int sharindx = rule->vl.sharindx;
473 vl_policing[i].type = 1;
474 vl_policing[i].sharindx = sharindx;
475 vl_policing[i].maxlen = rule->vl.maxlen;
476 vl_policing[sharindx].type = 1;
479 vl_fwd[sharindx].type = 1;
480 vl_fwd[sharindx].priority = rule->vl.ipv;
481 vl_fwd[sharindx].partition = 0;
482 vl_fwd[sharindx].destports = rule->vl.destports;
486 sja1105_frame_memory_partitioning(priv);
491 int sja1105_vl_redirect(struct sja1105_private *priv, int port,
492 struct netlink_ext_ack *extack, unsigned long cookie,
493 struct sja1105_key *key, unsigned long destports,
496 struct sja1105_rule *rule = sja1105_rule_find(priv, cookie);
499 if (priv->vlan_state == SJA1105_VLAN_UNAWARE &&
500 key->type != SJA1105_KEY_VLAN_UNAWARE_VL) {
501 NL_SET_ERR_MSG_MOD(extack,
502 "Can only redirect based on DMAC");
504 } else if ((priv->vlan_state == SJA1105_VLAN_BEST_EFFORT ||
505 priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) &&
506 key->type != SJA1105_KEY_VLAN_AWARE_VL) {
507 NL_SET_ERR_MSG_MOD(extack,
508 "Can only redirect based on {DMAC, VID, PCP}");
513 rule = kzalloc(sizeof(*rule), GFP_KERNEL);
517 rule->cookie = cookie;
518 rule->type = SJA1105_RULE_VL;
520 list_add(&rule->list, &priv->flow_block.rules);
523 rule->port_mask |= BIT(port);
525 rule->vl.destports |= destports;
527 rule->vl.destports = destports;
529 rc = sja1105_init_virtual_links(priv, extack);
531 rule->port_mask &= ~BIT(port);
532 if (!rule->port_mask) {
533 list_del(&rule->list);
541 int sja1105_vl_delete(struct sja1105_private *priv, int port,
542 struct sja1105_rule *rule, struct netlink_ext_ack *extack)
546 rule->port_mask &= ~BIT(port);
547 if (!rule->port_mask) {
548 list_del(&rule->list);
552 rc = sja1105_compose_gating_subschedule(priv, extack);
556 rc = sja1105_init_virtual_links(priv, extack);
560 rc = sja1105_init_scheduling(priv);
564 return sja1105_static_config_reload(priv, SJA1105_VIRTUAL_LINKS);
567 int sja1105_vl_gate(struct sja1105_private *priv, int port,
568 struct netlink_ext_ack *extack, unsigned long cookie,
569 struct sja1105_key *key, u32 index, s32 prio,
570 u64 base_time, u64 cycle_time, u64 cycle_time_ext,
571 u32 num_entries, struct action_gate_entry *entries)
573 struct sja1105_rule *rule = sja1105_rule_find(priv, cookie);
578 if (cycle_time_ext) {
579 NL_SET_ERR_MSG_MOD(extack,
580 "Cycle time extension not supported");
584 div_s64_rem(base_time, sja1105_delta_to_ns(1), &rem);
586 NL_SET_ERR_MSG_MOD(extack,
587 "Base time must be multiple of 200 ns");
591 div_s64_rem(cycle_time, sja1105_delta_to_ns(1), &rem);
593 NL_SET_ERR_MSG_MOD(extack,
594 "Cycle time must be multiple of 200 ns");
598 if (priv->vlan_state == SJA1105_VLAN_UNAWARE &&
599 key->type != SJA1105_KEY_VLAN_UNAWARE_VL) {
600 NL_SET_ERR_MSG_MOD(extack,
601 "Can only gate based on DMAC");
603 } else if ((priv->vlan_state == SJA1105_VLAN_BEST_EFFORT ||
604 priv->vlan_state == SJA1105_VLAN_FILTERING_FULL) &&
605 key->type != SJA1105_KEY_VLAN_AWARE_VL) {
606 NL_SET_ERR_MSG_MOD(extack,
607 "Can only gate based on {DMAC, VID, PCP}");
612 rule = kzalloc(sizeof(*rule), GFP_KERNEL);
616 list_add(&rule->list, &priv->flow_block.rules);
617 rule->cookie = cookie;
618 rule->type = SJA1105_RULE_VL;
620 rule->vl.type = SJA1105_VL_TIME_TRIGGERED;
621 rule->vl.sharindx = index;
622 rule->vl.base_time = base_time;
623 rule->vl.cycle_time = cycle_time;
624 rule->vl.num_entries = num_entries;
625 rule->vl.entries = kcalloc(num_entries,
626 sizeof(struct action_gate_entry),
628 if (!rule->vl.entries) {
633 for (i = 0; i < num_entries; i++) {
634 div_s64_rem(entries[i].interval,
635 sja1105_delta_to_ns(1), &rem);
637 NL_SET_ERR_MSG_MOD(extack,
638 "Interval must be multiple of 200 ns");
643 if (!entries[i].interval) {
644 NL_SET_ERR_MSG_MOD(extack,
645 "Interval cannot be zero");
650 if (ns_to_sja1105_delta(entries[i].interval) >
651 SJA1105_TAS_MAX_DELTA) {
652 NL_SET_ERR_MSG_MOD(extack,
653 "Maximum interval is 52 ms");
658 if (entries[i].maxoctets != -1) {
659 NL_SET_ERR_MSG_MOD(extack,
660 "Cannot offload IntervalOctetMax");
666 ipv = entries[i].ipv;
667 } else if (ipv != entries[i].ipv) {
668 NL_SET_ERR_MSG_MOD(extack,
669 "Only support a single IPV per VL");
674 rule->vl.entries[i] = entries[i];
678 if (key->type == SJA1105_KEY_VLAN_AWARE_VL)
684 /* TODO: support per-flow MTU */
685 rule->vl.maxlen = VLAN_ETH_FRAME_LEN + ETH_FCS_LEN;
689 rule->port_mask |= BIT(port);
691 rc = sja1105_compose_gating_subschedule(priv, extack);
695 rc = sja1105_init_virtual_links(priv, extack);
699 if (sja1105_gating_check_conflicts(priv, -1, extack)) {
700 NL_SET_ERR_MSG_MOD(extack, "Conflict with tc-taprio schedule");
707 rule->port_mask &= ~BIT(port);
708 if (!rule->port_mask) {
709 list_del(&rule->list);
710 kfree(rule->vl.entries);
718 static int sja1105_find_vlid(struct sja1105_private *priv, int port,
719 struct sja1105_key *key)
721 struct sja1105_vl_lookup_entry *vl_lookup;
722 struct sja1105_table *table;
725 if (WARN_ON(key->type != SJA1105_KEY_VLAN_AWARE_VL &&
726 key->type != SJA1105_KEY_VLAN_UNAWARE_VL))
729 table = &priv->static_config.tables[BLK_IDX_VL_LOOKUP];
730 vl_lookup = table->entries;
732 for (i = 0; i < table->entry_count; i++) {
733 if (key->type == SJA1105_KEY_VLAN_AWARE_VL) {
734 if (vl_lookup[i].port == port &&
735 vl_lookup[i].macaddr == key->vl.dmac &&
736 vl_lookup[i].vlanid == key->vl.vid &&
737 vl_lookup[i].vlanprior == key->vl.pcp)
740 if (vl_lookup[i].port == port &&
741 vl_lookup[i].macaddr == key->vl.dmac)
749 int sja1105_vl_stats(struct sja1105_private *priv, int port,
750 struct sja1105_rule *rule, struct flow_stats *stats,
751 struct netlink_ext_ack *extack)
753 const struct sja1105_regs *regs = priv->info->regs;
754 u8 buf[SJA1105_SIZE_VL_STATUS] = {0};
761 if (rule->vl.type != SJA1105_VL_TIME_TRIGGERED)
764 vlid = sja1105_find_vlid(priv, port, &rule->key);
768 rc = sja1105_xfer_buf(priv, SPI_READ, regs->vl_status + 2 * vlid, buf,
769 SJA1105_SIZE_VL_STATUS);
771 NL_SET_ERR_MSG_MOD(extack, "SPI access failed");
775 sja1105_unpack(buf, &timingerr, 31, 16, SJA1105_SIZE_VL_STATUS);
776 sja1105_unpack(buf, &unreleased, 15, 0, SJA1105_SIZE_VL_STATUS);
777 sja1105_unpack(buf, &lengtherr, 47, 32, SJA1105_SIZE_VL_STATUS);
779 pkts = timingerr + unreleased + lengtherr;
781 flow_stats_update(stats, 0, pkts - rule->vl.stats.pkts, 0,
782 jiffies - rule->vl.stats.lastused,
783 FLOW_ACTION_HW_STATS_IMMEDIATE);
785 rule->vl.stats.pkts = pkts;
786 rule->vl.stats.lastused = jiffies;