blob: 42bcfe19f988007f4fa1a458e316d8e9c96776e9 [file] [log] [blame]
Rakesh Nair28212a42015-08-31 14:51:49 +05301/*
2 **************************************************************************
3 * Copyright (c) 2015, The Linux Foundation. All rights reserved.
4 * 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);
68 tstamp->syststamp = ktime_set(ntm->ts_data_hi, ntm->ts_data_lo);
69}
70
71/*
72 * nss_tstamp_buf_receive()
73 * Receive nss exception packets.
74 */
75static void nss_tstamp_buf_receive(struct net_device *ndev, struct sk_buff *skb, struct napi_struct *napi)
76{
77 struct nss_tstamp_data *ntm = (struct nss_tstamp_data *)skb->data;
78 struct nss_ctx_instance *nss_ctx;
Rakesh Nair7c43b542015-12-03 16:45:24 +053079 struct net_device *dev;
Rakesh Nair28212a42015-08-31 14:51:49 +053080 uint32_t tstamp_sz;
81
82 BUG_ON(!ntm);
83 tstamp_sz = ntm->ts_hdr_sz;
84
85 nss_ctx = &nss_top_main.nss[nss_top_main.tstamp_handler_id];
86 BUG_ON(!nss_ctx);
87
88 skb_pull(skb, tstamp_sz);
89
Rakesh Nair7c43b542015-12-03 16:45:24 +053090 dev = nss_cmn_get_interface_dev(nss_ctx, ntm->ts_ifnum);
91 if (!dev) {
Rakesh Nair28212a42015-08-31 14:51:49 +053092 nss_warning("Tstamp: Invalid net device\n");
93 dev_kfree_skb_any(skb);
94 return;
95 }
96
Rakesh Nair7c43b542015-12-03 16:45:24 +053097 skb->dev = dev;
Rakesh Nair28212a42015-08-31 14:51:49 +053098
99 /*
100 * copy the time stamp and convert into ktime_t
101 */
102 nss_tstamp_copy_data(ntm, skb);
103
104 if (unlikely(ntm->ts_tx)) {
105 /*
106 * We are in TX Path
107 */
108 skb_tstamp_tx(skb, skb_hwtstamps(skb));
109
110 ndev->stats.tx_packets++;
111 ndev->stats.tx_bytes += skb->len;
112
113 dev_kfree_skb_any(skb);
114 return;
115 }
116
117 /*
118 * We are in RX Path
119 */
Rakesh Nair7c43b542015-12-03 16:45:24 +0530120 switch(dev->type) {
121 case NSS_IPSEC_ARPHRD_IPSEC:
122 /*
123 * It seems like the data came over IPsec, hence indicate
124 * it to the Linux over this interface
125 */
126 skb_reset_network_header(skb);
127 skb_reset_mac_header(skb);
128
129 skb->pkt_type = PACKET_HOST;
130 skb->protocol = cpu_to_be16(ETH_P_IP);
131 skb->skb_iif = dev->ifindex;
132 break;
133
134 default:
135 /*
136 * This is a plain non-encrypted data packet.
137 */
138 skb->protocol = eth_type_trans(skb, dev);
139 break;
140 }
Rakesh Nair28212a42015-08-31 14:51:49 +0530141
142 netif_receive_skb(skb);
143
144 ndev->stats.rx_packets++;
145 ndev->stats.rx_bytes += skb->len;
146}
147
148/*
Rakesh Nairf0140c82015-12-02 17:49:06 +0530149 * nss_tstamp_register_netdev()
Rakesh Nair28212a42015-08-31 14:51:49 +0530150 */
Rakesh Nairf0140c82015-12-02 17:49:06 +0530151struct net_device *nss_tstamp_register_netdev(void)
Rakesh Nair28212a42015-08-31 14:51:49 +0530152{
153 struct net_device *ndev;
154 uint32_t err = 0;
Rakesh Nair28212a42015-08-31 14:51:49 +0530155
Rakesh Nairf0140c82015-12-02 17:49:06 +0530156 ndev = alloc_netdev(sizeof(struct netdev_priv_instance), "qca-nss-tstamp", nss_tstamp_ndev_setup);
Rakesh Nair28212a42015-08-31 14:51:49 +0530157 if (!ndev) {
158 nss_warning("Tstamp: Could not allocate tstamp net_device ");
Rakesh Nairf0140c82015-12-02 17:49:06 +0530159 return NULL;
Rakesh Nair28212a42015-08-31 14:51:49 +0530160 }
161
162 ndev->netdev_ops = &nss_tstamp_ndev_ops;
163
164 err = register_netdev(ndev);
165 if (err) {
166 nss_warning("Tstamp: Could not register tstamp net_device ");
167 free_netdev(ndev);
Rakesh Nairf0140c82015-12-02 17:49:06 +0530168 return NULL;
Rakesh Nair28212a42015-08-31 14:51:49 +0530169 }
170
Rakesh Nairf0140c82015-12-02 17:49:06 +0530171 return ndev;
172}
173
174/*
175 * nss_tstamp_register_handler()
176 */
177void nss_tstamp_register_handler(struct net_device *ndev)
178{
179 uint32_t features = 0;
180 struct nss_ctx_instance *nss_ctx;
181
182 nss_ctx = &nss_top_main.nss[nss_top_main.tstamp_handler_id];
Rakesh Nair28212a42015-08-31 14:51:49 +0530183 nss_ctx->nss_top->subsys_dp_register[NSS_TSTAMP_INTERFACE].cb = nss_tstamp_buf_receive;
184 nss_ctx->nss_top->subsys_dp_register[NSS_TSTAMP_INTERFACE].app_data = NULL;
185 nss_ctx->nss_top->subsys_dp_register[NSS_TSTAMP_INTERFACE].ndev = ndev;
186 nss_ctx->nss_top->subsys_dp_register[NSS_TSTAMP_INTERFACE].features = features;
187
188}
189
190