Commit 317ab5b8 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

net: dsa: sja1105: Configure the Time-Aware Scheduler via tc-taprio offload

This qdisc offload is the closest thing to what the SJA1105 supports in
hardware for time-based egress shaping. The switch core really is built
around SAE AS6802/TTEthernet (a TTTech standard) but can be made to
operate similarly to IEEE 802.1Qbv with some constraints:

- The gate control list is a global list for all ports. There are 8
  execution threads that iterate through this global list in parallel.
  I don't know why 8, there are only 4 front-panel ports.

- Care must be taken by the user to make sure that two execution threads
  never get to execute a GCL entry simultaneously. I created a O(n^4)
  checker for this hardware limitation, prior to accepting a taprio
  offload configuration as valid.

- The spec says that if a GCL entry's interval is shorter than the frame
  length, you shouldn't send it (and end up in head-of-line blocking).
  Well, this switch does anyway.

- The switch has no concept of ADMIN and OPER configurations. Because
  it's so simple, the TAS settings are loaded through the static config
  tables interface, so there isn't even place for any discussion about
  'graceful switchover between ADMIN and OPER'. You just reset the
  switch and upload a new OPER config.

- The switch accepts multiple time sources for the gate events. Right
  now I am using the standalone clock source as opposed to PTP. So the
  base time parameter doesn't really do much. Support for the PTP clock
  source will be added in a future series.
Signed-off-by: default avatarVladimir Oltean <olteanv@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5f06c63b
...@@ -23,3 +23,11 @@ config NET_DSA_SJA1105_PTP ...@@ -23,3 +23,11 @@ config NET_DSA_SJA1105_PTP
help help
This enables support for timestamping and PTP clock manipulations in This enables support for timestamping and PTP clock manipulations in
the SJA1105 DSA driver. the SJA1105 DSA driver.
config NET_DSA_SJA1105_TAS
bool "Support for the Time-Aware Scheduler on NXP SJA1105"
depends on NET_DSA_SJA1105
help
This enables support for the TTEthernet-based egress scheduling
engine in the SJA1105 DSA driver, which is controlled using a
hardware offload of the tc-tqprio qdisc.
...@@ -12,3 +12,7 @@ sja1105-objs := \ ...@@ -12,3 +12,7 @@ sja1105-objs := \
ifdef CONFIG_NET_DSA_SJA1105_PTP ifdef CONFIG_NET_DSA_SJA1105_PTP
sja1105-objs += sja1105_ptp.o sja1105-objs += sja1105_ptp.o
endif endif
ifdef CONFIG_NET_DSA_SJA1105_TAS
sja1105-objs += sja1105_tas.o
endif
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
*/ */
#define SJA1105_AGEING_TIME_MS(ms) ((ms) / 10) #define SJA1105_AGEING_TIME_MS(ms) ((ms) / 10)
#include "sja1105_tas.h"
/* Keeps the different addresses between E/T and P/Q/R/S */ /* Keeps the different addresses between E/T and P/Q/R/S */
struct sja1105_regs { struct sja1105_regs {
u64 device_id; u64 device_id;
...@@ -104,6 +106,7 @@ struct sja1105_private { ...@@ -104,6 +106,7 @@ struct sja1105_private {
*/ */
struct mutex mgmt_lock; struct mutex mgmt_lock;
struct sja1105_tagger_data tagger_data; struct sja1105_tagger_data tagger_data;
struct sja1105_tas_data tas_data;
}; };
#include "sja1105_dynamic_config.h" #include "sja1105_dynamic_config.h"
...@@ -120,6 +123,9 @@ typedef enum { ...@@ -120,6 +123,9 @@ typedef enum {
SPI_WRITE = 1, SPI_WRITE = 1,
} sja1105_spi_rw_mode_t; } sja1105_spi_rw_mode_t;
/* From sja1105_main.c */
int sja1105_static_config_reload(struct sja1105_private *priv);
/* From sja1105_spi.c */ /* From sja1105_spi.c */
int sja1105_spi_send_packed_buf(const struct sja1105_private *priv, int sja1105_spi_send_packed_buf(const struct sja1105_private *priv,
sja1105_spi_rw_mode_t rw, u64 reg_addr, sja1105_spi_rw_mode_t rw, u64 reg_addr,
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/dsa/8021q.h> #include <linux/dsa/8021q.h>
#include "sja1105.h" #include "sja1105.h"
#include "sja1105_tas.h"
static void sja1105_hw_reset(struct gpio_desc *gpio, unsigned int pulse_len, static void sja1105_hw_reset(struct gpio_desc *gpio, unsigned int pulse_len,
unsigned int startup_delay) unsigned int startup_delay)
...@@ -1382,7 +1383,7 @@ static void sja1105_bridge_leave(struct dsa_switch *ds, int port, ...@@ -1382,7 +1383,7 @@ static void sja1105_bridge_leave(struct dsa_switch *ds, int port,
* modify at runtime (currently only MAC) and restore them after uploading, * modify at runtime (currently only MAC) and restore them after uploading,
* such that this operation is relatively seamless. * such that this operation is relatively seamless.
*/ */
static int sja1105_static_config_reload(struct sja1105_private *priv) int sja1105_static_config_reload(struct sja1105_private *priv)
{ {
struct sja1105_mac_config_entry *mac; struct sja1105_mac_config_entry *mac;
int speed_mbps[SJA1105_NUM_PORTS]; int speed_mbps[SJA1105_NUM_PORTS];
...@@ -1727,6 +1728,7 @@ static void sja1105_teardown(struct dsa_switch *ds) ...@@ -1727,6 +1728,7 @@ static void sja1105_teardown(struct dsa_switch *ds)
{ {
struct sja1105_private *priv = ds->priv; struct sja1105_private *priv = ds->priv;
sja1105_tas_teardown(ds);
cancel_work_sync(&priv->tagger_data.rxtstamp_work); cancel_work_sync(&priv->tagger_data.rxtstamp_work);
skb_queue_purge(&priv->tagger_data.skb_rxtstamp_queue); skb_queue_purge(&priv->tagger_data.skb_rxtstamp_queue);
sja1105_ptp_clock_unregister(priv); sja1105_ptp_clock_unregister(priv);
...@@ -2056,6 +2058,18 @@ static bool sja1105_port_txtstamp(struct dsa_switch *ds, int port, ...@@ -2056,6 +2058,18 @@ static bool sja1105_port_txtstamp(struct dsa_switch *ds, int port,
return true; return true;
} }
static int sja1105_port_setup_tc(struct dsa_switch *ds, int port,
enum tc_setup_type type,
void *type_data)
{
switch (type) {
case TC_SETUP_QDISC_TAPRIO:
return sja1105_setup_tc_taprio(ds, port, type_data);
default:
return -EOPNOTSUPP;
}
}
static const struct dsa_switch_ops sja1105_switch_ops = { static const struct dsa_switch_ops sja1105_switch_ops = {
.get_tag_protocol = sja1105_get_tag_protocol, .get_tag_protocol = sja1105_get_tag_protocol,
.setup = sja1105_setup, .setup = sja1105_setup,
...@@ -2088,6 +2102,7 @@ static const struct dsa_switch_ops sja1105_switch_ops = { ...@@ -2088,6 +2102,7 @@ static const struct dsa_switch_ops sja1105_switch_ops = {
.port_hwtstamp_set = sja1105_hwtstamp_set, .port_hwtstamp_set = sja1105_hwtstamp_set,
.port_rxtstamp = sja1105_port_rxtstamp, .port_rxtstamp = sja1105_port_rxtstamp,
.port_txtstamp = sja1105_port_txtstamp, .port_txtstamp = sja1105_port_txtstamp,
.port_setup_tc = sja1105_port_setup_tc,
}; };
static int sja1105_check_device_id(struct sja1105_private *priv) static int sja1105_check_device_id(struct sja1105_private *priv)
...@@ -2197,6 +2212,8 @@ static int sja1105_probe(struct spi_device *spi) ...@@ -2197,6 +2212,8 @@ static int sja1105_probe(struct spi_device *spi)
} }
mutex_init(&priv->mgmt_lock); mutex_init(&priv->mgmt_lock);
sja1105_tas_setup(ds);
return dsa_register_switch(priv->ds); return dsa_register_switch(priv->ds);
} }
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0
* Copyright (c) 2019, Vladimir Oltean <olteanv@gmail.com>
*/
#ifndef _SJA1105_TAS_H
#define _SJA1105_TAS_H
#include <net/pkt_sched.h>
#if IS_ENABLED(CONFIG_NET_DSA_SJA1105_TAS)
struct sja1105_tas_data {
struct tc_taprio_qopt_offload *offload[SJA1105_NUM_PORTS];
};
int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port,
struct tc_taprio_qopt_offload *admin);
void sja1105_tas_setup(struct dsa_switch *ds);
void sja1105_tas_teardown(struct dsa_switch *ds);
#else
/* C doesn't allow empty structures, bah! */
struct sja1105_tas_data {
u8 dummy;
};
static inline int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port,
struct tc_taprio_qopt_offload *admin)
{
return -EOPNOTSUPP;
}
static inline void sja1105_tas_setup(struct dsa_switch *ds) { }
static inline void sja1105_tas_teardown(struct dsa_switch *ds) { }
#endif /* IS_ENABLED(CONFIG_NET_DSA_SJA1105_TAS) */
#endif /* _SJA1105_TAS_H */
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