Commit 9b5bcb19 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'dsa-tagger-storage'

Vladimir Oltean says:

====================
Replace DSA dp->priv with tagger-owned storage

Ansuel's recent work on qca8k register access over Ethernet:
https://patchwork.kernel.org/project/netdevbpf/cover/20211207145942.7444-1-ansuelsmth@gmail.com/
has triggered me to do something which I should've done for a longer
time:
https://patchwork.kernel.org/project/netdevbpf/patch/20211109095013.27829-7-martin.kaistra@linutronix.de/#24585521
which is to replace dp->priv with something that has less caveats.

The dp->priv was introduced when sja1105 needed to hold stateful
information in the tagging protocol driver. In that design, dp->priv
held memory allocated by the switch driver, because the tagging protocol
driver design was 100% stateless.

Some years have passed and others have started to feel the need for
stateful information kept by the tagger, as well as passing data back
and forth between the tagging protocol driver and the switch driver.
This isn't possible cleanly in DSA due to a circular dependency which
leads to broken module autoloading:
https://lore.kernel.org/netdev/20210908220834.d7gmtnwrorhharna@skbuf/

This patchset introduces a framework that resembles something normal,
which allows data to be passed from the tagging protocol driver (things
like switch management packets, which aren't intended for the network
stack) to the switch driver, while the tagging protocol still remains
more or less stateless. The overall design of the framework was
discussed with Ansuel too and it appears to be flexible enough to cover
the "register access over Ethernet" use case. Additionally, the existing
uses of dp->priv, which have mainly to do with PTP timestamping, have
also been migrated.

Changes in v2:
Fix transient build breakage in patch 5/11 due to a missing parenthesis,
https://patchwork.hopto.org/static/nipa/592567/12665213/build_clang/
and another transient build warning in patch 4/11 that for some reason
doesn't appear in my W=1 C=1 build.
https://patchwork.hopto.org/static/nipa/592567/12665209/build_clang/stderr


====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e0068620 4f3cb343
Loading
Loading
Loading
Loading
+14 −50
Original line number Diff line number Diff line
@@ -1155,38 +1155,22 @@ static void felix_port_deferred_xmit(struct kthread_work *work)
	kfree(xmit_work);
}

static int felix_port_setup_tagger_data(struct dsa_switch *ds, int port)
static int felix_connect_tag_protocol(struct dsa_switch *ds,
				      enum dsa_tag_protocol proto)
{
	struct dsa_port *dp = dsa_to_port(ds, port);
	struct ocelot *ocelot = ds->priv;
	struct felix *felix = ocelot_to_felix(ocelot);
	struct felix_port *felix_port;
	struct ocelot_8021q_tagger_data *tagger_data;

	if (!dsa_port_is_user(dp))
	switch (proto) {
	case DSA_TAG_PROTO_OCELOT_8021Q:
		tagger_data = ocelot_8021q_tagger_data(ds);
		tagger_data->xmit_work_fn = felix_port_deferred_xmit;
		return 0;

	felix_port = kzalloc(sizeof(*felix_port), GFP_KERNEL);
	if (!felix_port)
		return -ENOMEM;

	felix_port->xmit_worker = felix->xmit_worker;
	felix_port->xmit_work_fn = felix_port_deferred_xmit;

	dp->priv = felix_port;

	case DSA_TAG_PROTO_OCELOT:
	case DSA_TAG_PROTO_SEVILLE:
		return 0;
	default:
		return -EPROTONOSUPPORT;
	}

static void felix_port_teardown_tagger_data(struct dsa_switch *ds, int port)
{
	struct dsa_port *dp = dsa_to_port(ds, port);
	struct felix_port *felix_port = dp->priv;

	if (!felix_port)
		return;

	dp->priv = NULL;
	kfree(felix_port);
}

/* Hardware initialization done here so that we can allocate structures with
@@ -1217,12 +1201,6 @@ static int felix_setup(struct dsa_switch *ds)
		}
	}

	felix->xmit_worker = kthread_create_worker(0, "felix_xmit");
	if (IS_ERR(felix->xmit_worker)) {
		err = PTR_ERR(felix->xmit_worker);
		goto out_deinit_timestamp;
	}

	for (port = 0; port < ds->num_ports; port++) {
		if (dsa_is_unused_port(ds, port))
			continue;
@@ -1233,14 +1211,6 @@ static int felix_setup(struct dsa_switch *ds)
		 * bits of vlan tag.
		 */
		felix_port_qos_map_init(ocelot, port);

		err = felix_port_setup_tagger_data(ds, port);
		if (err) {
			dev_err(ds->dev,
				"port %d failed to set up tagger data: %pe\n",
				port, ERR_PTR(err));
			goto out_deinit_ports;
		}
	}

	err = ocelot_devlink_sb_register(ocelot);
@@ -1268,13 +1238,9 @@ static int felix_setup(struct dsa_switch *ds)
		if (dsa_is_unused_port(ds, port))
			continue;

		felix_port_teardown_tagger_data(ds, port);
		ocelot_deinit_port(ocelot, port);
	}

	kthread_destroy_worker(felix->xmit_worker);

out_deinit_timestamp:
	ocelot_deinit_timestamp(ocelot);
	ocelot_deinit(ocelot);

@@ -1303,12 +1269,9 @@ static void felix_teardown(struct dsa_switch *ds)
		if (dsa_is_unused_port(ds, port))
			continue;

		felix_port_teardown_tagger_data(ds, port);
		ocelot_deinit_port(ocelot, port);
	}

	kthread_destroy_worker(felix->xmit_worker);

	ocelot_devlink_sb_unregister(ocelot);
	ocelot_deinit_timestamp(ocelot);
	ocelot_deinit(ocelot);
@@ -1648,6 +1611,7 @@ felix_mrp_del_ring_role(struct dsa_switch *ds, int port,
const struct dsa_switch_ops felix_switch_ops = {
	.get_tag_protocol		= felix_get_tag_protocol,
	.change_tag_protocol		= felix_change_tag_protocol,
	.connect_tag_protocol		= felix_connect_tag_protocol,
	.setup				= felix_setup,
	.teardown			= felix_teardown,
	.set_ageing_time		= felix_set_ageing_time,
+4 −2
Original line number Diff line number Diff line
@@ -249,6 +249,7 @@ struct sja1105_private {
	bool fixed_link[SJA1105_MAX_NUM_PORTS];
	unsigned long ucast_egress_floods;
	unsigned long bcast_egress_floods;
	unsigned long hwts_tx_en;
	const struct sja1105_info *info;
	size_t max_xfer_len;
	struct spi_device *spidev;
@@ -256,11 +257,13 @@ struct sja1105_private {
	u16 bridge_pvid[SJA1105_MAX_NUM_PORTS];
	u16 tag_8021q_pvid[SJA1105_MAX_NUM_PORTS];
	struct sja1105_flow_block flow_block;
	struct sja1105_port ports[SJA1105_MAX_NUM_PORTS];
	/* Serializes transmission of management frames so that
	 * the switch doesn't confuse them with one another.
	 */
	struct mutex mgmt_lock;
	/* PTP two-step TX timestamp ID, and its serialization lock */
	spinlock_t ts_id_lock;
	u8 ts_id;
	/* Serializes access to the dynamic config interface */
	struct mutex dynamic_config_lock;
	struct devlink_region **regions;
@@ -269,7 +272,6 @@ struct sja1105_private {
	struct mii_bus *mdio_base_tx;
	struct mii_bus *mdio_pcs;
	struct dw_xpcs *xpcs[SJA1105_MAX_NUM_PORTS];
	struct sja1105_tagger_data tagger_data;
	struct sja1105_ptp_data ptp_data;
	struct sja1105_tas_data tas_data;
};
+33 −88
Original line number Diff line number Diff line
@@ -2617,18 +2617,6 @@ static int sja1105_prechangeupper(struct dsa_switch *ds, int port,
	return 0;
}

static void sja1105_port_disable(struct dsa_switch *ds, int port)
{
	struct sja1105_private *priv = ds->priv;
	struct sja1105_port *sp = &priv->ports[port];

	if (!dsa_is_user_port(ds, port))
		return;

	kthread_cancel_work_sync(&sp->xmit_work);
	skb_queue_purge(&sp->xmit_queue);
}

static int sja1105_mgmt_xmit(struct dsa_switch *ds, int port, int slot,
			     struct sk_buff *skb, bool takets)
{
@@ -2687,10 +2675,8 @@ static int sja1105_mgmt_xmit(struct dsa_switch *ds, int port, int slot,
	return NETDEV_TX_OK;
}

#define work_to_port(work) \
		container_of((work), struct sja1105_port, xmit_work)
#define tagger_to_sja1105(t) \
		container_of((t), struct sja1105_private, tagger_data)
#define work_to_xmit_work(w) \
		container_of((w), struct sja1105_deferred_xmit_work, work)

/* Deferred work is unfortunately necessary because setting up the management
 * route cannot be done from atomit context (SPI transfer takes a sleepable
@@ -2698,24 +2684,40 @@ static int sja1105_mgmt_xmit(struct dsa_switch *ds, int port, int slot,
 */
static void sja1105_port_deferred_xmit(struct kthread_work *work)
{
	struct sja1105_port *sp = work_to_port(work);
	struct sja1105_tagger_data *tagger_data = sp->data;
	struct sja1105_private *priv = tagger_to_sja1105(tagger_data);
	int port = sp - priv->ports;
	struct sk_buff *skb;
	struct sja1105_deferred_xmit_work *xmit_work = work_to_xmit_work(work);
	struct sk_buff *clone, *skb = xmit_work->skb;
	struct dsa_switch *ds = xmit_work->dp->ds;
	struct sja1105_private *priv = ds->priv;
	int port = xmit_work->dp->index;

	while ((skb = skb_dequeue(&sp->xmit_queue)) != NULL) {
		struct sk_buff *clone = SJA1105_SKB_CB(skb)->clone;
	clone = SJA1105_SKB_CB(skb)->clone;

	mutex_lock(&priv->mgmt_lock);

		sja1105_mgmt_xmit(priv->ds, port, 0, skb, !!clone);
	sja1105_mgmt_xmit(ds, port, 0, skb, !!clone);

	/* The clone, if there, was made by dsa_skb_tx_timestamp */
	if (clone)
			sja1105_ptp_txtstamp_skb(priv->ds, port, clone);
		sja1105_ptp_txtstamp_skb(ds, port, clone);

	mutex_unlock(&priv->mgmt_lock);

	kfree(xmit_work);
}

static int sja1105_connect_tag_protocol(struct dsa_switch *ds,
					enum dsa_tag_protocol proto)
{
	struct sja1105_tagger_data *tagger_data;

	switch (proto) {
	case DSA_TAG_PROTO_SJA1105:
		tagger_data = sja1105_tagger_data(ds);
		tagger_data->xmit_work_fn = sja1105_port_deferred_xmit;
		tagger_data->meta_tstamp_handler = sja1110_process_meta_tstamp;
		return 0;
	default:
		return -EPROTONOSUPPORT;
	}
}

@@ -3019,58 +3021,6 @@ static int sja1105_port_bridge_flags(struct dsa_switch *ds, int port,
	return 0;
}

static void sja1105_teardown_ports(struct sja1105_private *priv)
{
	struct dsa_switch *ds = priv->ds;
	int port;

	for (port = 0; port < ds->num_ports; port++) {
		struct sja1105_port *sp = &priv->ports[port];

		if (sp->xmit_worker)
			kthread_destroy_worker(sp->xmit_worker);
	}
}

static int sja1105_setup_ports(struct sja1105_private *priv)
{
	struct sja1105_tagger_data *tagger_data = &priv->tagger_data;
	struct dsa_switch *ds = priv->ds;
	int port, rc;

	/* Connections between dsa_port and sja1105_port */
	for (port = 0; port < ds->num_ports; port++) {
		struct sja1105_port *sp = &priv->ports[port];
		struct dsa_port *dp = dsa_to_port(ds, port);
		struct kthread_worker *worker;
		struct net_device *slave;

		if (!dsa_port_is_user(dp))
			continue;

		dp->priv = sp;
		sp->data = tagger_data;
		slave = dp->slave;
		kthread_init_work(&sp->xmit_work, sja1105_port_deferred_xmit);
		worker = kthread_create_worker(0, "%s_xmit", slave->name);
		if (IS_ERR(worker)) {
			rc = PTR_ERR(worker);
			dev_err(ds->dev,
				"failed to create deferred xmit thread: %d\n",
				rc);
			goto out_destroy_workers;
		}
		sp->xmit_worker = worker;
		skb_queue_head_init(&sp->xmit_queue);
	}

	return 0;

out_destroy_workers:
	sja1105_teardown_ports(priv);
	return rc;
}

/* The programming model for the SJA1105 switch is "all-at-once" via static
 * configuration tables. Some of these can be dynamically modified at runtime,
 * but not the xMII mode parameters table.
@@ -3116,10 +3066,6 @@ static int sja1105_setup(struct dsa_switch *ds)
		}
	}

	rc = sja1105_setup_ports(priv);
	if (rc)
		goto out_static_config_free;

	sja1105_tas_setup(ds);
	sja1105_flower_setup(ds);

@@ -3176,7 +3122,6 @@ static int sja1105_setup(struct dsa_switch *ds)
out_flower_teardown:
	sja1105_flower_teardown(ds);
	sja1105_tas_teardown(ds);
	sja1105_teardown_ports(priv);
out_static_config_free:
	sja1105_static_config_free(&priv->static_config);

@@ -3196,12 +3141,12 @@ static void sja1105_teardown(struct dsa_switch *ds)
	sja1105_ptp_clock_unregister(ds);
	sja1105_flower_teardown(ds);
	sja1105_tas_teardown(ds);
	sja1105_teardown_ports(priv);
	sja1105_static_config_free(&priv->static_config);
}

static const struct dsa_switch_ops sja1105_switch_ops = {
	.get_tag_protocol	= sja1105_get_tag_protocol,
	.connect_tag_protocol	= sja1105_connect_tag_protocol,
	.setup			= sja1105_setup,
	.teardown		= sja1105_teardown,
	.set_ageing_time	= sja1105_set_ageing_time,
@@ -3215,7 +3160,6 @@ static const struct dsa_switch_ops sja1105_switch_ops = {
	.get_ethtool_stats	= sja1105_get_ethtool_stats,
	.get_sset_count		= sja1105_get_sset_count,
	.get_ts_info		= sja1105_get_ts_info,
	.port_disable		= sja1105_port_disable,
	.port_fdb_dump		= sja1105_fdb_dump,
	.port_fdb_add		= sja1105_fdb_add,
	.port_fdb_del		= sja1105_fdb_del,
@@ -3383,6 +3327,7 @@ static int sja1105_probe(struct spi_device *spi)
	mutex_init(&priv->ptp_data.lock);
	mutex_init(&priv->dynamic_config_lock);
	mutex_init(&priv->mgmt_lock);
	spin_lock_init(&priv->ts_id_lock);

	rc = sja1105_parse_dt(priv);
	if (rc < 0) {
+56 −30
Original line number Diff line number Diff line
@@ -58,13 +58,12 @@ enum sja1105_ptp_clk_mode {
#define ptp_data_to_sja1105(d) \
		container_of((d), struct sja1105_private, ptp_data)

/* Must be called only with priv->tagger_data.state bit
 * SJA1105_HWTS_RX_EN cleared
/* Must be called only while the RX timestamping state of the tagger
 * is turned off
 */
static int sja1105_change_rxtstamping(struct sja1105_private *priv,
				      bool on)
{
	struct sja1105_tagger_data *tagger_data = &priv->tagger_data;
	struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
	struct sja1105_general_params_entry *general_params;
	struct sja1105_table *table;
@@ -74,13 +73,8 @@ static int sja1105_change_rxtstamping(struct sja1105_private *priv,
	general_params->send_meta1 = on;
	general_params->send_meta0 = on;

	/* Initialize the meta state machine to a known state */
	if (priv->tagger_data.stampable_skb) {
		kfree_skb(priv->tagger_data.stampable_skb);
		priv->tagger_data.stampable_skb = NULL;
	}
	ptp_cancel_worker_sync(ptp_data->clock);
	skb_queue_purge(&tagger_data->skb_txtstamp_queue);
	skb_queue_purge(&ptp_data->skb_txtstamp_queue);
	skb_queue_purge(&ptp_data->skb_rxtstamp_queue);

	return sja1105_static_config_reload(priv, SJA1105_RX_HWTSTAMPING);
@@ -88,6 +82,7 @@ static int sja1105_change_rxtstamping(struct sja1105_private *priv,

int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
{
	struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds);
	struct sja1105_private *priv = ds->priv;
	struct hwtstamp_config config;
	bool rx_on;
@@ -98,10 +93,10 @@ int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)

	switch (config.tx_type) {
	case HWTSTAMP_TX_OFF:
		priv->ports[port].hwts_tx_en = false;
		priv->hwts_tx_en &= ~BIT(port);
		break;
	case HWTSTAMP_TX_ON:
		priv->ports[port].hwts_tx_en = true;
		priv->hwts_tx_en |= BIT(port);
		break;
	default:
		return -ERANGE;
@@ -116,8 +111,8 @@ int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
		break;
	}

	if (rx_on != test_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state)) {
		clear_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state);
	if (rx_on != tagger_data->rxtstamp_get_state(ds)) {
		tagger_data->rxtstamp_set_state(ds, false);

		rc = sja1105_change_rxtstamping(priv, rx_on);
		if (rc < 0) {
@@ -126,7 +121,7 @@ int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
			return rc;
		}
		if (rx_on)
			set_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state);
			tagger_data->rxtstamp_set_state(ds, true);
	}

	if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
@@ -136,15 +131,16 @@ int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)

int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr)
{
	struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds);
	struct sja1105_private *priv = ds->priv;
	struct hwtstamp_config config;

	config.flags = 0;
	if (priv->ports[port].hwts_tx_en)
	if (priv->hwts_tx_en & BIT(port))
		config.tx_type = HWTSTAMP_TX_ON;
	else
		config.tx_type = HWTSTAMP_TX_OFF;
	if (test_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state))
	if (tagger_data->rxtstamp_get_state(ds))
		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
	else
		config.rx_filter = HWTSTAMP_FILTER_NONE;
@@ -417,10 +413,11 @@ static long sja1105_rxtstamp_work(struct ptp_clock_info *ptp)

bool sja1105_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
{
	struct sja1105_tagger_data *tagger_data = sja1105_tagger_data(ds);
	struct sja1105_private *priv = ds->priv;
	struct sja1105_ptp_data *ptp_data = &priv->ptp_data;

	if (!test_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state))
	if (!tagger_data->rxtstamp_get_state(ds))
		return false;

	/* We need to read the full PTP clock to reconstruct the Rx
@@ -453,6 +450,39 @@ bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
	return priv->info->rxtstamp(ds, port, skb);
}

void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id,
				 enum sja1110_meta_tstamp dir, u64 tstamp)
{
	struct sja1105_private *priv = ds->priv;
	struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
	struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
	struct skb_shared_hwtstamps shwt = {0};

	/* We don't care about RX timestamps on the CPU port */
	if (dir == SJA1110_META_TSTAMP_RX)
		return;

	spin_lock(&ptp_data->skb_txtstamp_queue.lock);

	skb_queue_walk_safe(&ptp_data->skb_txtstamp_queue, skb, skb_tmp) {
		if (SJA1105_SKB_CB(skb)->ts_id != ts_id)
			continue;

		__skb_unlink(skb, &ptp_data->skb_txtstamp_queue);
		skb_match = skb;

		break;
	}

	spin_unlock(&ptp_data->skb_txtstamp_queue.lock);

	if (WARN_ON(!skb_match))
		return;

	shwt.hwtstamp = ns_to_ktime(sja1105_ticks_to_ns(tstamp));
	skb_complete_tx_timestamp(skb_match, &shwt);
}

/* In addition to cloning the skb which is done by the common
 * sja1105_port_txtstamp, we need to generate a timestamp ID and save the
 * packet to the TX timestamping queue.
@@ -461,22 +491,22 @@ void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
{
	struct sk_buff *clone = SJA1105_SKB_CB(skb)->clone;
	struct sja1105_private *priv = ds->priv;
	struct sja1105_port *sp = &priv->ports[port];
	struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
	u8 ts_id;

	skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;

	spin_lock(&sp->data->meta_lock);
	spin_lock(&priv->ts_id_lock);

	ts_id = sp->data->ts_id;
	ts_id = priv->ts_id;
	/* Deal automatically with 8-bit wraparound */
	sp->data->ts_id++;
	priv->ts_id++;

	SJA1105_SKB_CB(clone)->ts_id = ts_id;

	spin_unlock(&sp->data->meta_lock);
	spin_unlock(&priv->ts_id_lock);

	skb_queue_tail(&sp->data->skb_txtstamp_queue, clone);
	skb_queue_tail(&ptp_data->skb_txtstamp_queue, clone);
}

/* Called from dsa_skb_tx_timestamp. This callback is just to clone
@@ -486,10 +516,9 @@ void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
void sja1105_port_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb)
{
	struct sja1105_private *priv = ds->priv;
	struct sja1105_port *sp = &priv->ports[port];
	struct sk_buff *clone;

	if (!sp->hwts_tx_en)
	if (!(priv->hwts_tx_en & BIT(port)))
		return;

	clone = skb_clone_sk(skb);
@@ -896,7 +925,6 @@ static struct ptp_pin_desc sja1105_ptp_pin = {
int sja1105_ptp_clock_register(struct dsa_switch *ds)
{
	struct sja1105_private *priv = ds->priv;
	struct sja1105_tagger_data *tagger_data = &priv->tagger_data;
	struct sja1105_ptp_data *ptp_data = &priv->ptp_data;

	ptp_data->caps = (struct ptp_clock_info) {
@@ -919,8 +947,7 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds)
	/* Only used on SJA1105 */
	skb_queue_head_init(&ptp_data->skb_rxtstamp_queue);
	/* Only used on SJA1110 */
	skb_queue_head_init(&tagger_data->skb_txtstamp_queue);
	spin_lock_init(&tagger_data->meta_lock);
	skb_queue_head_init(&ptp_data->skb_txtstamp_queue);

	ptp_data->clock = ptp_clock_register(&ptp_data->caps, ds->dev);
	if (IS_ERR_OR_NULL(ptp_data->clock))
@@ -937,7 +964,6 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds)
void sja1105_ptp_clock_unregister(struct dsa_switch *ds)
{
	struct sja1105_private *priv = ds->priv;
	struct sja1105_tagger_data *tagger_data = &priv->tagger_data;
	struct sja1105_ptp_data *ptp_data = &priv->ptp_data;

	if (IS_ERR_OR_NULL(ptp_data->clock))
@@ -945,7 +971,7 @@ void sja1105_ptp_clock_unregister(struct dsa_switch *ds)

	del_timer_sync(&ptp_data->extts_timer);
	ptp_cancel_worker_sync(ptp_data->clock);
	skb_queue_purge(&tagger_data->skb_txtstamp_queue);
	skb_queue_purge(&ptp_data->skb_txtstamp_queue);
	skb_queue_purge(&ptp_data->skb_rxtstamp_queue);
	ptp_clock_unregister(ptp_data->clock);
	ptp_data->clock = NULL;
+24 −0
Original line number Diff line number Diff line
@@ -8,6 +8,21 @@

#if IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP)

/* Timestamps are in units of 8 ns clock ticks (equivalent to
 * a fixed 125 MHz clock).
 */
#define SJA1105_TICK_NS			8

static inline s64 ns_to_sja1105_ticks(s64 ns)
{
	return ns / SJA1105_TICK_NS;
}

static inline s64 sja1105_ticks_to_ns(s64 ticks)
{
	return ticks * SJA1105_TICK_NS;
}

/* Calculate the first base_time in the future that satisfies this
 * relationship:
 *
@@ -62,6 +77,10 @@ struct sja1105_ptp_data {
	struct timer_list extts_timer;
	/* Used only on SJA1105 to reconstruct partial timestamps */
	struct sk_buff_head skb_rxtstamp_queue;
	/* Used on SJA1110 where meta frames are generated only for
	 * 2-step TX timestamps
	 */
	struct sk_buff_head skb_txtstamp_queue;
	struct ptp_clock_info caps;
	struct ptp_clock *clock;
	struct sja1105_ptp_cmd cmd;
@@ -112,6 +131,9 @@ bool sja1105_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb);
bool sja1110_rxtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb);
void sja1110_txtstamp(struct dsa_switch *ds, int port, struct sk_buff *skb);

void sja1110_process_meta_tstamp(struct dsa_switch *ds, int port, u8 ts_id,
				 enum sja1110_meta_tstamp dir, u64 tstamp);

#else

struct sja1105_ptp_cmd;
@@ -178,6 +200,8 @@ static inline int sja1105_ptp_commit(struct dsa_switch *ds,
#define sja1110_rxtstamp NULL
#define sja1110_txtstamp NULL

#define sja1110_process_meta_tstamp NULL

#endif /* IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) */

#endif /* _SJA1105_PTP_H */
Loading