Commit d4671cb9 authored by David S. Miller's avatar David S. Miller

Merge branch 'lan966x-tx-rx-improve'

Horatiu Vultur says:

====================
net: lan966x: Improve TX/RX of frames from/to CPU

The first patch of this series improves the RX side. As it seems to be
an expensive operation to read the RX timestamp for every frame, then
read it only if it is required. This will give an improvement of ~70mbit
on the RX side.
The second patch stops using the packing library. This improves mostly
the TX side as this library is used to set diffent bits in the IFH. If
this library is replaced with a more simple/shorter implementation,
this gives an improvement of more than 100mbit on TX side.
All the measurements were done using iperf3.

v1->v2:
- update lan966x_ifh_set to set the bytes and not each bit individually
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 105a201e fd762783
...@@ -6,7 +6,6 @@ config LAN966X_SWITCH ...@@ -6,7 +6,6 @@ config LAN966X_SWITCH
depends on NET_SWITCHDEV depends on NET_SWITCHDEV
depends on BRIDGE || BRIDGE=n depends on BRIDGE || BRIDGE=n
select PHYLINK select PHYLINK
select PACKING
select PAGE_POOL select PAGE_POOL
select VCAP select VCAP
help help
......
...@@ -517,7 +517,7 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx, ...@@ -517,7 +517,7 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx,
if (likely(!(skb->dev->features & NETIF_F_RXFCS))) if (likely(!(skb->dev->features & NETIF_F_RXFCS)))
skb_trim(skb, skb->len - ETH_FCS_LEN); skb_trim(skb, skb->len - ETH_FCS_LEN);
lan966x_ptp_rxtstamp(lan966x, skb, timestamp); lan966x_ptp_rxtstamp(lan966x, skb, src_port, timestamp);
skb->protocol = eth_type_trans(skb, skb->dev); skb->protocol = eth_type_trans(skb, skb->dev);
if (lan966x->bridge_mask & BIT(src_port)) { if (lan966x->bridge_mask & BIT(src_port)) {
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/of_net.h> #include <linux/of_net.h>
#include <linux/packing.h>
#include <linux/phy/phy.h> #include <linux/phy/phy.h>
#include <linux/reset.h> #include <linux/reset.h>
#include <net/addrconf.h> #include <net/addrconf.h>
...@@ -305,46 +304,57 @@ static int lan966x_port_ifh_xmit(struct sk_buff *skb, ...@@ -305,46 +304,57 @@ static int lan966x_port_ifh_xmit(struct sk_buff *skb,
return NETDEV_TX_BUSY; return NETDEV_TX_BUSY;
} }
static void lan966x_ifh_set(u8 *ifh, size_t val, size_t pos, size_t length)
{
int i = 0;
do {
u8 p = IFH_LEN_BYTES - (pos + i) / 8 - 1;
u8 v = val >> i & 0xff;
/* There is no need to check for limits of the array, as these
* will never be written
*/
ifh[p] |= v << ((pos + i) % 8);
ifh[p - 1] |= v >> (8 - (pos + i) % 8);
i += 8;
} while (i < length);
}
void lan966x_ifh_set_bypass(void *ifh, u64 bypass) void lan966x_ifh_set_bypass(void *ifh, u64 bypass)
{ {
packing(ifh, &bypass, IFH_POS_BYPASS + IFH_WID_BYPASS - 1, lan966x_ifh_set(ifh, bypass, IFH_POS_BYPASS, IFH_WID_BYPASS);
IFH_POS_BYPASS, IFH_LEN * 4, PACK, 0);
} }
void lan966x_ifh_set_port(void *ifh, u64 bypass) void lan966x_ifh_set_port(void *ifh, u64 port)
{ {
packing(ifh, &bypass, IFH_POS_DSTS + IFH_WID_DSTS - 1, lan966x_ifh_set(ifh, port, IFH_POS_DSTS, IFH_WID_DSTS);
IFH_POS_DSTS, IFH_LEN * 4, PACK, 0);
} }
static void lan966x_ifh_set_qos_class(void *ifh, u64 bypass) static void lan966x_ifh_set_qos_class(void *ifh, u64 qos)
{ {
packing(ifh, &bypass, IFH_POS_QOS_CLASS + IFH_WID_QOS_CLASS - 1, lan966x_ifh_set(ifh, qos, IFH_POS_QOS_CLASS, IFH_WID_QOS_CLASS);
IFH_POS_QOS_CLASS, IFH_LEN * 4, PACK, 0);
} }
static void lan966x_ifh_set_ipv(void *ifh, u64 bypass) static void lan966x_ifh_set_ipv(void *ifh, u64 ipv)
{ {
packing(ifh, &bypass, IFH_POS_IPV + IFH_WID_IPV - 1, lan966x_ifh_set(ifh, ipv, IFH_POS_IPV, IFH_WID_IPV);
IFH_POS_IPV, IFH_LEN * 4, PACK, 0);
} }
static void lan966x_ifh_set_vid(void *ifh, u64 vid) static void lan966x_ifh_set_vid(void *ifh, u64 vid)
{ {
packing(ifh, &vid, IFH_POS_TCI + IFH_WID_TCI - 1, lan966x_ifh_set(ifh, vid, IFH_POS_TCI, IFH_WID_TCI);
IFH_POS_TCI, IFH_LEN * 4, PACK, 0);
} }
static void lan966x_ifh_set_rew_op(void *ifh, u64 rew_op) static void lan966x_ifh_set_rew_op(void *ifh, u64 rew_op)
{ {
packing(ifh, &rew_op, IFH_POS_REW_CMD + IFH_WID_REW_CMD - 1, lan966x_ifh_set(ifh, rew_op, IFH_POS_REW_CMD, IFH_WID_REW_CMD);
IFH_POS_REW_CMD, IFH_LEN * 4, PACK, 0);
} }
static void lan966x_ifh_set_timestamp(void *ifh, u64 timestamp) static void lan966x_ifh_set_timestamp(void *ifh, u64 timestamp)
{ {
packing(ifh, &timestamp, IFH_POS_TIMESTAMP + IFH_WID_TIMESTAMP - 1, lan966x_ifh_set(ifh, timestamp, IFH_POS_TIMESTAMP, IFH_WID_TIMESTAMP);
IFH_POS_TIMESTAMP, IFH_LEN * 4, PACK, 0);
} }
static netdev_tx_t lan966x_port_xmit(struct sk_buff *skb, static netdev_tx_t lan966x_port_xmit(struct sk_buff *skb,
...@@ -582,22 +592,38 @@ static int lan966x_rx_frame_word(struct lan966x *lan966x, u8 grp, u32 *rval) ...@@ -582,22 +592,38 @@ static int lan966x_rx_frame_word(struct lan966x *lan966x, u8 grp, u32 *rval)
} }
} }
static u64 lan966x_ifh_get(u8 *ifh, size_t pos, size_t length)
{
u64 val = 0;
u8 v;
for (int i = 0; i < length ; i++) {
int j = pos + i;
int k = j % 8;
if (i == 0 || k == 0)
v = ifh[IFH_LEN_BYTES - (j / 8) - 1];
if (v & (1 << k))
val |= (1 << i);
}
return val;
}
void lan966x_ifh_get_src_port(void *ifh, u64 *src_port) void lan966x_ifh_get_src_port(void *ifh, u64 *src_port)
{ {
packing(ifh, src_port, IFH_POS_SRCPORT + IFH_WID_SRCPORT - 1, *src_port = lan966x_ifh_get(ifh, IFH_POS_SRCPORT, IFH_WID_SRCPORT);
IFH_POS_SRCPORT, IFH_LEN * 4, UNPACK, 0);
} }
static void lan966x_ifh_get_len(void *ifh, u64 *len) static void lan966x_ifh_get_len(void *ifh, u64 *len)
{ {
packing(ifh, len, IFH_POS_LEN + IFH_WID_LEN - 1, *len = lan966x_ifh_get(ifh, IFH_POS_LEN, IFH_WID_LEN);
IFH_POS_LEN, IFH_LEN * 4, UNPACK, 0);
} }
void lan966x_ifh_get_timestamp(void *ifh, u64 *timestamp) void lan966x_ifh_get_timestamp(void *ifh, u64 *timestamp)
{ {
packing(ifh, timestamp, IFH_POS_TIMESTAMP + IFH_WID_TIMESTAMP - 1, *timestamp = lan966x_ifh_get(ifh, IFH_POS_TIMESTAMP, IFH_WID_TIMESTAMP);
IFH_POS_TIMESTAMP, IFH_LEN * 4, UNPACK, 0);
} }
static irqreturn_t lan966x_xtr_irq_handler(int irq, void *args) static irqreturn_t lan966x_xtr_irq_handler(int irq, void *args)
...@@ -668,7 +694,7 @@ static irqreturn_t lan966x_xtr_irq_handler(int irq, void *args) ...@@ -668,7 +694,7 @@ static irqreturn_t lan966x_xtr_irq_handler(int irq, void *args)
*buf = val; *buf = val;
} }
lan966x_ptp_rxtstamp(lan966x, skb, timestamp); lan966x_ptp_rxtstamp(lan966x, skb, src_port, timestamp);
skb->protocol = eth_type_trans(skb, dev); skb->protocol = eth_type_trans(skb, dev);
if (lan966x->bridge_mask & BIT(src_port)) { if (lan966x->bridge_mask & BIT(src_port)) {
......
...@@ -407,7 +407,8 @@ struct lan966x_port { ...@@ -407,7 +407,8 @@ struct lan966x_port {
struct phy *serdes; struct phy *serdes;
struct fwnode_handle *fwnode; struct fwnode_handle *fwnode;
u8 ptp_cmd; u8 ptp_tx_cmd;
bool ptp_rx_cmd;
u16 ts_id; u16 ts_id;
struct sk_buff_head tx_skbs; struct sk_buff_head tx_skbs;
...@@ -527,7 +528,7 @@ void lan966x_ptp_deinit(struct lan966x *lan966x); ...@@ -527,7 +528,7 @@ void lan966x_ptp_deinit(struct lan966x *lan966x);
int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr); int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr);
int lan966x_ptp_hwtstamp_get(struct lan966x_port *port, struct ifreq *ifr); int lan966x_ptp_hwtstamp_get(struct lan966x_port *port, struct ifreq *ifr);
void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb, void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb,
u64 timestamp); u64 src_port, u64 timestamp);
int lan966x_ptp_txtstamp_request(struct lan966x_port *port, int lan966x_ptp_txtstamp_request(struct lan966x_port *port,
struct sk_buff *skb); struct sk_buff *skb);
void lan966x_ptp_txtstamp_release(struct lan966x_port *port, void lan966x_ptp_txtstamp_release(struct lan966x_port *port,
......
...@@ -272,13 +272,13 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr) ...@@ -272,13 +272,13 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr)
switch (cfg.tx_type) { switch (cfg.tx_type) {
case HWTSTAMP_TX_ON: case HWTSTAMP_TX_ON:
port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP; port->ptp_tx_cmd = IFH_REW_OP_TWO_STEP_PTP;
break; break;
case HWTSTAMP_TX_ONESTEP_SYNC: case HWTSTAMP_TX_ONESTEP_SYNC:
port->ptp_cmd = IFH_REW_OP_ONE_STEP_PTP; port->ptp_tx_cmd = IFH_REW_OP_ONE_STEP_PTP;
break; break;
case HWTSTAMP_TX_OFF: case HWTSTAMP_TX_OFF:
port->ptp_cmd = IFH_REW_OP_NOOP; port->ptp_tx_cmd = IFH_REW_OP_NOOP;
break; break;
default: default:
return -ERANGE; return -ERANGE;
...@@ -286,6 +286,7 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr) ...@@ -286,6 +286,7 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr)
switch (cfg.rx_filter) { switch (cfg.rx_filter) {
case HWTSTAMP_FILTER_NONE: case HWTSTAMP_FILTER_NONE:
port->ptp_rx_cmd = false;
break; break;
case HWTSTAMP_FILTER_ALL: case HWTSTAMP_FILTER_ALL:
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
...@@ -301,6 +302,7 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr) ...@@ -301,6 +302,7 @@ int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr)
case HWTSTAMP_FILTER_PTP_V2_SYNC: case HWTSTAMP_FILTER_PTP_V2_SYNC:
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
case HWTSTAMP_FILTER_NTP_ALL: case HWTSTAMP_FILTER_NTP_ALL:
port->ptp_rx_cmd = true;
cfg.rx_filter = HWTSTAMP_FILTER_ALL; cfg.rx_filter = HWTSTAMP_FILTER_ALL;
break; break;
default: default:
...@@ -332,7 +334,7 @@ static int lan966x_ptp_classify(struct lan966x_port *port, struct sk_buff *skb) ...@@ -332,7 +334,7 @@ static int lan966x_ptp_classify(struct lan966x_port *port, struct sk_buff *skb)
u8 msgtype; u8 msgtype;
int type; int type;
if (port->ptp_cmd == IFH_REW_OP_NOOP) if (port->ptp_tx_cmd == IFH_REW_OP_NOOP)
return IFH_REW_OP_NOOP; return IFH_REW_OP_NOOP;
type = ptp_classify_raw(skb); type = ptp_classify_raw(skb);
...@@ -343,7 +345,7 @@ static int lan966x_ptp_classify(struct lan966x_port *port, struct sk_buff *skb) ...@@ -343,7 +345,7 @@ static int lan966x_ptp_classify(struct lan966x_port *port, struct sk_buff *skb)
if (!header) if (!header)
return IFH_REW_OP_NOOP; return IFH_REW_OP_NOOP;
if (port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) if (port->ptp_tx_cmd == IFH_REW_OP_TWO_STEP_PTP)
return IFH_REW_OP_TWO_STEP_PTP; return IFH_REW_OP_TWO_STEP_PTP;
/* If it is sync and run 1 step then set the correct operation, /* If it is sync and run 1 step then set the correct operation,
...@@ -1009,9 +1011,6 @@ static int lan966x_ptp_phc_init(struct lan966x *lan966x, ...@@ -1009,9 +1011,6 @@ static int lan966x_ptp_phc_init(struct lan966x *lan966x,
phc->index = index; phc->index = index;
phc->lan966x = lan966x; phc->lan966x = lan966x;
/* PTP Rx stamping is always enabled. */
phc->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
return 0; return 0;
} }
...@@ -1088,14 +1087,15 @@ void lan966x_ptp_deinit(struct lan966x *lan966x) ...@@ -1088,14 +1087,15 @@ void lan966x_ptp_deinit(struct lan966x *lan966x)
} }
void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb, void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb,
u64 timestamp) u64 src_port, u64 timestamp)
{ {
struct skb_shared_hwtstamps *shhwtstamps; struct skb_shared_hwtstamps *shhwtstamps;
struct lan966x_phc *phc; struct lan966x_phc *phc;
struct timespec64 ts; struct timespec64 ts;
u64 full_ts_in_ns; u64 full_ts_in_ns;
if (!lan966x->ptp) if (!lan966x->ptp ||
!lan966x->ports[src_port]->ptp_rx_cmd)
return; return;
phc = &lan966x->phc[LAN966X_PHC_PORT]; phc = &lan966x->phc[LAN966X_PHC_PORT];
......
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