32
32
*/
33
33
34
34
#include <linux/etherdevice.h>
35
+ #include <linux/io-64-nonatomic-hi-lo.h>
35
36
#include <linux/lockdep.h>
36
37
#include <net/dst_metadata.h>
37
38
38
39
#include "nfpcore/nfp_cpp.h"
39
40
#include "nfp_app.h"
40
41
#include "nfp_main.h"
42
+ #include "nfp_net_ctrl.h"
41
43
#include "nfp_net_repr.h"
42
44
#include "nfp_port.h"
43
45
46
+ static void
47
+ nfp_repr_inc_tx_stats (struct net_device * netdev , unsigned int len ,
48
+ int tx_status )
49
+ {
50
+ struct nfp_repr * repr = netdev_priv (netdev );
51
+ struct nfp_repr_pcpu_stats * stats ;
52
+
53
+ if (unlikely (tx_status != NET_XMIT_SUCCESS &&
54
+ tx_status != NET_XMIT_CN )) {
55
+ this_cpu_inc (repr -> stats -> tx_drops );
56
+ return ;
57
+ }
58
+
59
+ stats = this_cpu_ptr (repr -> stats );
60
+ u64_stats_update_begin (& stats -> syncp );
61
+ stats -> tx_packets ++ ;
62
+ stats -> tx_bytes += len ;
63
+ u64_stats_update_end (& stats -> syncp );
64
+ }
65
+
66
+ void nfp_repr_inc_rx_stats (struct net_device * netdev , unsigned int len )
67
+ {
68
+ struct nfp_repr * repr = netdev_priv (netdev );
69
+ struct nfp_repr_pcpu_stats * stats ;
70
+
71
+ stats = this_cpu_ptr (repr -> stats );
72
+ u64_stats_update_begin (& stats -> syncp );
73
+ stats -> rx_packets ++ ;
74
+ stats -> rx_bytes += len ;
75
+ u64_stats_update_end (& stats -> syncp );
76
+ }
77
+
78
+ static void
79
+ nfp_repr_phy_port_get_stats64 (const struct nfp_app * app , u8 phy_port ,
80
+ struct rtnl_link_stats64 * stats )
81
+ {
82
+ u8 __iomem * mem ;
83
+
84
+ mem = app -> pf -> mac_stats_mem + phy_port * NFP_MAC_STATS_SIZE ;
85
+
86
+ /* TX and RX stats are flipped as we are returning the stats as seen
87
+ * at the switch port corresponding to the phys port.
88
+ */
89
+ stats -> tx_packets = readq (mem + NFP_MAC_STATS_RX_FRAMES_RECEIVED_OK );
90
+ stats -> tx_bytes = readq (mem + NFP_MAC_STATS_RX_IN_OCTETS );
91
+ stats -> tx_dropped = readq (mem + NFP_MAC_STATS_RX_IN_ERRORS );
92
+
93
+ stats -> rx_packets = readq (mem + NFP_MAC_STATS_TX_FRAMES_TRANSMITTED_OK );
94
+ stats -> rx_bytes = readq (mem + NFP_MAC_STATS_TX_OUT_OCTETS );
95
+ stats -> rx_dropped = readq (mem + NFP_MAC_STATS_TX_OUT_ERRORS );
96
+ }
97
+
98
+ static void
99
+ nfp_repr_vf_get_stats64 (const struct nfp_app * app , u8 vf ,
100
+ struct rtnl_link_stats64 * stats )
101
+ {
102
+ u8 __iomem * mem ;
103
+
104
+ mem = app -> pf -> vf_cfg_mem + vf * NFP_NET_CFG_BAR_SZ ;
105
+
106
+ /* TX and RX stats are flipped as we are returning the stats as seen
107
+ * at the switch port corresponding to the VF.
108
+ */
109
+ stats -> tx_packets = readq (mem + NFP_NET_CFG_STATS_RX_FRAMES );
110
+ stats -> tx_bytes = readq (mem + NFP_NET_CFG_STATS_RX_OCTETS );
111
+ stats -> tx_dropped = readq (mem + NFP_NET_CFG_STATS_RX_DISCARDS );
112
+
113
+ stats -> rx_packets = readq (mem + NFP_NET_CFG_STATS_TX_FRAMES );
114
+ stats -> rx_bytes = readq (mem + NFP_NET_CFG_STATS_TX_OCTETS );
115
+ stats -> rx_dropped = readq (mem + NFP_NET_CFG_STATS_TX_DISCARDS );
116
+ }
117
+
118
+ static void
119
+ nfp_repr_pf_get_stats64 (const struct nfp_app * app , u8 pf ,
120
+ struct rtnl_link_stats64 * stats )
121
+ {
122
+ u8 __iomem * mem ;
123
+
124
+ if (pf )
125
+ return ;
126
+
127
+ mem = nfp_cpp_area_iomem (app -> pf -> data_vnic_bar );
128
+
129
+ stats -> tx_packets = readq (mem + NFP_NET_CFG_STATS_RX_FRAMES );
130
+ stats -> tx_bytes = readq (mem + NFP_NET_CFG_STATS_RX_OCTETS );
131
+ stats -> tx_dropped = readq (mem + NFP_NET_CFG_STATS_RX_DISCARDS );
132
+
133
+ stats -> rx_packets = readq (mem + NFP_NET_CFG_STATS_TX_FRAMES );
134
+ stats -> rx_bytes = readq (mem + NFP_NET_CFG_STATS_TX_OCTETS );
135
+ stats -> rx_dropped = readq (mem + NFP_NET_CFG_STATS_TX_DISCARDS );
136
+ }
137
+
138
+ void
139
+ nfp_repr_get_stats64 (const struct nfp_app * app , enum nfp_repr_type type ,
140
+ u8 port , struct rtnl_link_stats64 * stats )
141
+ {
142
+ switch (type ) {
143
+ case NFP_REPR_TYPE_PHYS_PORT :
144
+ nfp_repr_phy_port_get_stats64 (app , port , stats );
145
+ break ;
146
+ case NFP_REPR_TYPE_PF :
147
+ nfp_repr_pf_get_stats64 (app , port , stats );
148
+ break ;
149
+ case NFP_REPR_TYPE_VF :
150
+ nfp_repr_vf_get_stats64 (app , port , stats );
151
+ default :
152
+ break ;
153
+ }
154
+ }
155
+
156
+ bool
157
+ nfp_repr_has_offload_stats (const struct net_device * dev , int attr_id )
158
+ {
159
+ switch (attr_id ) {
160
+ case IFLA_OFFLOAD_XSTATS_CPU_HIT :
161
+ return true;
162
+ }
163
+
164
+ return false;
165
+ }
166
+
167
+ static int
168
+ nfp_repr_get_host_stats64 (const struct net_device * netdev ,
169
+ struct rtnl_link_stats64 * stats )
170
+ {
171
+ struct nfp_repr * repr = netdev_priv (netdev );
172
+ int i ;
173
+
174
+ for_each_possible_cpu (i ) {
175
+ u64 tbytes , tpkts , tdrops , rbytes , rpkts ;
176
+ struct nfp_repr_pcpu_stats * repr_stats ;
177
+ unsigned int start ;
178
+
179
+ repr_stats = per_cpu_ptr (repr -> stats , i );
180
+ do {
181
+ start = u64_stats_fetch_begin_irq (& repr_stats -> syncp );
182
+ tbytes = repr_stats -> tx_bytes ;
183
+ tpkts = repr_stats -> tx_packets ;
184
+ tdrops = repr_stats -> tx_drops ;
185
+ rbytes = repr_stats -> rx_bytes ;
186
+ rpkts = repr_stats -> rx_packets ;
187
+ } while (u64_stats_fetch_retry_irq (& repr_stats -> syncp , start ));
188
+
189
+ stats -> tx_bytes += tbytes ;
190
+ stats -> tx_packets += tpkts ;
191
+ stats -> tx_dropped += tdrops ;
192
+ stats -> rx_bytes += rbytes ;
193
+ stats -> rx_packets += rpkts ;
194
+ }
195
+
196
+ return 0 ;
197
+ }
198
+
199
+ int nfp_repr_get_offload_stats (int attr_id , const struct net_device * dev ,
200
+ void * stats )
201
+ {
202
+ switch (attr_id ) {
203
+ case IFLA_OFFLOAD_XSTATS_CPU_HIT :
204
+ return nfp_repr_get_host_stats64 (dev , stats );
205
+ }
206
+
207
+ return - EINVAL ;
208
+ }
209
+
210
+ netdev_tx_t nfp_repr_xmit (struct sk_buff * skb , struct net_device * netdev )
211
+ {
212
+ struct nfp_repr * repr = netdev_priv (netdev );
213
+ unsigned int len = skb -> len ;
214
+ int ret ;
215
+
216
+ skb_dst_drop (skb );
217
+ dst_hold ((struct dst_entry * )repr -> dst );
218
+ skb_dst_set (skb , (struct dst_entry * )repr -> dst );
219
+ skb -> dev = repr -> dst -> u .port_info .lower_dev ;
220
+
221
+ ret = dev_queue_xmit (skb );
222
+ nfp_repr_inc_tx_stats (netdev , len , ret );
223
+
224
+ return ret ;
225
+ }
226
+
44
227
static void nfp_repr_clean (struct nfp_repr * repr )
45
228
{
46
229
unregister_netdev (repr -> netdev );
@@ -93,6 +276,12 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
93
276
return err ;
94
277
}
95
278
279
+ static void nfp_repr_free (struct nfp_repr * repr )
280
+ {
281
+ free_percpu (repr -> stats );
282
+ free_netdev (repr -> netdev );
283
+ }
284
+
96
285
struct net_device * nfp_repr_alloc (struct nfp_app * app )
97
286
{
98
287
struct net_device * netdev ;
@@ -106,15 +295,23 @@ struct net_device *nfp_repr_alloc(struct nfp_app *app)
106
295
repr -> netdev = netdev ;
107
296
repr -> app = app ;
108
297
298
+ repr -> stats = netdev_alloc_pcpu_stats (struct nfp_repr_pcpu_stats );
299
+ if (!repr -> stats )
300
+ goto err_free_netdev ;
301
+
109
302
return netdev ;
303
+
304
+ err_free_netdev :
305
+ free_netdev (netdev );
306
+ return NULL ;
110
307
}
111
308
112
309
static void nfp_repr_clean_and_free (struct nfp_repr * repr )
113
310
{
114
311
nfp_info (repr -> app -> cpp , "Destroying Representor(%s)\n" ,
115
312
repr -> netdev -> name );
116
313
nfp_repr_clean (repr );
117
- free_netdev (repr -> netdev );
314
+ nfp_repr_free (repr );
118
315
}
119
316
120
317
void nfp_reprs_clean_and_free (struct nfp_reprs * reprs )
0 commit comments