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

Configure Feed

Select the types of activity you want to include in your feed.

net: micrel: Change to receive timestamp in the frame for lan8841

Currently for each timestamp frame, the SW needs to go and read the
received timestamp over the MDIO bus. But the HW has the capability
to store the received nanoseconds part and the least significant two
bits of the seconds in the reserved field of the PTP header. In this
way we could save few MDIO transactions (actually a little more
transactions because the access to the PTP registers are indirect)
for each received frame.

Instead of reading the rest of seconds part of the timestamp of the
frame using MDIO transactions schedule PTP worker thread to read the
seconds part every 500ms and then for each of the received frames use
this information. Because if for example running with 512 frames per
second, there is no point to read 512 times the second part.

Doing all these changes will give a great CPU usage performance.
Running ptp4l with logSyncInterval of -9 will give a ~60% CPU
improvement.

Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Acked-by: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Horatiu Vultur and committed by
David S. Miller
cc755495 4cb13ff1

+154 -96
+154 -96
drivers/net/phy/micrel.c
··· 252 252 #define PS_TO_REG 200 253 253 #define FIFO_SIZE 8 254 254 255 + /* Delay used to get the second part from the LTC */ 256 + #define LAN8841_GET_SEC_LTC_DELAY (500 * NSEC_PER_MSEC) 257 + 255 258 struct kszphy_hw_stat { 256 259 const char *string; 257 260 u8 reg; ··· 322 319 /* Lock for ptp_clock */ 323 320 struct mutex ptp_lock; 324 321 struct ptp_pin_desc *pin_config; 322 + 323 + s64 seconds; 324 + /* Lock for accessing seconds */ 325 + spinlock_t seconds_lock; 325 326 }; 326 327 327 328 struct kszphy_priv { ··· 3318 3311 #define LAN8841_PTP_CMD_CTL_PTP_RESET BIT(0) 3319 3312 #define LAN8841_PTP_RX_PARSE_CONFIG 368 3320 3313 #define LAN8841_PTP_TX_PARSE_CONFIG 432 3314 + #define LAN8841_PTP_RX_MODE 381 3315 + #define LAN8841_PTP_INSERT_TS_EN BIT(0) 3316 + #define LAN8841_PTP_INSERT_TS_32BIT BIT(1) 3321 3317 3322 3318 static int lan8841_config_init(struct phy_device *phydev) 3323 3319 { ··· 3469 3459 lan8814_match_tx_skb(ptp_priv, sec, nsec, seq); 3470 3460 } 3471 3461 3472 - #define LAN8841_PTP_RX_INGRESS_SEC_LO 389 3473 - #define LAN8841_PTP_RX_INGRESS_SEC_HI 388 3474 - #define LAN8841_PTP_RX_INGRESS_NS_LO 387 3475 - #define LAN8841_PTP_RX_INGRESS_NS_HI 386 3476 - #define LAN8841_PTP_RX_INGRESS_NSEC_HI_VALID BIT(15) 3477 - #define LAN8841_PTP_RX_MSG_HEADER2 391 3478 - 3479 - static struct lan8814_ptp_rx_ts *lan8841_ptp_get_rx_ts(struct kszphy_ptp_priv *ptp_priv) 3480 - { 3481 - struct phy_device *phydev = ptp_priv->phydev; 3482 - struct lan8814_ptp_rx_ts *rx_ts; 3483 - u32 sec, nsec; 3484 - u16 seq; 3485 - 3486 - nsec = phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_NS_HI); 3487 - if (!(nsec & LAN8841_PTP_RX_INGRESS_NSEC_HI_VALID)) 3488 - return NULL; 3489 - 3490 - nsec = ((nsec & 0x3fff) << 16); 3491 - nsec = nsec | phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_NS_LO); 3492 - 3493 - sec = phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_SEC_HI); 3494 - sec = sec << 16; 3495 - sec = sec | phy_read_mmd(phydev, 2, LAN8841_PTP_RX_INGRESS_SEC_LO); 3496 - 3497 - seq = phy_read_mmd(phydev, 2, LAN8841_PTP_RX_MSG_HEADER2); 3498 - 3499 - rx_ts = kzalloc(sizeof(*rx_ts), GFP_KERNEL); 3500 - if (!rx_ts) 3501 - return NULL; 3502 - 3503 - rx_ts->seconds = sec; 3504 - rx_ts->nsec = nsec; 3505 - rx_ts->seq_id = seq; 3506 - 3507 - return rx_ts; 3508 - } 3509 - 3510 - static void lan8841_ptp_process_rx_ts(struct kszphy_ptp_priv *ptp_priv) 3511 - { 3512 - struct lan8814_ptp_rx_ts *rx_ts; 3513 - 3514 - while ((rx_ts = lan8841_ptp_get_rx_ts(ptp_priv)) != NULL) 3515 - lan8814_match_rx_ts(ptp_priv, rx_ts); 3516 - } 3517 - 3518 3462 #define LAN8841_PTP_INT_STS 259 3519 3463 #define LAN8841_PTP_INT_STS_PTP_TX_TS_OVRFL_INT BIT(13) 3520 3464 #define LAN8841_PTP_INT_STS_PTP_TX_TS_INT BIT(12) 3521 - #define LAN8841_PTP_INT_STS_PTP_RX_TS_OVRFL_INT BIT(9) 3522 - #define LAN8841_PTP_INT_STS_PTP_RX_TS_INT BIT(8) 3523 3465 #define LAN8841_PTP_INT_STS_PTP_GPIO_CAP_INT BIT(2) 3524 3466 3525 - static void lan8841_ptp_flush_fifo(struct kszphy_ptp_priv *ptp_priv, bool egress) 3467 + static void lan8841_ptp_flush_fifo(struct kszphy_ptp_priv *ptp_priv) 3526 3468 { 3527 3469 struct phy_device *phydev = ptp_priv->phydev; 3528 3470 int i; 3529 3471 3530 3472 for (i = 0; i < FIFO_SIZE; ++i) 3531 - phy_read_mmd(phydev, 2, 3532 - egress ? LAN8841_PTP_TX_MSG_HEADER2 : 3533 - LAN8841_PTP_RX_MSG_HEADER2); 3473 + phy_read_mmd(phydev, 2, LAN8841_PTP_TX_MSG_HEADER2); 3534 3474 3535 3475 phy_read_mmd(phydev, 2, LAN8841_PTP_INT_STS); 3536 3476 } ··· 3558 3598 if (status & LAN8841_PTP_INT_STS_PTP_TX_TS_INT) 3559 3599 lan8841_ptp_process_tx_ts(ptp_priv); 3560 3600 3561 - if (status & LAN8841_PTP_INT_STS_PTP_RX_TS_INT) 3562 - lan8841_ptp_process_rx_ts(ptp_priv); 3563 - 3564 3601 if (status & LAN8841_PTP_INT_STS_PTP_GPIO_CAP_INT) 3565 3602 lan8841_gpio_process_cap(ptp_priv); 3566 3603 3567 3604 if (status & LAN8841_PTP_INT_STS_PTP_TX_TS_OVRFL_INT) { 3568 - lan8841_ptp_flush_fifo(ptp_priv, true); 3605 + lan8841_ptp_flush_fifo(ptp_priv); 3569 3606 skb_queue_purge(&ptp_priv->tx_queue); 3570 3607 } 3571 3608 3572 - if (status & LAN8841_PTP_INT_STS_PTP_RX_TS_OVRFL_INT) { 3573 - lan8841_ptp_flush_fifo(ptp_priv, false); 3574 - skb_queue_purge(&ptp_priv->rx_queue); 3575 - } 3576 - 3577 - } while (status); 3609 + } while (status & (LAN8841_PTP_INT_STS_PTP_TX_TS_INT | 3610 + LAN8841_PTP_INT_STS_PTP_GPIO_CAP_INT | 3611 + LAN8841_PTP_INT_STS_PTP_TX_TS_OVRFL_INT)); 3578 3612 } 3579 3613 3580 3614 #define LAN8841_INTS_PTP BIT(9) ··· 3632 3678 #define LAN8841_PTP_INT_EN 260 3633 3679 #define LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN BIT(13) 3634 3680 #define LAN8841_PTP_INT_EN_PTP_TX_TS_EN BIT(12) 3635 - #define LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN BIT(9) 3636 - #define LAN8841_PTP_INT_EN_PTP_RX_TS_EN BIT(8) 3637 3681 3638 - static void lan8841_ptp_enable_int(struct kszphy_ptp_priv *ptp_priv, 3639 - bool enable) 3682 + static void lan8841_ptp_enable_processing(struct kszphy_ptp_priv *ptp_priv, 3683 + bool enable) 3640 3684 { 3641 3685 struct phy_device *phydev = ptp_priv->phydev; 3642 3686 3643 - if (enable) 3644 - /* Enable interrupts */ 3687 + if (enable) { 3688 + /* Enable interrupts on the TX side */ 3645 3689 phy_modify_mmd(phydev, 2, LAN8841_PTP_INT_EN, 3646 3690 LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN | 3647 - LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN | 3648 - LAN8841_PTP_INT_EN_PTP_TX_TS_EN | 3649 - LAN8841_PTP_INT_EN_PTP_RX_TS_EN, 3691 + LAN8841_PTP_INT_EN_PTP_TX_TS_EN, 3650 3692 LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN | 3651 - LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN | 3652 - LAN8841_PTP_INT_EN_PTP_TX_TS_EN | 3653 - LAN8841_PTP_INT_EN_PTP_RX_TS_EN); 3654 - else 3655 - /* Disable interrupts */ 3693 + LAN8841_PTP_INT_EN_PTP_TX_TS_EN); 3694 + 3695 + /* Enable the modification of the frame on RX side, 3696 + * this will add the ns and 2 bits of sec in the reserved field 3697 + * of the PTP header 3698 + */ 3699 + phy_modify_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG, 3700 + LAN8841_PTP_RX_MODE, 3701 + LAN8841_PTP_INSERT_TS_EN | 3702 + LAN8841_PTP_INSERT_TS_32BIT, 3703 + LAN8841_PTP_INSERT_TS_EN | 3704 + LAN8841_PTP_INSERT_TS_32BIT); 3705 + 3706 + ptp_schedule_worker(ptp_priv->ptp_clock, 0); 3707 + } else { 3708 + /* Disable interrupts on the TX side */ 3656 3709 phy_modify_mmd(phydev, 2, LAN8841_PTP_INT_EN, 3657 3710 LAN8841_PTP_INT_EN_PTP_TX_TS_OVRFL_EN | 3658 - LAN8841_PTP_INT_EN_PTP_RX_TS_OVRFL_EN | 3659 - LAN8841_PTP_INT_EN_PTP_TX_TS_EN | 3660 - LAN8841_PTP_INT_EN_PTP_RX_TS_EN, 0); 3711 + LAN8841_PTP_INT_EN_PTP_TX_TS_EN, 0); 3712 + 3713 + /* Disable modification of the RX frames */ 3714 + phy_modify_mmd(phydev, KSZ9131RN_MMD_COMMON_CTRL_REG, 3715 + LAN8841_PTP_RX_MODE, 3716 + LAN8841_PTP_INSERT_TS_EN | 3717 + LAN8841_PTP_INSERT_TS_32BIT, 0); 3718 + 3719 + ptp_cancel_worker_sync(ptp_priv->ptp_clock); 3720 + } 3661 3721 } 3662 3722 3663 3723 #define LAN8841_PTP_RX_TIMESTAMP_EN 379 ··· 3682 3714 { 3683 3715 struct kszphy_ptp_priv *ptp_priv = container_of(mii_ts, struct kszphy_ptp_priv, mii_ts); 3684 3716 struct phy_device *phydev = ptp_priv->phydev; 3685 - struct lan8814_ptp_rx_ts *rx_ts, *tmp; 3686 3717 struct hwtstamp_config config; 3687 3718 int txcfg = 0, rxcfg = 0; 3688 3719 int pkt_ts_enable; ··· 3745 3778 PTP_TX_MOD_TX_PTP_SYNC_TS_INSERT_ : 0); 3746 3779 3747 3780 /* Now enable/disable the timestamping */ 3748 - lan8841_ptp_enable_int(ptp_priv, 3749 - config.rx_filter != HWTSTAMP_FILTER_NONE); 3781 + lan8841_ptp_enable_processing(ptp_priv, 3782 + config.rx_filter != HWTSTAMP_FILTER_NONE); 3750 3783 3751 - /* In case of multiple starts and stops, these needs to be cleared */ 3752 - list_for_each_entry_safe(rx_ts, tmp, &ptp_priv->rx_ts_list, list) { 3753 - list_del(&rx_ts->list); 3754 - kfree(rx_ts); 3755 - } 3756 - 3757 - skb_queue_purge(&ptp_priv->rx_queue); 3758 3784 skb_queue_purge(&ptp_priv->tx_queue); 3759 3785 3760 - lan8841_ptp_flush_fifo(ptp_priv, false); 3761 - lan8841_ptp_flush_fifo(ptp_priv, true); 3786 + lan8841_ptp_flush_fifo(ptp_priv); 3762 3787 3763 3788 return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? -EFAULT : 0; 3789 + } 3790 + 3791 + static bool lan8841_rxtstamp(struct mii_timestamper *mii_ts, 3792 + struct sk_buff *skb, int type) 3793 + { 3794 + struct kszphy_ptp_priv *ptp_priv = 3795 + container_of(mii_ts, struct kszphy_ptp_priv, mii_ts); 3796 + struct ptp_header *header = ptp_parse_header(skb, type); 3797 + struct skb_shared_hwtstamps *shhwtstamps; 3798 + struct timespec64 ts; 3799 + unsigned long flags; 3800 + u32 ts_header; 3801 + 3802 + if (!header) 3803 + return false; 3804 + 3805 + if (ptp_priv->rx_filter == HWTSTAMP_FILTER_NONE || 3806 + type == PTP_CLASS_NONE) 3807 + return false; 3808 + 3809 + if ((type & ptp_priv->version) == 0 || (type & ptp_priv->layer) == 0) 3810 + return false; 3811 + 3812 + spin_lock_irqsave(&ptp_priv->seconds_lock, flags); 3813 + ts.tv_sec = ptp_priv->seconds; 3814 + spin_unlock_irqrestore(&ptp_priv->seconds_lock, flags); 3815 + ts_header = __be32_to_cpu(header->reserved2); 3816 + 3817 + shhwtstamps = skb_hwtstamps(skb); 3818 + memset(shhwtstamps, 0, sizeof(*shhwtstamps)); 3819 + 3820 + /* Check for any wrap arounds for the second part */ 3821 + if ((ts.tv_sec & GENMASK(1, 0)) == 0 && (ts_header >> 30) == 3) 3822 + ts.tv_sec -= GENMASK(1, 0) + 1; 3823 + else if ((ts.tv_sec & GENMASK(1, 0)) == 3 && (ts_header >> 30) == 0) 3824 + ts.tv_sec += 1; 3825 + 3826 + shhwtstamps->hwtstamp = 3827 + ktime_set((ts.tv_sec & ~(GENMASK(1, 0))) | ts_header >> 30, 3828 + ts_header & GENMASK(29, 0)); 3829 + header->reserved2 = 0; 3830 + 3831 + netif_rx(skb); 3832 + 3833 + return true; 3764 3834 } 3765 3835 3766 3836 #define LAN8841_EVENT_A 0 ··· 3884 3880 struct kszphy_ptp_priv *ptp_priv = container_of(ptp, struct kszphy_ptp_priv, 3885 3881 ptp_clock_info); 3886 3882 struct phy_device *phydev = ptp_priv->phydev; 3883 + unsigned long flags; 3887 3884 int ret; 3888 3885 3889 3886 /* Set the value to be stored */ ··· 3900 3895 LAN8841_PTP_CMD_CTL_PTP_LTC_LOAD); 3901 3896 ret = lan8841_ptp_update_target(ptp_priv, ts); 3902 3897 mutex_unlock(&ptp_priv->ptp_lock); 3898 + 3899 + spin_lock_irqsave(&ptp_priv->seconds_lock, flags); 3900 + ptp_priv->seconds = ts->tv_sec; 3901 + spin_unlock_irqrestore(&ptp_priv->seconds_lock, flags); 3903 3902 3904 3903 return ret; 3905 3904 } ··· 3943 3934 3944 3935 set_normalized_timespec64(ts, s, ns); 3945 3936 return 0; 3937 + } 3938 + 3939 + static void lan8841_ptp_getseconds(struct ptp_clock_info *ptp, 3940 + struct timespec64 *ts) 3941 + { 3942 + struct kszphy_ptp_priv *ptp_priv = container_of(ptp, struct kszphy_ptp_priv, 3943 + ptp_clock_info); 3944 + struct phy_device *phydev = ptp_priv->phydev; 3945 + time64_t s; 3946 + 3947 + mutex_lock(&ptp_priv->ptp_lock); 3948 + /* Issue the command to read the LTC */ 3949 + phy_write_mmd(phydev, 2, LAN8841_PTP_CMD_CTL, 3950 + LAN8841_PTP_CMD_CTL_PTP_LTC_READ); 3951 + 3952 + /* Read the LTC */ 3953 + s = phy_read_mmd(phydev, 2, LAN8841_PTP_LTC_RD_SEC_HI); 3954 + s <<= 16; 3955 + s |= phy_read_mmd(phydev, 2, LAN8841_PTP_LTC_RD_SEC_MID); 3956 + s <<= 16; 3957 + s |= phy_read_mmd(phydev, 2, LAN8841_PTP_LTC_RD_SEC_LO); 3958 + mutex_unlock(&ptp_priv->ptp_lock); 3959 + 3960 + set_normalized_timespec64(ts, s, 0); 3946 3961 } 3947 3962 3948 3963 #define LAN8841_PTP_LTC_STEP_ADJ_LO 276 ··· 4471 4438 return 0; 4472 4439 } 4473 4440 4441 + static long lan8841_ptp_do_aux_work(struct ptp_clock_info *ptp) 4442 + { 4443 + struct kszphy_ptp_priv *ptp_priv = container_of(ptp, struct kszphy_ptp_priv, 4444 + ptp_clock_info); 4445 + struct timespec64 ts; 4446 + unsigned long flags; 4447 + 4448 + lan8841_ptp_getseconds(&ptp_priv->ptp_clock_info, &ts); 4449 + 4450 + spin_lock_irqsave(&ptp_priv->seconds_lock, flags); 4451 + ptp_priv->seconds = ts.tv_sec; 4452 + spin_unlock_irqrestore(&ptp_priv->seconds_lock, flags); 4453 + 4454 + return nsecs_to_jiffies(LAN8841_GET_SEC_LTC_DELAY); 4455 + } 4456 + 4474 4457 static struct ptp_clock_info lan8841_ptp_clock_info = { 4475 4458 .owner = THIS_MODULE, 4476 4459 .name = "lan8841 ptp", ··· 4497 4448 .adjfine = lan8841_ptp_adjfine, 4498 4449 .verify = lan8841_ptp_verify, 4499 4450 .enable = lan8841_ptp_enable, 4451 + .do_aux_work = lan8841_ptp_do_aux_work, 4500 4452 .n_per_out = LAN8841_PTP_GPIO_NUM, 4501 4453 .n_ext_ts = LAN8841_PTP_GPIO_NUM, 4502 4454 .n_pins = LAN8841_PTP_GPIO_NUM, ··· 4558 4508 4559 4509 /* Initialize the SW */ 4560 4510 skb_queue_head_init(&ptp_priv->tx_queue); 4561 - skb_queue_head_init(&ptp_priv->rx_queue); 4562 - INIT_LIST_HEAD(&ptp_priv->rx_ts_list); 4563 - spin_lock_init(&ptp_priv->rx_ts_lock); 4564 4511 ptp_priv->phydev = phydev; 4565 4512 mutex_init(&ptp_priv->ptp_lock); 4513 + spin_lock_init(&ptp_priv->seconds_lock); 4566 4514 4567 - ptp_priv->mii_ts.rxtstamp = lan8814_rxtstamp; 4515 + ptp_priv->mii_ts.rxtstamp = lan8841_rxtstamp; 4568 4516 ptp_priv->mii_ts.txtstamp = lan8814_txtstamp; 4569 4517 ptp_priv->mii_ts.hwtstamp = lan8841_hwtstamp; 4570 4518 ptp_priv->mii_ts.ts_info = lan8841_ts_info; ··· 4570 4522 phydev->mii_ts = &ptp_priv->mii_ts; 4571 4523 4572 4524 return 0; 4525 + } 4526 + 4527 + static int lan8841_suspend(struct phy_device *phydev) 4528 + { 4529 + struct kszphy_priv *priv = phydev->priv; 4530 + struct kszphy_ptp_priv *ptp_priv = &priv->ptp_priv; 4531 + 4532 + ptp_cancel_worker_sync(ptp_priv->ptp_clock); 4533 + 4534 + return genphy_suspend(phydev); 4573 4535 } 4574 4536 4575 4537 static struct phy_driver ksphy_driver[] = { ··· 4805 4747 .get_sset_count = kszphy_get_sset_count, 4806 4748 .get_strings = kszphy_get_strings, 4807 4749 .get_stats = kszphy_get_stats, 4808 - .suspend = genphy_suspend, 4750 + .suspend = lan8841_suspend, 4809 4751 .resume = genphy_resume, 4810 4752 .cable_test_start = lan8814_cable_test_start, 4811 4753 .cable_test_get_status = ksz886x_cable_test_get_status,