blob: 0cead929d69a98fe675d2443ef2c33cdc2d7dd16 [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/*
Rakesh Nairf0140c82015-12-02 17:49:06 +0530129 * nss_tstamp_register_netdev()
Rakesh Nair28212a42015-08-31 14:51:49 +0530130 */
Rakesh Nairf0140c82015-12-02 17:49:06 +0530131struct net_device *nss_tstamp_register_netdev(void)
Rakesh Nair28212a42015-08-31 14:51:49 +0530132{
133 struct net_device *ndev;
134 uint32_t err = 0;
Rakesh Nair28212a42015-08-31 14:51:49 +0530135
Rakesh Nairf0140c82015-12-02 17:49:06 +0530136 ndev = alloc_netdev(sizeof(struct netdev_priv_instance), "qca-nss-tstamp", nss_tstamp_ndev_setup);
Rakesh Nair28212a42015-08-31 14:51:49 +0530137 if (!ndev) {
138 nss_warning("Tstamp: Could not allocate tstamp net_device ");
Rakesh Nairf0140c82015-12-02 17:49:06 +0530139 return NULL;
Rakesh Nair28212a42015-08-31 14:51:49 +0530140 }
141
142 ndev->netdev_ops = &nss_tstamp_ndev_ops;
143
144 err = register_netdev(ndev);
145 if (err) {
146 nss_warning("Tstamp: Could not register tstamp net_device ");
147 free_netdev(ndev);
Rakesh Nairf0140c82015-12-02 17:49:06 +0530148 return NULL;
Rakesh Nair28212a42015-08-31 14:51:49 +0530149 }
150
Rakesh Nairf0140c82015-12-02 17:49:06 +0530151 return ndev;
152}
153
154/*
155 * nss_tstamp_register_handler()
156 */
157void nss_tstamp_register_handler(struct net_device *ndev)
158{
159 uint32_t features = 0;
160 struct nss_ctx_instance *nss_ctx;
161
162 nss_ctx = &nss_top_main.nss[nss_top_main.tstamp_handler_id];
Rakesh Nair28212a42015-08-31 14:51:49 +0530163 nss_ctx->nss_top->subsys_dp_register[NSS_TSTAMP_INTERFACE].cb = nss_tstamp_buf_receive;
164 nss_ctx->nss_top->subsys_dp_register[NSS_TSTAMP_INTERFACE].app_data = NULL;
165 nss_ctx->nss_top->subsys_dp_register[NSS_TSTAMP_INTERFACE].ndev = ndev;
166 nss_ctx->nss_top->subsys_dp_register[NSS_TSTAMP_INTERFACE].features = features;
167
168}
169
170