• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * Copyright IBM Corp. 2018
4   */
5  
6  #define KMSG_COMPONENT "qeth"
7  #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
8  
9  #include <linux/ethtool.h>
10  #include "qeth_core.h"
11  
12  
13  #define QETH_TXQ_STAT(_name, _stat) { \
14  	.name = _name, \
15  	.offset = offsetof(struct qeth_out_q_stats, _stat) \
16  }
17  
18  #define QETH_CARD_STAT(_name, _stat) { \
19  	.name = _name, \
20  	.offset = offsetof(struct qeth_card_stats, _stat) \
21  }
22  
23  struct qeth_stats {
24  	char name[ETH_GSTRING_LEN];
25  	unsigned int offset;
26  };
27  
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("Completion yield", completion_yield),
43  	QETH_TXQ_STAT("Completion timer", completion_timer),
44  };
45  
46  static const struct qeth_stats card_stats[] = {
47  	QETH_CARD_STAT("rx0 IO buffers", rx_bufs),
48  	QETH_CARD_STAT("rx0 HW csum skbs", rx_skb_csum),
49  	QETH_CARD_STAT("rx0 SG skbs", rx_sg_skbs),
50  	QETH_CARD_STAT("rx0 SG page frags", rx_sg_frags),
51  	QETH_CARD_STAT("rx0 SG page allocs", rx_sg_alloc_page),
52  };
53  
54  #define TXQ_STATS_LEN	ARRAY_SIZE(txq_stats)
55  #define CARD_STATS_LEN	ARRAY_SIZE(card_stats)
56  
qeth_add_stat_data(u64 ** dst,void * src,const struct qeth_stats stats[],unsigned int size)57  static void qeth_add_stat_data(u64 **dst, void *src,
58  			       const struct qeth_stats stats[],
59  			       unsigned int size)
60  {
61  	unsigned int i;
62  	char *stat;
63  
64  	for (i = 0; i < size; i++) {
65  		stat = (char *)src + stats[i].offset;
66  		**dst = *(u64 *)stat;
67  		(*dst)++;
68  	}
69  }
70  
qeth_add_stat_strings(u8 ** data,const char * prefix,const struct qeth_stats stats[],unsigned int size)71  static void qeth_add_stat_strings(u8 **data, const char *prefix,
72  				  const struct qeth_stats stats[],
73  				  unsigned int size)
74  {
75  	unsigned int i;
76  
77  	for (i = 0; i < size; i++) {
78  		snprintf(*data, ETH_GSTRING_LEN, "%s%s", prefix, stats[i].name);
79  		*data += ETH_GSTRING_LEN;
80  	}
81  }
82  
qeth_get_sset_count(struct net_device * dev,int stringset)83  static int qeth_get_sset_count(struct net_device *dev, int stringset)
84  {
85  	struct qeth_card *card = dev->ml_priv;
86  
87  	switch (stringset) {
88  	case ETH_SS_STATS:
89  		return CARD_STATS_LEN +
90  		       card->qdio.no_out_queues * TXQ_STATS_LEN;
91  	default:
92  		return -EINVAL;
93  	}
94  }
95  
qeth_get_ethtool_stats(struct net_device * dev,struct ethtool_stats * stats,u64 * data)96  static void qeth_get_ethtool_stats(struct net_device *dev,
97  				   struct ethtool_stats *stats, u64 *data)
98  {
99  	struct qeth_card *card = dev->ml_priv;
100  	unsigned int i;
101  
102  	qeth_add_stat_data(&data, &card->stats, card_stats, CARD_STATS_LEN);
103  	for (i = 0; i < card->qdio.no_out_queues; i++)
104  		qeth_add_stat_data(&data, &card->qdio.out_qs[i]->stats,
105  				   txq_stats, TXQ_STATS_LEN);
106  }
107  
qeth_get_ringparam(struct net_device * dev,struct ethtool_ringparam * param)108  static void qeth_get_ringparam(struct net_device *dev,
109  			       struct ethtool_ringparam *param)
110  {
111  	struct qeth_card *card = dev->ml_priv;
112  
113  	param->rx_max_pending = QDIO_MAX_BUFFERS_PER_Q;
114  	param->rx_mini_max_pending = 0;
115  	param->rx_jumbo_max_pending = 0;
116  	param->tx_max_pending = QDIO_MAX_BUFFERS_PER_Q;
117  
118  	param->rx_pending = card->qdio.in_buf_pool.buf_count;
119  	param->rx_mini_pending = 0;
120  	param->rx_jumbo_pending = 0;
121  	param->tx_pending = QDIO_MAX_BUFFERS_PER_Q;
122  }
123  
qeth_get_strings(struct net_device * dev,u32 stringset,u8 * data)124  static void qeth_get_strings(struct net_device *dev, u32 stringset, u8 *data)
125  {
126  	struct qeth_card *card = dev->ml_priv;
127  	char prefix[ETH_GSTRING_LEN] = "";
128  	unsigned int i;
129  
130  	switch (stringset) {
131  	case ETH_SS_STATS:
132  		qeth_add_stat_strings(&data, prefix, card_stats,
133  				      CARD_STATS_LEN);
134  		for (i = 0; i < card->qdio.no_out_queues; i++) {
135  			snprintf(prefix, ETH_GSTRING_LEN, "tx%u ", i);
136  			qeth_add_stat_strings(&data, prefix, txq_stats,
137  					      TXQ_STATS_LEN);
138  		}
139  		break;
140  	default:
141  		WARN_ON(1);
142  		break;
143  	}
144  }
145  
qeth_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * info)146  static void qeth_get_drvinfo(struct net_device *dev,
147  			     struct ethtool_drvinfo *info)
148  {
149  	struct qeth_card *card = dev->ml_priv;
150  
151  	strlcpy(info->driver, IS_LAYER2(card) ? "qeth_l2" : "qeth_l3",
152  		sizeof(info->driver));
153  	strlcpy(info->version, "1.0", sizeof(info->version));
154  	strlcpy(info->fw_version, card->info.mcl_level,
155  		sizeof(info->fw_version));
156  	snprintf(info->bus_info, sizeof(info->bus_info), "%s/%s/%s",
157  		 CARD_RDEV_ID(card), CARD_WDEV_ID(card), CARD_DDEV_ID(card));
158  }
159  
qeth_get_channels(struct net_device * dev,struct ethtool_channels * channels)160  static void qeth_get_channels(struct net_device *dev,
161  			      struct ethtool_channels *channels)
162  {
163  	struct qeth_card *card = dev->ml_priv;
164  
165  	channels->max_rx = dev->num_rx_queues;
166  	channels->max_tx = card->qdio.no_out_queues;
167  	channels->max_other = 0;
168  	channels->max_combined = 0;
169  	channels->rx_count = dev->real_num_rx_queues;
170  	channels->tx_count = dev->real_num_tx_queues;
171  	channels->other_count = 0;
172  	channels->combined_count = 0;
173  }
174  
175  /* Helper function to fill 'advertising' and 'supported' which are the same. */
176  /* Autoneg and full-duplex are supported and advertised unconditionally.     */
177  /* Always advertise and support all speeds up to specified, and only one     */
178  /* specified port type.							     */
qeth_set_cmd_adv_sup(struct ethtool_link_ksettings * cmd,int maxspeed,int porttype)179  static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd,
180  				int maxspeed, int porttype)
181  {
182  	ethtool_link_ksettings_zero_link_mode(cmd, supported);
183  	ethtool_link_ksettings_zero_link_mode(cmd, advertising);
184  	ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising);
185  
186  	ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
187  	ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
188  
189  	switch (porttype) {
190  	case PORT_TP:
191  		ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
192  		ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
193  		break;
194  	case PORT_FIBRE:
195  		ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
196  		ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
197  		break;
198  	default:
199  		ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
200  		ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
201  		WARN_ON_ONCE(1);
202  	}
203  
204  	/* partially does fall through, to also select lower speeds */
205  	switch (maxspeed) {
206  	case SPEED_25000:
207  		ethtool_link_ksettings_add_link_mode(cmd, supported,
208  						     25000baseSR_Full);
209  		ethtool_link_ksettings_add_link_mode(cmd, advertising,
210  						     25000baseSR_Full);
211  		break;
212  	case SPEED_10000:
213  		ethtool_link_ksettings_add_link_mode(cmd, supported,
214  						     10000baseT_Full);
215  		ethtool_link_ksettings_add_link_mode(cmd, advertising,
216  						     10000baseT_Full);
217  		/* fall through */
218  	case SPEED_1000:
219  		ethtool_link_ksettings_add_link_mode(cmd, supported,
220  						     1000baseT_Full);
221  		ethtool_link_ksettings_add_link_mode(cmd, advertising,
222  						     1000baseT_Full);
223  		ethtool_link_ksettings_add_link_mode(cmd, supported,
224  						     1000baseT_Half);
225  		ethtool_link_ksettings_add_link_mode(cmd, advertising,
226  						     1000baseT_Half);
227  		/* fall through */
228  	case SPEED_100:
229  		ethtool_link_ksettings_add_link_mode(cmd, supported,
230  						     100baseT_Full);
231  		ethtool_link_ksettings_add_link_mode(cmd, advertising,
232  						     100baseT_Full);
233  		ethtool_link_ksettings_add_link_mode(cmd, supported,
234  						     100baseT_Half);
235  		ethtool_link_ksettings_add_link_mode(cmd, advertising,
236  						     100baseT_Half);
237  		/* fall through */
238  	case SPEED_10:
239  		ethtool_link_ksettings_add_link_mode(cmd, supported,
240  						     10baseT_Full);
241  		ethtool_link_ksettings_add_link_mode(cmd, advertising,
242  						     10baseT_Full);
243  		ethtool_link_ksettings_add_link_mode(cmd, supported,
244  						     10baseT_Half);
245  		ethtool_link_ksettings_add_link_mode(cmd, advertising,
246  						     10baseT_Half);
247  		break;
248  	default:
249  		ethtool_link_ksettings_add_link_mode(cmd, supported,
250  						     10baseT_Full);
251  		ethtool_link_ksettings_add_link_mode(cmd, advertising,
252  						     10baseT_Full);
253  		ethtool_link_ksettings_add_link_mode(cmd, supported,
254  						     10baseT_Half);
255  		ethtool_link_ksettings_add_link_mode(cmd, advertising,
256  						     10baseT_Half);
257  		WARN_ON_ONCE(1);
258  	}
259  }
260  
261  
qeth_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * cmd)262  static int qeth_get_link_ksettings(struct net_device *netdev,
263  				   struct ethtool_link_ksettings *cmd)
264  {
265  	struct qeth_card *card = netdev->ml_priv;
266  	enum qeth_link_types link_type;
267  	struct carrier_info carrier_info;
268  	int rc;
269  
270  	if (IS_IQD(card) || IS_VM_NIC(card))
271  		link_type = QETH_LINK_TYPE_10GBIT_ETH;
272  	else
273  		link_type = card->info.link_type;
274  
275  	cmd->base.duplex = DUPLEX_FULL;
276  	cmd->base.autoneg = AUTONEG_ENABLE;
277  	cmd->base.phy_address = 0;
278  	cmd->base.mdio_support = 0;
279  	cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
280  	cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
281  
282  	switch (link_type) {
283  	case QETH_LINK_TYPE_FAST_ETH:
284  	case QETH_LINK_TYPE_LANE_ETH100:
285  		cmd->base.speed = SPEED_100;
286  		cmd->base.port = PORT_TP;
287  		break;
288  	case QETH_LINK_TYPE_GBIT_ETH:
289  	case QETH_LINK_TYPE_LANE_ETH1000:
290  		cmd->base.speed = SPEED_1000;
291  		cmd->base.port = PORT_FIBRE;
292  		break;
293  	case QETH_LINK_TYPE_10GBIT_ETH:
294  		cmd->base.speed = SPEED_10000;
295  		cmd->base.port = PORT_FIBRE;
296  		break;
297  	case QETH_LINK_TYPE_25GBIT_ETH:
298  		cmd->base.speed = SPEED_25000;
299  		cmd->base.port = PORT_FIBRE;
300  		break;
301  	default:
302  		cmd->base.speed = SPEED_10;
303  		cmd->base.port = PORT_TP;
304  	}
305  	qeth_set_cmd_adv_sup(cmd, cmd->base.speed, cmd->base.port);
306  
307  	/* Check if we can obtain more accurate information.	 */
308  	/* If QUERY_CARD_INFO command is not supported or fails, */
309  	/* just return the heuristics that was filled above.	 */
310  	rc = qeth_query_card_info(card, &carrier_info);
311  	if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */
312  		return 0;
313  	if (rc) /* report error from the hardware operation */
314  		return rc;
315  	/* on success, fill in the information got from the hardware */
316  
317  	netdev_dbg(netdev,
318  	"card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
319  			carrier_info.card_type,
320  			carrier_info.port_mode,
321  			carrier_info.port_speed);
322  
323  	/* Update attributes for which we've obtained more authoritative */
324  	/* information, leave the rest the way they where filled above.  */
325  	switch (carrier_info.card_type) {
326  	case CARD_INFO_TYPE_1G_COPPER_A:
327  	case CARD_INFO_TYPE_1G_COPPER_B:
328  		cmd->base.port = PORT_TP;
329  		qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
330  		break;
331  	case CARD_INFO_TYPE_1G_FIBRE_A:
332  	case CARD_INFO_TYPE_1G_FIBRE_B:
333  		cmd->base.port = PORT_FIBRE;
334  		qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
335  		break;
336  	case CARD_INFO_TYPE_10G_FIBRE_A:
337  	case CARD_INFO_TYPE_10G_FIBRE_B:
338  		cmd->base.port = PORT_FIBRE;
339  		qeth_set_cmd_adv_sup(cmd, SPEED_10000, cmd->base.port);
340  		break;
341  	}
342  
343  	switch (carrier_info.port_mode) {
344  	case CARD_INFO_PORTM_FULLDUPLEX:
345  		cmd->base.duplex = DUPLEX_FULL;
346  		break;
347  	case CARD_INFO_PORTM_HALFDUPLEX:
348  		cmd->base.duplex = DUPLEX_HALF;
349  		break;
350  	}
351  
352  	switch (carrier_info.port_speed) {
353  	case CARD_INFO_PORTS_10M:
354  		cmd->base.speed = SPEED_10;
355  		break;
356  	case CARD_INFO_PORTS_100M:
357  		cmd->base.speed = SPEED_100;
358  		break;
359  	case CARD_INFO_PORTS_1G:
360  		cmd->base.speed = SPEED_1000;
361  		break;
362  	case CARD_INFO_PORTS_10G:
363  		cmd->base.speed = SPEED_10000;
364  		break;
365  	case CARD_INFO_PORTS_25G:
366  		cmd->base.speed = SPEED_25000;
367  		break;
368  	}
369  
370  	return 0;
371  }
372  
373  const struct ethtool_ops qeth_ethtool_ops = {
374  	.get_link = ethtool_op_get_link,
375  	.get_ringparam = qeth_get_ringparam,
376  	.get_strings = qeth_get_strings,
377  	.get_ethtool_stats = qeth_get_ethtool_stats,
378  	.get_sset_count = qeth_get_sset_count,
379  	.get_drvinfo = qeth_get_drvinfo,
380  	.get_channels = qeth_get_channels,
381  	.get_link_ksettings = qeth_get_link_ksettings,
382  };
383  
384  const struct ethtool_ops qeth_osn_ethtool_ops = {
385  	.get_strings = qeth_get_strings,
386  	.get_ethtool_stats = qeth_get_ethtool_stats,
387  	.get_sset_count = qeth_get_sset_count,
388  	.get_drvinfo = qeth_get_drvinfo,
389  };
390