1 // SPDX-License-Identifier: GPL-2.0
2 /* Texas Instruments ICSSG Ethernet driver
4 * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
8 #include "icssg_prueth.h"
9 #include "icssg_stats.h"
11 static void emac_get_drvinfo(struct net_device
*ndev
,
12 struct ethtool_drvinfo
*info
)
14 struct prueth_emac
*emac
= netdev_priv(ndev
);
15 struct prueth
*prueth
= emac
->prueth
;
17 strscpy(info
->driver
, dev_driver_string(prueth
->dev
),
18 sizeof(info
->driver
));
19 strscpy(info
->bus_info
, dev_name(prueth
->dev
), sizeof(info
->bus_info
));
22 static u32
emac_get_msglevel(struct net_device
*ndev
)
24 struct prueth_emac
*emac
= netdev_priv(ndev
);
26 return emac
->msg_enable
;
29 static void emac_set_msglevel(struct net_device
*ndev
, u32 value
)
31 struct prueth_emac
*emac
= netdev_priv(ndev
);
33 emac
->msg_enable
= value
;
36 static int emac_get_link_ksettings(struct net_device
*ndev
,
37 struct ethtool_link_ksettings
*ecmd
)
39 return phy_ethtool_get_link_ksettings(ndev
, ecmd
);
42 static int emac_set_link_ksettings(struct net_device
*ndev
,
43 const struct ethtool_link_ksettings
*ecmd
)
45 return phy_ethtool_set_link_ksettings(ndev
, ecmd
);
48 static int emac_get_eee(struct net_device
*ndev
, struct ethtool_keee
*edata
)
53 return phy_ethtool_get_eee(ndev
->phydev
, edata
);
56 static int emac_set_eee(struct net_device
*ndev
, struct ethtool_keee
*edata
)
61 return phy_ethtool_set_eee(ndev
->phydev
, edata
);
64 static int emac_nway_reset(struct net_device
*ndev
)
66 return phy_ethtool_nway_reset(ndev
);
69 static int emac_get_sset_count(struct net_device
*ndev
, int stringset
)
71 struct prueth_emac
*emac
= netdev_priv(ndev
);
74 if (emac
->prueth
->pa_stats
)
75 return ICSSG_NUM_ETHTOOL_STATS
;
77 return ICSSG_NUM_ETHTOOL_STATS
- ICSSG_NUM_PA_STATS
;
83 static void emac_get_strings(struct net_device
*ndev
, u32 stringset
, u8
*data
)
85 struct prueth_emac
*emac
= netdev_priv(ndev
);
91 for (i
= 0; i
< ARRAY_SIZE(icssg_all_miig_stats
); i
++)
92 if (!icssg_all_miig_stats
[i
].standard_stats
)
93 ethtool_puts(&p
, icssg_all_miig_stats
[i
].name
);
94 if (emac
->prueth
->pa_stats
)
95 for (i
= 0; i
< ARRAY_SIZE(icssg_all_pa_stats
); i
++)
96 ethtool_puts(&p
, icssg_all_pa_stats
[i
].name
);
103 static void emac_get_ethtool_stats(struct net_device
*ndev
,
104 struct ethtool_stats
*stats
, u64
*data
)
106 struct prueth_emac
*emac
= netdev_priv(ndev
);
109 emac_update_hardware_stats(emac
);
111 for (i
= 0; i
< ARRAY_SIZE(icssg_all_miig_stats
); i
++)
112 if (!icssg_all_miig_stats
[i
].standard_stats
)
113 *(data
++) = emac
->stats
[i
];
115 if (emac
->prueth
->pa_stats
)
116 for (i
= 0; i
< ARRAY_SIZE(icssg_all_pa_stats
); i
++)
117 *(data
++) = emac
->pa_stats
[i
];
120 static int emac_get_ts_info(struct net_device
*ndev
,
121 struct kernel_ethtool_ts_info
*info
)
123 struct prueth_emac
*emac
= netdev_priv(ndev
);
125 info
->so_timestamping
=
126 SOF_TIMESTAMPING_TX_HARDWARE
|
127 SOF_TIMESTAMPING_TX_SOFTWARE
|
128 SOF_TIMESTAMPING_RX_HARDWARE
|
129 SOF_TIMESTAMPING_RAW_HARDWARE
;
131 info
->phc_index
= icss_iep_get_ptp_clock_idx(emac
->iep
);
132 info
->tx_types
= BIT(HWTSTAMP_TX_OFF
) | BIT(HWTSTAMP_TX_ON
);
133 info
->rx_filters
= BIT(HWTSTAMP_FILTER_NONE
) | BIT(HWTSTAMP_FILTER_ALL
);
138 static int emac_set_channels(struct net_device
*ndev
,
139 struct ethtool_channels
*ch
)
141 struct prueth_emac
*emac
= netdev_priv(ndev
);
143 /* Check if interface is up. Can change the num queues when
144 * the interface is down.
146 if (netif_running(emac
->ndev
))
149 emac
->tx_ch_num
= ch
->tx_count
;
157 static void emac_get_channels(struct net_device
*ndev
,
158 struct ethtool_channels
*ch
)
160 struct prueth_emac
*emac
= netdev_priv(ndev
);
163 ch
->max_tx
= PRUETH_MAX_TX_QUEUES
;
165 /* Disable multiple TX channels due to timeouts
166 * when using more than one queue */
171 ch
->tx_count
= emac
->tx_ch_num
;
177 static const struct ethtool_rmon_hist_range emac_rmon_ranges
[] = {
182 { 513, PRUETH_MAX_PKT_SIZE
},
186 static void emac_get_rmon_stats(struct net_device
*ndev
,
187 struct ethtool_rmon_stats
*rmon_stats
,
188 const struct ethtool_rmon_hist_range
**ranges
)
190 struct prueth_emac
*emac
= netdev_priv(ndev
);
192 *ranges
= emac_rmon_ranges
;
194 rmon_stats
->undersize_pkts
= emac_get_stat_by_name(emac
, "rx_bucket1_frames") -
195 emac_get_stat_by_name(emac
, "rx_64B_frames");
197 rmon_stats
->hist
[0] = emac_get_stat_by_name(emac
, "rx_bucket1_frames");
198 rmon_stats
->hist
[1] = emac_get_stat_by_name(emac
, "rx_bucket2_frames");
199 rmon_stats
->hist
[2] = emac_get_stat_by_name(emac
, "rx_bucket3_frames");
200 rmon_stats
->hist
[3] = emac_get_stat_by_name(emac
, "rx_bucket4_frames");
201 rmon_stats
->hist
[4] = emac_get_stat_by_name(emac
, "rx_bucket5_frames");
203 rmon_stats
->hist_tx
[0] = emac_get_stat_by_name(emac
, "tx_bucket1_frames");
204 rmon_stats
->hist_tx
[1] = emac_get_stat_by_name(emac
, "tx_bucket2_frames");
205 rmon_stats
->hist_tx
[2] = emac_get_stat_by_name(emac
, "tx_bucket3_frames");
206 rmon_stats
->hist_tx
[3] = emac_get_stat_by_name(emac
, "tx_bucket4_frames");
207 rmon_stats
->hist_tx
[4] = emac_get_stat_by_name(emac
, "tx_bucket5_frames");
210 static int emac_get_coalesce(struct net_device
*ndev
,
211 struct ethtool_coalesce
*coal
,
212 struct kernel_ethtool_coalesce
*kernel_coal
,
213 struct netlink_ext_ack
*extack
)
215 struct prueth_emac
*emac
= netdev_priv(ndev
);
216 struct prueth_tx_chn
*tx_chn
;
218 tx_chn
= &emac
->tx_chns
[0];
220 coal
->rx_coalesce_usecs
= emac
->rx_pace_timeout_ns
/ 1000;
221 coal
->tx_coalesce_usecs
= tx_chn
->tx_pace_timeout_ns
/ 1000;
226 static int emac_get_per_queue_coalesce(struct net_device
*ndev
, u32 queue
,
227 struct ethtool_coalesce
*coal
)
229 struct prueth_emac
*emac
= netdev_priv(ndev
);
230 struct prueth_tx_chn
*tx_chn
;
232 if (queue
>= PRUETH_MAX_TX_QUEUES
)
235 tx_chn
= &emac
->tx_chns
[queue
];
237 coal
->tx_coalesce_usecs
= tx_chn
->tx_pace_timeout_ns
/ 1000;
242 static int emac_set_coalesce(struct net_device
*ndev
,
243 struct ethtool_coalesce
*coal
,
244 struct kernel_ethtool_coalesce
*kernel_coal
,
245 struct netlink_ext_ack
*extack
)
247 struct prueth_emac
*emac
= netdev_priv(ndev
);
248 struct prueth
*prueth
= emac
->prueth
;
249 struct prueth_tx_chn
*tx_chn
;
251 tx_chn
= &emac
->tx_chns
[0];
253 if (coal
->rx_coalesce_usecs
&&
254 coal
->rx_coalesce_usecs
< ICSSG_MIN_COALESCE_USECS
) {
255 dev_info(prueth
->dev
, "defaulting to min value of %dus for rx-usecs\n",
256 ICSSG_MIN_COALESCE_USECS
);
257 coal
->rx_coalesce_usecs
= ICSSG_MIN_COALESCE_USECS
;
260 if (coal
->tx_coalesce_usecs
&&
261 coal
->tx_coalesce_usecs
< ICSSG_MIN_COALESCE_USECS
) {
262 dev_info(prueth
->dev
, "defaulting to min value of %dus for tx-usecs\n",
263 ICSSG_MIN_COALESCE_USECS
);
264 coal
->tx_coalesce_usecs
= ICSSG_MIN_COALESCE_USECS
;
267 emac
->rx_pace_timeout_ns
= coal
->rx_coalesce_usecs
* 1000;
268 tx_chn
->tx_pace_timeout_ns
= coal
->tx_coalesce_usecs
* 1000;
273 static int emac_set_per_queue_coalesce(struct net_device
*ndev
, u32 queue
,
274 struct ethtool_coalesce
*coal
)
276 struct prueth_emac
*emac
= netdev_priv(ndev
);
277 struct prueth
*prueth
= emac
->prueth
;
278 struct prueth_tx_chn
*tx_chn
;
280 if (queue
>= PRUETH_MAX_TX_QUEUES
)
283 tx_chn
= &emac
->tx_chns
[queue
];
285 if (coal
->tx_coalesce_usecs
&&
286 coal
->tx_coalesce_usecs
< ICSSG_MIN_COALESCE_USECS
) {
287 dev_info(prueth
->dev
, "defaulting to min value of %dus for tx-usecs for tx-%u\n",
288 ICSSG_MIN_COALESCE_USECS
, queue
);
289 coal
->tx_coalesce_usecs
= ICSSG_MIN_COALESCE_USECS
;
292 tx_chn
->tx_pace_timeout_ns
= coal
->tx_coalesce_usecs
* 1000;
297 const struct ethtool_ops icssg_ethtool_ops
= {
298 .get_drvinfo
= emac_get_drvinfo
,
299 .get_msglevel
= emac_get_msglevel
,
300 .set_msglevel
= emac_set_msglevel
,
301 .get_sset_count
= emac_get_sset_count
,
302 .get_ethtool_stats
= emac_get_ethtool_stats
,
303 .get_strings
= emac_get_strings
,
304 .get_ts_info
= emac_get_ts_info
,
305 .supported_coalesce_params
= ETHTOOL_COALESCE_RX_USECS
|
306 ETHTOOL_COALESCE_TX_USECS
,
307 .get_coalesce
= emac_get_coalesce
,
308 .set_coalesce
= emac_set_coalesce
,
309 .get_per_queue_coalesce
= emac_get_per_queue_coalesce
,
310 .set_per_queue_coalesce
= emac_set_per_queue_coalesce
,
311 .get_channels
= emac_get_channels
,
312 .set_channels
= emac_set_channels
,
313 .get_link_ksettings
= emac_get_link_ksettings
,
314 .set_link_ksettings
= emac_set_link_ksettings
,
315 .get_link
= ethtool_op_get_link
,
316 .get_eee
= emac_get_eee
,
317 .set_eee
= emac_set_eee
,
318 .nway_reset
= emac_nway_reset
,
319 .get_rmon_stats
= emac_get_rmon_stats
,
321 EXPORT_SYMBOL_GPL(icssg_ethtool_ops
);