diff options
Diffstat (limited to 'drivers/net/ethernet/amd')
-rw-r--r-- | drivers/net/ethernet/amd/a2065.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/amd8111e.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/declance.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/pcnet32.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/pds_core/main.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/sunlance.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-common.h | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-dev.c | 142 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-drv.c | 210 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-hwtstamp.c | 401 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-main.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-pci.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 24 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe-ptp.c | 75 | ||||
-rw-r--r-- | drivers/net/ethernet/amd/xgbe/xgbe.h | 53 |
17 files changed, 554 insertions, 403 deletions
diff --git a/drivers/net/ethernet/amd/a2065.c b/drivers/net/ethernet/amd/a2065.c index b923ad9e1581..ce9445425045 100644 --- a/drivers/net/ethernet/amd/a2065.c +++ b/drivers/net/ethernet/amd/a2065.c @@ -636,7 +636,7 @@ static void lance_set_multicast(struct net_device *dev) static void lance_set_multicast_retry(struct timer_list *t) { - struct lance_private *lp = from_timer(lp, t, multicast_timer); + struct lance_private *lp = timer_container_of(lp, t, multicast_timer); lance_set_multicast(lp->dev); } diff --git a/drivers/net/ethernet/amd/amd8111e.c b/drivers/net/ethernet/amd/amd8111e.c index 86522e8574cb..76e8c13d5985 100644 --- a/drivers/net/ethernet/amd/amd8111e.c +++ b/drivers/net/ethernet/amd/amd8111e.c @@ -1641,7 +1641,8 @@ static int __maybe_unused amd8111e_resume(struct device *dev_d) static void amd8111e_config_ipg(struct timer_list *t) { - struct amd8111e_priv *lp = from_timer(lp, t, ipg_data.ipg_timer); + struct amd8111e_priv *lp = timer_container_of(lp, t, + ipg_data.ipg_timer); struct ipg_info *ipg_data = &lp->ipg_data; void __iomem *mmio = lp->mmio; unsigned int prev_col_cnt = ipg_data->col_cnt; diff --git a/drivers/net/ethernet/amd/declance.c b/drivers/net/ethernet/amd/declance.c index b072ca5930fc..8d05a0c5f2d5 100644 --- a/drivers/net/ethernet/amd/declance.c +++ b/drivers/net/ethernet/amd/declance.c @@ -1004,7 +1004,7 @@ static void lance_set_multicast(struct net_device *dev) static void lance_set_multicast_retry(struct timer_list *t) { - struct lance_private *lp = from_timer(lp, t, multicast_timer); + struct lance_private *lp = timer_container_of(lp, t, multicast_timer); struct net_device *dev = lp->dev; lance_set_multicast(dev); diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c index e5adafecc686..9eaefa0f5e80 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c @@ -2905,7 +2905,7 @@ static void pcnet32_check_media(struct net_device *dev, int verbose) static void pcnet32_watchdog(struct timer_list *t) { - struct pcnet32_private *lp = from_timer(lp, t, watchdog_timer); + struct pcnet32_private *lp = timer_container_of(lp, t, watchdog_timer); struct net_device *dev = lp->dev; unsigned long flags; diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c index 4843f9249a31..9b81e1c260c2 100644 --- a/drivers/net/ethernet/amd/pds_core/main.c +++ b/drivers/net/ethernet/amd/pds_core/main.c @@ -23,7 +23,7 @@ MODULE_DEVICE_TABLE(pci, pdsc_id_table); static void pdsc_wdtimer_cb(struct timer_list *t) { - struct pdsc *pdsc = from_timer(pdsc, t, wdtimer); + struct pdsc *pdsc = timer_container_of(pdsc, t, wdtimer); dev_dbg(pdsc->dev, "%s: jiffies %ld\n", __func__, jiffies); mod_timer(&pdsc->wdtimer, diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c index 3cd31855a5f6..0b273327f5a6 100644 --- a/drivers/net/ethernet/amd/sunlance.c +++ b/drivers/net/ethernet/amd/sunlance.c @@ -1246,7 +1246,7 @@ static void lance_set_multicast(struct net_device *dev) static void lance_set_multicast_retry(struct timer_list *t) { - struct lance_private *lp = from_timer(lp, t, multicast_timer); + struct lance_private *lp = timer_container_of(lp, t, multicast_timer); struct net_device *dev = lp->dev; lance_set_multicast(dev); diff --git a/drivers/net/ethernet/amd/xgbe/Makefile b/drivers/net/ethernet/amd/xgbe/Makefile index 620785ffbd51..5b0ab6240cf2 100644 --- a/drivers/net/ethernet/amd/xgbe/Makefile +++ b/drivers/net/ethernet/amd/xgbe/Makefile @@ -3,7 +3,7 @@ obj-$(CONFIG_AMD_XGBE) += amd-xgbe.o amd-xgbe-objs := xgbe-main.o xgbe-drv.o xgbe-dev.o \ xgbe-desc.o xgbe-ethtool.o xgbe-mdio.o \ - xgbe-ptp.o \ + xgbe-hwtstamp.o xgbe-ptp.o \ xgbe-i2c.o xgbe-phy-v1.o xgbe-phy-v2.o \ xgbe-platform.o diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-common.h b/drivers/net/ethernet/amd/xgbe/xgbe-common.h index e1296cbf4ff3..009fbc9b11ce 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-common.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe-common.h @@ -223,6 +223,10 @@ #define MAC_TSSR 0x0d20 #define MAC_TXSNR 0x0d30 #define MAC_TXSSR 0x0d34 +#define MAC_TICNR 0x0d58 +#define MAC_TICSNR 0x0d5C +#define MAC_TECNR 0x0d60 +#define MAC_TECSNR 0x0d64 #define MAC_QTFCR_INC 4 #define MAC_MACA_INC 4 @@ -364,6 +368,10 @@ #define MAC_RCR_CST_WIDTH 1 #define MAC_RCR_DCRCC_INDEX 3 #define MAC_RCR_DCRCC_WIDTH 1 +#define MAC_RCR_GPSLCE_INDEX 6 +#define MAC_RCR_GPSLCE_WIDTH 1 +#define MAC_RCR_WD_INDEX 7 +#define MAC_RCR_WD_WIDTH 1 #define MAC_RCR_HDSMS_INDEX 12 #define MAC_RCR_HDSMS_WIDTH 3 #define MAC_RCR_IPC_INDEX 9 @@ -374,6 +382,8 @@ #define MAC_RCR_LM_WIDTH 1 #define MAC_RCR_RE_INDEX 0 #define MAC_RCR_RE_WIDTH 1 +#define MAC_RCR_GPSL_INDEX 16 +#define MAC_RCR_GPSL_WIDTH 14 #define MAC_RFCR_PFCE_INDEX 8 #define MAC_RFCR_PFCE_WIDTH 1 #define MAC_RFCR_RFE_INDEX 0 @@ -412,6 +422,8 @@ #define MAC_TCR_VNE_WIDTH 1 #define MAC_TCR_VNM_INDEX 25 #define MAC_TCR_VNM_WIDTH 1 +#define MAC_TCR_JD_INDEX 16 +#define MAC_TCR_JD_WIDTH 1 #define MAC_TIR_TNID_INDEX 0 #define MAC_TIR_TNID_WIDTH 16 #define MAC_TSCR_AV8021ASMEN_INDEX 28 @@ -420,6 +432,8 @@ #define MAC_TSCR_SNAPTYPSEL_WIDTH 2 #define MAC_TSCR_TSADDREG_INDEX 5 #define MAC_TSCR_TSADDREG_WIDTH 1 +#define MAC_TSCR_TSUPDT_INDEX 3 +#define MAC_TSCR_TSUPDT_WIDTH 1 #define MAC_TSCR_TSCFUPDT_INDEX 1 #define MAC_TSCR_TSCFUPDT_WIDTH 1 #define MAC_TSCR_TSCTRLSSR_INDEX 9 @@ -448,6 +462,10 @@ #define MAC_TSSR_TXTSC_WIDTH 1 #define MAC_TXSNR_TXTSSTSMIS_INDEX 31 #define MAC_TXSNR_TXTSSTSMIS_WIDTH 1 +#define MAC_TICSNR_TSICSNS_INDEX 8 +#define MAC_TICSNR_TSICSNS_WIDTH 8 +#define MAC_TECSNR_TSECSNS_INDEX 8 +#define MAC_TECSNR_TSECSNS_WIDTH 8 #define MAC_VLANHTR_VLHT_INDEX 0 #define MAC_VLANHTR_VLHT_WIDTH 16 #define MAC_VLANIR_VLTI_INDEX 20 @@ -1269,6 +1287,8 @@ #define MDIO_VEND2_CTRL1_SS13 BIT(13) #endif +#define XGBE_VEND2_MAC_AUTO_SW BIT(9) + /* MDIO mask values */ #define XGBE_AN_CL73_INT_CMPLT BIT(0) #define XGBE_AN_CL73_INC_LINK BIT(1) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 466b5f6e5578..e5391a2eca51 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -1558,125 +1558,6 @@ static void xgbe_rx_desc_init(struct xgbe_channel *channel) DBGPR("<--rx_desc_init\n"); } -static void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata, - unsigned int addend) -{ - unsigned int count = 10000; - - /* Set the addend register value and tell the device */ - XGMAC_IOWRITE(pdata, MAC_TSAR, addend); - XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSADDREG, 1); - - /* Wait for addend update to complete */ - while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSADDREG)) - udelay(5); - - if (!count) - netdev_err(pdata->netdev, - "timed out updating timestamp addend register\n"); -} - -static void xgbe_set_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec, - unsigned int nsec) -{ - unsigned int count = 10000; - - /* Set the time values and tell the device */ - XGMAC_IOWRITE(pdata, MAC_STSUR, sec); - XGMAC_IOWRITE(pdata, MAC_STNUR, nsec); - XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSINIT, 1); - - /* Wait for time update to complete */ - while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSINIT)) - udelay(5); - - if (!count) - netdev_err(pdata->netdev, "timed out initializing timestamp\n"); -} - -static u64 xgbe_get_tstamp_time(struct xgbe_prv_data *pdata) -{ - u64 nsec; - - nsec = XGMAC_IOREAD(pdata, MAC_STSR); - nsec *= NSEC_PER_SEC; - nsec += XGMAC_IOREAD(pdata, MAC_STNR); - - return nsec; -} - -static u64 xgbe_get_tx_tstamp(struct xgbe_prv_data *pdata) -{ - unsigned int tx_snr, tx_ssr; - u64 nsec; - - if (pdata->vdata->tx_tstamp_workaround) { - tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR); - tx_ssr = XGMAC_IOREAD(pdata, MAC_TXSSR); - } else { - tx_ssr = XGMAC_IOREAD(pdata, MAC_TXSSR); - tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR); - } - - if (XGMAC_GET_BITS(tx_snr, MAC_TXSNR, TXTSSTSMIS)) - return 0; - - nsec = tx_ssr; - nsec *= NSEC_PER_SEC; - nsec += tx_snr; - - return nsec; -} - -static void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet, - struct xgbe_ring_desc *rdesc) -{ - u64 nsec; - - if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSA) && - !XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSD)) { - nsec = le32_to_cpu(rdesc->desc1); - nsec <<= 32; - nsec |= le32_to_cpu(rdesc->desc0); - if (nsec != 0xffffffffffffffffULL) { - packet->rx_tstamp = nsec; - XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, - RX_TSTAMP, 1); - } - } -} - -static int xgbe_config_tstamp(struct xgbe_prv_data *pdata, - unsigned int mac_tscr) -{ - /* Set one nano-second accuracy */ - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCTRLSSR, 1); - - /* Set fine timestamp update */ - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCFUPDT, 1); - - /* Overwrite earlier timestamps */ - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TXTSSTSM, 1); - - XGMAC_IOWRITE(pdata, MAC_TSCR, mac_tscr); - - /* Exit if timestamping is not enabled */ - if (!XGMAC_GET_BITS(mac_tscr, MAC_TSCR, TSENA)) - return 0; - - /* Initialize time registers */ - XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_TSTAMP_SSINC); - XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_TSTAMP_SNSINC); - xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend); - xgbe_set_tstamp_time(pdata, 0, 0); - - /* Initialize the timecounter */ - timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, - ktime_to_ns(ktime_get_real())); - - return 0; -} - static void xgbe_tx_start_xmit(struct xgbe_channel *channel, struct xgbe_ring *ring) { @@ -2850,9 +2731,19 @@ static void xgbe_config_jumbo_enable(struct xgbe_prv_data *pdata) { unsigned int val; - val = (pdata->netdev->mtu > XGMAC_STD_PACKET_MTU) ? 1 : 0; - - XGMAC_IOWRITE_BITS(pdata, MAC_RCR, JE, val); + if (pdata->netdev->mtu > XGMAC_JUMBO_PACKET_MTU) { + XGMAC_IOWRITE_BITS(pdata, MAC_RCR, GPSL, + XGMAC_GIANT_PACKET_MTU); + XGMAC_IOWRITE_BITS(pdata, MAC_RCR, WD, 1); + XGMAC_IOWRITE_BITS(pdata, MAC_TCR, JD, 1); + XGMAC_IOWRITE_BITS(pdata, MAC_RCR, GPSLCE, 1); + } else { + val = pdata->netdev->mtu > XGMAC_STD_PACKET_MTU ? 1 : 0; + XGMAC_IOWRITE_BITS(pdata, MAC_RCR, GPSLCE, 0); + XGMAC_IOWRITE_BITS(pdata, MAC_RCR, WD, 0); + XGMAC_IOWRITE_BITS(pdata, MAC_TCR, JD, 0); + XGMAC_IOWRITE_BITS(pdata, MAC_RCR, JE, val); + } } static void xgbe_config_mac_speed(struct xgbe_prv_data *pdata) @@ -3661,13 +3552,6 @@ void xgbe_init_function_ptrs_dev(struct xgbe_hw_if *hw_if) hw_if->rx_mmc_int = xgbe_rx_mmc_int; hw_if->read_mmc_stats = xgbe_read_mmc_stats; - /* For PTP config */ - hw_if->config_tstamp = xgbe_config_tstamp; - hw_if->update_tstamp_addend = xgbe_update_tstamp_addend; - hw_if->set_tstamp_time = xgbe_set_tstamp_time; - hw_if->get_tstamp_time = xgbe_get_tstamp_time; - hw_if->get_tx_tstamp = xgbe_get_tx_tstamp; - /* For Data Center Bridging config */ hw_if->config_tc = xgbe_config_tc; hw_if->config_dcb_tc = xgbe_config_dcb_tc; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 76c328721fcd..2e9b95a94f89 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -448,7 +448,7 @@ static void xgbe_isr_bh_work(struct work_struct *work) if (XGMAC_GET_BITS(mac_tssr, MAC_TSSR, TXTSC)) { /* Read Tx Timestamp to clear interrupt */ pdata->tx_tstamp = - hw_if->get_tx_tstamp(pdata); + xgbe_get_tx_tstamp(pdata); queue_work(pdata->dev_workqueue, &pdata->tx_tstamp_work); } @@ -534,7 +534,8 @@ static irqreturn_t xgbe_dma_isr(int irq, void *data) static void xgbe_tx_timer(struct timer_list *t) { - struct xgbe_channel *channel = from_timer(channel, t, tx_timer); + struct xgbe_channel *channel = timer_container_of(channel, t, + tx_timer); struct xgbe_prv_data *pdata = channel->pdata; struct napi_struct *napi; @@ -572,7 +573,8 @@ static void xgbe_service(struct work_struct *work) static void xgbe_service_timer(struct timer_list *t) { - struct xgbe_prv_data *pdata = from_timer(pdata, t, service_timer); + struct xgbe_prv_data *pdata = timer_container_of(pdata, t, + service_timer); struct xgbe_channel *channel; unsigned int i; @@ -1369,199 +1371,6 @@ static void xgbe_restart(struct work_struct *work) rtnl_unlock(); } -static void xgbe_tx_tstamp(struct work_struct *work) -{ - struct xgbe_prv_data *pdata = container_of(work, - struct xgbe_prv_data, - tx_tstamp_work); - struct skb_shared_hwtstamps hwtstamps; - u64 nsec; - unsigned long flags; - - spin_lock_irqsave(&pdata->tstamp_lock, flags); - if (!pdata->tx_tstamp_skb) - goto unlock; - - if (pdata->tx_tstamp) { - nsec = timecounter_cyc2time(&pdata->tstamp_tc, - pdata->tx_tstamp); - - memset(&hwtstamps, 0, sizeof(hwtstamps)); - hwtstamps.hwtstamp = ns_to_ktime(nsec); - skb_tstamp_tx(pdata->tx_tstamp_skb, &hwtstamps); - } - - dev_kfree_skb_any(pdata->tx_tstamp_skb); - - pdata->tx_tstamp_skb = NULL; - -unlock: - spin_unlock_irqrestore(&pdata->tstamp_lock, flags); -} - -static int xgbe_get_hwtstamp_settings(struct xgbe_prv_data *pdata, - struct ifreq *ifreq) -{ - if (copy_to_user(ifreq->ifr_data, &pdata->tstamp_config, - sizeof(pdata->tstamp_config))) - return -EFAULT; - - return 0; -} - -static int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata, - struct ifreq *ifreq) -{ - struct hwtstamp_config config; - unsigned int mac_tscr; - - if (copy_from_user(&config, ifreq->ifr_data, sizeof(config))) - return -EFAULT; - - mac_tscr = 0; - - switch (config.tx_type) { - case HWTSTAMP_TX_OFF: - break; - - case HWTSTAMP_TX_ON: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); - break; - - default: - return -ERANGE; - } - - switch (config.rx_filter) { - case HWTSTAMP_FILTER_NONE: - break; - - case HWTSTAMP_FILTER_NTP_ALL: - case HWTSTAMP_FILTER_ALL: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENALL, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); - break; - - /* PTP v2, UDP, any kind of event packet */ - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); - fallthrough; /* to PTP v1, UDP, any kind of event packet */ - case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); - break; - - /* PTP v2, UDP, Sync packet */ - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); - fallthrough; /* to PTP v1, UDP, Sync packet */ - case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); - break; - - /* PTP v2, UDP, Delay_req packet */ - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); - fallthrough; /* to PTP v1, UDP, Delay_req packet */ - case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); - break; - - /* 802.AS1, Ethernet, any kind of event packet */ - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); - break; - - /* 802.AS1, Ethernet, Sync packet */ - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); - break; - - /* 802.AS1, Ethernet, Delay_req packet */ - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); - break; - - /* PTP v2/802.AS1, any layer, any kind of event packet */ - case HWTSTAMP_FILTER_PTP_V2_EVENT: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); - break; - - /* PTP v2/802.AS1, any layer, Sync packet */ - case HWTSTAMP_FILTER_PTP_V2_SYNC: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); - break; - - /* PTP v2/802.AS1, any layer, Delay_req packet */ - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); - XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); - break; - - default: - return -ERANGE; - } - - pdata->hw_if.config_tstamp(pdata, mac_tscr); - - memcpy(&pdata->tstamp_config, &config, sizeof(config)); - - return 0; -} - -static void xgbe_prep_tx_tstamp(struct xgbe_prv_data *pdata, - struct sk_buff *skb, - struct xgbe_packet_data *packet) -{ - unsigned long flags; - - if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP)) { - spin_lock_irqsave(&pdata->tstamp_lock, flags); - if (pdata->tx_tstamp_skb) { - /* Another timestamp in progress, ignore this one */ - XGMAC_SET_BITS(packet->attributes, - TX_PACKET_ATTRIBUTES, PTP, 0); - } else { - pdata->tx_tstamp_skb = skb_get(skb); - skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - } - spin_unlock_irqrestore(&pdata->tstamp_lock, flags); - } - - skb_tx_timestamp(skb); -} - static void xgbe_prep_vlan(struct sk_buff *skb, struct xgbe_packet_data *packet) { if (skb_vlan_tag_present(skb)) @@ -1774,6 +1583,9 @@ static int xgbe_open(struct net_device *netdev) INIT_WORK(&pdata->stopdev_work, xgbe_stopdev); INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp); + /* Initialize PTP timestamping and clock. */ + xgbe_init_ptp(pdata); + ret = xgbe_alloc_memory(pdata); if (ret) goto err_ptpclk; @@ -2544,12 +2356,8 @@ skip_data: if (XGMAC_GET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, RX_TSTAMP)) { - u64 nsec; - - nsec = timecounter_cyc2time(&pdata->tstamp_tc, - packet->rx_tstamp); hwtstamps = skb_hwtstamps(skb); - hwtstamps->hwtstamp = ns_to_ktime(nsec); + hwtstamps->hwtstamp = ns_to_ktime(packet->rx_tstamp); } if (XGMAC_GET_BITS(packet->attributes, diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-hwtstamp.c b/drivers/net/ethernet/amd/xgbe/xgbe-hwtstamp.c new file mode 100644 index 000000000000..bc52e5ec6420 --- /dev/null +++ b/drivers/net/ethernet/amd/xgbe/xgbe-hwtstamp.c @@ -0,0 +1,401 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) +/* + * Copyright (c) 2014-2025, Advanced Micro Devices, Inc. + * Copyright (c) 2014, Synopsys, Inc. + * All rights reserved + * + * Author: Raju Rangoju <Raju.Rangoju@amd.com> + */ + +#include "xgbe.h" +#include "xgbe-common.h" + +void xgbe_update_tstamp_time(struct xgbe_prv_data *pdata, + unsigned int sec, unsigned int nsec) +{ + int count; + + /* Set the time values and tell the device */ + XGMAC_IOWRITE(pdata, MAC_STSUR, sec); + XGMAC_IOWRITE(pdata, MAC_STNUR, nsec); + + /* issue command to update the system time value */ + XGMAC_IOWRITE(pdata, MAC_TSCR, + XGMAC_IOREAD(pdata, MAC_TSCR) | + (1 << MAC_TSCR_TSUPDT_INDEX)); + + /* Wait for the time adjust/update to complete */ + count = 10000; + while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSUPDT)) + udelay(5); + + if (count < 0) + netdev_err(pdata->netdev, + "timed out updating system timestamp\n"); +} + +void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata, + unsigned int addend) +{ + unsigned int count = 10000; + + /* Set the addend register value and tell the device */ + XGMAC_IOWRITE(pdata, MAC_TSAR, addend); + XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSADDREG, 1); + + /* Wait for addend update to complete */ + while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSADDREG)) + udelay(5); + + if (!count) + netdev_err(pdata->netdev, + "timed out updating timestamp addend register\n"); +} + +void xgbe_set_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec, + unsigned int nsec) +{ + unsigned int count = 10000; + + /* Set the time values and tell the device */ + XGMAC_IOWRITE(pdata, MAC_STSUR, sec); + XGMAC_IOWRITE(pdata, MAC_STNUR, nsec); + XGMAC_IOWRITE_BITS(pdata, MAC_TSCR, TSINIT, 1); + + /* Wait for time update to complete */ + while (--count && XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSINIT)) + udelay(5); + + if (!count) + netdev_err(pdata->netdev, "timed out initializing timestamp\n"); +} + +u64 xgbe_get_tstamp_time(struct xgbe_prv_data *pdata) +{ + u64 nsec; + + nsec = XGMAC_IOREAD(pdata, MAC_STSR); + nsec *= NSEC_PER_SEC; + nsec += XGMAC_IOREAD(pdata, MAC_STNR); + + return nsec; +} + +u64 xgbe_get_tx_tstamp(struct xgbe_prv_data *pdata) +{ + unsigned int tx_snr, tx_ssr; + u64 nsec; + + if (pdata->vdata->tx_tstamp_workaround) { + tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR); + tx_ssr = XGMAC_IOREAD(pdata, MAC_TXSSR); + } else { + tx_ssr = XGMAC_IOREAD(pdata, MAC_TXSSR); + tx_snr = XGMAC_IOREAD(pdata, MAC_TXSNR); + } + + if (XGMAC_GET_BITS(tx_snr, MAC_TXSNR, TXTSSTSMIS)) + return 0; + + nsec = tx_ssr; + nsec *= NSEC_PER_SEC; + nsec += tx_snr; + + return nsec; +} + +void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet, + struct xgbe_ring_desc *rdesc) +{ + u64 nsec; + + if (XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSA) && + !XGMAC_GET_BITS_LE(rdesc->desc3, RX_CONTEXT_DESC3, TSD)) { + nsec = le32_to_cpu(rdesc->desc1); + nsec *= NSEC_PER_SEC; + nsec += le32_to_cpu(rdesc->desc0); + if (nsec != 0xffffffffffffffffULL) { + packet->rx_tstamp = nsec; + XGMAC_SET_BITS(packet->attributes, RX_PACKET_ATTRIBUTES, + RX_TSTAMP, 1); + } + } +} + +void xgbe_config_tstamp(struct xgbe_prv_data *pdata, unsigned int mac_tscr) +{ + unsigned int value = 0; + + value = XGMAC_IOREAD(pdata, MAC_TSCR); + value |= mac_tscr; + XGMAC_IOWRITE(pdata, MAC_TSCR, value); +} + +void xgbe_tx_tstamp(struct work_struct *work) +{ + struct xgbe_prv_data *pdata = container_of(work, + struct xgbe_prv_data, + tx_tstamp_work); + struct skb_shared_hwtstamps hwtstamps; + unsigned long flags; + + spin_lock_irqsave(&pdata->tstamp_lock, flags); + if (!pdata->tx_tstamp_skb) + goto unlock; + + if (pdata->tx_tstamp) { + memset(&hwtstamps, 0, sizeof(hwtstamps)); + hwtstamps.hwtstamp = ns_to_ktime(pdata->tx_tstamp); + skb_tstamp_tx(pdata->tx_tstamp_skb, &hwtstamps); + } + + dev_kfree_skb_any(pdata->tx_tstamp_skb); + + pdata->tx_tstamp_skb = NULL; + +unlock: + spin_unlock_irqrestore(&pdata->tstamp_lock, flags); +} + +int xgbe_get_hwtstamp_settings(struct xgbe_prv_data *pdata, struct ifreq *ifreq) +{ + if (copy_to_user(ifreq->ifr_data, &pdata->tstamp_config, + sizeof(pdata->tstamp_config))) + return -EFAULT; + + return 0; +} + +int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata, struct ifreq *ifreq) +{ + struct hwtstamp_config config; + unsigned int mac_tscr; + + if (copy_from_user(&config, ifreq->ifr_data, sizeof(config))) + return -EFAULT; + + mac_tscr = 0; + + switch (config.tx_type) { + case HWTSTAMP_TX_OFF: + break; + + case HWTSTAMP_TX_ON: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); + break; + + default: + return -ERANGE; + } + + switch (config.rx_filter) { + case HWTSTAMP_FILTER_NONE: + break; + + case HWTSTAMP_FILTER_NTP_ALL: + case HWTSTAMP_FILTER_ALL: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENALL, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); + break; + + /* PTP v2, UDP, any kind of event packet */ + case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); + fallthrough; /* to PTP v1, UDP, any kind of event packet */ + case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); + break; + /* PTP v2, UDP, Sync packet */ + case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); + fallthrough; /* to PTP v1, UDP, Sync packet */ + case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); + break; + + /* PTP v2, UDP, Delay_req packet */ + case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); + fallthrough; /* to PTP v1, UDP, Delay_req packet */ + case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); + break; + + /* 802.AS1, Ethernet, any kind of event packet */ + case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); + break; + + /* 802.AS1, Ethernet, Sync packet */ + case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); + break; + + /* 802.AS1, Ethernet, Delay_req packet */ + case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, AV8021ASMEN, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); + break; + + /* PTP v2/802.AS1, any layer, any kind of event packet */ + case HWTSTAMP_FILTER_PTP_V2_EVENT: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, SNAPTYPSEL, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); + break; + + /* PTP v2/802.AS1, any layer, Sync packet */ + case HWTSTAMP_FILTER_PTP_V2_SYNC: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); + break; + + /* PTP v2/802.AS1, any layer, Delay_req packet */ + case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSVER2ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV4ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSIPV6ENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSMSTRENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSEVNTENA, 1); + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); + break; + + default: + return -ERANGE; + } + + xgbe_config_tstamp(pdata, mac_tscr); + + memcpy(&pdata->tstamp_config, &config, sizeof(config)); + + return 0; +} + +void xgbe_prep_tx_tstamp(struct xgbe_prv_data *pdata, + struct sk_buff *skb, + struct xgbe_packet_data *packet) +{ + unsigned long flags; + + if (XGMAC_GET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES, PTP)) { + spin_lock_irqsave(&pdata->tstamp_lock, flags); + if (pdata->tx_tstamp_skb) { + /* Another timestamp in progress, ignore this one */ + XGMAC_SET_BITS(packet->attributes, + TX_PACKET_ATTRIBUTES, PTP, 0); + } else { + pdata->tx_tstamp_skb = skb_get(skb); + skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; + } + spin_unlock_irqrestore(&pdata->tstamp_lock, flags); + } + + skb_tx_timestamp(skb); +} + +int xgbe_init_ptp(struct xgbe_prv_data *pdata) +{ + unsigned int mac_tscr = 0; + struct timespec64 now; + u64 dividend; + + /* Register Settings to be done based on the link speed. */ + switch (pdata->phy.speed) { + case SPEED_1000: + XGMAC_IOWRITE(pdata, MAC_TICNR, MAC_TICNR_1G_INITVAL); + XGMAC_IOWRITE(pdata, MAC_TECNR, MAC_TECNR_1G_INITVAL); + break; + case SPEED_2500: + case SPEED_10000: + XGMAC_IOWRITE_BITS(pdata, MAC_TICSNR, TSICSNS, + MAC_TICSNR_10G_INITVAL); + XGMAC_IOWRITE(pdata, MAC_TECNR, MAC_TECNR_10G_INITVAL); + XGMAC_IOWRITE_BITS(pdata, MAC_TECSNR, TSECSNS, + MAC_TECSNR_10G_INITVAL); + break; + case SPEED_UNKNOWN: + default: + break; + } + + /* Enable IEEE1588 PTP clock. */ + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSENA, 1); + + /* Overwrite earlier timestamps */ + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TXTSSTSM, 1); + + /* Set one nano-second accuracy */ + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCTRLSSR, 1); + + /* Set fine timestamp update */ + XGMAC_SET_BITS(mac_tscr, MAC_TSCR, TSCFUPDT, 1); + + xgbe_config_tstamp(pdata, mac_tscr); + + /* Exit if timestamping is not enabled */ + if (!XGMAC_GET_BITS(mac_tscr, MAC_TSCR, TSENA)) + return -EOPNOTSUPP; + + if (pdata->vdata->tstamp_ptp_clock_freq) { + /* Initialize time registers based on + * 125MHz PTP Clock Frequency + */ + XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, + XGBE_V2_TSTAMP_SSINC); + XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, + XGBE_V2_TSTAMP_SNSINC); + } else { + /* Initialize time registers based on + * 50MHz PTP Clock Frequency + */ + XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SSINC, XGBE_TSTAMP_SSINC); + XGMAC_IOWRITE_BITS(pdata, MAC_SSIR, SNSINC, XGBE_TSTAMP_SNSINC); + } + + /* Calculate the addend: + * addend = 2^32 / (PTP ref clock / (PTP clock based on SSINC)) + * = (2^32 * (PTP clock based on SSINC)) / PTP ref clock + */ + if (pdata->vdata->tstamp_ptp_clock_freq) + dividend = XGBE_V2_PTP_ACT_CLK_FREQ; + else + dividend = XGBE_PTP_ACT_CLK_FREQ; + + dividend = (u64)(dividend << 32); + pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate); + + xgbe_update_tstamp_addend(pdata, pdata->tstamp_addend); + + dma_wmb(); + /* initialize system time */ + ktime_get_real_ts64(&now); + + /* lower 32 bits of tv_sec are safe until y2106 */ + xgbe_set_tstamp_time(pdata, (u32)now.tv_sec, now.tv_nsec); + + return 0; +} diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c index 4ebdd123c435..d1f0419edb23 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c @@ -275,7 +275,7 @@ int xgbe_config_netdev(struct xgbe_prv_data *pdata) netdev->priv_flags |= IFF_UNICAST_FLT; netdev->min_mtu = 0; - netdev->max_mtu = XGMAC_JUMBO_PACKET_MTU; + netdev->max_mtu = XGMAC_GIANT_PACKET_MTU - XGBE_ETH_FRAME_HDR; /* Use default watchdog timeout */ netdev->watchdog_timeo = 0; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index 71449edbb76d..1a37ec45e650 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c @@ -266,6 +266,10 @@ static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable, reg |= MDIO_VEND2_CTRL1_AN_RESTART; XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg); + + reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL); + reg |= XGBE_VEND2_MAC_AUTO_SW; + XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_PCS_DIG_CTRL, reg); } static void xgbe_an37_restart(struct xgbe_prv_data *pdata) @@ -894,6 +898,11 @@ static void xgbe_an37_init(struct xgbe_prv_data *pdata) netif_dbg(pdata, link, pdata->netdev, "CL37 AN (%s) initialized\n", (pdata->an_mode == XGBE_AN_MODE_CL37) ? "BaseX" : "SGMII"); + + reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_CTRL1); + reg &= ~MDIO_AN_CTRL1_ENABLE; + XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_CTRL1, reg); + } static void xgbe_an73_init(struct xgbe_prv_data *pdata) @@ -1295,6 +1304,10 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata) pdata->phy.link = pdata->phy_if.phy_impl.link_status(pdata, &an_restart); + /* bail out if the link status register read fails */ + if (pdata->phy.link < 0) + return; + if (an_restart) { xgbe_phy_config_aneg(pdata); goto adjust_link; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c index 097ec5e4f261..e3e1dca9856a 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-pci.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-pci.c @@ -414,6 +414,7 @@ static struct xgbe_version_data xgbe_v2a = { .tx_max_fifo_size = 229376, .rx_max_fifo_size = 229376, .tx_tstamp_workaround = 1, + .tstamp_ptp_clock_freq = 1, .ecc_support = 1, .i2c_support = 1, .irq_reissue_support = 1, @@ -430,6 +431,7 @@ static struct xgbe_version_data xgbe_v2b = { .tx_max_fifo_size = 65536, .rx_max_fifo_size = 65536, .tx_tstamp_workaround = 1, + .tstamp_ptp_clock_freq = 1, .ecc_support = 1, .i2c_support = 1, .irq_reissue_support = 1, diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 7a4dfa4e19c7..23c39e92e783 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -2746,8 +2746,7 @@ static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed) static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart) { struct xgbe_phy_data *phy_data = pdata->phy_data; - unsigned int reg; - int ret; + int reg, ret; *an_restart = 0; @@ -2781,11 +2780,20 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart) return 0; } - /* Link status is latched low, so read once to clear - * and then read again to get current state - */ - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); + if (reg < 0) + return reg; + + /* Link status is latched low so that momentary link drops + * can be detected. If link was already down read again + * to get the latest state. + */ + + if (!pdata->phy.link && !(reg & MDIO_STAT1_LSTATUS)) { + reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); + if (reg < 0) + return reg; + } if (pdata->en_rx_adap) { /* if the link is available and adaptation is done, @@ -2804,9 +2812,7 @@ static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart) xgbe_phy_set_mode(pdata, phy_data->cur_mode); } - /* check again for the link and adaptation status */ - reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1); - if ((reg & MDIO_STAT1_LSTATUS) && pdata->rx_adapt_done) + if (pdata->rx_adapt_done) return 1; } else if (reg & MDIO_STAT1_LSTATUS) return 1; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c index 978c4dd01fa0..3658afc7801d 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-ptp.c @@ -13,18 +13,6 @@ #include "xgbe.h" #include "xgbe-common.h" -static u64 xgbe_cc_read(const struct cyclecounter *cc) -{ - struct xgbe_prv_data *pdata = container_of(cc, - struct xgbe_prv_data, - tstamp_cc); - u64 nsec; - - nsec = pdata->hw_if.get_tstamp_time(pdata); - - return nsec; -} - static int xgbe_adjfine(struct ptp_clock_info *info, long scaled_ppm) { struct xgbe_prv_data *pdata = container_of(info, @@ -37,7 +25,7 @@ static int xgbe_adjfine(struct ptp_clock_info *info, long scaled_ppm) spin_lock_irqsave(&pdata->tstamp_lock, flags); - pdata->hw_if.update_tstamp_addend(pdata, addend); + xgbe_update_tstamp_addend(pdata, addend); spin_unlock_irqrestore(&pdata->tstamp_lock, flags); @@ -49,16 +37,39 @@ static int xgbe_adjtime(struct ptp_clock_info *info, s64 delta) struct xgbe_prv_data *pdata = container_of(info, struct xgbe_prv_data, ptp_clock_info); + unsigned int neg_adjust = 0; + unsigned int sec, nsec; + u32 quotient, reminder; unsigned long flags; + if (delta < 0) { + neg_adjust = 1; + delta = -delta; + } + + quotient = div_u64_rem(delta, 1000000000ULL, &reminder); + sec = quotient; + nsec = reminder; + + /* Negative adjustment for Hw timer register. */ + if (neg_adjust) { + sec = -sec; + if (XGMAC_IOREAD_BITS(pdata, MAC_TSCR, TSCTRLSSR)) + nsec = (1000000000UL - nsec); + else + nsec = (0x80000000UL - nsec); + } + nsec = (neg_adjust << 31) | nsec; + spin_lock_irqsave(&pdata->tstamp_lock, flags); - timecounter_adjtime(&pdata->tstamp_tc, delta); + xgbe_update_tstamp_time(pdata, sec, nsec); spin_unlock_irqrestore(&pdata->tstamp_lock, flags); return 0; } -static int xgbe_gettime(struct ptp_clock_info *info, struct timespec64 *ts) +static int xgbe_gettimex(struct ptp_clock_info *info, struct timespec64 *ts, + struct ptp_system_timestamp *sts) { struct xgbe_prv_data *pdata = container_of(info, struct xgbe_prv_data, @@ -67,9 +78,9 @@ static int xgbe_gettime(struct ptp_clock_info *info, struct timespec64 *ts) u64 nsec; spin_lock_irqsave(&pdata->tstamp_lock, flags); - - nsec = timecounter_read(&pdata->tstamp_tc); - + ptp_read_system_prets(sts); + nsec = xgbe_get_tstamp_time(pdata); + ptp_read_system_postts(sts); spin_unlock_irqrestore(&pdata->tstamp_lock, flags); *ts = ns_to_timespec64(nsec); @@ -84,14 +95,9 @@ static int xgbe_settime(struct ptp_clock_info *info, struct xgbe_prv_data, ptp_clock_info); unsigned long flags; - u64 nsec; - - nsec = timespec64_to_ns(ts); spin_lock_irqsave(&pdata->tstamp_lock, flags); - - timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec); - + xgbe_set_tstamp_time(pdata, ts->tv_sec, ts->tv_nsec); spin_unlock_irqrestore(&pdata->tstamp_lock, flags); return 0; @@ -107,8 +113,6 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata) { struct ptp_clock_info *info = &pdata->ptp_clock_info; struct ptp_clock *clock; - struct cyclecounter *cc = &pdata->tstamp_cc; - u64 dividend; snprintf(info->name, sizeof(info->name), "%s", netdev_name(pdata->netdev)); @@ -116,7 +120,7 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata) info->max_adj = pdata->ptpclk_rate; info->adjfine = xgbe_adjfine; info->adjtime = xgbe_adjtime; - info->gettime64 = xgbe_gettime; + info->gettimex64 = xgbe_gettimex; info->settime64 = xgbe_settime; info->enable = xgbe_enable; @@ -128,23 +132,6 @@ void xgbe_ptp_register(struct xgbe_prv_data *pdata) pdata->ptp_clock = clock; - /* Calculate the addend: - * addend = 2^32 / (PTP ref clock / 50Mhz) - * = (2^32 * 50Mhz) / PTP ref clock - */ - dividend = 50000000; - dividend <<= 32; - pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate); - - /* Setup the timecounter */ - cc->read = xgbe_cc_read; - cc->mask = CLOCKSOURCE_MASK(64); - cc->mult = 1; - cc->shift = 0; - - timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, - ktime_to_ns(ktime_get_real())); - /* Disable all timestamping to start */ XGMAC_IOWRITE(pdata, MAC_TSCR, 0); pdata->tstamp_config.tx_type = HWTSTAMP_TX_OFF; diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index 6359bb87dc13..d7e03e292ec4 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -80,11 +80,13 @@ #define XGBE_IRQ_MODE_EDGE 0 #define XGBE_IRQ_MODE_LEVEL 1 +#define XGBE_ETH_FRAME_HDR (ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN) #define XGMAC_MIN_PACKET 60 #define XGMAC_STD_PACKET_MTU 1500 #define XGMAC_MAX_STD_PACKET 1518 #define XGMAC_JUMBO_PACKET_MTU 9000 #define XGMAC_MAX_JUMBO_PACKET 9018 +#define XGMAC_GIANT_PACKET_MTU 16368 #define XGMAC_ETH_PREAMBLE (12 + 8) /* Inter-frame gap + preamble */ #define XGMAC_PFC_DATA_LEN 46 @@ -117,6 +119,14 @@ #define XGBE_MSI_BASE_COUNT 4 #define XGBE_MSI_MIN_COUNT (XGBE_MSI_BASE_COUNT + 1) +/* Initial PTP register values based on Link Speed. */ +#define MAC_TICNR_1G_INITVAL 0x10 +#define MAC_TECNR_1G_INITVAL 0x28 + +#define MAC_TICSNR_10G_INITVAL 0x33 +#define MAC_TECNR_10G_INITVAL 0x14 +#define MAC_TECSNR_10G_INITVAL 0xCC + /* PCI clock frequencies */ #define XGBE_V2_DMA_CLOCK_FREQ 500000000 /* 500 MHz */ #define XGBE_V2_PTP_CLOCK_FREQ 125000000 /* 125 MHz */ @@ -126,6 +136,11 @@ */ #define XGBE_TSTAMP_SSINC 20 #define XGBE_TSTAMP_SNSINC 0 +#define XGBE_PTP_ACT_CLK_FREQ 500000000 + +#define XGBE_V2_TSTAMP_SSINC 0xA +#define XGBE_V2_TSTAMP_SNSINC 0 +#define XGBE_V2_PTP_ACT_CLK_FREQ 1000000000 /* Driver PMT macros */ #define XGMAC_DRIVER_CONTEXT 1 @@ -183,12 +198,12 @@ #define XGBE_LINK_TIMEOUT 5 #define XGBE_KR_TRAINING_WAIT_ITER 50 -#define XGBE_SGMII_AN_LINK_STATUS BIT(1) +#define XGBE_SGMII_AN_LINK_DUPLEX BIT(1) #define XGBE_SGMII_AN_LINK_SPEED (BIT(2) | BIT(3)) #define XGBE_SGMII_AN_LINK_SPEED_10 0x00 #define XGBE_SGMII_AN_LINK_SPEED_100 0x04 #define XGBE_SGMII_AN_LINK_SPEED_1000 0x08 -#define XGBE_SGMII_AN_LINK_DUPLEX BIT(4) +#define XGBE_SGMII_AN_LINK_STATUS BIT(4) /* ECC correctable error notification window (seconds) */ #define XGBE_ECC_LIMIT 60 @@ -739,14 +754,6 @@ struct xgbe_hw_if { void (*tx_mmc_int)(struct xgbe_prv_data *); void (*read_mmc_stats)(struct xgbe_prv_data *); - /* For Timestamp config */ - int (*config_tstamp)(struct xgbe_prv_data *, unsigned int); - void (*update_tstamp_addend)(struct xgbe_prv_data *, unsigned int); - void (*set_tstamp_time)(struct xgbe_prv_data *, unsigned int sec, - unsigned int nsec); - u64 (*get_tstamp_time)(struct xgbe_prv_data *); - u64 (*get_tx_tstamp)(struct xgbe_prv_data *); - /* For Data Center Bridging config */ void (*config_tc)(struct xgbe_prv_data *); void (*config_dcb_tc)(struct xgbe_prv_data *); @@ -944,6 +951,7 @@ struct xgbe_version_data { unsigned int tx_max_fifo_size; unsigned int rx_max_fifo_size; unsigned int tx_tstamp_workaround; + unsigned int tstamp_ptp_clock_freq; unsigned int ecc_support; unsigned int i2c_support; unsigned int irq_reissue_support; @@ -1129,8 +1137,6 @@ struct xgbe_prv_data { struct ptp_clock_info ptp_clock_info; struct ptp_clock *ptp_clock; struct hwtstamp_config tstamp_config; - struct cyclecounter tstamp_cc; - struct timecounter tstamp_tc; unsigned int tstamp_addend; struct work_struct tx_tstamp_work; struct sk_buff *tx_tstamp_skb; @@ -1275,6 +1281,29 @@ void xgbe_init_tx_coalesce(struct xgbe_prv_data *); void xgbe_restart_dev(struct xgbe_prv_data *pdata); void xgbe_full_restart_dev(struct xgbe_prv_data *pdata); +/* For Timestamp config */ +void xgbe_config_tstamp(struct xgbe_prv_data *pdata, unsigned int mac_tscr); +u64 xgbe_get_tstamp_time(struct xgbe_prv_data *pdata); +u64 xgbe_get_tx_tstamp(struct xgbe_prv_data *pdata); +void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet, + struct xgbe_ring_desc *rdesc); +void xgbe_get_rx_tstamp(struct xgbe_packet_data *packet, + struct xgbe_ring_desc *rdesc); +void xgbe_update_tstamp_addend(struct xgbe_prv_data *pdata, + unsigned int addend); +void xgbe_set_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec, + unsigned int nsec); +void xgbe_tx_tstamp(struct work_struct *work); +int xgbe_get_hwtstamp_settings(struct xgbe_prv_data *pdata, + struct ifreq *ifreq); +int xgbe_set_hwtstamp_settings(struct xgbe_prv_data *pdata, + struct ifreq *ifreq); +void xgbe_prep_tx_tstamp(struct xgbe_prv_data *pdata, + struct sk_buff *skb, + struct xgbe_packet_data *packet); +int xgbe_init_ptp(struct xgbe_prv_data *pdata); +void xgbe_update_tstamp_time(struct xgbe_prv_data *pdata, unsigned int sec, + unsigned int nsec); #ifdef CONFIG_DEBUG_FS void xgbe_debugfs_init(struct xgbe_prv_data *); void xgbe_debugfs_exit(struct xgbe_prv_data *); |