blob: a59e28647318f57743ca7c97789f673d97324e5e [file] [log] [blame]
Rakesh Nair28212a42015-08-31 14:51:49 +05301/*
2 **************************************************************************
Stephen Wang90c67de2016-04-26 15:15:59 -07003 * Copyright (c) 2015, 2016, The Linux Foundation. All rights reserved.
Rakesh Nair28212a42015-08-31 14:51:49 +05304 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all copies.
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
13 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 **************************************************************************
15 */
16
17/*
18 * nss_tstamp.c
19 * NSS Tstamp APIs
20 */
21
22#include "nss_tx_rx_common.h"
23#include <linux/etherdevice.h>
24
25static struct net_device_stats *nss_tstamp_ndev_stats(struct net_device *ndev);
26
27static const struct net_device_ops nss_tstamp_ndev_ops = {
28 .ndo_get_stats = nss_tstamp_ndev_stats,
29};
30
31struct nss_tstamp_data {
32 uint32_t ts_ifnum; /* time stamp interface number */
33 uint32_t ts_data_lo; /* time stamp lower order bits */
34 uint32_t ts_data_hi; /* time stamp higher order bits */
35
36 uint8_t ts_tx; /* time stamp direction */
37 uint8_t ts_hdr_sz; /* padding bytes */
38};
39
40/*
41 * nss_tstamp_ndev_setup()
42 * Dummy setup for net_device handler
43 */
44static void nss_tstamp_ndev_setup(struct net_device *ndev)
45{
46 return;
47}
48
49/*
50 * nss_tstamp_ndev_stats()
51 * Return net device stats
52 */
53static struct net_device_stats *nss_tstamp_ndev_stats(struct net_device *ndev)
54{
55 return &ndev->stats;
56};
57
58/*
59 * nss_tstamp_copy_data()
60 * Copy timestamps from received nss frame into skb
61 */
62static void nss_tstamp_copy_data(struct nss_tstamp_data *ntm, struct sk_buff *skb)
63{
64 struct skb_shared_hwtstamps *tstamp;
65
66 tstamp = skb_hwtstamps(skb);
67 tstamp->hwtstamp = ktime_set(ntm->ts_data_hi, ntm->ts_data_lo);
Stephen Wang90c67de2016-04-26 15:15:59 -070068#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 16, 0))
Rakesh Nair28212a42015-08-31 14:51:49 +053069 tstamp->syststamp = ktime_set(ntm->ts_data_hi, ntm->ts_data_lo);
Stephen Wang90c67de2016-04-26 15:15:59 -070070#endif
Rakesh Nair28212a42015-08-31 14:51:49 +053071}
72
73/*
74 * nss_tstamp_buf_receive()
75 * Receive nss exception packets.
76 */
77static void nss_tstamp_buf_receive(struct net_device *ndev, struct sk_buff *skb, struct napi_struct *napi)
78{
79 struct nss_tstamp_data *ntm = (struct nss_tstamp_data *)skb->data;
80 struct nss_ctx_instance *nss_ctx;
Rakesh Nair7c43b542015-12-03 16:45:24 +053081 struct net_device *dev;
Rakesh Nair28212a42015-08-31 14:51:49 +053082 uint32_t tstamp_sz;
83
84 BUG_ON(!ntm);
85 tstamp_sz = ntm->ts_hdr_sz;
86
87 nss_ctx = &nss_top_main.nss[nss_top_main.tstamp_handler_id];
88 BUG_ON(!nss_ctx);
89
90 skb_pull(skb, tstamp_sz);
91
Rakesh Nair7c43b542015-12-03 16:45:24 +053092 dev = nss_cmn_get_interface_dev(nss_ctx, ntm->ts_ifnum);
93 if (!dev) {
Rakesh Nair28212a42015-08-31 14:51:49 +053094 nss_warning("Tstamp: Invalid net device\n");
95 dev_kfree_skb_any(skb);
96 return;
97 }
98
Rakesh Nair7c43b542015-12-03 16:45:24 +053099 skb->dev = dev;
Rakesh Nair28212a42015-08-31 14:51:49 +0530100
101 /*
102 * copy the time stamp and convert into ktime_t
103 */
104 nss_tstamp_copy_data(ntm, skb);
105
106 if (unlikely(ntm->ts_tx)) {
107 /*
108 * We are in TX Path
109 */
110 skb_tstamp_tx(skb, skb_hwtstamps(skb));
111
112 ndev->stats.tx_packets++;
113 ndev->stats.tx_bytes += skb->len;
114
115 dev_kfree_skb_any(skb);
116 return;
117 }
118
119 /*
120 * We are in RX Path
121 */
Rakesh Nair7c43b542015-12-03 16:45:24 +0530122 switch(dev->type) {
123 case NSS_IPSEC_ARPHRD_IPSEC:
124 /*
125 * It seems like the data came over IPsec, hence indicate
126 * it to the Linux over this interface
127 */
128 skb_reset_network_header(skb);
129 skb_reset_mac_header(skb);
130
131 skb->pkt_type = PACKET_HOST;
132 skb->protocol = cpu_to_be16(ETH_P_IP);
133 skb->skb_iif = dev->ifindex;
134 break;
135
136 default:
137 /*
138 * This is a plain non-encrypted data packet.
139 */
140 skb->protocol = eth_type_trans(skb, dev);
141 break;
142 }
Rakesh Nair28212a42015-08-31 14:51:49 +0530143
144 netif_receive_skb(skb);
145
146 ndev->stats.rx_packets++;
147 ndev->stats.rx_bytes += skb->len;
148}
149
150/*
Rakesh Nairf0140c82015-12-02 17:49:06 +0530151 * nss_tstamp_register_netdev()
Rakesh Nair28212a42015-08-31 14:51:49 +0530152 */
Rakesh Nairf0140c82015-12-02 17:49:06 +0530153struct net_device *nss_tstamp_register_netdev(void)
Rakesh Nair28212a42015-08-31 14:51:49 +0530154{
155 struct net_device *ndev;
156 uint32_t err = 0;
Rakesh Nair28212a42015-08-31 14:51:49 +0530157
Stephen Wang90c67de2016-04-26 15:15:59 -0700158#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 16, 0))
Rakesh Nairf0140c82015-12-02 17:49:06 +0530159 ndev = alloc_netdev(sizeof(struct netdev_priv_instance), "qca-nss-tstamp", nss_tstamp_ndev_setup);
Stephen Wang90c67de2016-04-26 15:15:59 -0700160#else
161 ndev = alloc_netdev(sizeof(struct netdev_priv_instance), "qca-nss-tstamp", NET_NAME_ENUM, nss_tstamp_ndev_setup);
162#endif
Rakesh Nair28212a42015-08-31 14:51:49 +0530163 if (!ndev) {
164 nss_warning("Tstamp: Could not allocate tstamp net_device ");
Rakesh Nairf0140c82015-12-02 17:49:06 +0530165 return NULL;
Rakesh Nair28212a42015-08-31 14:51:49 +0530166 }
167
168 ndev->netdev_ops = &nss_tstamp_ndev_ops;
169
170 err = register_netdev(ndev);
171 if (err) {
172 nss_warning("Tstamp: Could not register tstamp net_device ");
173 free_netdev(ndev);
Rakesh Nairf0140c82015-12-02 17:49:06 +0530174 return NULL;
Rakesh Nair28212a42015-08-31 14:51:49 +0530175 }
176
Rakesh Nairf0140c82015-12-02 17:49:06 +0530177 return ndev;
178}
179
180/*
181 * nss_tstamp_register_handler()
182 */
183void nss_tstamp_register_handler(struct net_device *ndev)
184{
185 uint32_t features = 0;
186 struct nss_ctx_instance *nss_ctx;
187
188 nss_ctx = &nss_top_main.nss[nss_top_main.tstamp_handler_id];
Stephen Wang84e0e992016-09-07 12:31:40 -0700189 nss_ctx->subsys_dp_register[NSS_TSTAMP_INTERFACE].cb = nss_tstamp_buf_receive;
190 nss_ctx->subsys_dp_register[NSS_TSTAMP_INTERFACE].app_data = NULL;
191 nss_ctx->subsys_dp_register[NSS_TSTAMP_INTERFACE].ndev = ndev;
192 nss_ctx->subsys_dp_register[NSS_TSTAMP_INTERFACE].features = features;
Rakesh Nair28212a42015-08-31 14:51:49 +0530193}
194
195