Commit 3b1c3147 authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-ptp-spectrum-2'

Ido Schimmel says:

====================
mlxsw: Add PTP support for Spectrum-2 and newer ASICs

This patchset adds PTP support for Spectrum-{2,3,4} switch ASICs. They
all act largely the same with respect to PTP except for a workaround
implemented for Spectrum-{2,3} in patch #6.

Spectrum-2 and newer ASICs essentially implement a transparent clock
between all the switch ports, including the CPU port. The hardware will
generate the UTC time stamp for transmitted / received packets at the
CPU port, but will compensate for forwarding delays in the ASIC by
adjusting the correction field in the PTP header (for PTP events) at the
ingress and egress ports.

Specifically, the hardware will subtract the current time stamp from the
correction field at the ingress port and will add the current time stamp
to the correction field at the egress port. For the purpose of an
ordinary or boundary clock (this patchset), the correction field will
always be adjusted between the CPU port and one of the front panel
ports, but never between two front panel ports.

Patchset overview:

Patch #1 extracts a helper to configure traps for PTP packets (event and
general messages). The helper is shared between all Spectrum
generations.

Patch #2 transitions Spectrum-2 and newer ASICs to use a different
format of Tx completions that includes the UTC time stamp of transmitted
packets.

Patch #3 adds basic initialization required for Spectrum-2 PTP support.
It mainly invokes the helper from patch #1.

Patch #4 adds helpers to read the UTC time (seconds and nanoseconds)
from the device over memory-mapped I/O instead of going through firmware
which is slower and therefore inaccurate. The helpers will be used to
implement various PHC operations (e.g., gettimex64) and to construct the
full UTC time stamp from the truncated one reported over Tx / Rx
completions.

Patch #5 implements the various PHC operations.

Patch #6 implements the previously described workaround for
Spectrum-{2,3}.

Patch #7 adds the ability to report a hardware time stamp for a received
/ transmitted packet based off the associated Rx / Tx completion that
includes a truncated UTC time stamp.

Patches #8 and #9 implement support for the SIOCGHWTSTAMP /
SIOCSHWTSTAMP ioctls and the get_ts_info ethtool callback, respectively.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ba323f6b eba28aaf
...@@ -3335,6 +3335,24 @@ u32 mlxsw_core_read_frc_l(struct mlxsw_core *mlxsw_core) ...@@ -3335,6 +3335,24 @@ u32 mlxsw_core_read_frc_l(struct mlxsw_core *mlxsw_core)
} }
EXPORT_SYMBOL(mlxsw_core_read_frc_l); EXPORT_SYMBOL(mlxsw_core_read_frc_l);
u32 mlxsw_core_read_utc_sec(struct mlxsw_core *mlxsw_core)
{
return mlxsw_core->bus->read_utc_sec(mlxsw_core->bus_priv);
}
EXPORT_SYMBOL(mlxsw_core_read_utc_sec);
u32 mlxsw_core_read_utc_nsec(struct mlxsw_core *mlxsw_core)
{
return mlxsw_core->bus->read_utc_nsec(mlxsw_core->bus_priv);
}
EXPORT_SYMBOL(mlxsw_core_read_utc_nsec);
bool mlxsw_core_sdq_supports_cqe_v2(struct mlxsw_core *mlxsw_core)
{
return mlxsw_core->driver->sdq_supports_cqe_v2;
}
EXPORT_SYMBOL(mlxsw_core_sdq_supports_cqe_v2);
void mlxsw_core_emad_string_tlv_enable(struct mlxsw_core *mlxsw_core) void mlxsw_core_emad_string_tlv_enable(struct mlxsw_core *mlxsw_core)
{ {
mlxsw_core->emad.enable_string_tlv = true; mlxsw_core->emad.enable_string_tlv = true;
......
...@@ -427,6 +427,7 @@ struct mlxsw_driver { ...@@ -427,6 +427,7 @@ struct mlxsw_driver {
u8 txhdr_len; u8 txhdr_len;
const struct mlxsw_config_profile *profile; const struct mlxsw_config_profile *profile;
bool sdq_supports_cqe_v2;
}; };
int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core, int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core,
...@@ -437,6 +438,11 @@ int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core, ...@@ -437,6 +438,11 @@ int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core,
u32 mlxsw_core_read_frc_h(struct mlxsw_core *mlxsw_core); u32 mlxsw_core_read_frc_h(struct mlxsw_core *mlxsw_core);
u32 mlxsw_core_read_frc_l(struct mlxsw_core *mlxsw_core); u32 mlxsw_core_read_frc_l(struct mlxsw_core *mlxsw_core);
u32 mlxsw_core_read_utc_sec(struct mlxsw_core *mlxsw_core);
u32 mlxsw_core_read_utc_nsec(struct mlxsw_core *mlxsw_core);
bool mlxsw_core_sdq_supports_cqe_v2(struct mlxsw_core *mlxsw_core);
void mlxsw_core_emad_string_tlv_enable(struct mlxsw_core *mlxsw_core); void mlxsw_core_emad_string_tlv_enable(struct mlxsw_core *mlxsw_core);
bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core, bool mlxsw_core_res_valid(struct mlxsw_core *mlxsw_core,
...@@ -476,6 +482,8 @@ struct mlxsw_bus { ...@@ -476,6 +482,8 @@ struct mlxsw_bus {
u8 *p_status); u8 *p_status);
u32 (*read_frc_h)(void *bus_priv); u32 (*read_frc_h)(void *bus_priv);
u32 (*read_frc_l)(void *bus_priv); u32 (*read_frc_l)(void *bus_priv);
u32 (*read_utc_sec)(void *bus_priv);
u32 (*read_utc_nsec)(void *bus_priv);
u8 features; u8 features;
}; };
...@@ -550,11 +558,17 @@ enum mlxsw_devlink_param_id { ...@@ -550,11 +558,17 @@ enum mlxsw_devlink_param_id {
MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL, MLXSW_DEVLINK_PARAM_ID_ACL_REGION_REHASH_INTERVAL,
}; };
struct mlxsw_cqe_ts {
u8 sec;
u32 nsec;
};
struct mlxsw_skb_cb { struct mlxsw_skb_cb {
union { union {
struct mlxsw_tx_info tx_info; struct mlxsw_tx_info tx_info;
struct mlxsw_rx_md_info rx_md_info; struct mlxsw_rx_md_info rx_md_info;
}; };
struct mlxsw_cqe_ts cqe_ts;
}; };
static inline struct mlxsw_skb_cb *mlxsw_skb_cb(struct sk_buff *skb) static inline struct mlxsw_skb_cb *mlxsw_skb_cb(struct sk_buff *skb)
......
...@@ -103,6 +103,8 @@ struct mlxsw_pci { ...@@ -103,6 +103,8 @@ struct mlxsw_pci {
struct pci_dev *pdev; struct pci_dev *pdev;
u8 __iomem *hw_addr; u8 __iomem *hw_addr;
u64 free_running_clock_offset; u64 free_running_clock_offset;
u64 utc_sec_offset;
u64 utc_nsec_offset;
struct mlxsw_pci_queue_type_group queues[MLXSW_PCI_QUEUE_TYPE_COUNT]; struct mlxsw_pci_queue_type_group queues[MLXSW_PCI_QUEUE_TYPE_COUNT];
u32 doorbell_offset; u32 doorbell_offset;
struct mlxsw_core *core; struct mlxsw_core *core;
...@@ -456,9 +458,9 @@ static void mlxsw_pci_cq_pre_init(struct mlxsw_pci *mlxsw_pci, ...@@ -456,9 +458,9 @@ static void mlxsw_pci_cq_pre_init(struct mlxsw_pci *mlxsw_pci,
{ {
q->u.cq.v = mlxsw_pci->max_cqe_ver; q->u.cq.v = mlxsw_pci->max_cqe_ver;
/* For SDQ it is pointless to use CQEv2, so use CQEv1 instead */
if (q->u.cq.v == MLXSW_PCI_CQE_V2 && if (q->u.cq.v == MLXSW_PCI_CQE_V2 &&
q->num < mlxsw_pci->num_sdq_cqs) q->num < mlxsw_pci->num_sdq_cqs &&
!mlxsw_core_sdq_supports_cqe_v2(mlxsw_pci->core))
q->u.cq.v = MLXSW_PCI_CQE_V1; q->u.cq.v = MLXSW_PCI_CQE_V1;
} }
...@@ -511,9 +513,26 @@ static unsigned int mlxsw_pci_read32_off(struct mlxsw_pci *mlxsw_pci, ...@@ -511,9 +513,26 @@ static unsigned int mlxsw_pci_read32_off(struct mlxsw_pci *mlxsw_pci,
return ioread32be(mlxsw_pci->hw_addr + off); return ioread32be(mlxsw_pci->hw_addr + off);
} }
static void mlxsw_pci_skb_cb_ts_set(struct mlxsw_pci *mlxsw_pci,
struct sk_buff *skb,
enum mlxsw_pci_cqe_v cqe_v, char *cqe)
{
if (cqe_v != MLXSW_PCI_CQE_V2)
return;
if (mlxsw_pci_cqe2_time_stamp_type_get(cqe) !=
MLXSW_PCI_CQE_TIME_STAMP_TYPE_UTC)
return;
mlxsw_skb_cb(skb)->cqe_ts.sec = mlxsw_pci_cqe2_time_stamp_sec_get(cqe);
mlxsw_skb_cb(skb)->cqe_ts.nsec =
mlxsw_pci_cqe2_time_stamp_nsec_get(cqe);
}
static void mlxsw_pci_cqe_sdq_handle(struct mlxsw_pci *mlxsw_pci, static void mlxsw_pci_cqe_sdq_handle(struct mlxsw_pci *mlxsw_pci,
struct mlxsw_pci_queue *q, struct mlxsw_pci_queue *q,
u16 consumer_counter_limit, u16 consumer_counter_limit,
enum mlxsw_pci_cqe_v cqe_v,
char *cqe) char *cqe)
{ {
struct pci_dev *pdev = mlxsw_pci->pdev; struct pci_dev *pdev = mlxsw_pci->pdev;
...@@ -533,6 +552,7 @@ static void mlxsw_pci_cqe_sdq_handle(struct mlxsw_pci *mlxsw_pci, ...@@ -533,6 +552,7 @@ static void mlxsw_pci_cqe_sdq_handle(struct mlxsw_pci *mlxsw_pci,
if (unlikely(!tx_info.is_emad && if (unlikely(!tx_info.is_emad &&
skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
mlxsw_pci_skb_cb_ts_set(mlxsw_pci, skb, cqe_v, cqe);
mlxsw_core_ptp_transmitted(mlxsw_pci->core, skb, mlxsw_core_ptp_transmitted(mlxsw_pci->core, skb,
tx_info.local_port); tx_info.local_port);
skb = NULL; skb = NULL;
...@@ -653,6 +673,8 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci, ...@@ -653,6 +673,8 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci,
mlxsw_pci_cqe_rdq_md_tx_port_init(skb, cqe); mlxsw_pci_cqe_rdq_md_tx_port_init(skb, cqe);
} }
mlxsw_pci_skb_cb_ts_set(mlxsw_pci, skb, cqe_v, cqe);
byte_count = mlxsw_pci_cqe_byte_count_get(cqe); byte_count = mlxsw_pci_cqe_byte_count_get(cqe);
if (mlxsw_pci_cqe_crc_get(cqe_v, cqe)) if (mlxsw_pci_cqe_crc_get(cqe_v, cqe))
byte_count -= ETH_FCS_LEN; byte_count -= ETH_FCS_LEN;
...@@ -704,7 +726,7 @@ static void mlxsw_pci_cq_tasklet(struct tasklet_struct *t) ...@@ -704,7 +726,7 @@ static void mlxsw_pci_cq_tasklet(struct tasklet_struct *t)
sdq = mlxsw_pci_sdq_get(mlxsw_pci, dqn); sdq = mlxsw_pci_sdq_get(mlxsw_pci, dqn);
mlxsw_pci_cqe_sdq_handle(mlxsw_pci, sdq, mlxsw_pci_cqe_sdq_handle(mlxsw_pci, sdq,
wqe_counter, ncqe); wqe_counter, q->u.cq.v, ncqe);
q->u.cq.comp_sdq_count++; q->u.cq.comp_sdq_count++;
} else { } else {
struct mlxsw_pci_queue *rdq; struct mlxsw_pci_queue *rdq;
...@@ -1537,6 +1559,24 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, ...@@ -1537,6 +1559,24 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
mlxsw_pci->free_running_clock_offset = mlxsw_pci->free_running_clock_offset =
mlxsw_cmd_mbox_query_fw_free_running_clock_offset_get(mbox); mlxsw_cmd_mbox_query_fw_free_running_clock_offset_get(mbox);
if (mlxsw_cmd_mbox_query_fw_utc_sec_bar_get(mbox) != 0) {
dev_err(&pdev->dev, "Unsupported UTC sec BAR queried from hw\n");
err = -EINVAL;
goto err_utc_sec_bar;
}
mlxsw_pci->utc_sec_offset =
mlxsw_cmd_mbox_query_fw_utc_sec_offset_get(mbox);
if (mlxsw_cmd_mbox_query_fw_utc_nsec_bar_get(mbox) != 0) {
dev_err(&pdev->dev, "Unsupported UTC nsec BAR queried from hw\n");
err = -EINVAL;
goto err_utc_nsec_bar;
}
mlxsw_pci->utc_nsec_offset =
mlxsw_cmd_mbox_query_fw_utc_nsec_offset_get(mbox);
num_pages = mlxsw_cmd_mbox_query_fw_fw_pages_get(mbox); num_pages = mlxsw_cmd_mbox_query_fw_fw_pages_get(mbox);
err = mlxsw_pci_fw_area_init(mlxsw_pci, mbox, num_pages); err = mlxsw_pci_fw_area_init(mlxsw_pci, mbox, num_pages);
if (err) if (err)
...@@ -1601,6 +1641,8 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, ...@@ -1601,6 +1641,8 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
err_boardinfo: err_boardinfo:
mlxsw_pci_fw_area_fini(mlxsw_pci); mlxsw_pci_fw_area_fini(mlxsw_pci);
err_fw_area_init: err_fw_area_init:
err_utc_nsec_bar:
err_utc_sec_bar:
err_fr_rn_clk_bar: err_fr_rn_clk_bar:
err_doorbell_page_bar: err_doorbell_page_bar:
err_iface_rev: err_iface_rev:
...@@ -1830,6 +1872,20 @@ static u32 mlxsw_pci_read_frc_l(void *bus_priv) ...@@ -1830,6 +1872,20 @@ static u32 mlxsw_pci_read_frc_l(void *bus_priv)
return mlxsw_pci_read32_off(mlxsw_pci, frc_offset_l); return mlxsw_pci_read32_off(mlxsw_pci, frc_offset_l);
} }
static u32 mlxsw_pci_read_utc_sec(void *bus_priv)
{
struct mlxsw_pci *mlxsw_pci = bus_priv;
return mlxsw_pci_read32_off(mlxsw_pci, mlxsw_pci->utc_sec_offset);
}
static u32 mlxsw_pci_read_utc_nsec(void *bus_priv)
{
struct mlxsw_pci *mlxsw_pci = bus_priv;
return mlxsw_pci_read32_off(mlxsw_pci, mlxsw_pci->utc_nsec_offset);
}
static const struct mlxsw_bus mlxsw_pci_bus = { static const struct mlxsw_bus mlxsw_pci_bus = {
.kind = "pci", .kind = "pci",
.init = mlxsw_pci_init, .init = mlxsw_pci_init,
...@@ -1839,6 +1895,8 @@ static const struct mlxsw_bus mlxsw_pci_bus = { ...@@ -1839,6 +1895,8 @@ static const struct mlxsw_bus mlxsw_pci_bus = {
.cmd_exec = mlxsw_pci_cmd_exec, .cmd_exec = mlxsw_pci_cmd_exec,
.read_frc_h = mlxsw_pci_read_frc_h, .read_frc_h = mlxsw_pci_read_frc_h,
.read_frc_l = mlxsw_pci_read_frc_l, .read_frc_l = mlxsw_pci_read_frc_l,
.read_utc_sec = mlxsw_pci_read_utc_sec,
.read_utc_nsec = mlxsw_pci_read_utc_nsec,
.features = MLXSW_BUS_F_TXRX | MLXSW_BUS_F_RESET, .features = MLXSW_BUS_F_TXRX | MLXSW_BUS_F_RESET,
}; };
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <net/pkt_cls.h> #include <net/pkt_cls.h>
#include <net/netevent.h> #include <net/netevent.h>
#include <net/addrconf.h> #include <net/addrconf.h>
#include <linux/ptp_classify.h>
#include "spectrum.h" #include "spectrum.h"
#include "pci.h" #include "pci.h"
...@@ -230,8 +231,8 @@ void mlxsw_sp_flow_counter_free(struct mlxsw_sp *mlxsw_sp, ...@@ -230,8 +231,8 @@ void mlxsw_sp_flow_counter_free(struct mlxsw_sp *mlxsw_sp,
counter_index); counter_index);
} }
static void mlxsw_sp_txhdr_construct(struct sk_buff *skb, void mlxsw_sp_txhdr_construct(struct sk_buff *skb,
const struct mlxsw_tx_info *tx_info) const struct mlxsw_tx_info *tx_info)
{ {
char *txhdr = skb_push(skb, MLXSW_TXHDR_LEN); char *txhdr = skb_push(skb, MLXSW_TXHDR_LEN);
...@@ -246,6 +247,82 @@ static void mlxsw_sp_txhdr_construct(struct sk_buff *skb, ...@@ -246,6 +247,82 @@ static void mlxsw_sp_txhdr_construct(struct sk_buff *skb,
mlxsw_tx_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL); mlxsw_tx_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_CONTROL);
} }
int
mlxsw_sp_txhdr_ptp_data_construct(struct mlxsw_core *mlxsw_core,
struct mlxsw_sp_port *mlxsw_sp_port,
struct sk_buff *skb,
const struct mlxsw_tx_info *tx_info)
{
char *txhdr;
u16 max_fid;
int err;
if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) {
err = -ENOMEM;
goto err_skb_cow_head;
}
if (!MLXSW_CORE_RES_VALID(mlxsw_core, FID)) {
err = -EIO;
goto err_res_valid;
}
max_fid = MLXSW_CORE_RES_GET(mlxsw_core, FID);
txhdr = skb_push(skb, MLXSW_TXHDR_LEN);
memset(txhdr, 0, MLXSW_TXHDR_LEN);
mlxsw_tx_hdr_version_set(txhdr, MLXSW_TXHDR_VERSION_1);
mlxsw_tx_hdr_proto_set(txhdr, MLXSW_TXHDR_PROTO_ETH);
mlxsw_tx_hdr_rx_is_router_set(txhdr, true);
mlxsw_tx_hdr_fid_valid_set(txhdr, true);
mlxsw_tx_hdr_fid_set(txhdr, max_fid + tx_info->local_port - 1);
mlxsw_tx_hdr_type_set(txhdr, MLXSW_TXHDR_TYPE_DATA);
return 0;
err_res_valid:
err_skb_cow_head:
this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
dev_kfree_skb_any(skb);
return err;
}
static bool mlxsw_sp_skb_requires_ts(struct sk_buff *skb)
{
unsigned int type;
if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
return false;
type = ptp_classify_raw(skb);
return !!ptp_parse_header(skb, type);
}
static int mlxsw_sp_txhdr_handle(struct mlxsw_core *mlxsw_core,
struct mlxsw_sp_port *mlxsw_sp_port,
struct sk_buff *skb,
const struct mlxsw_tx_info *tx_info)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
/* In Spectrum-2 and Spectrum-3, PTP events that require a time stamp
* need special handling and cannot be transmitted as regular control
* packets.
*/
if (unlikely(mlxsw_sp_skb_requires_ts(skb)))
return mlxsw_sp->ptp_ops->txhdr_construct(mlxsw_core,
mlxsw_sp_port, skb,
tx_info);
if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) {
this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
dev_kfree_skb_any(skb);
return -ENOMEM;
}
mlxsw_sp_txhdr_construct(skb, tx_info);
return 0;
}
enum mlxsw_reg_spms_state mlxsw_sp_stp_spms_state(u8 state) enum mlxsw_reg_spms_state mlxsw_sp_stp_spms_state(u8 state)
{ {
switch (state) { switch (state) {
...@@ -648,12 +725,6 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb, ...@@ -648,12 +725,6 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb,
u64 len; u64 len;
int err; int err;
if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) {
this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
memset(skb->cb, 0, sizeof(struct mlxsw_skb_cb)); memset(skb->cb, 0, sizeof(struct mlxsw_skb_cb));
if (mlxsw_core_skb_transmit_busy(mlxsw_sp->core, &tx_info)) if (mlxsw_core_skb_transmit_busy(mlxsw_sp->core, &tx_info))
...@@ -664,7 +735,11 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb, ...@@ -664,7 +735,11 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb,
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
mlxsw_sp_txhdr_construct(skb, &tx_info); err = mlxsw_sp_txhdr_handle(mlxsw_sp->core, mlxsw_sp_port, skb,
&tx_info);
if (err)
return NETDEV_TX_OK;
/* TX header is consumed by HW on the way so we shouldn't count its /* TX header is consumed by HW on the way so we shouldn't count its
* bytes as being sent. * bytes as being sent.
*/ */
...@@ -2666,6 +2741,7 @@ static const struct mlxsw_sp_ptp_ops mlxsw_sp1_ptp_ops = { ...@@ -2666,6 +2741,7 @@ static const struct mlxsw_sp_ptp_ops mlxsw_sp1_ptp_ops = {
.get_stats_count = mlxsw_sp1_get_stats_count, .get_stats_count = mlxsw_sp1_get_stats_count,
.get_stats_strings = mlxsw_sp1_get_stats_strings, .get_stats_strings = mlxsw_sp1_get_stats_strings,
.get_stats = mlxsw_sp1_get_stats, .get_stats = mlxsw_sp1_get_stats,
.txhdr_construct = mlxsw_sp_ptp_txhdr_construct,
}; };
static const struct mlxsw_sp_ptp_ops mlxsw_sp2_ptp_ops = { static const struct mlxsw_sp_ptp_ops mlxsw_sp2_ptp_ops = {
...@@ -2682,6 +2758,24 @@ static const struct mlxsw_sp_ptp_ops mlxsw_sp2_ptp_ops = { ...@@ -2682,6 +2758,24 @@ static const struct mlxsw_sp_ptp_ops mlxsw_sp2_ptp_ops = {
.get_stats_count = mlxsw_sp2_get_stats_count, .get_stats_count = mlxsw_sp2_get_stats_count,
.get_stats_strings = mlxsw_sp2_get_stats_strings, .get_stats_strings = mlxsw_sp2_get_stats_strings,
.get_stats = mlxsw_sp2_get_stats, .get_stats = mlxsw_sp2_get_stats,
.txhdr_construct = mlxsw_sp2_ptp_txhdr_construct,
};
static const struct mlxsw_sp_ptp_ops mlxsw_sp4_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,
.hwtstamp_get = mlxsw_sp2_ptp_hwtstamp_get,
.hwtstamp_set = mlxsw_sp2_ptp_hwtstamp_set,
.shaper_work = mlxsw_sp2_ptp_shaper_work,
.get_ts_info = mlxsw_sp2_ptp_get_ts_info,
.get_stats_count = mlxsw_sp2_get_stats_count,
.get_stats_strings = mlxsw_sp2_get_stats_strings,
.get_stats = mlxsw_sp2_get_stats,
.txhdr_construct = mlxsw_sp_ptp_txhdr_construct,
}; };
struct mlxsw_sp_sample_trigger_node { struct mlxsw_sp_sample_trigger_node {
...@@ -3327,7 +3421,7 @@ static int mlxsw_sp4_init(struct mlxsw_core *mlxsw_core, ...@@ -3327,7 +3421,7 @@ static int mlxsw_sp4_init(struct mlxsw_core *mlxsw_core,
mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals; mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals;
mlxsw_sp->sb_ops = &mlxsw_sp3_sb_ops; mlxsw_sp->sb_ops = &mlxsw_sp3_sb_ops;
mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops; mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops; mlxsw_sp->ptp_ops = &mlxsw_sp4_ptp_ops;
mlxsw_sp->span_ops = &mlxsw_sp3_span_ops; mlxsw_sp->span_ops = &mlxsw_sp3_span_ops;
mlxsw_sp->policer_core_ops = &mlxsw_sp2_policer_core_ops; mlxsw_sp->policer_core_ops = &mlxsw_sp2_policer_core_ops;
mlxsw_sp->trap_ops = &mlxsw_sp2_trap_ops; mlxsw_sp->trap_ops = &mlxsw_sp2_trap_ops;
...@@ -3831,6 +3925,7 @@ static struct mlxsw_driver mlxsw_sp1_driver = { ...@@ -3831,6 +3925,7 @@ static struct mlxsw_driver mlxsw_sp1_driver = {
.ptp_transmitted = mlxsw_sp_ptp_transmitted, .ptp_transmitted = mlxsw_sp_ptp_transmitted,
.txhdr_len = MLXSW_TXHDR_LEN, .txhdr_len = MLXSW_TXHDR_LEN,
.profile = &mlxsw_sp1_config_profile, .profile = &mlxsw_sp1_config_profile,
.sdq_supports_cqe_v2 = false,
}; };
static struct mlxsw_driver mlxsw_sp2_driver = { static struct mlxsw_driver mlxsw_sp2_driver = {
...@@ -3869,6 +3964,7 @@ static struct mlxsw_driver mlxsw_sp2_driver = { ...@@ -3869,6 +3964,7 @@ static struct mlxsw_driver mlxsw_sp2_driver = {
.ptp_transmitted = mlxsw_sp_ptp_transmitted, .ptp_transmitted = mlxsw_sp_ptp_transmitted,
.txhdr_len = MLXSW_TXHDR_LEN, .txhdr_len = MLXSW_TXHDR_LEN,
.profile = &mlxsw_sp2_config_profile, .profile = &mlxsw_sp2_config_profile,
.sdq_supports_cqe_v2 = true,
}; };
static struct mlxsw_driver mlxsw_sp3_driver = { static struct mlxsw_driver mlxsw_sp3_driver = {
...@@ -3907,6 +4003,7 @@ static struct mlxsw_driver mlxsw_sp3_driver = { ...@@ -3907,6 +4003,7 @@ static struct mlxsw_driver mlxsw_sp3_driver = {
.ptp_transmitted = mlxsw_sp_ptp_transmitted, .ptp_transmitted = mlxsw_sp_ptp_transmitted,
.txhdr_len = MLXSW_TXHDR_LEN, .txhdr_len = MLXSW_TXHDR_LEN,
.profile = &mlxsw_sp2_config_profile, .profile = &mlxsw_sp2_config_profile,
.sdq_supports_cqe_v2 = true,
}; };
static struct mlxsw_driver mlxsw_sp4_driver = { static struct mlxsw_driver mlxsw_sp4_driver = {
...@@ -3943,6 +4040,7 @@ static struct mlxsw_driver mlxsw_sp4_driver = { ...@@ -3943,6 +4040,7 @@ static struct mlxsw_driver mlxsw_sp4_driver = {
.ptp_transmitted = mlxsw_sp_ptp_transmitted, .ptp_transmitted = mlxsw_sp_ptp_transmitted,
.txhdr_len = MLXSW_TXHDR_LEN, .txhdr_len = MLXSW_TXHDR_LEN,
.profile = &mlxsw_sp2_config_profile, .profile = &mlxsw_sp2_config_profile,
.sdq_supports_cqe_v2 = true,
}; };
bool mlxsw_sp_port_dev_check(const struct net_device *dev) bool mlxsw_sp_port_dev_check(const struct net_device *dev)
......
...@@ -243,6 +243,10 @@ struct mlxsw_sp_ptp_ops { ...@@ -243,6 +243,10 @@ struct mlxsw_sp_ptp_ops {
void (*get_stats_strings)(u8 **p); void (*get_stats_strings)(u8 **p);
void (*get_stats)(struct mlxsw_sp_port *mlxsw_sp_port, void (*get_stats)(struct mlxsw_sp_port *mlxsw_sp_port,
u64 *data, int data_index); u64 *data, int data_index);
int (*txhdr_construct)(struct mlxsw_core *mlxsw_core,
struct mlxsw_sp_port *mlxsw_sp_port,
struct sk_buff *skb,
const struct mlxsw_tx_info *tx_info);
}; };
static inline struct mlxsw_sp_upper * static inline struct mlxsw_sp_upper *
...@@ -700,6 +704,12 @@ int mlxsw_sp_flow_counter_alloc(struct mlxsw_sp *mlxsw_sp, ...@@ -700,6 +704,12 @@ int mlxsw_sp_flow_counter_alloc(struct mlxsw_sp *mlxsw_sp,
unsigned int *p_counter_index); unsigned int *p_counter_index);
void mlxsw_sp_flow_counter_free(struct mlxsw_sp *mlxsw_sp, void mlxsw_sp_flow_counter_free(struct mlxsw_sp *mlxsw_sp,
unsigned int counter_index); unsigned int counter_index);
void mlxsw_sp_txhdr_construct(struct sk_buff *skb,
const struct mlxsw_tx_info *tx_info);
int mlxsw_sp_txhdr_ptp_data_construct(struct mlxsw_core *mlxsw_core,
struct mlxsw_sp_port *mlxsw_sp_port,
struct sk_buff *skb,
const struct mlxsw_tx_info *tx_info);
bool mlxsw_sp_port_dev_check(const struct net_device *dev); bool mlxsw_sp_port_dev_check(const struct net_device *dev);
struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev); struct mlxsw_sp *mlxsw_sp_lower_get(struct net_device *dev);
struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev); struct mlxsw_sp_port *mlxsw_sp_port_dev_lower_find(struct net_device *dev);
......
...@@ -57,6 +57,40 @@ void mlxsw_sp1_get_stats_strings(u8 **p); ...@@ -57,6 +57,40 @@ void mlxsw_sp1_get_stats_strings(u8 **p);
void mlxsw_sp1_get_stats(struct mlxsw_sp_port *mlxsw_sp_port, void mlxsw_sp1_get_stats(struct mlxsw_sp_port *mlxsw_sp_port,
u64 *data, int data_index); u64 *data, int data_index);
int mlxsw_sp_ptp_txhdr_construct(struct mlxsw_core *mlxsw_core,
struct mlxsw_sp_port *mlxsw_sp_port,
struct sk_buff *skb,
const struct mlxsw_tx_info *tx_info);
struct mlxsw_sp_ptp_clock *
mlxsw_sp2_ptp_clock_init(struct mlxsw_sp *mlxsw_sp, struct device *dev);
void mlxsw_sp2_ptp_clock_fini(struct mlxsw_sp_ptp_clock *clock);
struct mlxsw_sp_ptp_state *mlxsw_sp2_ptp_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp2_ptp_fini(struct mlxsw_sp_ptp_state *ptp_state);
void mlxsw_sp2_ptp_receive(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
u16 local_port);
void mlxsw_sp2_ptp_transmitted(struct mlxsw_sp *mlxsw_sp,
struct sk_buff *skb, u16 local_port);
int mlxsw_sp2_ptp_hwtstamp_get(struct mlxsw_sp_port *mlxsw_sp_port,
struct hwtstamp_config *config);
int mlxsw_sp2_ptp_hwtstamp_set(struct mlxsw_sp_port *mlxsw_sp_port,
struct hwtstamp_config *config);
int mlxsw_sp2_ptp_get_ts_info(struct mlxsw_sp *mlxsw_sp,
struct ethtool_ts_info *info);
int mlxsw_sp2_ptp_txhdr_construct(struct mlxsw_core *mlxsw_core,
struct mlxsw_sp_port *mlxsw_sp_port,
struct sk_buff *skb,
const struct mlxsw_tx_info *tx_info);
#else #else
static inline struct mlxsw_sp_ptp_clock * static inline struct mlxsw_sp_ptp_clock *
...@@ -136,7 +170,14 @@ static inline void mlxsw_sp1_get_stats(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -136,7 +170,14 @@ static inline void mlxsw_sp1_get_stats(struct mlxsw_sp_port *mlxsw_sp_port,
u64 *data, int data_index) u64 *data, int data_index)
{ {
} }
#endif
int mlxsw_sp_ptp_txhdr_construct(struct mlxsw_core *mlxsw_core,
struct mlxsw_sp_port *mlxsw_sp_port,
struct sk_buff *skb,
const struct mlxsw_tx_info *tx_info)
{
return -EOPNOTSUPP;
}
static inline struct mlxsw_sp_ptp_clock * static inline struct mlxsw_sp_ptp_clock *
mlxsw_sp2_ptp_clock_init(struct mlxsw_sp *mlxsw_sp, struct device *dev) mlxsw_sp2_ptp_clock_init(struct mlxsw_sp *mlxsw_sp, struct device *dev)
...@@ -184,16 +225,25 @@ mlxsw_sp2_ptp_hwtstamp_set(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -184,16 +225,25 @@ mlxsw_sp2_ptp_hwtstamp_set(struct mlxsw_sp_port *mlxsw_sp_port,
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline void mlxsw_sp2_ptp_shaper_work(struct work_struct *work)
{
}
static inline int mlxsw_sp2_ptp_get_ts_info(struct mlxsw_sp *mlxsw_sp, static inline int mlxsw_sp2_ptp_get_ts_info(struct mlxsw_sp *mlxsw_sp,
struct ethtool_ts_info *info) struct ethtool_ts_info *info)
{ {
return mlxsw_sp_ptp_get_ts_info_noptp(info); return mlxsw_sp_ptp_get_ts_info_noptp(info);
} }
int mlxsw_sp2_ptp_txhdr_construct(struct mlxsw_core *mlxsw_core,
struct mlxsw_sp_port *mlxsw_sp_port,
struct sk_buff *skb,
const struct mlxsw_tx_info *tx_info)
{
return -EOPNOTSUPP;
}
#endif
static inline void mlxsw_sp2_ptp_shaper_work(struct work_struct *work)
{
}
static inline int mlxsw_sp2_get_stats_count(void) static inline int mlxsw_sp2_get_stats_count(void)
{ {
return 0; return 0;
......
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