Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: David S. Miller <davem@davemloft.net>

+65 -39
-1
drivers/net/ethernet/microchip/lan966x/Kconfig
··· 6 6 depends on NET_SWITCHDEV 7 7 depends on BRIDGE || BRIDGE=n 8 8 select PHYLINK 9 - select PACKING 10 9 select PAGE_POOL 11 10 select VCAP 12 11 help
+1 -1
drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
··· 517 517 if (likely(!(skb->dev->features & NETIF_F_RXFCS))) 518 518 skb_trim(skb, skb->len - ETH_FCS_LEN); 519 519 520 - lan966x_ptp_rxtstamp(lan966x, skb, timestamp); 520 + lan966x_ptp_rxtstamp(lan966x, skb, src_port, timestamp); 521 521 skb->protocol = eth_type_trans(skb, skb->dev); 522 522 523 523 if (lan966x->bridge_mask & BIT(src_port)) {
+51 -25
drivers/net/ethernet/microchip/lan966x/lan966x_main.c
··· 7 7 #include <linux/ip.h> 8 8 #include <linux/of_platform.h> 9 9 #include <linux/of_net.h> 10 - #include <linux/packing.h> 11 10 #include <linux/phy/phy.h> 12 11 #include <linux/reset.h> 13 12 #include <net/addrconf.h> ··· 304 305 return NETDEV_TX_BUSY; 305 306 } 306 307 308 + static void lan966x_ifh_set(u8 *ifh, size_t val, size_t pos, size_t length) 309 + { 310 + int i = 0; 311 + 312 + do { 313 + u8 p = IFH_LEN_BYTES - (pos + i) / 8 - 1; 314 + u8 v = val >> i & 0xff; 315 + 316 + /* There is no need to check for limits of the array, as these 317 + * will never be written 318 + */ 319 + ifh[p] |= v << ((pos + i) % 8); 320 + ifh[p - 1] |= v >> (8 - (pos + i) % 8); 321 + 322 + i += 8; 323 + } while (i < length); 324 + } 325 + 307 326 void lan966x_ifh_set_bypass(void *ifh, u64 bypass) 308 327 { 309 - packing(ifh, &bypass, IFH_POS_BYPASS + IFH_WID_BYPASS - 1, 310 - IFH_POS_BYPASS, IFH_LEN * 4, PACK, 0); 328 + lan966x_ifh_set(ifh, bypass, IFH_POS_BYPASS, IFH_WID_BYPASS); 311 329 } 312 330 313 - void lan966x_ifh_set_port(void *ifh, u64 bypass) 331 + void lan966x_ifh_set_port(void *ifh, u64 port) 314 332 { 315 - packing(ifh, &bypass, IFH_POS_DSTS + IFH_WID_DSTS - 1, 316 - IFH_POS_DSTS, IFH_LEN * 4, PACK, 0); 333 + lan966x_ifh_set(ifh, port, IFH_POS_DSTS, IFH_WID_DSTS); 317 334 } 318 335 319 - static void lan966x_ifh_set_qos_class(void *ifh, u64 bypass) 336 + static void lan966x_ifh_set_qos_class(void *ifh, u64 qos) 320 337 { 321 - packing(ifh, &bypass, IFH_POS_QOS_CLASS + IFH_WID_QOS_CLASS - 1, 322 - IFH_POS_QOS_CLASS, IFH_LEN * 4, PACK, 0); 338 + lan966x_ifh_set(ifh, qos, IFH_POS_QOS_CLASS, IFH_WID_QOS_CLASS); 323 339 } 324 340 325 - static void lan966x_ifh_set_ipv(void *ifh, u64 bypass) 341 + static void lan966x_ifh_set_ipv(void *ifh, u64 ipv) 326 342 { 327 - packing(ifh, &bypass, IFH_POS_IPV + IFH_WID_IPV - 1, 328 - IFH_POS_IPV, IFH_LEN * 4, PACK, 0); 343 + lan966x_ifh_set(ifh, ipv, IFH_POS_IPV, IFH_WID_IPV); 329 344 } 330 345 331 346 static void lan966x_ifh_set_vid(void *ifh, u64 vid) 332 347 { 333 - packing(ifh, &vid, IFH_POS_TCI + IFH_WID_TCI - 1, 334 - IFH_POS_TCI, IFH_LEN * 4, PACK, 0); 348 + lan966x_ifh_set(ifh, vid, IFH_POS_TCI, IFH_WID_TCI); 335 349 } 336 350 337 351 static void lan966x_ifh_set_rew_op(void *ifh, u64 rew_op) 338 352 { 339 - packing(ifh, &rew_op, IFH_POS_REW_CMD + IFH_WID_REW_CMD - 1, 340 - IFH_POS_REW_CMD, IFH_LEN * 4, PACK, 0); 353 + lan966x_ifh_set(ifh, rew_op, IFH_POS_REW_CMD, IFH_WID_REW_CMD); 341 354 } 342 355 343 356 static void lan966x_ifh_set_timestamp(void *ifh, u64 timestamp) 344 357 { 345 - packing(ifh, &timestamp, IFH_POS_TIMESTAMP + IFH_WID_TIMESTAMP - 1, 346 - IFH_POS_TIMESTAMP, IFH_LEN * 4, PACK, 0); 358 + lan966x_ifh_set(ifh, timestamp, IFH_POS_TIMESTAMP, IFH_WID_TIMESTAMP); 347 359 } 348 360 349 361 static netdev_tx_t lan966x_port_xmit(struct sk_buff *skb, ··· 592 582 } 593 583 } 594 584 585 + static u64 lan966x_ifh_get(u8 *ifh, size_t pos, size_t length) 586 + { 587 + u64 val = 0; 588 + u8 v; 589 + 590 + for (int i = 0; i < length ; i++) { 591 + int j = pos + i; 592 + int k = j % 8; 593 + 594 + if (i == 0 || k == 0) 595 + v = ifh[IFH_LEN_BYTES - (j / 8) - 1]; 596 + 597 + if (v & (1 << k)) 598 + val |= (1 << i); 599 + } 600 + 601 + return val; 602 + } 603 + 595 604 void lan966x_ifh_get_src_port(void *ifh, u64 *src_port) 596 605 { 597 - packing(ifh, src_port, IFH_POS_SRCPORT + IFH_WID_SRCPORT - 1, 598 - IFH_POS_SRCPORT, IFH_LEN * 4, UNPACK, 0); 606 + *src_port = lan966x_ifh_get(ifh, IFH_POS_SRCPORT, IFH_WID_SRCPORT); 599 607 } 600 608 601 609 static void lan966x_ifh_get_len(void *ifh, u64 *len) 602 610 { 603 - packing(ifh, len, IFH_POS_LEN + IFH_WID_LEN - 1, 604 - IFH_POS_LEN, IFH_LEN * 4, UNPACK, 0); 611 + *len = lan966x_ifh_get(ifh, IFH_POS_LEN, IFH_WID_LEN); 605 612 } 606 613 607 614 void lan966x_ifh_get_timestamp(void *ifh, u64 *timestamp) 608 615 { 609 - packing(ifh, timestamp, IFH_POS_TIMESTAMP + IFH_WID_TIMESTAMP - 1, 610 - IFH_POS_TIMESTAMP, IFH_LEN * 4, UNPACK, 0); 616 + *timestamp = lan966x_ifh_get(ifh, IFH_POS_TIMESTAMP, IFH_WID_TIMESTAMP); 611 617 } 612 618 613 619 static irqreturn_t lan966x_xtr_irq_handler(int irq, void *args) ··· 694 668 *buf = val; 695 669 } 696 670 697 - lan966x_ptp_rxtstamp(lan966x, skb, timestamp); 671 + lan966x_ptp_rxtstamp(lan966x, skb, src_port, timestamp); 698 672 skb->protocol = eth_type_trans(skb, dev); 699 673 700 674 if (lan966x->bridge_mask & BIT(src_port)) {
+3 -2
drivers/net/ethernet/microchip/lan966x/lan966x_main.h
··· 407 407 struct phy *serdes; 408 408 struct fwnode_handle *fwnode; 409 409 410 - u8 ptp_cmd; 410 + u8 ptp_tx_cmd; 411 + bool ptp_rx_cmd; 411 412 u16 ts_id; 412 413 struct sk_buff_head tx_skbs; 413 414 ··· 528 527 int lan966x_ptp_hwtstamp_set(struct lan966x_port *port, struct ifreq *ifr); 529 528 int lan966x_ptp_hwtstamp_get(struct lan966x_port *port, struct ifreq *ifr); 530 529 void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb, 531 - u64 timestamp); 530 + u64 src_port, u64 timestamp); 532 531 int lan966x_ptp_txtstamp_request(struct lan966x_port *port, 533 532 struct sk_buff *skb); 534 533 void lan966x_ptp_txtstamp_release(struct lan966x_port *port,
+10 -10
drivers/net/ethernet/microchip/lan966x/lan966x_ptp.c
··· 272 272 273 273 switch (cfg.tx_type) { 274 274 case HWTSTAMP_TX_ON: 275 - port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP; 275 + port->ptp_tx_cmd = IFH_REW_OP_TWO_STEP_PTP; 276 276 break; 277 277 case HWTSTAMP_TX_ONESTEP_SYNC: 278 - port->ptp_cmd = IFH_REW_OP_ONE_STEP_PTP; 278 + port->ptp_tx_cmd = IFH_REW_OP_ONE_STEP_PTP; 279 279 break; 280 280 case HWTSTAMP_TX_OFF: 281 - port->ptp_cmd = IFH_REW_OP_NOOP; 281 + port->ptp_tx_cmd = IFH_REW_OP_NOOP; 282 282 break; 283 283 default: 284 284 return -ERANGE; ··· 286 286 287 287 switch (cfg.rx_filter) { 288 288 case HWTSTAMP_FILTER_NONE: 289 + port->ptp_rx_cmd = false; 289 290 break; 290 291 case HWTSTAMP_FILTER_ALL: 291 292 case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: ··· 302 301 case HWTSTAMP_FILTER_PTP_V2_SYNC: 303 302 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 304 303 case HWTSTAMP_FILTER_NTP_ALL: 304 + port->ptp_rx_cmd = true; 305 305 cfg.rx_filter = HWTSTAMP_FILTER_ALL; 306 306 break; 307 307 default: ··· 334 332 u8 msgtype; 335 333 int type; 336 334 337 - if (port->ptp_cmd == IFH_REW_OP_NOOP) 335 + if (port->ptp_tx_cmd == IFH_REW_OP_NOOP) 338 336 return IFH_REW_OP_NOOP; 339 337 340 338 type = ptp_classify_raw(skb); ··· 345 343 if (!header) 346 344 return IFH_REW_OP_NOOP; 347 345 348 - if (port->ptp_cmd == IFH_REW_OP_TWO_STEP_PTP) 346 + if (port->ptp_tx_cmd == IFH_REW_OP_TWO_STEP_PTP) 349 347 return IFH_REW_OP_TWO_STEP_PTP; 350 348 351 349 /* If it is sync and run 1 step then set the correct operation, ··· 1011 1009 phc->index = index; 1012 1010 phc->lan966x = lan966x; 1013 1011 1014 - /* PTP Rx stamping is always enabled. */ 1015 - phc->hwtstamp_config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 1016 - 1017 1012 return 0; 1018 1013 } 1019 1014 ··· 1087 1088 } 1088 1089 1089 1090 void lan966x_ptp_rxtstamp(struct lan966x *lan966x, struct sk_buff *skb, 1090 - u64 timestamp) 1091 + u64 src_port, u64 timestamp) 1091 1092 { 1092 1093 struct skb_shared_hwtstamps *shhwtstamps; 1093 1094 struct lan966x_phc *phc; 1094 1095 struct timespec64 ts; 1095 1096 u64 full_ts_in_ns; 1096 1097 1097 - if (!lan966x->ptp) 1098 + if (!lan966x->ptp || 1099 + !lan966x->ports[src_port]->ptp_rx_cmd) 1098 1100 return; 1099 1101 1100 1102 phc = &lan966x->phc[LAN966X_PHC_PORT];