blob: c63c23d463d06c7d424b2336222487340f1eafb0 [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;
79 struct net_device *gmac_ndev;
80 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
90 gmac_ndev = nss_cmn_get_interface_dev(nss_ctx, ntm->ts_ifnum);
91 if (!gmac_ndev) {
92 nss_warning("Tstamp: Invalid net device\n");
93 dev_kfree_skb_any(skb);
94 return;
95 }
96
97 skb->dev = gmac_ndev;
98
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 */
120 skb->protocol = eth_type_trans(skb, gmac_ndev);
121
122 netif_receive_skb(skb);
123
124 ndev->stats.rx_packets++;
125 ndev->stats.rx_bytes += skb->len;
126}
127
128/*
129 * nss_tstamp_register_handler()
130 */
131void nss_tstamp_register_handler(void)
132{
133 struct net_device *ndev;
134 uint32_t err = 0;
135 uint32_t features = 0;
136
137 struct nss_ctx_instance *nss_ctx;
138
139 nss_ctx = &nss_top_main.nss[nss_top_main.tstamp_handler_id];
140 ndev = alloc_netdev(sizeof(struct netdev_priv_instance),
141 "qca-nss-tstamp", nss_tstamp_ndev_setup);
142 if (!ndev) {
143 nss_warning("Tstamp: Could not allocate tstamp net_device ");
144 return;
145 }
146
147 ndev->netdev_ops = &nss_tstamp_ndev_ops;
148
149 err = register_netdev(ndev);
150 if (err) {
151 nss_warning("Tstamp: Could not register tstamp net_device ");
152 free_netdev(ndev);
153 return;
154 }
155
156 nss_ctx->nss_top->subsys_dp_register[NSS_TSTAMP_INTERFACE].cb = nss_tstamp_buf_receive;
157 nss_ctx->nss_top->subsys_dp_register[NSS_TSTAMP_INTERFACE].app_data = NULL;
158 nss_ctx->nss_top->subsys_dp_register[NSS_TSTAMP_INTERFACE].ndev = ndev;
159 nss_ctx->nss_top->subsys_dp_register[NSS_TSTAMP_INTERFACE].features = features;
160
161}
162
163