3232 */
3333
3434#include <linux/etherdevice.h>
35+ #include <linux/io-64-nonatomic-hi-lo.h>
3536#include <linux/lockdep.h>
3637#include <net/dst_metadata.h>
3738
3839#include "nfpcore/nfp_cpp.h"
3940#include "nfp_app.h"
4041#include "nfp_main.h"
42+ #include "nfp_net_ctrl.h"
4143#include "nfp_net_repr.h"
4244#include "nfp_port.h"
4345
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+
44227static void nfp_repr_clean (struct nfp_repr * repr )
45228{
46229 unregister_netdev (repr -> netdev );
@@ -93,6 +276,12 @@ int nfp_repr_init(struct nfp_app *app, struct net_device *netdev,
93276 return err ;
94277}
95278
279+ static void nfp_repr_free (struct nfp_repr * repr )
280+ {
281+ free_percpu (repr -> stats );
282+ free_netdev (repr -> netdev );
283+ }
284+
96285struct net_device * nfp_repr_alloc (struct nfp_app * app )
97286{
98287 struct net_device * netdev ;
@@ -106,15 +295,23 @@ struct net_device *nfp_repr_alloc(struct nfp_app *app)
106295 repr -> netdev = netdev ;
107296 repr -> app = app ;
108297
298+ repr -> stats = netdev_alloc_pcpu_stats (struct nfp_repr_pcpu_stats );
299+ if (!repr -> stats )
300+ goto err_free_netdev ;
301+
109302 return netdev ;
303+
304+ err_free_netdev :
305+ free_netdev (netdev );
306+ return NULL ;
110307}
111308
112309static void nfp_repr_clean_and_free (struct nfp_repr * repr )
113310{
114311 nfp_info (repr -> app -> cpp , "Destroying Representor(%s)\n" ,
115312 repr -> netdev -> name );
116313 nfp_repr_clean (repr );
117- free_netdev (repr -> netdev );
314+ nfp_repr_free (repr );
118315}
119316
120317void nfp_reprs_clean_and_free (struct nfp_reprs * reprs )
0 commit comments