Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 55fa6091d83160ca772fc37cebae45d42695a708 300 lines 7.5 kB view raw
1/* 2 * linux/drivers/net/ehea/ehea_ethtool.c 3 * 4 * eHEA ethernet device driver for IBM eServer System p 5 * 6 * (C) Copyright IBM Corp. 2006 7 * 8 * Authors: 9 * Christoph Raisch <raisch@de.ibm.com> 10 * Jan-Bernd Themann <themann@de.ibm.com> 11 * Thomas Klein <tklein@de.ibm.com> 12 * 13 * 14 * This program is free software; you can redistribute it and/or modify 15 * it under the terms of the GNU General Public License as published by 16 * the Free Software Foundation; either version 2, or (at your option) 17 * any later version. 18 * 19 * This program is distributed in the hope that it will be useful, 20 * but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * GNU General Public License for more details. 23 * 24 * You should have received a copy of the GNU General Public License 25 * along with this program; if not, write to the Free Software 26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 27 */ 28 29#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 30 31#include "ehea.h" 32#include "ehea_phyp.h" 33 34static int ehea_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 35{ 36 struct ehea_port *port = netdev_priv(dev); 37 int ret; 38 39 ret = ehea_sense_port_attr(port); 40 41 if (ret) 42 return ret; 43 44 if (netif_carrier_ok(dev)) { 45 switch (port->port_speed) { 46 case EHEA_SPEED_10M: cmd->speed = SPEED_10; break; 47 case EHEA_SPEED_100M: cmd->speed = SPEED_100; break; 48 case EHEA_SPEED_1G: cmd->speed = SPEED_1000; break; 49 case EHEA_SPEED_10G: cmd->speed = SPEED_10000; break; 50 } 51 cmd->duplex = port->full_duplex == 1 ? 52 DUPLEX_FULL : DUPLEX_HALF; 53 } else { 54 cmd->speed = -1; 55 cmd->duplex = -1; 56 } 57 58 cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full 59 | SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Half 60 | SUPPORTED_10baseT_Full | SUPPORTED_10baseT_Half 61 | SUPPORTED_Autoneg | SUPPORTED_FIBRE); 62 63 cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_Autoneg 64 | ADVERTISED_FIBRE); 65 66 cmd->port = PORT_FIBRE; 67 cmd->autoneg = port->autoneg == 1 ? AUTONEG_ENABLE : AUTONEG_DISABLE; 68 69 return 0; 70} 71 72static int ehea_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 73{ 74 struct ehea_port *port = netdev_priv(dev); 75 int ret = 0; 76 u32 sp; 77 78 if (cmd->autoneg == AUTONEG_ENABLE) { 79 sp = EHEA_SPEED_AUTONEG; 80 goto doit; 81 } 82 83 switch (cmd->speed) { 84 case SPEED_10: 85 if (cmd->duplex == DUPLEX_FULL) 86 sp = H_SPEED_10M_F; 87 else 88 sp = H_SPEED_10M_H; 89 break; 90 91 case SPEED_100: 92 if (cmd->duplex == DUPLEX_FULL) 93 sp = H_SPEED_100M_F; 94 else 95 sp = H_SPEED_100M_H; 96 break; 97 98 case SPEED_1000: 99 if (cmd->duplex == DUPLEX_FULL) 100 sp = H_SPEED_1G_F; 101 else 102 ret = -EINVAL; 103 break; 104 105 case SPEED_10000: 106 if (cmd->duplex == DUPLEX_FULL) 107 sp = H_SPEED_10G_F; 108 else 109 ret = -EINVAL; 110 break; 111 112 default: 113 ret = -EINVAL; 114 break; 115 } 116 117 if (ret) 118 goto out; 119doit: 120 ret = ehea_set_portspeed(port, sp); 121 122 if (!ret) 123 netdev_info(dev, 124 "Port speed successfully set: %dMbps %s Duplex\n", 125 port->port_speed, 126 port->full_duplex == 1 ? "Full" : "Half"); 127out: 128 return ret; 129} 130 131static int ehea_nway_reset(struct net_device *dev) 132{ 133 struct ehea_port *port = netdev_priv(dev); 134 int ret; 135 136 ret = ehea_set_portspeed(port, EHEA_SPEED_AUTONEG); 137 138 if (!ret) 139 netdev_info(port->netdev, 140 "Port speed successfully set: %dMbps %s Duplex\n", 141 port->port_speed, 142 port->full_duplex == 1 ? "Full" : "Half"); 143 return ret; 144} 145 146static void ehea_get_drvinfo(struct net_device *dev, 147 struct ethtool_drvinfo *info) 148{ 149 strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); 150 strlcpy(info->version, DRV_VERSION, sizeof(info->version)); 151} 152 153static u32 ehea_get_msglevel(struct net_device *dev) 154{ 155 struct ehea_port *port = netdev_priv(dev); 156 return port->msg_enable; 157} 158 159static void ehea_set_msglevel(struct net_device *dev, u32 value) 160{ 161 struct ehea_port *port = netdev_priv(dev); 162 port->msg_enable = value; 163} 164 165static u32 ehea_get_rx_csum(struct net_device *dev) 166{ 167 return 1; 168} 169 170static char ehea_ethtool_stats_keys[][ETH_GSTRING_LEN] = { 171 {"sig_comp_iv"}, 172 {"swqe_refill_th"}, 173 {"port resets"}, 174 {"Receive errors"}, 175 {"TCP cksum errors"}, 176 {"IP cksum errors"}, 177 {"Frame cksum errors"}, 178 {"num SQ stopped"}, 179 {"SQ stopped"}, 180 {"PR0 free_swqes"}, 181 {"PR1 free_swqes"}, 182 {"PR2 free_swqes"}, 183 {"PR3 free_swqes"}, 184 {"PR4 free_swqes"}, 185 {"PR5 free_swqes"}, 186 {"PR6 free_swqes"}, 187 {"PR7 free_swqes"}, 188 {"LRO aggregated"}, 189 {"LRO flushed"}, 190 {"LRO no_desc"}, 191}; 192 193static void ehea_get_strings(struct net_device *dev, u32 stringset, u8 *data) 194{ 195 if (stringset == ETH_SS_STATS) { 196 memcpy(data, &ehea_ethtool_stats_keys, 197 sizeof(ehea_ethtool_stats_keys)); 198 } 199} 200 201static int ehea_get_sset_count(struct net_device *dev, int sset) 202{ 203 switch (sset) { 204 case ETH_SS_STATS: 205 return ARRAY_SIZE(ehea_ethtool_stats_keys); 206 default: 207 return -EOPNOTSUPP; 208 } 209} 210 211static void ehea_get_ethtool_stats(struct net_device *dev, 212 struct ethtool_stats *stats, u64 *data) 213{ 214 int i, k, tmp; 215 struct ehea_port *port = netdev_priv(dev); 216 217 for (i = 0; i < ehea_get_sset_count(dev, ETH_SS_STATS); i++) 218 data[i] = 0; 219 i = 0; 220 221 data[i++] = port->sig_comp_iv; 222 data[i++] = port->port_res[0].swqe_refill_th; 223 data[i++] = port->resets; 224 225 for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++) 226 tmp += port->port_res[k].p_stats.poll_receive_errors; 227 data[i++] = tmp; 228 229 for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++) 230 tmp += port->port_res[k].p_stats.err_tcp_cksum; 231 data[i++] = tmp; 232 233 for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++) 234 tmp += port->port_res[k].p_stats.err_ip_cksum; 235 data[i++] = tmp; 236 237 for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++) 238 tmp += port->port_res[k].p_stats.err_frame_crc; 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.queue_stopped; 243 data[i++] = tmp; 244 245 for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++) 246 tmp |= port->port_res[k].queue_stopped; 247 data[i++] = tmp; 248 249 for (k = 0; k < 8; k++) 250 data[i++] = atomic_read(&port->port_res[k].swqe_avail); 251 252 for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++) 253 tmp |= port->port_res[k].lro_mgr.stats.aggregated; 254 data[i++] = tmp; 255 256 for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++) 257 tmp |= port->port_res[k].lro_mgr.stats.flushed; 258 data[i++] = tmp; 259 260 for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++) 261 tmp |= port->port_res[k].lro_mgr.stats.no_desc; 262 data[i++] = tmp; 263 264} 265 266static int ehea_set_flags(struct net_device *dev, u32 data) 267{ 268 /* Avoid changing the VLAN flags */ 269 if ((data & (ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN)) != 270 (ethtool_op_get_flags(dev) & (ETH_FLAG_RXVLAN | 271 ETH_FLAG_TXVLAN))){ 272 return -EINVAL; 273 } 274 275 return ethtool_op_set_flags(dev, data, ETH_FLAG_LRO 276 | ETH_FLAG_TXVLAN 277 | ETH_FLAG_RXVLAN); 278} 279 280const struct ethtool_ops ehea_ethtool_ops = { 281 .get_settings = ehea_get_settings, 282 .get_drvinfo = ehea_get_drvinfo, 283 .get_msglevel = ehea_get_msglevel, 284 .set_msglevel = ehea_set_msglevel, 285 .get_link = ethtool_op_get_link, 286 .set_tso = ethtool_op_set_tso, 287 .get_strings = ehea_get_strings, 288 .get_sset_count = ehea_get_sset_count, 289 .get_ethtool_stats = ehea_get_ethtool_stats, 290 .get_rx_csum = ehea_get_rx_csum, 291 .set_settings = ehea_set_settings, 292 .get_flags = ethtool_op_get_flags, 293 .set_flags = ehea_set_flags, 294 .nway_reset = ehea_nway_reset, /* Restart autonegotiation */ 295}; 296 297void ehea_set_ethtool_ops(struct net_device *netdev) 298{ 299 SET_ETHTOOL_OPS(netdev, &ehea_ethtool_ops); 300}