aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/vxge/vxge-main.c
diff options
context:
space:
mode:
authorJon Mason <jon.mason@exar.com>2010-11-10 23:25:58 -0500
committerDavid S. Miller <davem@davemloft.net>2010-11-11 12:30:21 -0500
commitb81b37338412e3215670641e5025c85146521dea (patch)
treeb6a4a1280223e21d5108cde1a9377d98653b44d7 /drivers/net/vxge/vxge-main.c
parente8ac175615b9458a00193c55617b5b8865e67817 (diff)
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: Jon Mason <jon.mason@exar.com> Signed-off-by: Ram Vepa <ram.vepa@exar.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/vxge/vxge-main.c')
-rw-r--r--drivers/net/vxge/vxge-main.c133
1 files changed, 127 insertions, 6 deletions
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c
index 10549bd39221..ea303a2af3aa 100644
--- a/drivers/net/vxge/vxge-main.c
+++ b/drivers/net/vxge/vxge-main.c
@@ -51,6 +51,7 @@
51#include <linux/netdevice.h> 51#include <linux/netdevice.h>
52#include <linux/etherdevice.h> 52#include <linux/etherdevice.h>
53#include <linux/firmware.h> 53#include <linux/firmware.h>
54#include <linux/net_tstamp.h>
54#include "vxge-main.h" 55#include "vxge-main.h"
55#include "vxge-reg.h" 56#include "vxge-reg.h"
56 57
@@ -369,7 +370,7 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
369 u8 t_code, void *userdata) 370 u8 t_code, void *userdata)
370{ 371{
371 struct vxge_ring *ring = (struct vxge_ring *)userdata; 372 struct vxge_ring *ring = (struct vxge_ring *)userdata;
372 struct net_device *dev = ring->ndev; 373 struct net_device *dev = ring->ndev;
373 unsigned int dma_sizes; 374 unsigned int dma_sizes;
374 void *first_dtr = NULL; 375 void *first_dtr = NULL;
375 int dtr_cnt = 0; 376 int dtr_cnt = 0;
@@ -513,6 +514,16 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr,
513 else 514 else
514 skb_checksum_none_assert(skb); 515 skb_checksum_none_assert(skb);
515 516
517
518 if (ring->rx_hwts) {
519 struct skb_shared_hwtstamps *skb_hwts;
520 u32 ns = *(u32 *)(skb->head + pkt_length);
521
522 skb_hwts = skb_hwtstamps(skb);
523 skb_hwts->hwtstamp = ns_to_ktime(ns);
524 skb_hwts->syststamp.tv64 = 0;
525 }
526
516 /* rth_hash_type and rth_it_hit are non-zero regardless of 527 /* rth_hash_type and rth_it_hit are non-zero regardless of
517 * whether rss is enabled. Only the rth_value is zero/non-zero 528 * whether rss is enabled. Only the rth_value is zero/non-zero
518 * if rss is disabled/enabled, so key off of that. 529 * if rss is disabled/enabled, so key off of that.
@@ -2037,6 +2048,7 @@ static int vxge_open_vpaths(struct vxgedev *vdev)
2037 vdev->config.fifo_indicate_max_pkts; 2048 vdev->config.fifo_indicate_max_pkts;
2038 vpath->ring.rx_vector_no = 0; 2049 vpath->ring.rx_vector_no = 0;
2039 vpath->ring.rx_csum = vdev->rx_csum; 2050 vpath->ring.rx_csum = vdev->rx_csum;
2051 vpath->ring.rx_hwts = vdev->rx_hwts;
2040 vpath->is_open = 1; 2052 vpath->is_open = 1;
2041 vdev->vp_handles[i] = vpath->handle; 2053 vdev->vp_handles[i] = vpath->handle;
2042 vpath->ring.gro_enable = vdev->config.gro_enable; 2054 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 return net_stats; 2983 return net_stats;
2972} 2984}
2973 2985
2986static enum vxge_hw_status vxge_timestamp_config(struct vxgedev *vdev,
2987 int enable)
2988{
2989 enum vxge_hw_status status;
2990 u64 val64;
2991
2992 /* Timestamp is passed to the driver via the FCS, therefore we
2993 * must disable the FCS stripping by the adapter. Since this is
2994 * required for the driver to load (due to a hardware bug),
2995 * there is no need to do anything special here.
2996 */
2997 if (enable)
2998 val64 = VXGE_HW_XMAC_TIMESTAMP_EN |
2999 VXGE_HW_XMAC_TIMESTAMP_USE_LINK_ID(0) |
3000 VXGE_HW_XMAC_TIMESTAMP_INTERVAL(0);
3001 else
3002 val64 = 0;
3003
3004 status = vxge_hw_mgmt_reg_write(vdev->devh,
3005 vxge_hw_mgmt_reg_type_mrpcim,
3006 0,
3007 offsetof(struct vxge_hw_mrpcim_reg,
3008 xmac_timestamp),
3009 val64);
3010 vxge_hw_device_flush_io(vdev->devh);
3011 return status;
3012}
3013
3014static int vxge_hwtstamp_ioctl(struct vxgedev *vdev, void __user *data)
3015{
3016 struct hwtstamp_config config;
3017 enum vxge_hw_status status;
3018 int i;
3019
3020 if (copy_from_user(&config, data, sizeof(config)))
3021 return -EFAULT;
3022
3023 /* reserved for future extensions */
3024 if (config.flags)
3025 return -EINVAL;
3026
3027 /* Transmit HW Timestamp not supported */
3028 switch (config.tx_type) {
3029 case HWTSTAMP_TX_OFF:
3030 break;
3031 case HWTSTAMP_TX_ON:
3032 default:
3033 return -ERANGE;
3034 }
3035
3036 switch (config.rx_filter) {
3037 case HWTSTAMP_FILTER_NONE:
3038 status = vxge_timestamp_config(vdev, 0);
3039 if (status != VXGE_HW_OK)
3040 return -EFAULT;
3041
3042 vdev->rx_hwts = 0;
3043 config.rx_filter = HWTSTAMP_FILTER_NONE;
3044 break;
3045
3046 case HWTSTAMP_FILTER_ALL:
3047 case HWTSTAMP_FILTER_SOME:
3048 case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
3049 case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
3050 case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
3051 case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
3052 case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
3053 case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
3054 case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
3055 case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
3056 case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
3057 case HWTSTAMP_FILTER_PTP_V2_EVENT:
3058 case HWTSTAMP_FILTER_PTP_V2_SYNC:
3059 case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
3060 status = vxge_timestamp_config(vdev, 1);
3061 if (status != VXGE_HW_OK)
3062 return -EFAULT;
3063
3064 vdev->rx_hwts = 1;
3065 config.rx_filter = HWTSTAMP_FILTER_ALL;
3066 break;
3067
3068 default:
3069 return -ERANGE;
3070 }
3071
3072 for (i = 0; i < vdev->no_of_vpath; i++)
3073 vdev->vpaths[i].ring.rx_hwts = vdev->rx_hwts;
3074
3075 if (copy_to_user(data, &config, sizeof(config)))
3076 return -EFAULT;
3077
3078 return 0;
3079}
3080
2974/** 3081/**
2975 * vxge_ioctl 3082 * vxge_ioctl
2976 * @dev: Device pointer. 3083 * @dev: Device pointer.
@@ -2983,7 +3090,20 @@ vxge_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *net_stats)
2983 */ 3090 */
2984static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 3091static int vxge_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
2985{ 3092{
2986 return -EOPNOTSUPP; 3093 struct vxgedev *vdev = netdev_priv(dev);
3094 int ret;
3095
3096 switch (cmd) {
3097 case SIOCSHWTSTAMP:
3098 ret = vxge_hwtstamp_ioctl(vdev, rq->ifr_data);
3099 if (ret)
3100 return ret;
3101 break;
3102 default:
3103 return -EOPNOTSUPP;
3104 }
3105
3106 return 0;
2987} 3107}
2988 3108
2989/** 3109/**
@@ -3180,6 +3300,7 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
3180 vdev->pdev = hldev->pdev; 3300 vdev->pdev = hldev->pdev;
3181 memcpy(&vdev->config, config, sizeof(struct vxge_config)); 3301 memcpy(&vdev->config, config, sizeof(struct vxge_config));
3182 vdev->rx_csum = 1; /* Enable Rx CSUM by default. */ 3302 vdev->rx_csum = 1; /* Enable Rx CSUM by default. */
3303 vdev->rx_hwts = 0;
3183 3304
3184 SET_NETDEV_DEV(ndev, &vdev->pdev->dev); 3305 SET_NETDEV_DEV(ndev, &vdev->pdev->dev);
3185 3306
@@ -4321,10 +4442,10 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre)
4321 } 4442 }
4322 4443
4323 /* if FCS stripping is not disabled in MAC fail driver load */ 4444 /* if FCS stripping is not disabled in MAC fail driver load */
4324 if (vxge_hw_vpath_strip_fcs_check(hldev, vpath_mask) != VXGE_HW_OK) { 4445 status = vxge_hw_vpath_strip_fcs_check(hldev, vpath_mask);
4325 vxge_debug_init(VXGE_ERR, 4446 if (status != VXGE_HW_OK) {
4326 "%s: FCS stripping is not disabled in MAC" 4447 vxge_debug_init(VXGE_ERR, "%s: FCS stripping is enabled in MAC"
4327 " failing driver load", VXGE_DRIVER_NAME); 4448 " failing driver load", VXGE_DRIVER_NAME);
4328 ret = -EINVAL; 4449 ret = -EINVAL;
4329 goto _exit4; 4450 goto _exit4;
4330 } 4451 }