Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0714256c authored by Petr Machata's avatar Petr Machata Committed by David S. Miller
Browse files

mlxsw: pci: PTP: Hook into packet transmit path



On Spectrum-1, timestamps are delivered separately from the packets, and
need to paired up. Therefore, at some point after mlxsw_sp_port_xmit()
is invoked, it is necessary to involve the chip-specific driver code to
allow it to do the necessary bookkeeping and matching.

On Spectrum-2, timestamps are delivered in CQE. For that reason,
position the point of driver involvement into mlxsw_pci_cqe_sdq_handle()
to make it hopefully easier to extend for Spectrum-2 in the future.

To tell the driver what port the packet was sent on, keep tx_info
in SKB control buffer.

Introduce a new driver core interface mlxsw_core_ptp_transmitted(), a
driver callback ptp_transmitted, and a PTP op transmitted. The callee is
responsible for taking care of releasing the SKB passed to the new
interfaces, and correspondingly have the new stub callbacks just call
dev_kfree_skb_any().

Follow-up patches will introduce the actual content into
mlxsw_sp1_ptp_transmitted() in particular.

Signed-off-by: default avatarPetr Machata <petrm@mellanox.com>
Acked-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent d7cd206d
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1245,6 +1245,15 @@ int mlxsw_core_skb_transmit(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
}
EXPORT_SYMBOL(mlxsw_core_skb_transmit);

void mlxsw_core_ptp_transmitted(struct mlxsw_core *mlxsw_core,
				struct sk_buff *skb, u8 local_port)
{
	if (mlxsw_core->driver->ptp_transmitted)
		mlxsw_core->driver->ptp_transmitted(mlxsw_core, skb,
						    local_port);
}
EXPORT_SYMBOL(mlxsw_core_ptp_transmitted);

static bool __is_rx_listener_equal(const struct mlxsw_rx_listener *rxl_a,
				   const struct mlxsw_rx_listener *rxl_b)
{
+10 −0
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ bool mlxsw_core_skb_transmit_busy(struct mlxsw_core *mlxsw_core,
				  const struct mlxsw_tx_info *tx_info);
int mlxsw_core_skb_transmit(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
			    const struct mlxsw_tx_info *tx_info);
void mlxsw_core_ptp_transmitted(struct mlxsw_core *mlxsw_core,
				struct sk_buff *skb, u8 local_port);

struct mlxsw_rx_listener {
	void (*func)(struct sk_buff *skb, u8 local_port, void *priv);
@@ -296,6 +298,13 @@ struct mlxsw_driver {
			     u64 *p_linear_size);
	int (*params_register)(struct mlxsw_core *mlxsw_core);
	void (*params_unregister)(struct mlxsw_core *mlxsw_core);

	/* Notify a driver that a timestamped packet was transmitted. Driver
	 * is responsible for freeing the passed-in SKB.
	 */
	void (*ptp_transmitted)(struct mlxsw_core *mlxsw_core,
				struct sk_buff *skb, u8 local_port);

	u8 txhdr_len;
	const struct mlxsw_config_profile *profile;
	bool res_query_enabled;
@@ -419,6 +428,7 @@ enum mlxsw_devlink_param_id {
};

struct mlxsw_skb_cb {
	struct mlxsw_tx_info tx_info;
};

static inline struct mlxsw_skb_cb *mlxsw_skb_cb(struct sk_buff *skb)
+16 −1
Original line number Diff line number Diff line
@@ -508,16 +508,27 @@ static void mlxsw_pci_cqe_sdq_handle(struct mlxsw_pci *mlxsw_pci,
{
	struct pci_dev *pdev = mlxsw_pci->pdev;
	struct mlxsw_pci_queue_elem_info *elem_info;
	struct mlxsw_tx_info tx_info;
	char *wqe;
	struct sk_buff *skb;
	int i;

	spin_lock(&q->lock);
	elem_info = mlxsw_pci_queue_elem_info_consumer_get(q);
	tx_info = mlxsw_skb_cb(elem_info->u.sdq.skb)->tx_info;
	skb = elem_info->u.sdq.skb;
	wqe = elem_info->elem;
	for (i = 0; i < MLXSW_PCI_WQE_SG_ENTRIES; i++)
		mlxsw_pci_wqe_frag_unmap(mlxsw_pci, wqe, i, DMA_TO_DEVICE);

	if (unlikely(!tx_info.is_emad &&
		     skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
		mlxsw_core_ptp_transmitted(mlxsw_pci->core, skb,
					   tx_info.local_port);
		skb = NULL;
	}

	if (skb)
		dev_kfree_skb_any(skb);
	elem_info->u.sdq.skb = NULL;

@@ -1548,6 +1559,7 @@ static int mlxsw_pci_skb_transmit(void *bus_priv, struct sk_buff *skb,
		err = -EAGAIN;
		goto unlock;
	}
	mlxsw_skb_cb(skb)->tx_info = *tx_info;
	elem_info->u.sdq.skb = skb;

	wqe = elem_info->elem;
@@ -1571,6 +1583,9 @@ static int mlxsw_pci_skb_transmit(void *bus_priv, struct sk_buff *skb,
			goto unmap_frags;
	}

	if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;

	/* Set unused sq entries byte count to zero. */
	for (i++; i < MLXSW_PCI_WQE_SG_ENTRIES; i++)
		mlxsw_pci_wqe_byte_count_set(wqe, i, 0);
+19 −0
Original line number Diff line number Diff line
@@ -157,6 +157,12 @@ struct mlxsw_sp_ptp_ops {
	 */
	void (*receive)(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
			u8 local_port);

	/* Notify a driver that a timestamped packet was transmitted. Driver
	 * is responsible for freeing the passed-in SKB.
	 */
	void (*transmitted)(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
			    u8 local_port);
};

static int mlxsw_sp_component_query(struct mlxfw_dev *mlxfw_dev,
@@ -4424,12 +4430,14 @@ 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,
	.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,
	.receive	= mlxsw_sp2_ptp_receive,
	.transmitted	= mlxsw_sp2_ptp_transmitted,
};

static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
@@ -4995,6 +5003,15 @@ static void mlxsw_sp2_params_unregister(struct mlxsw_core *mlxsw_core)
	mlxsw_sp_params_unregister(mlxsw_core);
}

static void mlxsw_sp_ptp_transmitted(struct mlxsw_core *mlxsw_core,
				     struct sk_buff *skb, u8 local_port)
{
	struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);

	skb_pull(skb, MLXSW_TXHDR_LEN);
	mlxsw_sp->ptp_ops->transmitted(mlxsw_sp, skb, local_port);
}

static struct mlxsw_driver mlxsw_sp1_driver = {
	.kind				= mlxsw_sp1_driver_name,
	.priv_size			= sizeof(struct mlxsw_sp),
@@ -5019,6 +5036,7 @@ static struct mlxsw_driver mlxsw_sp1_driver = {
	.kvd_sizes_get			= mlxsw_sp_kvd_sizes_get,
	.params_register		= mlxsw_sp_params_register,
	.params_unregister		= mlxsw_sp_params_unregister,
	.ptp_transmitted		= mlxsw_sp_ptp_transmitted,
	.txhdr_len			= MLXSW_TXHDR_LEN,
	.profile			= &mlxsw_sp1_config_profile,
	.res_query_enabled		= true,
@@ -5047,6 +5065,7 @@ static struct mlxsw_driver mlxsw_sp2_driver = {
	.resources_register		= mlxsw_sp2_resources_register,
	.params_register		= mlxsw_sp2_params_register,
	.params_unregister		= mlxsw_sp2_params_unregister,
	.ptp_transmitted		= mlxsw_sp_ptp_transmitted,
	.txhdr_len			= MLXSW_TXHDR_LEN,
	.profile			= &mlxsw_sp2_config_profile,
	.res_query_enabled		= true,
+6 −0
Original line number Diff line number Diff line
@@ -270,3 +270,9 @@ void mlxsw_sp1_ptp_receive(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
{
	mlxsw_sp_rx_listener_no_mark_func(skb, local_port, mlxsw_sp);
}

void mlxsw_sp1_ptp_transmitted(struct mlxsw_sp *mlxsw_sp,
			       struct sk_buff *skb, u8 local_port)
{
	dev_kfree_skb_any(skb);
}
Loading