提交 b81b3733 编写于 作者: J Jon Mason 提交者: David S. Miller

vxge: add receive hardware timestamping

Add support for enable/disabling hardware timestamping on receive
packets via ioctl call.  When enabled, the hardware timestamp replaces
the FCS in the payload.
Signed-off-by: NJon Mason <jon.mason@exar.com>
Signed-off-by: NRam Vepa <ram.vepa@exar.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 e8ac1756
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/net_tstamp.h>
#include "vxge-main.h" #include "vxge-main.h"
#include "vxge-reg.h" #include "vxge-reg.h"
...@@ -369,7 +370,7 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr, ...@@ -369,7 +370,7 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
u8 t_code, void *userdata) u8 t_code, void *userdata)
{ {
struct vxge_ring *ring = (struct vxge_ring *)userdata; struct vxge_ring *ring = (struct vxge_ring *)userdata;
struct net_device *dev = ring->ndev; struct net_device *dev = ring->ndev;
unsigned int dma_sizes; unsigned int dma_sizes;
void *first_dtr = NULL; void *first_dtr = NULL;
int dtr_cnt = 0; int dtr_cnt = 0;
...@@ -513,6 +514,16 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr, ...@@ -513,6 +514,16 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
else else
skb_checksum_none_assert(skb); skb_checksum_none_assert(skb);
if (ring->rx_hwts) {
struct skb_shared_hwtstamps *skb_hwts;
u32 ns = *(u32 *)(skb->head + pkt_length);
skb_hwts = skb_hwtstamps(skb);
skb_hwts->hwtstamp = ns_to_ktime(ns);
skb_hwts->syststamp.tv64 = 0;
}
/* rth_hash_type and rth_it_hit are non-zero regardless of /* rth_hash_type and rth_it_hit are non-zero regardless of
* whether rss is enabled. Only the rth_value is zero/non-zero * whether rss is enabled. Only the rth_value is zero/non-zero
* if rss is disabled/enabled, so key off of that. * if rss is disabled/enabled, so key off of that.
...@@ -2037,6 +2048,7 @@ static int vxge_open_vpaths(struct vxgedev *vdev) ...@@ -2037,6 +2048,7 @@ static int vxge_open_vpaths(struct vxgedev *vdev)
vdev->config.fifo_indicate_max_pkts; vdev->config.fifo_indicate_max_pkts;
vpath->ring.rx_vector_no = 0; vpath->ring.rx_vector_no = 0;
vpath->ring.rx_csum = vdev->rx_csum; vpath->ring.rx_csum = vdev->rx_csum;
vpath->ring.rx_hwts = vdev->rx_hwts;
vpath->is_open = 1; vpath->is_open = 1;
vdev->vp_handles[i] = vpath->handle; vdev->vp_handles[i] = vpath->handle;
vpath->ring.gro_enable = vdev->config.gro_enable; vpath->ring.gro_enable = vdev->config.gro_enable;
...@@ -2971,6 +2983,101 @@ vxge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats) ...@@ -2971,6 +2983,101 @@ vxge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats)
return net_stats; return net_stats;
} }
static enum vxge_hw_status vxge_timestamp_config(struct vxgedev *vdev,
int enable)
{
enum vxge_hw_status status;
u64 val64;
/* Timestamp is passed to the driver via the FCS, therefore we
* must disable the FCS stripping by the adapter. Since this is
* required for the driver to load (due to a hardware bug),
* there is no need to do anything special here.
*/
if (enable)
val64 = VXGE_HW_XMAC_TIMESTAMP_EN |
VXGE_HW_XMAC_TIMESTAMP_USE_LINK_ID(0) |
VXGE_HW_XMAC_TIMESTAMP_INTERVAL(0);
else
val64 = 0;
status = vxge_hw_mgmt_reg_write(vdev->devh,
vxge_hw_mgmt_reg_type_mrpcim,
0,
offsetof(struct vxge_hw_mrpcim_reg,
xmac_timestamp),
val64);
vxge_hw_device_flush_io(vdev->devh);
return status;
}
static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data)
{
struct hwtstamp_config config;
enum vxge_hw_status status;
int i;
if (copy_from_user(&config, data, sizeof(config)))
return -EFAULT;
/* reserved for future extensions */
if (config.flags)
return -EINVAL;
/* Transmit HW Timestamp not supported */
switch (config.tx_type) {
case HWTSTAMP_TX_OFF:
break;
case HWTSTAMP_TX_ON:
default:
return -ERANGE;
}
switch (config.rx_filter) {
case HWTSTAMP_FILTER_NONE:
status = vxge_timestamp_config(vdev, 0);
if (status != VXGE_HW_OK)
return -EFAULT;
vdev->rx_hwts = 0;
config.rx_filter = 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:
status = vxge_timestamp_config(vdev, 1);
if (status != VXGE_HW_OK)
return -EFAULT;
vdev->rx_hwts = 1;
config.rx_filter = HWTSTAMP_FILTER_ALL;
break;
default:
return -ERANGE;
}
for (i = 0; i < vdev->no_of_vpath; i++)
vdev->vpaths[i].ring.rx_hwts = vdev->rx_hwts;
if (copy_to_user(data, &config, sizeof(config)))
return -EFAULT;
return 0;
}
/** /**
* vxge_ioctl * vxge_ioctl
* @dev: Device pointer. * @dev: Device pointer.
...@@ -2983,7 +3090,20 @@ vxge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats) ...@@ -2983,7 +3090,20 @@ vxge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats)
*/ */
static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{ {
return -EOPNOTSUPP; struct vxgedev *vdev = netdev_priv(dev);
int ret;
switch (cmd) {
case SIOCSHWTSTAMP:
ret = vxge_hwtstamp_ioctl(vdev, rq->ifr_data);
if (ret)
return ret;
break;
default:
return -EOPNOTSUPP;
}
return 0;
} }
/** /**
...@@ -3180,6 +3300,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, ...@@ -3180,6 +3300,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
vdev->pdev = hldev->pdev; vdev->pdev = hldev->pdev;
memcpy(&vdev->config, config, sizeof(struct vxge_config)); memcpy(&vdev->config, config, sizeof(struct vxge_config));
vdev->rx_csum = 1; /* Enable Rx CSUM by default. */ vdev->rx_csum = 1; /* Enable Rx CSUM by default. */
vdev->rx_hwts = 0;
SET_NETDEV_DEV(ndev, &vdev->pdev->dev); SET_NETDEV_DEV(ndev, &vdev->pdev->dev);
...@@ -4321,10 +4442,10 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) ...@@ -4321,10 +4442,10 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
} }
/* if FCS stripping is not disabled in MAC fail driver load */ /* if FCS stripping is not disabled in MAC fail driver load */
if (vxge_hw_vpath_strip_fcs_check(hldev, vpath_mask) != VXGE_HW_OK) { status = vxge_hw_vpath_strip_fcs_check(hldev, vpath_mask);
vxge_debug_init(VXGE_ERR, if (status != VXGE_HW_OK) {
"%s: FCS stripping is not disabled in MAC" vxge_debug_init(VXGE_ERR, "%s: FCS stripping is enabled in MAC"
" failing driver load", VXGE_DRIVER_NAME); " failing driver load", VXGE_DRIVER_NAME);
ret = -EINVAL; ret = -EINVAL;
goto _exit4; goto _exit4;
} }
......
...@@ -248,8 +248,9 @@ struct vxge_ring { ...@@ -248,8 +248,9 @@ struct vxge_ring {
*/ */
int driver_id; int driver_id;
/* copy of the flag indicating whether rx_csum is to be used */ /* copy of the flag indicating whether rx_csum is to be used */
u32 rx_csum; u32 rx_csum:1,
rx_hwts:1;
int pkts_processed; int pkts_processed;
int budget; int budget;
...@@ -327,7 +328,8 @@ struct vxgedev { ...@@ -327,7 +328,8 @@ struct vxgedev {
u16 all_multi_flg; u16 all_multi_flg;
/* A flag indicating whether rx_csum is to be used or not. */ /* A flag indicating whether rx_csum is to be used or not. */
u32 rx_csum; u32 rx_csum:1,
rx_hwts:1;
struct vxge_msix_entry *vxge_entries; struct vxge_msix_entry *vxge_entries;
struct msix_entry *entries; struct msix_entry *entries;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册