diff options
author | Petr Machata | 2019-06-30 08:04:54 +0200 |
---|---|---|
committer | David S. Miller | 2019-07-02 03:58:34 +0200 |
commit | 810256cec105b3b1ff977f0cd47dac1a1a9a184b (patch) | |
tree | ebe27a1e83c9c3d995257c1f819115173a708290 /drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c | |
parent | mlxsw: pci: PTP: Hook into packet transmit path (diff) | |
download | kernel-qcow2-linux-810256cec105b3b1ff977f0cd47dac1a1a9a184b.tar.gz kernel-qcow2-linux-810256cec105b3b1ff977f0cd47dac1a1a9a184b.tar.xz kernel-qcow2-linux-810256cec105b3b1ff977f0cd47dac1a1a9a184b.zip |
mlxsw: spectrum: PTP: Add PTP initialization / finalization
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>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c index 3af4573a4261..6725a4d53f87 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c @@ -7,6 +7,7 @@ #include <linux/spinlock.h> #include <linux/device.h> +#include "spectrum.h" #include "spectrum_ptp.h" #include "core.h" @@ -14,6 +15,33 @@ #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 */ @@ -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) { @@ -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); +} |