2 * FUJITSU Extended Socket Network Device driver
3 * Copyright (c) 2015 FUJITSU LIMITED
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, see <http://www.gnu.org/licenses/>.
17 * The full GNU General Public License is included in this distribution in
18 * the file called "COPYING".
22 /* ethtool support for fjes */
24 #include <linux/vmalloc.h>
25 #include <linux/netdevice.h>
26 #include <linux/ethtool.h>
27 #include <linux/platform_device.h>
32 char stat_string
[ETH_GSTRING_LEN
];
37 #define FJES_STAT(name, stat) { \
38 .stat_string = name, \
39 .sizeof_stat = FIELD_SIZEOF(struct fjes_adapter, stat), \
40 .stat_offset = offsetof(struct fjes_adapter, stat) \
43 static const struct fjes_stats fjes_gstrings_stats
[] = {
44 FJES_STAT("rx_packets", stats64
.rx_packets
),
45 FJES_STAT("tx_packets", stats64
.tx_packets
),
46 FJES_STAT("rx_bytes", stats64
.rx_bytes
),
47 FJES_STAT("tx_bytes", stats64
.rx_bytes
),
48 FJES_STAT("rx_dropped", stats64
.rx_dropped
),
49 FJES_STAT("tx_dropped", stats64
.tx_dropped
),
52 #define FJES_EP_STATS_LEN 14
53 #define FJES_STATS_LEN \
54 (ARRAY_SIZE(fjes_gstrings_stats) + \
55 ((&((struct fjes_adapter *)netdev_priv(netdev))->hw)->max_epid - 1) * \
58 static void fjes_get_ethtool_stats(struct net_device
*netdev
,
59 struct ethtool_stats
*stats
, u64
*data
)
61 struct fjes_adapter
*adapter
= netdev_priv(netdev
);
62 struct fjes_hw
*hw
= &adapter
->hw
;
67 for (i
= 0; i
< ARRAY_SIZE(fjes_gstrings_stats
); i
++) {
68 p
= (char *)adapter
+ fjes_gstrings_stats
[i
].stat_offset
;
69 data
[i
] = (fjes_gstrings_stats
[i
].sizeof_stat
== sizeof(u64
))
70 ? *(u64
*)p
: *(u32
*)p
;
72 for (epidx
= 0; epidx
< hw
->max_epid
; epidx
++) {
73 if (epidx
== hw
->my_epid
)
75 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
77 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
78 .com_unregist_buf_exec
;
79 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
.send_intr_rx
;
80 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
.send_intr_unshare
;
81 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
82 .send_intr_zoneupdate
;
83 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
.recv_intr_rx
;
84 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
.recv_intr_unshare
;
85 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
.recv_intr_stop
;
86 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
87 .recv_intr_zoneupdate
;
88 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
.tx_buffer_full
;
89 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
90 .tx_dropped_not_shared
;
91 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
92 .tx_dropped_ver_mismatch
;
93 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
94 .tx_dropped_buf_size_mismatch
;
95 data
[i
++] = hw
->ep_shm_info
[epidx
].ep_stats
96 .tx_dropped_vlanid_mismatch
;
100 static void fjes_get_strings(struct net_device
*netdev
,
101 u32 stringset
, u8
*data
)
103 struct fjes_adapter
*adapter
= netdev_priv(netdev
);
104 struct fjes_hw
*hw
= &adapter
->hw
;
110 for (i
= 0; i
< ARRAY_SIZE(fjes_gstrings_stats
); i
++) {
111 memcpy(p
, fjes_gstrings_stats
[i
].stat_string
,
113 p
+= ETH_GSTRING_LEN
;
115 for (i
= 0; i
< hw
->max_epid
; i
++) {
116 if (i
== hw
->my_epid
)
118 sprintf(p
, "ep%u_com_regist_buf_exec", i
);
119 p
+= ETH_GSTRING_LEN
;
120 sprintf(p
, "ep%u_com_unregist_buf_exec", i
);
121 p
+= ETH_GSTRING_LEN
;
122 sprintf(p
, "ep%u_send_intr_rx", i
);
123 p
+= ETH_GSTRING_LEN
;
124 sprintf(p
, "ep%u_send_intr_unshare", i
);
125 p
+= ETH_GSTRING_LEN
;
126 sprintf(p
, "ep%u_send_intr_zoneupdate", i
);
127 p
+= ETH_GSTRING_LEN
;
128 sprintf(p
, "ep%u_recv_intr_rx", i
);
129 p
+= ETH_GSTRING_LEN
;
130 sprintf(p
, "ep%u_recv_intr_unshare", i
);
131 p
+= ETH_GSTRING_LEN
;
132 sprintf(p
, "ep%u_recv_intr_stop", i
);
133 p
+= ETH_GSTRING_LEN
;
134 sprintf(p
, "ep%u_recv_intr_zoneupdate", i
);
135 p
+= ETH_GSTRING_LEN
;
136 sprintf(p
, "ep%u_tx_buffer_full", i
);
137 p
+= ETH_GSTRING_LEN
;
138 sprintf(p
, "ep%u_tx_dropped_not_shared", i
);
139 p
+= ETH_GSTRING_LEN
;
140 sprintf(p
, "ep%u_tx_dropped_ver_mismatch", i
);
141 p
+= ETH_GSTRING_LEN
;
142 sprintf(p
, "ep%u_tx_dropped_buf_size_mismatch", i
);
143 p
+= ETH_GSTRING_LEN
;
144 sprintf(p
, "ep%u_tx_dropped_vlanid_mismatch", i
);
145 p
+= ETH_GSTRING_LEN
;
151 static int fjes_get_sset_count(struct net_device
*netdev
, int sset
)
155 return FJES_STATS_LEN
;
161 static void fjes_get_drvinfo(struct net_device
*netdev
,
162 struct ethtool_drvinfo
*drvinfo
)
164 struct fjes_adapter
*adapter
= netdev_priv(netdev
);
165 struct platform_device
*plat_dev
;
167 plat_dev
= adapter
->plat_dev
;
169 strlcpy(drvinfo
->driver
, fjes_driver_name
, sizeof(drvinfo
->driver
));
170 strlcpy(drvinfo
->version
, fjes_driver_version
,
171 sizeof(drvinfo
->version
));
173 strlcpy(drvinfo
->fw_version
, "none", sizeof(drvinfo
->fw_version
));
174 snprintf(drvinfo
->bus_info
, sizeof(drvinfo
->bus_info
),
175 "platform:%s", plat_dev
->name
);
178 static int fjes_get_settings(struct net_device
*netdev
,
179 struct ethtool_cmd
*ecmd
)
182 ecmd
->advertising
= 0;
183 ecmd
->duplex
= DUPLEX_FULL
;
184 ecmd
->autoneg
= AUTONEG_DISABLE
;
185 ecmd
->transceiver
= XCVR_DUMMY1
;
186 ecmd
->port
= PORT_NONE
;
187 ethtool_cmd_speed_set(ecmd
, 20000); /* 20Gb/s */
192 static int fjes_get_regs_len(struct net_device
*netdev
)
194 #define FJES_REGS_LEN 37
195 return FJES_REGS_LEN
* sizeof(u32
);
198 static void fjes_get_regs(struct net_device
*netdev
,
199 struct ethtool_regs
*regs
, void *p
)
201 struct fjes_adapter
*adapter
= netdev_priv(netdev
);
202 struct fjes_hw
*hw
= &adapter
->hw
;
205 memset(p
, 0, FJES_REGS_LEN
* sizeof(u32
));
209 /* Information registers */
210 regs_buff
[0] = rd32(XSCT_OWNER_EPID
);
211 regs_buff
[1] = rd32(XSCT_MAX_EP
);
213 /* Device Control registers */
214 regs_buff
[4] = rd32(XSCT_DCTL
);
216 /* Command Control registers */
217 regs_buff
[8] = rd32(XSCT_CR
);
218 regs_buff
[9] = rd32(XSCT_CS
);
219 regs_buff
[10] = rd32(XSCT_SHSTSAL
);
220 regs_buff
[11] = rd32(XSCT_SHSTSAH
);
222 regs_buff
[13] = rd32(XSCT_REQBL
);
223 regs_buff
[14] = rd32(XSCT_REQBAL
);
224 regs_buff
[15] = rd32(XSCT_REQBAH
);
226 regs_buff
[17] = rd32(XSCT_RESPBL
);
227 regs_buff
[18] = rd32(XSCT_RESPBAL
);
228 regs_buff
[19] = rd32(XSCT_RESPBAH
);
230 /* Interrupt Control registers */
231 regs_buff
[32] = rd32(XSCT_IS
);
232 regs_buff
[33] = rd32(XSCT_IMS
);
233 regs_buff
[34] = rd32(XSCT_IMC
);
234 regs_buff
[35] = rd32(XSCT_IG
);
235 regs_buff
[36] = rd32(XSCT_ICTL
);
238 static int fjes_set_dump(struct net_device
*netdev
, struct ethtool_dump
*dump
)
240 struct fjes_adapter
*adapter
= netdev_priv(netdev
);
241 struct fjes_hw
*hw
= &adapter
->hw
;
248 hw
->debug_mode
= dump
->flag
;
250 /* enable debug mode */
251 mutex_lock(&hw
->hw_info
.lock
);
252 ret
= fjes_hw_start_debug(hw
);
253 mutex_unlock(&hw
->hw_info
.lock
);
261 /* disable debug mode */
262 mutex_lock(&hw
->hw_info
.lock
);
263 ret
= fjes_hw_stop_debug(hw
);
264 mutex_unlock(&hw
->hw_info
.lock
);
270 static int fjes_get_dump_flag(struct net_device
*netdev
,
271 struct ethtool_dump
*dump
)
273 struct fjes_adapter
*adapter
= netdev_priv(netdev
);
274 struct fjes_hw
*hw
= &adapter
->hw
;
276 dump
->len
= hw
->hw_info
.trace_size
;
278 dump
->flag
= hw
->debug_mode
;
283 static int fjes_get_dump_data(struct net_device
*netdev
,
284 struct ethtool_dump
*dump
, void *buf
)
286 struct fjes_adapter
*adapter
= netdev_priv(netdev
);
287 struct fjes_hw
*hw
= &adapter
->hw
;
290 if (hw
->hw_info
.trace
)
291 memcpy(buf
, hw
->hw_info
.trace
, hw
->hw_info
.trace_size
);
298 static const struct ethtool_ops fjes_ethtool_ops
= {
299 .get_settings
= fjes_get_settings
,
300 .get_drvinfo
= fjes_get_drvinfo
,
301 .get_ethtool_stats
= fjes_get_ethtool_stats
,
302 .get_strings
= fjes_get_strings
,
303 .get_sset_count
= fjes_get_sset_count
,
304 .get_regs
= fjes_get_regs
,
305 .get_regs_len
= fjes_get_regs_len
,
306 .set_dump
= fjes_set_dump
,
307 .get_dump_flag
= fjes_get_dump_flag
,
308 .get_dump_data
= fjes_get_dump_data
,
311 void fjes_set_ethtool_ops(struct net_device
*netdev
)
313 netdev
->ethtool_ops
= &fjes_ethtool_ops
;