brintos

brintos / linux-shallow public Read only

0
0
Text · 6.4 KiB · 1db5b67 Raw
278 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *  linux/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c4 *5 *  eHEA ethernet device driver for IBM eServer System p6 *7 *  (C) Copyright IBM Corp. 20068 *9 *  Authors:10 *       Christoph Raisch <raisch@de.ibm.com>11 *       Jan-Bernd Themann <themann@de.ibm.com>12 *       Thomas Klein <tklein@de.ibm.com>13 */14 15#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt16 17#include "ehea.h"18#include "ehea_phyp.h"19 20static int ehea_get_link_ksettings(struct net_device *dev,21				   struct ethtool_link_ksettings *cmd)22{23	struct ehea_port *port = netdev_priv(dev);24	u32 supported, advertising;25	u32 speed;26	int ret;27 28	ret = ehea_sense_port_attr(port);29 30	if (ret)31		return ret;32 33	if (netif_carrier_ok(dev)) {34		switch (port->port_speed) {35		case EHEA_SPEED_10M:36			speed = SPEED_10;37			break;38		case EHEA_SPEED_100M:39			speed = SPEED_100;40			break;41		case EHEA_SPEED_1G:42			speed = SPEED_1000;43			break;44		case EHEA_SPEED_10G:45			speed = SPEED_10000;46			break;47		default:48			speed = -1;49			break; /* BUG */50		}51		cmd->base.duplex = port->full_duplex == 1 ?52						     DUPLEX_FULL : DUPLEX_HALF;53	} else {54		speed = SPEED_UNKNOWN;55		cmd->base.duplex = DUPLEX_UNKNOWN;56	}57	cmd->base.speed = speed;58 59	if (cmd->base.speed == SPEED_10000) {60		supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);61		advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);62		cmd->base.port = PORT_FIBRE;63	} else {64		supported = (SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full65			       | SUPPORTED_100baseT_Half | SUPPORTED_10baseT_Full66			       | SUPPORTED_10baseT_Half | SUPPORTED_Autoneg67			       | SUPPORTED_TP);68		advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg69				 | ADVERTISED_TP);70		cmd->base.port = PORT_TP;71	}72 73	cmd->base.autoneg = port->autoneg == 1 ?74		AUTONEG_ENABLE : AUTONEG_DISABLE;75 76	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,77						supported);78	ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,79						advertising);80 81	return 0;82}83 84static int ehea_set_link_ksettings(struct net_device *dev,85				   const struct ethtool_link_ksettings *cmd)86{87	struct ehea_port *port = netdev_priv(dev);88	int ret = 0;89	u32 sp;90 91	if (cmd->base.autoneg == AUTONEG_ENABLE) {92		sp = EHEA_SPEED_AUTONEG;93		goto doit;94	}95 96	switch (cmd->base.speed) {97	case SPEED_10:98		if (cmd->base.duplex == DUPLEX_FULL)99			sp = H_SPEED_10M_F;100		else101			sp = H_SPEED_10M_H;102		break;103 104	case SPEED_100:105		if (cmd->base.duplex == DUPLEX_FULL)106			sp = H_SPEED_100M_F;107		else108			sp = H_SPEED_100M_H;109		break;110 111	case SPEED_1000:112		if (cmd->base.duplex == DUPLEX_FULL)113			sp = H_SPEED_1G_F;114		else115			ret = -EINVAL;116		break;117 118	case SPEED_10000:119		if (cmd->base.duplex == DUPLEX_FULL)120			sp = H_SPEED_10G_F;121		else122			ret = -EINVAL;123		break;124 125	default:126			ret = -EINVAL;127		break;128	}129 130	if (ret)131		goto out;132doit:133	ret = ehea_set_portspeed(port, sp);134 135	if (!ret)136		netdev_info(dev,137			    "Port speed successfully set: %dMbps %s Duplex\n",138			    port->port_speed,139			    port->full_duplex == 1 ? "Full" : "Half");140out:141	return ret;142}143 144static int ehea_nway_reset(struct net_device *dev)145{146	struct ehea_port *port = netdev_priv(dev);147	int ret;148 149	ret = ehea_set_portspeed(port, EHEA_SPEED_AUTONEG);150 151	if (!ret)152		netdev_info(port->netdev,153			    "Port speed successfully set: %dMbps %s Duplex\n",154			    port->port_speed,155			    port->full_duplex == 1 ? "Full" : "Half");156	return ret;157}158 159static void ehea_get_drvinfo(struct net_device *dev,160			       struct ethtool_drvinfo *info)161{162	strscpy(info->driver, DRV_NAME, sizeof(info->driver));163	strscpy(info->version, DRV_VERSION, sizeof(info->version));164}165 166static u32 ehea_get_msglevel(struct net_device *dev)167{168	struct ehea_port *port = netdev_priv(dev);169	return port->msg_enable;170}171 172static void ehea_set_msglevel(struct net_device *dev, u32 value)173{174	struct ehea_port *port = netdev_priv(dev);175	port->msg_enable = value;176}177 178static const char ehea_ethtool_stats_keys[][ETH_GSTRING_LEN] = {179	{"sig_comp_iv"},180	{"swqe_refill_th"},181	{"port resets"},182	{"Receive errors"},183	{"TCP cksum errors"},184	{"IP cksum errors"},185	{"Frame cksum errors"},186	{"num SQ stopped"},187	{"PR0 free_swqes"},188	{"PR1 free_swqes"},189	{"PR2 free_swqes"},190	{"PR3 free_swqes"},191	{"PR4 free_swqes"},192	{"PR5 free_swqes"},193	{"PR6 free_swqes"},194	{"PR7 free_swqes"},195	{"PR8 free_swqes"},196	{"PR9 free_swqes"},197	{"PR10 free_swqes"},198	{"PR11 free_swqes"},199	{"PR12 free_swqes"},200	{"PR13 free_swqes"},201	{"PR14 free_swqes"},202	{"PR15 free_swqes"},203};204 205static void ehea_get_strings(struct net_device *dev, u32 stringset, u8 *data)206{207	if (stringset == ETH_SS_STATS) {208		memcpy(data, &ehea_ethtool_stats_keys,209		       sizeof(ehea_ethtool_stats_keys));210	}211}212 213static int ehea_get_sset_count(struct net_device *dev, int sset)214{215	switch (sset) {216	case ETH_SS_STATS:217		return ARRAY_SIZE(ehea_ethtool_stats_keys);218	default:219		return -EOPNOTSUPP;220	}221}222 223static void ehea_get_ethtool_stats(struct net_device *dev,224				     struct ethtool_stats *stats, u64 *data)225{226	int i, k, tmp;227	struct ehea_port *port = netdev_priv(dev);228 229	for (i = 0; i < ehea_get_sset_count(dev, ETH_SS_STATS); i++)230		data[i] = 0;231	i = 0;232 233	data[i++] = port->sig_comp_iv;234	data[i++] = port->port_res[0].swqe_refill_th;235	data[i++] = port->resets;236 237	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)238		tmp += port->port_res[k].p_stats.poll_receive_errors;239	data[i++] = tmp;240 241	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)242		tmp += port->port_res[k].p_stats.err_tcp_cksum;243	data[i++] = tmp;244 245	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)246		tmp += port->port_res[k].p_stats.err_ip_cksum;247	data[i++] = tmp;248 249	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)250		tmp += port->port_res[k].p_stats.err_frame_crc;251	data[i++] = tmp;252 253	for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)254		tmp += port->port_res[k].p_stats.queue_stopped;255	data[i++] = tmp;256 257	for (k = 0; k < 16; k++)258		data[i++] = atomic_read(&port->port_res[k].swqe_avail);259}260 261static const struct ethtool_ops ehea_ethtool_ops = {262	.get_drvinfo = ehea_get_drvinfo,263	.get_msglevel = ehea_get_msglevel,264	.set_msglevel = ehea_set_msglevel,265	.get_link = ethtool_op_get_link,266	.get_strings = ehea_get_strings,267	.get_sset_count = ehea_get_sset_count,268	.get_ethtool_stats = ehea_get_ethtool_stats,269	.nway_reset = ehea_nway_reset,		/* Restart autonegotiation */270	.get_link_ksettings = ehea_get_link_ksettings,271	.set_link_ksettings = ehea_set_link_ksettings,272};273 274void ehea_set_ethtool_ops(struct net_device *netdev)275{276	netdev->ethtool_ops = &ehea_ethtool_ops;277}278