static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) { struct bfin_mac_local *lp = netdev_priv(netdev); u32 valid; u64 regval, ns; struct skb_shared_hwtstamps *shhwtstamps; if (bfin_mac_hwtstamp_is_none(lp->stamp_cfg.rx_filter)) return; valid = bfin_read_EMAC_PTP_ISTAT() & RXEL; if (!valid) return; shhwtstamps = skb_hwtstamps(skb); regval = bfin_read_EMAC_PTP_RXSNAPLO(); regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32; ns = timecounter_cyc2time(&lp->clock, regval); timecompare_update(&lp->compare, ns); memset(shhwtstamps, 0, sizeof(*shhwtstamps)); shhwtstamps->hwtstamp = ns_to_ktime(ns); shhwtstamps->syststamp = timecompare_transform(&lp->compare, ns); bfin_dump_hwtamp("RX", &shhwtstamps->hwtstamp, &shhwtstamps->syststamp, &lp->compare); }
static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) { struct bfin_mac_local *lp = netdev_priv(netdev); if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) { int timeout_cnt = MAX_TIMEOUT_CNT; skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; while ((!(bfin_read_EMAC_PTP_ISTAT() & TXTL)) && (--timeout_cnt)) udelay(1); if (timeout_cnt == 0) netdev_err(netdev, "timestamp the TX packet failed\n"); else { struct skb_shared_hwtstamps shhwtstamps; u64 ns; u64 regval; regval = bfin_read_EMAC_PTP_TXSNAPLO(); regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32; memset(&shhwtstamps, 0, sizeof(shhwtstamps)); ns = timecounter_cyc2time(&lp->clock, regval); timecompare_update(&lp->compare, ns); shhwtstamps.hwtstamp = ns_to_ktime(ns); shhwtstamps.syststamp = timecompare_transform(&lp->compare, ns); skb_tstamp_tx(skb, &shhwtstamps); bfin_dump_hwtamp("TX", &shhwtstamps.hwtstamp, &shhwtstamps.syststamp, &lp->compare); } } }
static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) { struct bfin_mac_local *lp = netdev_priv(netdev); union skb_shared_tx *shtx = skb_tx(skb); if (shtx->hardware) { int timeout_cnt = MAX_TIMEOUT_CNT; /* When doing time stamping, keep the connection to the socket * a while longer */ shtx->in_progress = 1; /* * The timestamping is done at the EMAC module's MII/RMII interface * when the module sees the Start of Frame of an event message packet. This * interface is the closest possible place to the physical Ethernet transmission * medium, providing the best timing accuracy. */ while ((!(bfin_read_EMAC_PTP_ISTAT() & TXTL)) && (--timeout_cnt)) udelay(1); if (timeout_cnt == 0) printk(KERN_ERR DRV_NAME ": fails to timestamp the TX packet\n"); else { struct skb_shared_hwtstamps shhwtstamps; u64 ns; u64 regval; regval = bfin_read_EMAC_PTP_TXSNAPLO(); regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32; memset(&shhwtstamps, 0, sizeof(shhwtstamps)); ns = timecounter_cyc2time(&lp->clock, regval); timecompare_update(&lp->compare, ns); shhwtstamps.hwtstamp = ns_to_ktime(ns); shhwtstamps.syststamp = timecompare_transform(&lp->compare, ns); skb_tstamp_tx(skb, &shhwtstamps); bfin_dump_hwtamp("TX", &shhwtstamps.hwtstamp, &shhwtstamps.syststamp, &lp->compare); } } }
static void bfin_rx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) { struct bfin_mac_local *lp = netdev_priv(netdev); u32 valid; u64 regval, ns; struct skb_shared_hwtstamps *shhwtstamps; if (bfin_mac_hwtstamp_is_none(lp->stamp_cfg.rx_filter)) return; valid = bfin_read_EMAC_PTP_ISTAT() & RXEL; if (!valid) return; shhwtstamps = skb_hwtstamps(skb); regval = bfin_read_EMAC_PTP_RXSNAPLO(); regval |= (u64)bfin_read_EMAC_PTP_RXSNAPHI() << 32; ns = regval << lp->shift; memset(shhwtstamps, 0, sizeof(*shhwtstamps)); shhwtstamps->hwtstamp = ns_to_ktime(ns); }
static void bfin_tx_hwtstamp(struct net_device *netdev, struct sk_buff *skb) { struct bfin_mac_local *lp = netdev_priv(netdev); if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) { int timeout_cnt = MAX_TIMEOUT_CNT; /* When doing time stamping, keep the connection to the socket * a while longer */ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; /* * The timestamping is done at the EMAC module's MII/RMII interface * when the module sees the Start of Frame of an event message packet. This * interface is the closest possible place to the physical Ethernet transmission * medium, providing the best timing accuracy. */ while ((!(bfin_read_EMAC_PTP_ISTAT() & TXTL)) && (--timeout_cnt)) udelay(1); if (timeout_cnt == 0) netdev_err(netdev, "timestamp the TX packet failed\n"); else { struct skb_shared_hwtstamps shhwtstamps; u64 ns; u64 regval; regval = bfin_read_EMAC_PTP_TXSNAPLO(); regval |= (u64)bfin_read_EMAC_PTP_TXSNAPHI() << 32; memset(&shhwtstamps, 0, sizeof(shhwtstamps)); ns = regval << lp->shift; shhwtstamps.hwtstamp = ns_to_ktime(ns); skb_tstamp_tx(skb, &shhwtstamps); } } }