Skip to content

Commit

Permalink
mlxsw: spectrum: PTP: Add PTP initialization / finalization
Browse files Browse the repository at this point in the history
Add two ptp_ops: init and fini, to initialize and finalize the PTP
subsystem. Call as appropriate from mlxsw_sp_init() and _fini().

Lay the groundwork for Spectrum-1 support. On Spectrum-1, the received
timestamped packets and their corresponding timestamps arrive
independently, and need to be matched up. Introduce the related data types
and add to struct mlxsw_sp_ptp_state the hash table that will keep the
unmatched entries.

Signed-off-by: Petr Machata <petrm@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Petr Machata authored and David S. Miller committed Jul 2, 2019
1 parent 0714256 commit 810256c
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 3 deletions.
24 changes: 23 additions & 1 deletion drivers/net/ethernet/mellanox/mlxsw/spectrum.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ struct mlxsw_sp_ptp_ops {
(*clock_init)(struct mlxsw_sp *mlxsw_sp, struct device *dev);
void (*clock_fini)(struct mlxsw_sp_ptp_clock *clock);

struct mlxsw_sp_ptp_state *(*init)(struct mlxsw_sp *mlxsw_sp);
void (*fini)(struct mlxsw_sp_ptp_state *ptp_state);

/* Notify a driver that a packet that might be PTP was received. Driver
* is responsible for freeing the passed-in SKB.
*/
Expand Down Expand Up @@ -4429,13 +4432,17 @@ static int mlxsw_sp_basic_trap_groups_set(struct mlxsw_core *mlxsw_core)
static const struct mlxsw_sp_ptp_ops mlxsw_sp1_ptp_ops = {
.clock_init = mlxsw_sp1_ptp_clock_init,
.clock_fini = mlxsw_sp1_ptp_clock_fini,
.init = mlxsw_sp1_ptp_init,
.fini = mlxsw_sp1_ptp_fini,
.receive = mlxsw_sp1_ptp_receive,
.transmitted = mlxsw_sp1_ptp_transmitted,
};

static const struct mlxsw_sp_ptp_ops mlxsw_sp2_ptp_ops = {
.clock_init = mlxsw_sp2_ptp_clock_init,
.clock_fini = mlxsw_sp2_ptp_clock_fini,
.init = mlxsw_sp2_ptp_init,
.fini = mlxsw_sp2_ptp_fini,
.receive = mlxsw_sp2_ptp_receive,
.transmitted = mlxsw_sp2_ptp_transmitted,
};
Expand Down Expand Up @@ -4549,6 +4556,16 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
}
}

if (mlxsw_sp->clock) {
/* NULL is a valid return value from ptp_ops->init */
mlxsw_sp->ptp_state = mlxsw_sp->ptp_ops->init(mlxsw_sp);
if (IS_ERR(mlxsw_sp->ptp_state)) {
err = PTR_ERR(mlxsw_sp->ptp_state);
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize PTP\n");
goto err_ptp_init;
}
}

/* Initialize netdevice notifier after router and SPAN is initialized,
* so that the event handler can use router structures and call SPAN
* respin.
Expand Down Expand Up @@ -4579,6 +4596,9 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
err_dpipe_init:
unregister_netdevice_notifier(&mlxsw_sp->netdevice_nb);
err_netdev_notifier:
if (mlxsw_sp->clock)
mlxsw_sp->ptp_ops->fini(mlxsw_sp->ptp_state);
err_ptp_init:
if (mlxsw_sp->clock)
mlxsw_sp->ptp_ops->clock_fini(mlxsw_sp->clock);
err_ptp_clock_init:
Expand Down Expand Up @@ -4659,8 +4679,10 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
mlxsw_sp_ports_remove(mlxsw_sp);
mlxsw_sp_dpipe_fini(mlxsw_sp);
unregister_netdevice_notifier(&mlxsw_sp->netdevice_nb);
if (mlxsw_sp->clock)
if (mlxsw_sp->clock) {
mlxsw_sp->ptp_ops->fini(mlxsw_sp->ptp_state);
mlxsw_sp->ptp_ops->clock_fini(mlxsw_sp->clock);
}
mlxsw_sp_router_fini(mlxsw_sp);
mlxsw_sp_acl_fini(mlxsw_sp);
mlxsw_sp_nve_fini(mlxsw_sp);
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ struct mlxsw_sp_acl_tcam_ops;
struct mlxsw_sp_nve_ops;
struct mlxsw_sp_sb_vals;
struct mlxsw_sp_port_type_speed_ops;
struct mlxsw_sp_ptp_state;
struct mlxsw_sp_ptp_ops;

struct mlxsw_sp {
Expand All @@ -157,6 +158,7 @@ struct mlxsw_sp {
struct mlxsw_sp_nve *nve;
struct notifier_block netdevice_nb;
struct mlxsw_sp_ptp_clock *clock;
struct mlxsw_sp_ptp_state *ptp_state;

struct mlxsw_sp_counter_pool *counter_pool;
struct {
Expand Down
70 changes: 70 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,41 @@
#include <linux/spinlock.h>
#include <linux/device.h>

#include "spectrum.h"
#include "spectrum_ptp.h"
#include "core.h"

#define MLXSW_SP1_PTP_CLOCK_CYCLES_SHIFT 29
#define MLXSW_SP1_PTP_CLOCK_FREQ_KHZ 156257 /* 6.4nSec */
#define MLXSW_SP1_PTP_CLOCK_MASK 64

struct mlxsw_sp_ptp_state {
struct rhashtable unmatched_ht;
spinlock_t unmatched_lock; /* protects the HT */
};

struct mlxsw_sp1_ptp_key {
u8 local_port;
u8 message_type;
u16 sequence_id;
u8 domain_number;
bool ingress;
};

struct mlxsw_sp1_ptp_unmatched {
struct mlxsw_sp1_ptp_key key;
struct rhash_head ht_node;
struct rcu_head rcu;
struct sk_buff *skb;
u64 timestamp;
};

static const struct rhashtable_params mlxsw_sp1_ptp_unmatched_ht_params = {
.key_len = sizeof_field(struct mlxsw_sp1_ptp_unmatched, key),
.key_offset = offsetof(struct mlxsw_sp1_ptp_unmatched, key),
.head_offset = offsetof(struct mlxsw_sp1_ptp_unmatched, ht_node),
};

struct mlxsw_sp_ptp_clock {
struct mlxsw_core *core;
spinlock_t lock; /* protect this structure */
Expand Down Expand Up @@ -265,6 +293,18 @@ void mlxsw_sp1_ptp_clock_fini(struct mlxsw_sp_ptp_clock *clock)
kfree(clock);
}

static void mlxsw_sp1_ptp_unmatched_free_fn(void *ptr, void *arg)
{
struct mlxsw_sp1_ptp_unmatched *unmatched = ptr;

/* This is invoked at a point where the ports are gone already. Nothing
* to do with whatever is left in the HT but to free it.
*/
if (unmatched->skb)
dev_kfree_skb_any(unmatched->skb);
kfree_rcu(unmatched, rcu);
}

void mlxsw_sp1_ptp_receive(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
u8 local_port)
{
Expand All @@ -276,3 +316,33 @@ void mlxsw_sp1_ptp_transmitted(struct mlxsw_sp *mlxsw_sp,
{
dev_kfree_skb_any(skb);
}

struct mlxsw_sp_ptp_state *mlxsw_sp1_ptp_init(struct mlxsw_sp *mlxsw_sp)
{
struct mlxsw_sp_ptp_state *ptp_state;
int err;

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

spin_lock_init(&ptp_state->unmatched_lock);

err = rhashtable_init(&ptp_state->unmatched_ht,
&mlxsw_sp1_ptp_unmatched_ht_params);
if (err)
goto err_hashtable_init;

return ptp_state;

err_hashtable_init:
kfree(ptp_state);
return ERR_PTR(err);
}

void mlxsw_sp1_ptp_fini(struct mlxsw_sp_ptp_state *ptp_state)
{
rhashtable_free_and_destroy(&ptp_state->unmatched_ht,
&mlxsw_sp1_ptp_unmatched_free_fn, NULL);
kfree(ptp_state);
}
29 changes: 27 additions & 2 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
#define _MLXSW_SPECTRUM_PTP_H

#include <linux/device.h>
#include <linux/rhashtable.h>

#include "spectrum.h"

struct mlxsw_sp;
struct mlxsw_sp_port;
struct mlxsw_sp_ptp_clock;

#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
Expand All @@ -17,6 +18,10 @@ mlxsw_sp1_ptp_clock_init(struct mlxsw_sp *mlxsw_sp, struct device *dev);

void mlxsw_sp1_ptp_clock_fini(struct mlxsw_sp_ptp_clock *clock);

struct mlxsw_sp_ptp_state *mlxsw_sp1_ptp_init(struct mlxsw_sp *mlxsw_sp);

void mlxsw_sp1_ptp_fini(struct mlxsw_sp_ptp_state *ptp_state);

void mlxsw_sp1_ptp_receive(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
u8 local_port);

Expand All @@ -35,6 +40,16 @@ static inline void mlxsw_sp1_ptp_clock_fini(struct mlxsw_sp_ptp_clock *clock)
{
}

static inline struct mlxsw_sp_ptp_state *
mlxsw_sp1_ptp_init(struct mlxsw_sp *mlxsw_sp)
{
return NULL;
}

static inline void mlxsw_sp1_ptp_fini(struct mlxsw_sp_ptp_state *ptp_state)
{
}

static inline void mlxsw_sp1_ptp_receive(struct mlxsw_sp *mlxsw_sp,
struct sk_buff *skb, u8 local_port)
{
Expand All @@ -59,6 +74,16 @@ static inline void mlxsw_sp2_ptp_clock_fini(struct mlxsw_sp_ptp_clock *clock)
{
}

static inline struct mlxsw_sp_ptp_state *
mlxsw_sp2_ptp_init(struct mlxsw_sp *mlxsw_sp)
{
return NULL;
}

static inline void mlxsw_sp2_ptp_fini(struct mlxsw_sp_ptp_state *ptp_state)
{
}

static inline void mlxsw_sp2_ptp_receive(struct mlxsw_sp *mlxsw_sp,
struct sk_buff *skb, u8 local_port)
{
Expand Down

0 comments on commit 810256c

Please sign in to comment.