diff options
-rw-r--r-- | arch/tile/gxio/iorpc_mpipe.c | 19 | ||||
-rw-r--r-- | arch/tile/include/gxio/iorpc_mpipe.h | 10 | ||||
-rw-r--r-- | arch/tile/include/gxio/mpipe.h | 14 | ||||
-rw-r--r-- | drivers/net/ethernet/tile/Kconfig | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/tile/tilegx.c | 216 |
5 files changed, 266 insertions, 4 deletions
diff --git a/arch/tile/gxio/iorpc_mpipe.c b/arch/tile/gxio/iorpc_mpipe.c index c2fb15167aee..4f8f3d619c4a 100644 --- a/arch/tile/gxio/iorpc_mpipe.c +++ b/arch/tile/gxio/iorpc_mpipe.c | |||
@@ -475,6 +475,25 @@ int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context, | |||
475 | 475 | ||
476 | EXPORT_SYMBOL(gxio_mpipe_adjust_timestamp_aux); | 476 | EXPORT_SYMBOL(gxio_mpipe_adjust_timestamp_aux); |
477 | 477 | ||
478 | struct adjust_timestamp_freq_param { | ||
479 | int32_t ppb; | ||
480 | }; | ||
481 | |||
482 | int gxio_mpipe_adjust_timestamp_freq(gxio_mpipe_context_t * context, | ||
483 | int32_t ppb) | ||
484 | { | ||
485 | struct adjust_timestamp_freq_param temp; | ||
486 | struct adjust_timestamp_freq_param *params = &temp; | ||
487 | |||
488 | params->ppb = ppb; | ||
489 | |||
490 | return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, | ||
491 | sizeof(*params), | ||
492 | GXIO_MPIPE_OP_ADJUST_TIMESTAMP_FREQ); | ||
493 | } | ||
494 | |||
495 | EXPORT_SYMBOL(gxio_mpipe_adjust_timestamp_freq); | ||
496 | |||
478 | struct config_edma_ring_blks_param { | 497 | struct config_edma_ring_blks_param { |
479 | unsigned int ering; | 498 | unsigned int ering; |
480 | unsigned int max_blks; | 499 | unsigned int max_blks; |
diff --git a/arch/tile/include/gxio/iorpc_mpipe.h b/arch/tile/include/gxio/iorpc_mpipe.h index eef60fdd8525..fdd07f88cfd7 100644 --- a/arch/tile/include/gxio/iorpc_mpipe.h +++ b/arch/tile/include/gxio/iorpc_mpipe.h | |||
@@ -46,10 +46,11 @@ | |||
46 | #define GXIO_MPIPE_OP_LINK_CLOSE_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1212) | 46 | #define GXIO_MPIPE_OP_LINK_CLOSE_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1212) |
47 | #define GXIO_MPIPE_OP_LINK_SET_ATTR_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1213) | 47 | #define GXIO_MPIPE_OP_LINK_SET_ATTR_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1213) |
48 | 48 | ||
49 | #define GXIO_MPIPE_OP_GET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x121e) | 49 | #define GXIO_MPIPE_OP_GET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x121e) |
50 | #define GXIO_MPIPE_OP_SET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x121f) | 50 | #define GXIO_MPIPE_OP_SET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x121f) |
51 | #define GXIO_MPIPE_OP_ADJUST_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1220) | 51 | #define GXIO_MPIPE_OP_ADJUST_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1220) |
52 | #define GXIO_MPIPE_OP_CONFIG_EDMA_RING_BLKS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1221) | 52 | #define GXIO_MPIPE_OP_CONFIG_EDMA_RING_BLKS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1221) |
53 | #define GXIO_MPIPE_OP_ADJUST_TIMESTAMP_FREQ IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1222) | ||
53 | #define GXIO_MPIPE_OP_ARM_POLLFD IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9000) | 54 | #define GXIO_MPIPE_OP_ARM_POLLFD IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9000) |
54 | #define GXIO_MPIPE_OP_CLOSE_POLLFD IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9001) | 55 | #define GXIO_MPIPE_OP_CLOSE_POLLFD IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9001) |
55 | #define GXIO_MPIPE_OP_GET_MMIO_BASE IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000) | 56 | #define GXIO_MPIPE_OP_GET_MMIO_BASE IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000) |
@@ -128,6 +129,9 @@ int gxio_mpipe_set_timestamp_aux(gxio_mpipe_context_t * context, uint64_t sec, | |||
128 | int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context, | 129 | int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context, |
129 | int64_t nsec); | 130 | int64_t nsec); |
130 | 131 | ||
132 | int gxio_mpipe_adjust_timestamp_freq(gxio_mpipe_context_t * context, | ||
133 | int32_t ppb); | ||
134 | |||
131 | int gxio_mpipe_arm_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie); | 135 | int gxio_mpipe_arm_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie); |
132 | 136 | ||
133 | int gxio_mpipe_close_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie); | 137 | int gxio_mpipe_close_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie); |
diff --git a/arch/tile/include/gxio/mpipe.h b/arch/tile/include/gxio/mpipe.h index eb7fee41c9b6..e37cf4f0cffd 100644 --- a/arch/tile/include/gxio/mpipe.h +++ b/arch/tile/include/gxio/mpipe.h | |||
@@ -1854,4 +1854,18 @@ extern int gxio_mpipe_set_timestamp(gxio_mpipe_context_t *context, | |||
1854 | extern int gxio_mpipe_adjust_timestamp(gxio_mpipe_context_t *context, | 1854 | extern int gxio_mpipe_adjust_timestamp(gxio_mpipe_context_t *context, |
1855 | int64_t delta); | 1855 | int64_t delta); |
1856 | 1856 | ||
1857 | /** Adjust the mPIPE timestamp clock frequency. | ||
1858 | * | ||
1859 | * @param context An initialized mPIPE context. | ||
1860 | * @param ppb A 32-bit signed PPB (Parts Per Billion) value to adjust. | ||
1861 | * The absolute value of ppb must be less than or equal to 1000000000. | ||
1862 | * Values less than about 30000 will generally cause a GXIO_ERR_INVAL | ||
1863 | * return due to the granularity of the hardware that converts reference | ||
1864 | * clock cycles into seconds and nanoseconds. | ||
1865 | * @return If the call was successful, zero; otherwise, a negative error | ||
1866 | * code. | ||
1867 | */ | ||
1868 | extern int gxio_mpipe_adjust_timestamp_freq(gxio_mpipe_context_t* context, | ||
1869 | int32_t ppb); | ||
1870 | |||
1857 | #endif /* !_GXIO_MPIPE_H_ */ | 1871 | #endif /* !_GXIO_MPIPE_H_ */ |
diff --git a/drivers/net/ethernet/tile/Kconfig b/drivers/net/ethernet/tile/Kconfig index 098b1c42b393..4083ba8839e1 100644 --- a/drivers/net/ethernet/tile/Kconfig +++ b/drivers/net/ethernet/tile/Kconfig | |||
@@ -15,3 +15,14 @@ config TILE_NET | |||
15 | 15 | ||
16 | To compile this driver as a module, choose M here: the module | 16 | To compile this driver as a module, choose M here: the module |
17 | will be called tile_net. | 17 | will be called tile_net. |
18 | |||
19 | config PTP_1588_CLOCK_TILEGX | ||
20 | tristate "Tilera TILE-Gx mPIPE as PTP clock" | ||
21 | select PTP_1588_CLOCK | ||
22 | depends on TILE_NET | ||
23 | depends on TILEGX | ||
24 | ---help--- | ||
25 | This driver adds support for using the mPIPE as a PTP | ||
26 | clock. This clock is only useful if your PTP programs are | ||
27 | getting hardware time stamps on the PTP Ethernet packets | ||
28 | using the SO_TIMESTAMPING API. | ||
diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 0beed7e31f9e..907b5772fd55 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c | |||
@@ -38,6 +38,8 @@ | |||
38 | #include <linux/ip.h> | 38 | #include <linux/ip.h> |
39 | #include <linux/ipv6.h> | 39 | #include <linux/ipv6.h> |
40 | #include <linux/tcp.h> | 40 | #include <linux/tcp.h> |
41 | #include <linux/net_tstamp.h> | ||
42 | #include <linux/ptp_clock_kernel.h> | ||
41 | 43 | ||
42 | #include <asm/checksum.h> | 44 | #include <asm/checksum.h> |
43 | #include <asm/homecache.h> | 45 | #include <asm/homecache.h> |
@@ -185,6 +187,10 @@ struct tile_net_priv { | |||
185 | int echannel; | 187 | int echannel; |
186 | /* mPIPE instance, 0 or 1. */ | 188 | /* mPIPE instance, 0 or 1. */ |
187 | int instance; | 189 | int instance; |
190 | #ifdef CONFIG_PTP_1588_CLOCK_TILEGX | ||
191 | /* The timestamp config. */ | ||
192 | struct hwtstamp_config stamp_cfg; | ||
193 | #endif | ||
188 | }; | 194 | }; |
189 | 195 | ||
190 | static struct mpipe_data { | 196 | static struct mpipe_data { |
@@ -223,6 +229,15 @@ static struct mpipe_data { | |||
223 | int first_bucket; | 229 | int first_bucket; |
224 | int num_buckets; | 230 | int num_buckets; |
225 | 231 | ||
232 | #ifdef CONFIG_PTP_1588_CLOCK_TILEGX | ||
233 | /* PTP-specific data. */ | ||
234 | struct ptp_clock *ptp_clock; | ||
235 | struct ptp_clock_info caps; | ||
236 | |||
237 | /* Lock for ptp accessors. */ | ||
238 | struct mutex ptp_lock; | ||
239 | #endif | ||
240 | |||
226 | } mpipe_data[NR_MPIPE_MAX] = { | 241 | } mpipe_data[NR_MPIPE_MAX] = { |
227 | [0 ... (NR_MPIPE_MAX - 1)] { | 242 | [0 ... (NR_MPIPE_MAX - 1)] { |
228 | .ingress_irq = -1, | 243 | .ingress_irq = -1, |
@@ -432,6 +447,94 @@ static void tile_net_provide_needed_buffers(void) | |||
432 | } | 447 | } |
433 | } | 448 | } |
434 | 449 | ||
450 | /* Get RX timestamp, and store it in the skb. */ | ||
451 | static void tile_rx_timestamp(struct tile_net_priv *priv, struct sk_buff *skb, | ||
452 | gxio_mpipe_idesc_t *idesc) | ||
453 | { | ||
454 | #ifdef CONFIG_PTP_1588_CLOCK_TILEGX | ||
455 | if (unlikely(priv->stamp_cfg.rx_filter != HWTSTAMP_FILTER_NONE)) { | ||
456 | struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); | ||
457 | memset(shhwtstamps, 0, sizeof(*shhwtstamps)); | ||
458 | shhwtstamps->hwtstamp = ktime_set(idesc->time_stamp_sec, | ||
459 | idesc->time_stamp_ns); | ||
460 | } | ||
461 | #endif | ||
462 | } | ||
463 | |||
464 | /* Get TX timestamp, and store it in the skb. */ | ||
465 | static void tile_tx_timestamp(struct sk_buff *skb, int instance) | ||
466 | { | ||
467 | #ifdef CONFIG_PTP_1588_CLOCK_TILEGX | ||
468 | struct skb_shared_info *shtx = skb_shinfo(skb); | ||
469 | if (unlikely((shtx->tx_flags & SKBTX_HW_TSTAMP) != 0)) { | ||
470 | struct mpipe_data *md = &mpipe_data[instance]; | ||
471 | struct skb_shared_hwtstamps shhwtstamps; | ||
472 | struct timespec ts; | ||
473 | |||
474 | shtx->tx_flags |= SKBTX_IN_PROGRESS; | ||
475 | gxio_mpipe_get_timestamp(&md->context, &ts); | ||
476 | memset(&shhwtstamps, 0, sizeof(shhwtstamps)); | ||
477 | shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec); | ||
478 | skb_tstamp_tx(skb, &shhwtstamps); | ||
479 | } | ||
480 | #endif | ||
481 | } | ||
482 | |||
483 | /* Use ioctl() to enable or disable TX or RX timestamping. */ | ||
484 | static int tile_hwtstamp_ioctl(struct net_device *dev, struct ifreq *rq, | ||
485 | int cmd) | ||
486 | { | ||
487 | #ifdef CONFIG_PTP_1588_CLOCK_TILEGX | ||
488 | struct hwtstamp_config config; | ||
489 | struct tile_net_priv *priv = netdev_priv(dev); | ||
490 | |||
491 | if (copy_from_user(&config, rq->ifr_data, sizeof(config))) | ||
492 | return -EFAULT; | ||
493 | |||
494 | if (config.flags) /* reserved for future extensions */ | ||
495 | return -EINVAL; | ||
496 | |||
497 | switch (config.tx_type) { | ||
498 | case HWTSTAMP_TX_OFF: | ||
499 | case HWTSTAMP_TX_ON: | ||
500 | break; | ||
501 | default: | ||
502 | return -ERANGE; | ||
503 | } | ||
504 | |||
505 | switch (config.rx_filter) { | ||
506 | case HWTSTAMP_FILTER_NONE: | ||
507 | break; | ||
508 | case HWTSTAMP_FILTER_ALL: | ||
509 | case HWTSTAMP_FILTER_SOME: | ||
510 | case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: | ||
511 | case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: | ||
512 | case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: | ||
513 | case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: | ||
514 | case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: | ||
515 | case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: | ||
516 | case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: | ||
517 | case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: | ||
518 | case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: | ||
519 | case HWTSTAMP_FILTER_PTP_V2_EVENT: | ||
520 | case HWTSTAMP_FILTER_PTP_V2_SYNC: | ||
521 | case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: | ||
522 | config.rx_filter = HWTSTAMP_FILTER_ALL; | ||
523 | break; | ||
524 | default: | ||
525 | return -ERANGE; | ||
526 | } | ||
527 | |||
528 | if (copy_to_user(rq->ifr_data, &config, sizeof(config))) | ||
529 | return -EFAULT; | ||
530 | |||
531 | priv->stamp_cfg = config; | ||
532 | return 0; | ||
533 | #else | ||
534 | return -EOPNOTSUPP; | ||
535 | #endif | ||
536 | } | ||
537 | |||
435 | static inline bool filter_packet(struct net_device *dev, void *buf) | 538 | static inline bool filter_packet(struct net_device *dev, void *buf) |
436 | { | 539 | { |
437 | /* Filter packets received before we're up. */ | 540 | /* Filter packets received before we're up. */ |
@@ -451,7 +554,8 @@ static void tile_net_receive_skb(struct net_device *dev, struct sk_buff *skb, | |||
451 | gxio_mpipe_idesc_t *idesc, unsigned long len) | 554 | gxio_mpipe_idesc_t *idesc, unsigned long len) |
452 | { | 555 | { |
453 | struct tile_net_info *info = &__get_cpu_var(per_cpu_info); | 556 | struct tile_net_info *info = &__get_cpu_var(per_cpu_info); |
454 | int instance = mpipe_instance(dev); | 557 | struct tile_net_priv *priv = netdev_priv(dev); |
558 | int instance = priv->instance; | ||
455 | 559 | ||
456 | /* Encode the actual packet length. */ | 560 | /* Encode the actual packet length. */ |
457 | skb_put(skb, len); | 561 | skb_put(skb, len); |
@@ -462,6 +566,9 @@ static void tile_net_receive_skb(struct net_device *dev, struct sk_buff *skb, | |||
462 | if (idesc->cs && idesc->csum_seed_val == 0xFFFF) | 566 | if (idesc->cs && idesc->csum_seed_val == 0xFFFF) |
463 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 567 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
464 | 568 | ||
569 | /* Get RX timestamp from idesc. */ | ||
570 | tile_rx_timestamp(priv, skb, idesc); | ||
571 | |||
465 | napi_gro_receive(&info->mpipe[instance].napi, skb); | 572 | napi_gro_receive(&info->mpipe[instance].napi, skb); |
466 | 573 | ||
467 | /* Update stats. */ | 574 | /* Update stats. */ |
@@ -707,6 +814,103 @@ static enum hrtimer_restart tile_net_handle_egress_timer(struct hrtimer *t) | |||
707 | return HRTIMER_NORESTART; | 814 | return HRTIMER_NORESTART; |
708 | } | 815 | } |
709 | 816 | ||
817 | #ifdef CONFIG_PTP_1588_CLOCK_TILEGX | ||
818 | |||
819 | /* PTP clock operations. */ | ||
820 | |||
821 | static int ptp_mpipe_adjfreq(struct ptp_clock_info *ptp, s32 ppb) | ||
822 | { | ||
823 | int ret = 0; | ||
824 | struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps); | ||
825 | mutex_lock(&md->ptp_lock); | ||
826 | if (gxio_mpipe_adjust_timestamp_freq(&md->context, ppb)) | ||
827 | ret = -EINVAL; | ||
828 | mutex_unlock(&md->ptp_lock); | ||
829 | return ret; | ||
830 | } | ||
831 | |||
832 | static int ptp_mpipe_adjtime(struct ptp_clock_info *ptp, s64 delta) | ||
833 | { | ||
834 | int ret = 0; | ||
835 | struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps); | ||
836 | mutex_lock(&md->ptp_lock); | ||
837 | if (gxio_mpipe_adjust_timestamp(&md->context, delta)) | ||
838 | ret = -EBUSY; | ||
839 | mutex_unlock(&md->ptp_lock); | ||
840 | return ret; | ||
841 | } | ||
842 | |||
843 | static int ptp_mpipe_gettime(struct ptp_clock_info *ptp, struct timespec *ts) | ||
844 | { | ||
845 | int ret = 0; | ||
846 | struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps); | ||
847 | mutex_lock(&md->ptp_lock); | ||
848 | if (gxio_mpipe_get_timestamp(&md->context, ts)) | ||
849 | ret = -EBUSY; | ||
850 | mutex_unlock(&md->ptp_lock); | ||
851 | return ret; | ||
852 | } | ||
853 | |||
854 | static int ptp_mpipe_settime(struct ptp_clock_info *ptp, | ||
855 | const struct timespec *ts) | ||
856 | { | ||
857 | int ret = 0; | ||
858 | struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps); | ||
859 | mutex_lock(&md->ptp_lock); | ||
860 | if (gxio_mpipe_set_timestamp(&md->context, ts)) | ||
861 | ret = -EBUSY; | ||
862 | mutex_unlock(&md->ptp_lock); | ||
863 | return ret; | ||
864 | } | ||
865 | |||
866 | static int ptp_mpipe_enable(struct ptp_clock_info *ptp, | ||
867 | struct ptp_clock_request *request, int on) | ||
868 | { | ||
869 | return -EOPNOTSUPP; | ||
870 | } | ||
871 | |||
872 | static struct ptp_clock_info ptp_mpipe_caps = { | ||
873 | .owner = THIS_MODULE, | ||
874 | .name = "mPIPE clock", | ||
875 | .max_adj = 999999999, | ||
876 | .n_ext_ts = 0, | ||
877 | .pps = 0, | ||
878 | .adjfreq = ptp_mpipe_adjfreq, | ||
879 | .adjtime = ptp_mpipe_adjtime, | ||
880 | .gettime = ptp_mpipe_gettime, | ||
881 | .settime = ptp_mpipe_settime, | ||
882 | .enable = ptp_mpipe_enable, | ||
883 | }; | ||
884 | |||
885 | #endif /* CONFIG_PTP_1588_CLOCK_TILEGX */ | ||
886 | |||
887 | /* Sync mPIPE's timestamp up with Linux system time and register PTP clock. */ | ||
888 | static void register_ptp_clock(struct net_device *dev, struct mpipe_data *md) | ||
889 | { | ||
890 | #ifdef CONFIG_PTP_1588_CLOCK_TILEGX | ||
891 | struct timespec ts; | ||
892 | |||
893 | getnstimeofday(&ts); | ||
894 | gxio_mpipe_set_timestamp(&md->context, &ts); | ||
895 | |||
896 | mutex_init(&md->ptp_lock); | ||
897 | md->caps = ptp_mpipe_caps; | ||
898 | md->ptp_clock = ptp_clock_register(&md->caps, NULL); | ||
899 | if (IS_ERR(md->ptp_clock)) | ||
900 | netdev_err(dev, "ptp_clock_register failed %ld\n", | ||
901 | PTR_ERR(md->ptp_clock)); | ||
902 | #endif | ||
903 | } | ||
904 | |||
905 | /* Initialize PTP fields in a new device. */ | ||
906 | static void init_ptp_dev(struct tile_net_priv *priv) | ||
907 | { | ||
908 | #ifdef CONFIG_PTP_1588_CLOCK_TILEGX | ||
909 | priv->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE; | ||
910 | priv->stamp_cfg.tx_type = HWTSTAMP_TX_OFF; | ||
911 | #endif | ||
912 | } | ||
913 | |||
710 | /* Helper functions for "tile_net_update()". */ | 914 | /* Helper functions for "tile_net_update()". */ |
711 | static void enable_ingress_irq(void *irq) | 915 | static void enable_ingress_irq(void *irq) |
712 | { | 916 | { |
@@ -1149,6 +1353,9 @@ static int tile_net_init_mpipe(struct net_device *dev) | |||
1149 | if (rc != 0) | 1353 | if (rc != 0) |
1150 | goto fail; | 1354 | goto fail; |
1151 | 1355 | ||
1356 | /* Register PTP clock and set mPIPE timestamp, if configured. */ | ||
1357 | register_ptp_clock(dev, md); | ||
1358 | |||
1152 | return 0; | 1359 | return 0; |
1153 | 1360 | ||
1154 | fail: | 1361 | fail: |
@@ -1851,6 +2058,9 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev) | |||
1851 | for (i = 0; i < num_edescs; i++) | 2058 | for (i = 0; i < num_edescs; i++) |
1852 | gxio_mpipe_equeue_put_at(equeue, edescs[i], slot++); | 2059 | gxio_mpipe_equeue_put_at(equeue, edescs[i], slot++); |
1853 | 2060 | ||
2061 | /* Store TX timestamp if needed. */ | ||
2062 | tile_tx_timestamp(skb, instance); | ||
2063 | |||
1854 | /* Add a completion record. */ | 2064 | /* Add a completion record. */ |
1855 | add_comp(equeue, comps, slot - 1, skb); | 2065 | add_comp(equeue, comps, slot - 1, skb); |
1856 | 2066 | ||
@@ -1885,6 +2095,9 @@ static void tile_net_tx_timeout(struct net_device *dev) | |||
1885 | /* Ioctl commands. */ | 2095 | /* Ioctl commands. */ |
1886 | static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 2096 | static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) |
1887 | { | 2097 | { |
2098 | if (cmd == SIOCSHWTSTAMP) | ||
2099 | return tile_hwtstamp_ioctl(dev, rq, cmd); | ||
2100 | |||
1888 | return -EOPNOTSUPP; | 2101 | return -EOPNOTSUPP; |
1889 | } | 2102 | } |
1890 | 2103 | ||
@@ -2005,6 +2218,7 @@ static void tile_net_dev_init(const char *name, const uint8_t *mac) | |||
2005 | priv->channel = -1; | 2218 | priv->channel = -1; |
2006 | priv->loopify_channel = -1; | 2219 | priv->loopify_channel = -1; |
2007 | priv->echannel = -1; | 2220 | priv->echannel = -1; |
2221 | init_ptp_dev(priv); | ||
2008 | 2222 | ||
2009 | /* Get the MAC address and set it in the device struct; this must | 2223 | /* Get the MAC address and set it in the device struct; this must |
2010 | * be done before the device is opened. If the MAC is all zeroes, | 2224 | * be done before the device is opened. If the MAC is all zeroes, |