tile: support PTP using the tilegx mPIPE (IEEE 1588)
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com> Acked-by: Richard Cochran <richardcochran@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
84e181ba36
commit
9ab5ec59c8
5 changed files with 266 additions and 4 deletions
|
@ -475,6 +475,25 @@ int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context,
|
||||||
|
|
||||||
EXPORT_SYMBOL(gxio_mpipe_adjust_timestamp_aux);
|
EXPORT_SYMBOL(gxio_mpipe_adjust_timestamp_aux);
|
||||||
|
|
||||||
|
struct adjust_timestamp_freq_param {
|
||||||
|
int32_t ppb;
|
||||||
|
};
|
||||||
|
|
||||||
|
int gxio_mpipe_adjust_timestamp_freq(gxio_mpipe_context_t * context,
|
||||||
|
int32_t ppb)
|
||||||
|
{
|
||||||
|
struct adjust_timestamp_freq_param temp;
|
||||||
|
struct adjust_timestamp_freq_param *params = &temp;
|
||||||
|
|
||||||
|
params->ppb = ppb;
|
||||||
|
|
||||||
|
return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
|
||||||
|
sizeof(*params),
|
||||||
|
GXIO_MPIPE_OP_ADJUST_TIMESTAMP_FREQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(gxio_mpipe_adjust_timestamp_freq);
|
||||||
|
|
||||||
struct config_edma_ring_blks_param {
|
struct config_edma_ring_blks_param {
|
||||||
unsigned int ering;
|
unsigned int ering;
|
||||||
unsigned int max_blks;
|
unsigned int max_blks;
|
||||||
|
|
|
@ -46,10 +46,11 @@
|
||||||
#define GXIO_MPIPE_OP_LINK_CLOSE_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1212)
|
#define GXIO_MPIPE_OP_LINK_CLOSE_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1212)
|
||||||
#define GXIO_MPIPE_OP_LINK_SET_ATTR_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1213)
|
#define GXIO_MPIPE_OP_LINK_SET_ATTR_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1213)
|
||||||
|
|
||||||
#define GXIO_MPIPE_OP_GET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x121e)
|
#define GXIO_MPIPE_OP_GET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x121e)
|
||||||
#define GXIO_MPIPE_OP_SET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x121f)
|
#define GXIO_MPIPE_OP_SET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x121f)
|
||||||
#define GXIO_MPIPE_OP_ADJUST_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1220)
|
#define GXIO_MPIPE_OP_ADJUST_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1220)
|
||||||
#define GXIO_MPIPE_OP_CONFIG_EDMA_RING_BLKS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1221)
|
#define GXIO_MPIPE_OP_CONFIG_EDMA_RING_BLKS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1221)
|
||||||
|
#define GXIO_MPIPE_OP_ADJUST_TIMESTAMP_FREQ IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1222)
|
||||||
#define GXIO_MPIPE_OP_ARM_POLLFD IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9000)
|
#define GXIO_MPIPE_OP_ARM_POLLFD IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9000)
|
||||||
#define GXIO_MPIPE_OP_CLOSE_POLLFD IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9001)
|
#define GXIO_MPIPE_OP_CLOSE_POLLFD IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9001)
|
||||||
#define GXIO_MPIPE_OP_GET_MMIO_BASE IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
|
#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,
|
||||||
int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context,
|
int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context,
|
||||||
int64_t nsec);
|
int64_t nsec);
|
||||||
|
|
||||||
|
int gxio_mpipe_adjust_timestamp_freq(gxio_mpipe_context_t * context,
|
||||||
|
int32_t ppb);
|
||||||
|
|
||||||
int gxio_mpipe_arm_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie);
|
int gxio_mpipe_arm_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie);
|
||||||
|
|
||||||
int gxio_mpipe_close_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie);
|
int gxio_mpipe_close_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie);
|
||||||
|
|
|
@ -1854,4 +1854,18 @@ extern int gxio_mpipe_set_timestamp(gxio_mpipe_context_t *context,
|
||||||
extern int gxio_mpipe_adjust_timestamp(gxio_mpipe_context_t *context,
|
extern int gxio_mpipe_adjust_timestamp(gxio_mpipe_context_t *context,
|
||||||
int64_t delta);
|
int64_t delta);
|
||||||
|
|
||||||
|
/** Adjust the mPIPE timestamp clock frequency.
|
||||||
|
*
|
||||||
|
* @param context An initialized mPIPE context.
|
||||||
|
* @param ppb A 32-bit signed PPB (Parts Per Billion) value to adjust.
|
||||||
|
* The absolute value of ppb must be less than or equal to 1000000000.
|
||||||
|
* Values less than about 30000 will generally cause a GXIO_ERR_INVAL
|
||||||
|
* return due to the granularity of the hardware that converts reference
|
||||||
|
* clock cycles into seconds and nanoseconds.
|
||||||
|
* @return If the call was successful, zero; otherwise, a negative error
|
||||||
|
* code.
|
||||||
|
*/
|
||||||
|
extern int gxio_mpipe_adjust_timestamp_freq(gxio_mpipe_context_t* context,
|
||||||
|
int32_t ppb);
|
||||||
|
|
||||||
#endif /* !_GXIO_MPIPE_H_ */
|
#endif /* !_GXIO_MPIPE_H_ */
|
||||||
|
|
|
@ -15,3 +15,14 @@ config TILE_NET
|
||||||
|
|
||||||
To compile this driver as a module, choose M here: the module
|
To compile this driver as a module, choose M here: the module
|
||||||
will be called tile_net.
|
will be called tile_net.
|
||||||
|
|
||||||
|
config PTP_1588_CLOCK_TILEGX
|
||||||
|
tristate "Tilera TILE-Gx mPIPE as PTP clock"
|
||||||
|
select PTP_1588_CLOCK
|
||||||
|
depends on TILE_NET
|
||||||
|
depends on TILEGX
|
||||||
|
---help---
|
||||||
|
This driver adds support for using the mPIPE as a PTP
|
||||||
|
clock. This clock is only useful if your PTP programs are
|
||||||
|
getting hardware time stamps on the PTP Ethernet packets
|
||||||
|
using the SO_TIMESTAMPING API.
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
#include <linux/ip.h>
|
#include <linux/ip.h>
|
||||||
#include <linux/ipv6.h>
|
#include <linux/ipv6.h>
|
||||||
#include <linux/tcp.h>
|
#include <linux/tcp.h>
|
||||||
|
#include <linux/net_tstamp.h>
|
||||||
|
#include <linux/ptp_clock_kernel.h>
|
||||||
|
|
||||||
#include <asm/checksum.h>
|
#include <asm/checksum.h>
|
||||||
#include <asm/homecache.h>
|
#include <asm/homecache.h>
|
||||||
|
@ -185,6 +187,10 @@ struct tile_net_priv {
|
||||||
int echannel;
|
int echannel;
|
||||||
/* mPIPE instance, 0 or 1. */
|
/* mPIPE instance, 0 or 1. */
|
||||||
int instance;
|
int instance;
|
||||||
|
#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
|
||||||
|
/* The timestamp config. */
|
||||||
|
struct hwtstamp_config stamp_cfg;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct mpipe_data {
|
static struct mpipe_data {
|
||||||
|
@ -223,6 +229,15 @@ static struct mpipe_data {
|
||||||
int first_bucket;
|
int first_bucket;
|
||||||
int num_buckets;
|
int num_buckets;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
|
||||||
|
/* PTP-specific data. */
|
||||||
|
struct ptp_clock *ptp_clock;
|
||||||
|
struct ptp_clock_info caps;
|
||||||
|
|
||||||
|
/* Lock for ptp accessors. */
|
||||||
|
struct mutex ptp_lock;
|
||||||
|
#endif
|
||||||
|
|
||||||
} mpipe_data[NR_MPIPE_MAX] = {
|
} mpipe_data[NR_MPIPE_MAX] = {
|
||||||
[0 ... (NR_MPIPE_MAX - 1)] {
|
[0 ... (NR_MPIPE_MAX - 1)] {
|
||||||
.ingress_irq = -1,
|
.ingress_irq = -1,
|
||||||
|
@ -432,6 +447,94 @@ static void tile_net_provide_needed_buffers(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get RX timestamp, and store it in the skb. */
|
||||||
|
static void tile_rx_timestamp(struct tile_net_priv *priv, struct sk_buff *skb,
|
||||||
|
gxio_mpipe_idesc_t *idesc)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
|
||||||
|
if (unlikely(priv->stamp_cfg.rx_filter != HWTSTAMP_FILTER_NONE)) {
|
||||||
|
struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
|
||||||
|
memset(shhwtstamps, 0, sizeof(*shhwtstamps));
|
||||||
|
shhwtstamps->hwtstamp = ktime_set(idesc->time_stamp_sec,
|
||||||
|
idesc->time_stamp_ns);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get TX timestamp, and store it in the skb. */
|
||||||
|
static void tile_tx_timestamp(struct sk_buff *skb, int instance)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
|
||||||
|
struct skb_shared_info *shtx = skb_shinfo(skb);
|
||||||
|
if (unlikely((shtx->tx_flags & SKBTX_HW_TSTAMP) != 0)) {
|
||||||
|
struct mpipe_data *md = &mpipe_data[instance];
|
||||||
|
struct skb_shared_hwtstamps shhwtstamps;
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
|
shtx->tx_flags |= SKBTX_IN_PROGRESS;
|
||||||
|
gxio_mpipe_get_timestamp(&md->context, &ts);
|
||||||
|
memset(&shhwtstamps, 0, sizeof(shhwtstamps));
|
||||||
|
shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
|
||||||
|
skb_tstamp_tx(skb, &shhwtstamps);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Use ioctl() to enable or disable TX or RX timestamping. */
|
||||||
|
static int tile_hwtstamp_ioctl(struct net_device *dev, struct ifreq *rq,
|
||||||
|
int cmd)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
|
||||||
|
struct hwtstamp_config config;
|
||||||
|
struct tile_net_priv *priv = netdev_priv(dev);
|
||||||
|
|
||||||
|
if (copy_from_user(&config, rq->ifr_data, sizeof(config)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
if (config.flags) /* reserved for future extensions */
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (config.tx_type) {
|
||||||
|
case HWTSTAMP_TX_OFF:
|
||||||
|
case HWTSTAMP_TX_ON:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (config.rx_filter) {
|
||||||
|
case HWTSTAMP_FILTER_NONE:
|
||||||
|
break;
|
||||||
|
case HWTSTAMP_FILTER_ALL:
|
||||||
|
case HWTSTAMP_FILTER_SOME:
|
||||||
|
case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
|
||||||
|
case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
|
||||||
|
case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
|
||||||
|
case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
|
||||||
|
case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
|
||||||
|
case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
|
||||||
|
case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
|
||||||
|
case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
|
||||||
|
case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
|
||||||
|
case HWTSTAMP_FILTER_PTP_V2_EVENT:
|
||||||
|
case HWTSTAMP_FILTER_PTP_V2_SYNC:
|
||||||
|
case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
|
||||||
|
config.rx_filter = HWTSTAMP_FILTER_ALL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ERANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (copy_to_user(rq->ifr_data, &config, sizeof(config)))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
|
priv->stamp_cfg = config;
|
||||||
|
return 0;
|
||||||
|
#else
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool filter_packet(struct net_device *dev, void *buf)
|
static inline bool filter_packet(struct net_device *dev, void *buf)
|
||||||
{
|
{
|
||||||
/* Filter packets received before we're up. */
|
/* 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,
|
||||||
gxio_mpipe_idesc_t *idesc, unsigned long len)
|
gxio_mpipe_idesc_t *idesc, unsigned long len)
|
||||||
{
|
{
|
||||||
struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
|
struct tile_net_info *info = &__get_cpu_var(per_cpu_info);
|
||||||
int instance = mpipe_instance(dev);
|
struct tile_net_priv *priv = netdev_priv(dev);
|
||||||
|
int instance = priv->instance;
|
||||||
|
|
||||||
/* Encode the actual packet length. */
|
/* Encode the actual packet length. */
|
||||||
skb_put(skb, len);
|
skb_put(skb, len);
|
||||||
|
@ -462,6 +566,9 @@ static void tile_net_receive_skb(struct net_device *dev, struct sk_buff *skb,
|
||||||
if (idesc->cs && idesc->csum_seed_val == 0xFFFF)
|
if (idesc->cs && idesc->csum_seed_val == 0xFFFF)
|
||||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||||
|
|
||||||
|
/* Get RX timestamp from idesc. */
|
||||||
|
tile_rx_timestamp(priv, skb, idesc);
|
||||||
|
|
||||||
napi_gro_receive(&info->mpipe[instance].napi, skb);
|
napi_gro_receive(&info->mpipe[instance].napi, skb);
|
||||||
|
|
||||||
/* Update stats. */
|
/* Update stats. */
|
||||||
|
@ -707,6 +814,103 @@ static enum hrtimer_restart tile_net_handle_egress_timer(struct hrtimer *t)
|
||||||
return HRTIMER_NORESTART;
|
return HRTIMER_NORESTART;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
|
||||||
|
|
||||||
|
/* PTP clock operations. */
|
||||||
|
|
||||||
|
static int ptp_mpipe_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps);
|
||||||
|
mutex_lock(&md->ptp_lock);
|
||||||
|
if (gxio_mpipe_adjust_timestamp_freq(&md->context, ppb))
|
||||||
|
ret = -EINVAL;
|
||||||
|
mutex_unlock(&md->ptp_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ptp_mpipe_adjtime(struct ptp_clock_info *ptp, s64 delta)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps);
|
||||||
|
mutex_lock(&md->ptp_lock);
|
||||||
|
if (gxio_mpipe_adjust_timestamp(&md->context, delta))
|
||||||
|
ret = -EBUSY;
|
||||||
|
mutex_unlock(&md->ptp_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ptp_mpipe_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps);
|
||||||
|
mutex_lock(&md->ptp_lock);
|
||||||
|
if (gxio_mpipe_get_timestamp(&md->context, ts))
|
||||||
|
ret = -EBUSY;
|
||||||
|
mutex_unlock(&md->ptp_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ptp_mpipe_settime(struct ptp_clock_info *ptp,
|
||||||
|
const struct timespec *ts)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct mpipe_data *md = container_of(ptp, struct mpipe_data, caps);
|
||||||
|
mutex_lock(&md->ptp_lock);
|
||||||
|
if (gxio_mpipe_set_timestamp(&md->context, ts))
|
||||||
|
ret = -EBUSY;
|
||||||
|
mutex_unlock(&md->ptp_lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ptp_mpipe_enable(struct ptp_clock_info *ptp,
|
||||||
|
struct ptp_clock_request *request, int on)
|
||||||
|
{
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ptp_clock_info ptp_mpipe_caps = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "mPIPE clock",
|
||||||
|
.max_adj = 999999999,
|
||||||
|
.n_ext_ts = 0,
|
||||||
|
.pps = 0,
|
||||||
|
.adjfreq = ptp_mpipe_adjfreq,
|
||||||
|
.adjtime = ptp_mpipe_adjtime,
|
||||||
|
.gettime = ptp_mpipe_gettime,
|
||||||
|
.settime = ptp_mpipe_settime,
|
||||||
|
.enable = ptp_mpipe_enable,
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* CONFIG_PTP_1588_CLOCK_TILEGX */
|
||||||
|
|
||||||
|
/* Sync mPIPE's timestamp up with Linux system time and register PTP clock. */
|
||||||
|
static void register_ptp_clock(struct net_device *dev, struct mpipe_data *md)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
|
getnstimeofday(&ts);
|
||||||
|
gxio_mpipe_set_timestamp(&md->context, &ts);
|
||||||
|
|
||||||
|
mutex_init(&md->ptp_lock);
|
||||||
|
md->caps = ptp_mpipe_caps;
|
||||||
|
md->ptp_clock = ptp_clock_register(&md->caps, NULL);
|
||||||
|
if (IS_ERR(md->ptp_clock))
|
||||||
|
netdev_err(dev, "ptp_clock_register failed %ld\n",
|
||||||
|
PTR_ERR(md->ptp_clock));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize PTP fields in a new device. */
|
||||||
|
static void init_ptp_dev(struct tile_net_priv *priv)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_PTP_1588_CLOCK_TILEGX
|
||||||
|
priv->stamp_cfg.rx_filter = HWTSTAMP_FILTER_NONE;
|
||||||
|
priv->stamp_cfg.tx_type = HWTSTAMP_TX_OFF;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* Helper functions for "tile_net_update()". */
|
/* Helper functions for "tile_net_update()". */
|
||||||
static void enable_ingress_irq(void *irq)
|
static void enable_ingress_irq(void *irq)
|
||||||
{
|
{
|
||||||
|
@ -1149,6 +1353,9 @@ static int tile_net_init_mpipe(struct net_device *dev)
|
||||||
if (rc != 0)
|
if (rc != 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
/* Register PTP clock and set mPIPE timestamp, if configured. */
|
||||||
|
register_ptp_clock(dev, md);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -1851,6 +2058,9 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev)
|
||||||
for (i = 0; i < num_edescs; i++)
|
for (i = 0; i < num_edescs; i++)
|
||||||
gxio_mpipe_equeue_put_at(equeue, edescs[i], slot++);
|
gxio_mpipe_equeue_put_at(equeue, edescs[i], slot++);
|
||||||
|
|
||||||
|
/* Store TX timestamp if needed. */
|
||||||
|
tile_tx_timestamp(skb, instance);
|
||||||
|
|
||||||
/* Add a completion record. */
|
/* Add a completion record. */
|
||||||
add_comp(equeue, comps, slot - 1, skb);
|
add_comp(equeue, comps, slot - 1, skb);
|
||||||
|
|
||||||
|
@ -1885,6 +2095,9 @@ static void tile_net_tx_timeout(struct net_device *dev)
|
||||||
/* Ioctl commands. */
|
/* Ioctl commands. */
|
||||||
static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
static int tile_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||||
{
|
{
|
||||||
|
if (cmd == SIOCSHWTSTAMP)
|
||||||
|
return tile_hwtstamp_ioctl(dev, rq, cmd);
|
||||||
|
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2005,6 +2218,7 @@ static void tile_net_dev_init(const char *name, const uint8_t *mac)
|
||||||
priv->channel = -1;
|
priv->channel = -1;
|
||||||
priv->loopify_channel = -1;
|
priv->loopify_channel = -1;
|
||||||
priv->echannel = -1;
|
priv->echannel = -1;
|
||||||
|
init_ptp_dev(priv);
|
||||||
|
|
||||||
/* Get the MAC address and set it in the device struct; this must
|
/* Get the MAC address and set it in the device struct; this must
|
||||||
* be done before the device is opened. If the MAC is all zeroes,
|
* be done before the device is opened. If the MAC is all zeroes,
|
||||||
|
|
Loading…
Add table
Reference in a new issue