1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright IBM Corp. 2018
6 #define KMSG_COMPONENT "qeth"
7 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
9 #include <linux/ethtool.h>
10 #include "qeth_core.h"
13 #define QETH_TXQ_STAT(_name, _stat) { \
15 .offset = offsetof(struct qeth_out_q_stats, _stat) \
18 #define QETH_CARD_STAT(_name, _stat) { \
20 .offset = offsetof(struct qeth_card_stats, _stat) \
24 char name
[ETH_GSTRING_LEN
];
28 static const struct qeth_stats txq_stats
[] = {
29 QETH_TXQ_STAT("IO buffers", bufs
),
30 QETH_TXQ_STAT("IO buffer elements", buf_elements
),
31 QETH_TXQ_STAT("packed IO buffers", bufs_pack
),
32 QETH_TXQ_STAT("skbs", tx_packets
),
33 QETH_TXQ_STAT("packed skbs", skbs_pack
),
34 QETH_TXQ_STAT("SG skbs", skbs_sg
),
35 QETH_TXQ_STAT("HW csum skbs", skbs_csum
),
36 QETH_TXQ_STAT("TSO skbs", skbs_tso
),
37 QETH_TXQ_STAT("linearized skbs", skbs_linearized
),
38 QETH_TXQ_STAT("linearized+error skbs", skbs_linearized_fail
),
39 QETH_TXQ_STAT("TSO bytes", tso_bytes
),
40 QETH_TXQ_STAT("Packing mode switches", packing_mode_switch
),
41 QETH_TXQ_STAT("Queue stopped", stopped
),
42 QETH_TXQ_STAT("Doorbell", doorbell
),
43 QETH_TXQ_STAT("IRQ for frames", coal_frames
),
44 QETH_TXQ_STAT("Completion IRQ", completion_irq
),
45 QETH_TXQ_STAT("Completion yield", completion_yield
),
46 QETH_TXQ_STAT("Completion timer", completion_timer
),
49 static const struct qeth_stats card_stats
[] = {
50 QETH_CARD_STAT("rx0 IO buffers", rx_bufs
),
51 QETH_CARD_STAT("rx0 HW csum skbs", rx_skb_csum
),
52 QETH_CARD_STAT("rx0 SG skbs", rx_sg_skbs
),
53 QETH_CARD_STAT("rx0 SG page frags", rx_sg_frags
),
54 QETH_CARD_STAT("rx0 SG page allocs", rx_sg_alloc_page
),
55 QETH_CARD_STAT("rx0 dropped, no memory", rx_dropped_nomem
),
56 QETH_CARD_STAT("rx0 dropped, bad format", rx_dropped_notsupp
),
57 QETH_CARD_STAT("rx0 dropped, runt", rx_dropped_runt
),
60 #define TXQ_STATS_LEN ARRAY_SIZE(txq_stats)
61 #define CARD_STATS_LEN ARRAY_SIZE(card_stats)
63 static void qeth_add_stat_data(u64
**dst
, void *src
,
64 const struct qeth_stats stats
[],
70 for (i
= 0; i
< size
; i
++) {
71 stat
= (char *)src
+ stats
[i
].offset
;
77 static void qeth_add_stat_strings(u8
**data
, const char *prefix
,
78 const struct qeth_stats stats
[],
83 for (i
= 0; i
< size
; i
++)
84 ethtool_sprintf(data
, "%s%s", prefix
, stats
[i
].name
);
87 static int qeth_get_sset_count(struct net_device
*dev
, int stringset
)
89 struct qeth_card
*card
= dev
->ml_priv
;
93 return CARD_STATS_LEN
+
94 card
->qdio
.no_out_queues
* TXQ_STATS_LEN
;
100 static void qeth_get_ethtool_stats(struct net_device
*dev
,
101 struct ethtool_stats
*stats
, u64
*data
)
103 struct qeth_card
*card
= dev
->ml_priv
;
106 qeth_add_stat_data(&data
, &card
->stats
, card_stats
, CARD_STATS_LEN
);
107 for (i
= 0; i
< card
->qdio
.no_out_queues
; i
++)
108 qeth_add_stat_data(&data
, &card
->qdio
.out_qs
[i
]->stats
,
109 txq_stats
, TXQ_STATS_LEN
);
112 static void __qeth_set_coalesce(struct net_device
*dev
,
113 struct qeth_qdio_out_q
*queue
,
114 struct ethtool_coalesce
*coal
)
116 WRITE_ONCE(queue
->coalesce_usecs
, coal
->tx_coalesce_usecs
);
117 WRITE_ONCE(queue
->max_coalesced_frames
, coal
->tx_max_coalesced_frames
);
119 if (coal
->tx_coalesce_usecs
&&
120 netif_running(dev
) &&
121 !qeth_out_queue_is_empty(queue
))
122 qeth_tx_arm_timer(queue
, coal
->tx_coalesce_usecs
);
125 static int qeth_set_coalesce(struct net_device
*dev
,
126 struct ethtool_coalesce
*coal
,
127 struct kernel_ethtool_coalesce
*kernel_coal
,
128 struct netlink_ext_ack
*extack
)
130 struct qeth_card
*card
= dev
->ml_priv
;
131 struct qeth_qdio_out_q
*queue
;
137 if (!coal
->tx_coalesce_usecs
&& !coal
->tx_max_coalesced_frames
)
140 qeth_for_each_output_queue(card
, queue
, i
)
141 __qeth_set_coalesce(dev
, queue
, coal
);
146 static void qeth_get_ringparam(struct net_device
*dev
,
147 struct ethtool_ringparam
*param
,
148 struct kernel_ethtool_ringparam
*kernel_param
,
149 struct netlink_ext_ack
*extack
)
151 struct qeth_card
*card
= dev
->ml_priv
;
153 param
->rx_max_pending
= QDIO_MAX_BUFFERS_PER_Q
;
154 param
->rx_mini_max_pending
= 0;
155 param
->rx_jumbo_max_pending
= 0;
156 param
->tx_max_pending
= QDIO_MAX_BUFFERS_PER_Q
;
158 param
->rx_pending
= card
->qdio
.in_buf_pool
.buf_count
;
159 param
->rx_mini_pending
= 0;
160 param
->rx_jumbo_pending
= 0;
161 param
->tx_pending
= QDIO_MAX_BUFFERS_PER_Q
;
164 static void qeth_get_strings(struct net_device
*dev
, u32 stringset
, u8
*data
)
166 struct qeth_card
*card
= dev
->ml_priv
;
167 char prefix
[ETH_GSTRING_LEN
] = "";
172 qeth_add_stat_strings(&data
, prefix
, card_stats
,
174 for (i
= 0; i
< card
->qdio
.no_out_queues
; i
++) {
175 scnprintf(prefix
, ETH_GSTRING_LEN
, "tx%u ", i
);
176 qeth_add_stat_strings(&data
, prefix
, txq_stats
,
186 static void qeth_get_drvinfo(struct net_device
*dev
,
187 struct ethtool_drvinfo
*info
)
189 struct qeth_card
*card
= dev
->ml_priv
;
191 strscpy(info
->driver
, IS_LAYER2(card
) ? "qeth_l2" : "qeth_l3",
192 sizeof(info
->driver
));
193 strscpy(info
->fw_version
, card
->info
.mcl_level
,
194 sizeof(info
->fw_version
));
195 scnprintf(info
->bus_info
, sizeof(info
->bus_info
), "%s/%s/%s",
196 CARD_RDEV_ID(card
), CARD_WDEV_ID(card
), CARD_DDEV_ID(card
));
199 static void qeth_get_channels(struct net_device
*dev
,
200 struct ethtool_channels
*channels
)
202 struct qeth_card
*card
= dev
->ml_priv
;
204 channels
->max_rx
= dev
->num_rx_queues
;
205 channels
->max_tx
= card
->qdio
.no_out_queues
;
206 channels
->max_other
= 0;
207 channels
->max_combined
= 0;
208 channels
->rx_count
= dev
->real_num_rx_queues
;
209 channels
->tx_count
= dev
->real_num_tx_queues
;
210 channels
->other_count
= 0;
211 channels
->combined_count
= 0;
214 static int qeth_set_channels(struct net_device
*dev
,
215 struct ethtool_channels
*channels
)
217 struct qeth_priv
*priv
= netdev_priv(dev
);
218 struct qeth_card
*card
= dev
->ml_priv
;
221 if (channels
->rx_count
== 0 || channels
->tx_count
== 0)
223 if (channels
->tx_count
> card
->qdio
.no_out_queues
)
226 /* Prio-queueing needs all TX queues: */
227 if (qeth_uses_tx_prio_queueing(card
))
231 if (channels
->tx_count
< QETH_IQD_MIN_TXQ
)
234 /* Reject downgrade while running. It could push displaced
235 * ucast flows onto txq0, which is reserved for mcast.
237 if (netif_running(dev
) &&
238 channels
->tx_count
< dev
->real_num_tx_queues
)
242 rc
= qeth_set_real_num_tx_queues(card
, channels
->tx_count
);
244 priv
->tx_wanted_queues
= channels
->tx_count
;
249 static int qeth_get_ts_info(struct net_device
*dev
,
250 struct kernel_ethtool_ts_info
*info
)
252 struct qeth_card
*card
= dev
->ml_priv
;
257 return ethtool_op_get_ts_info(dev
, info
);
260 static int qeth_get_tunable(struct net_device
*dev
,
261 const struct ethtool_tunable
*tuna
, void *data
)
263 struct qeth_priv
*priv
= netdev_priv(dev
);
266 case ETHTOOL_RX_COPYBREAK
:
267 *(u32
*)data
= priv
->rx_copybreak
;
274 static int qeth_set_tunable(struct net_device
*dev
,
275 const struct ethtool_tunable
*tuna
,
278 struct qeth_priv
*priv
= netdev_priv(dev
);
281 case ETHTOOL_RX_COPYBREAK
:
282 WRITE_ONCE(priv
->rx_copybreak
, *(u32
*)data
);
289 static int qeth_get_per_queue_coalesce(struct net_device
*dev
, u32 __queue
,
290 struct ethtool_coalesce
*coal
)
292 struct qeth_card
*card
= dev
->ml_priv
;
293 struct qeth_qdio_out_q
*queue
;
298 if (__queue
>= card
->qdio
.no_out_queues
)
301 queue
= card
->qdio
.out_qs
[__queue
];
303 coal
->tx_coalesce_usecs
= queue
->coalesce_usecs
;
304 coal
->tx_max_coalesced_frames
= queue
->max_coalesced_frames
;
308 static int qeth_set_per_queue_coalesce(struct net_device
*dev
, u32 queue
,
309 struct ethtool_coalesce
*coal
)
311 struct qeth_card
*card
= dev
->ml_priv
;
316 if (queue
>= card
->qdio
.no_out_queues
)
319 if (!coal
->tx_coalesce_usecs
&& !coal
->tx_max_coalesced_frames
)
322 __qeth_set_coalesce(dev
, card
->qdio
.out_qs
[queue
], coal
);
326 /* Helper function to fill 'advertising' and 'supported' which are the same. */
327 /* Autoneg and full-duplex are supported and advertised unconditionally. */
328 /* Always advertise and support all speeds up to specified, and only one */
329 /* specified port type. */
330 static void qeth_set_ethtool_link_modes(struct ethtool_link_ksettings
*cmd
,
331 enum qeth_link_mode link_mode
)
333 ethtool_link_ksettings_zero_link_mode(cmd
, supported
);
334 ethtool_link_ksettings_zero_link_mode(cmd
, advertising
);
335 ethtool_link_ksettings_zero_link_mode(cmd
, lp_advertising
);
337 ethtool_link_ksettings_add_link_mode(cmd
, supported
, Autoneg
);
338 ethtool_link_ksettings_add_link_mode(cmd
, advertising
, Autoneg
);
340 switch (cmd
->base
.port
) {
342 ethtool_link_ksettings_add_link_mode(cmd
, supported
, TP
);
343 ethtool_link_ksettings_add_link_mode(cmd
, advertising
, TP
);
345 switch (cmd
->base
.speed
) {
347 ethtool_link_ksettings_add_link_mode(cmd
, supported
,
349 ethtool_link_ksettings_add_link_mode(cmd
, advertising
,
353 ethtool_link_ksettings_add_link_mode(cmd
, supported
,
355 ethtool_link_ksettings_add_link_mode(cmd
, advertising
,
357 ethtool_link_ksettings_add_link_mode(cmd
, supported
,
359 ethtool_link_ksettings_add_link_mode(cmd
, advertising
,
363 ethtool_link_ksettings_add_link_mode(cmd
, supported
,
365 ethtool_link_ksettings_add_link_mode(cmd
, advertising
,
367 ethtool_link_ksettings_add_link_mode(cmd
, supported
,
369 ethtool_link_ksettings_add_link_mode(cmd
, advertising
,
373 ethtool_link_ksettings_add_link_mode(cmd
, supported
,
375 ethtool_link_ksettings_add_link_mode(cmd
, advertising
,
377 ethtool_link_ksettings_add_link_mode(cmd
, supported
,
379 ethtool_link_ksettings_add_link_mode(cmd
, advertising
,
388 ethtool_link_ksettings_add_link_mode(cmd
, supported
, FIBRE
);
389 ethtool_link_ksettings_add_link_mode(cmd
, advertising
, FIBRE
);
391 switch (cmd
->base
.speed
) {
393 ethtool_link_ksettings_add_link_mode(cmd
, supported
,
395 ethtool_link_ksettings_add_link_mode(cmd
, advertising
,
399 if (link_mode
== QETH_LINK_MODE_FIBRE_LONG
) {
400 ethtool_link_ksettings_add_link_mode(cmd
, supported
,
402 ethtool_link_ksettings_add_link_mode(cmd
, advertising
,
404 } else if (link_mode
== QETH_LINK_MODE_FIBRE_SHORT
) {
405 ethtool_link_ksettings_add_link_mode(cmd
, supported
,
407 ethtool_link_ksettings_add_link_mode(cmd
, advertising
,
412 ethtool_link_ksettings_add_link_mode(cmd
, supported
,
414 ethtool_link_ksettings_add_link_mode(cmd
, advertising
,
427 static int qeth_get_link_ksettings(struct net_device
*netdev
,
428 struct ethtool_link_ksettings
*cmd
)
430 struct qeth_card
*card
= netdev
->ml_priv
;
432 QETH_CARD_TEXT(card
, 4, "ethtglks");
433 cmd
->base
.speed
= card
->info
.link_info
.speed
;
434 cmd
->base
.duplex
= card
->info
.link_info
.duplex
;
435 cmd
->base
.port
= card
->info
.link_info
.port
;
436 cmd
->base
.autoneg
= AUTONEG_ENABLE
;
437 cmd
->base
.phy_address
= 0;
438 cmd
->base
.mdio_support
= 0;
439 cmd
->base
.eth_tp_mdix
= ETH_TP_MDI_INVALID
;
440 cmd
->base
.eth_tp_mdix_ctrl
= ETH_TP_MDI_INVALID
;
442 qeth_set_ethtool_link_modes(cmd
, card
->info
.link_info
.link_mode
);
447 const struct ethtool_ops qeth_ethtool_ops
= {
448 .supported_coalesce_params
= ETHTOOL_COALESCE_TX_USECS
|
449 ETHTOOL_COALESCE_TX_MAX_FRAMES
,
450 .get_link
= ethtool_op_get_link
,
451 .set_coalesce
= qeth_set_coalesce
,
452 .get_ringparam
= qeth_get_ringparam
,
453 .get_strings
= qeth_get_strings
,
454 .get_ethtool_stats
= qeth_get_ethtool_stats
,
455 .get_sset_count
= qeth_get_sset_count
,
456 .get_drvinfo
= qeth_get_drvinfo
,
457 .get_channels
= qeth_get_channels
,
458 .set_channels
= qeth_set_channels
,
459 .get_ts_info
= qeth_get_ts_info
,
460 .get_tunable
= qeth_get_tunable
,
461 .set_tunable
= qeth_set_tunable
,
462 .get_per_queue_coalesce
= qeth_get_per_queue_coalesce
,
463 .set_per_queue_coalesce
= qeth_set_per_queue_coalesce
,
464 .get_link_ksettings
= qeth_get_link_ksettings
,