Skip to content

Commit

Permalink
Merge branch 'Improvements-to-SJA1105-DSA-RX-timestamping'
Browse files Browse the repository at this point in the history
Vladimir Oltean says:

====================
Improvements to SJA1105 DSA RX timestamping

This series makes the sja1105 DSA driver use a dedicated kernel thread
for RX timestamping, a process which is time-sensitive and otherwise a
bit fragile. This allows users to customize their system (probabil an
embedded PTP switch) fully and allocate the CPU bandwidth for the driver
to expedite the RX timestamps as quickly as possible.

While doing this conversion, add a function to the PTP core for
cancelling this kernel thread (function which I found rather strange to
be missing).
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Dec 31, 2019
2 parents db99d51 + 19d1f0e commit 9010ef5
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 20 deletions.
36 changes: 18 additions & 18 deletions drivers/net/dsa/sja1105/sja1105_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ static int sja1105_init_avb_params(struct sja1105_private *priv,
static int sja1105_change_rxtstamping(struct sja1105_private *priv,
bool on)
{
struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
struct sja1105_general_params_entry *general_params;
struct sja1105_table *table;
int rc;
Expand All @@ -101,6 +102,8 @@ static int sja1105_change_rxtstamping(struct sja1105_private *priv,
kfree_skb(priv->tagger_data.stampable_skb);
priv->tagger_data.stampable_skb = NULL;
}
ptp_cancel_worker_sync(ptp_data->clock);
skb_queue_purge(&ptp_data->skb_rxtstamp_queue);

return sja1105_static_config_reload(priv, SJA1105_RX_HWTSTAMPING);
}
Expand Down Expand Up @@ -367,22 +370,16 @@ static int sja1105_ptpclkval_write(struct sja1105_private *priv, u64 ticks,
ptp_sts);
}

#define rxtstamp_to_tagger(d) \
container_of((d), struct sja1105_tagger_data, rxtstamp_work)
#define tagger_to_sja1105(d) \
container_of((d), struct sja1105_private, tagger_data)

static void sja1105_rxtstamp_work(struct work_struct *work)
static long sja1105_rxtstamp_work(struct ptp_clock_info *ptp)
{
struct sja1105_tagger_data *tagger_data = rxtstamp_to_tagger(work);
struct sja1105_private *priv = tagger_to_sja1105(tagger_data);
struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
struct sja1105_ptp_data *ptp_data = ptp_caps_to_data(ptp);
struct sja1105_private *priv = ptp_data_to_sja1105(ptp_data);
struct dsa_switch *ds = priv->ds;
struct sk_buff *skb;

mutex_lock(&ptp_data->lock);

while ((skb = skb_dequeue(&tagger_data->skb_rxtstamp_queue)) != NULL) {
while ((skb = skb_dequeue(&ptp_data->skb_rxtstamp_queue)) != NULL) {
struct skb_shared_hwtstamps *shwt = skb_hwtstamps(skb);
u64 ticks, ts;
int rc;
Expand All @@ -404,23 +401,26 @@ static void sja1105_rxtstamp_work(struct work_struct *work)
}

mutex_unlock(&ptp_data->lock);

/* Don't restart */
return -1;
}

/* Called from dsa_skb_defer_rx_timestamp */
bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
struct sk_buff *skb, unsigned int type)
{
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 (!test_bit(SJA1105_HWTS_RX_EN, &tagger_data->state))
if (!test_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state))
return false;

/* We need to read the full PTP clock to reconstruct the Rx
* timestamp. For that we need a sleepable context.
*/
skb_queue_tail(&tagger_data->skb_rxtstamp_queue, skb);
schedule_work(&tagger_data->rxtstamp_work);
skb_queue_tail(&ptp_data->skb_rxtstamp_queue, skb);
ptp_schedule_worker(ptp_data->clock, 0);
return true;
}

Expand Down Expand Up @@ -628,11 +628,11 @@ int sja1105_ptp_clock_register(struct dsa_switch *ds)
.adjtime = sja1105_ptp_adjtime,
.gettimex64 = sja1105_ptp_gettimex,
.settime64 = sja1105_ptp_settime,
.do_aux_work = sja1105_rxtstamp_work,
.max_adj = SJA1105_MAX_ADJ_PPB,
};

skb_queue_head_init(&tagger_data->skb_rxtstamp_queue);
INIT_WORK(&tagger_data->rxtstamp_work, sja1105_rxtstamp_work);
skb_queue_head_init(&ptp_data->skb_rxtstamp_queue);
spin_lock_init(&tagger_data->meta_lock);

ptp_data->clock = ptp_clock_register(&ptp_data->caps, ds->dev);
Expand All @@ -653,8 +653,8 @@ void sja1105_ptp_clock_unregister(struct dsa_switch *ds)
if (IS_ERR_OR_NULL(ptp_data->clock))
return;

cancel_work_sync(&priv->tagger_data.rxtstamp_work);
skb_queue_purge(&priv->tagger_data.skb_rxtstamp_queue);
ptp_cancel_worker_sync(ptp_data->clock);
skb_queue_purge(&ptp_data->skb_rxtstamp_queue);
ptp_clock_unregister(ptp_data->clock);
ptp_data->clock = NULL;
}
Expand Down
1 change: 1 addition & 0 deletions drivers/net/dsa/sja1105/sja1105_ptp.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct sja1105_ptp_cmd {
};

struct sja1105_ptp_data {
struct sk_buff_head skb_rxtstamp_queue;
struct ptp_clock_info caps;
struct ptp_clock *clock;
struct sja1105_ptp_cmd cmd;
Expand Down
6 changes: 6 additions & 0 deletions drivers/ptp/ptp_clock.c
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,12 @@ int ptp_schedule_worker(struct ptp_clock *ptp, unsigned long delay)
}
EXPORT_SYMBOL(ptp_schedule_worker);

void ptp_cancel_worker_sync(struct ptp_clock *ptp)
{
kthread_cancel_delayed_work_sync(&ptp->aux_work);
}
EXPORT_SYMBOL(ptp_cancel_worker_sync);

/* module operations */

static void __exit ptp_exit(void)
Expand Down
2 changes: 0 additions & 2 deletions include/linux/dsa/sja1105.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@
* the structure defined in struct sja1105_private.
*/
struct sja1105_tagger_data {
struct sk_buff_head skb_rxtstamp_queue;
struct work_struct rxtstamp_work;
struct sk_buff *stampable_skb;
/* Protects concurrent access to the meta state machine
* from taggers running on multiple ports on SMP systems
Expand Down
9 changes: 9 additions & 0 deletions include/linux/ptp_clock_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,13 @@ int ptp_find_pin(struct ptp_clock *ptp,

int ptp_schedule_worker(struct ptp_clock *ptp, unsigned long delay);

/**
* ptp_cancel_worker_sync() - cancel ptp auxiliary clock
*
* @ptp: The clock obtained from ptp_clock_register().
*/
void ptp_cancel_worker_sync(struct ptp_clock *ptp);

#else
static inline struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
struct device *parent)
Expand All @@ -260,6 +267,8 @@ static inline int ptp_find_pin(struct ptp_clock *ptp,
static inline int ptp_schedule_worker(struct ptp_clock *ptp,
unsigned long delay)
{ return -EOPNOTSUPP; }
static inline void ptp_cancel_worker_sync(struct ptp_clock *ptp)
{ }

#endif

Expand Down

0 comments on commit 9010ef5

Please sign in to comment.