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 v2.6.21-rc2 294 lines 7.1 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#include "ehea.h" 30#include "ehea_phyp.h" 31 32static int ehea_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 33{ 34 struct ehea_port *port = netdev_priv(dev); 35 int ret; 36 37 ret = ehea_sense_port_attr(port); 38 39 if (ret) 40 return ret; 41 42 if (netif_carrier_ok(dev)) { 43 switch(port->port_speed) { 44 case EHEA_SPEED_10M: cmd->speed = SPEED_10; break; 45 case EHEA_SPEED_100M: cmd->speed = SPEED_100; break; 46 case EHEA_SPEED_1G: cmd->speed = SPEED_1000; break; 47 case EHEA_SPEED_10G: cmd->speed = SPEED_10000; break; 48 } 49 cmd->duplex = port->full_duplex == 1 ? 50 DUPLEX_FULL : DUPLEX_HALF; 51 } else { 52 cmd->speed = -1; 53 cmd->duplex = -1; 54 } 55 56 cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full 57 | SUPPORTED_100baseT_Full | SUPPORTED_100baseT_Half 58 | SUPPORTED_10baseT_Full | SUPPORTED_10baseT_Half 59 | SUPPORTED_Autoneg | SUPPORTED_FIBRE); 60 61 cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_Autoneg 62 | ADVERTISED_FIBRE); 63 64 cmd->port = PORT_FIBRE; 65 cmd->autoneg = port->autoneg == 1 ? AUTONEG_ENABLE : AUTONEG_DISABLE; 66 67 return 0; 68} 69 70static int ehea_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 71{ 72 struct ehea_port *port = netdev_priv(dev); 73 int ret = 0; 74 u32 sp; 75 76 if (cmd->autoneg == AUTONEG_ENABLE) { 77 sp = EHEA_SPEED_AUTONEG; 78 goto doit; 79 } 80 81 switch(cmd->speed) { 82 case SPEED_10: 83 if (cmd->duplex == DUPLEX_FULL) 84 sp = H_SPEED_10M_F; 85 else 86 sp = H_SPEED_10M_H; 87 break; 88 89 case SPEED_100: 90 if (cmd->duplex == DUPLEX_FULL) 91 sp = H_SPEED_100M_F; 92 else 93 sp = H_SPEED_100M_H; 94 break; 95 96 case SPEED_1000: 97 if (cmd->duplex == DUPLEX_FULL) 98 sp = H_SPEED_1G_F; 99 else 100 ret = -EINVAL; 101 break; 102 103 case SPEED_10000: 104 if (cmd->duplex == DUPLEX_FULL) 105 sp = H_SPEED_10G_F; 106 else 107 ret = -EINVAL; 108 break; 109 110 default: 111 ret = -EINVAL; 112 break; 113 } 114 115 if (ret) 116 goto out; 117doit: 118 ret = ehea_set_portspeed(port, sp); 119 120 if (!ret) 121 ehea_info("%s: Port speed succesfully set: %dMbps " 122 "%s Duplex", 123 port->netdev->name, port->port_speed, 124 port->full_duplex == 1 ? "Full" : "Half"); 125out: 126 return ret; 127} 128 129static int ehea_nway_reset(struct net_device *dev) 130{ 131 struct ehea_port *port = netdev_priv(dev); 132 int ret; 133 134 ret = ehea_set_portspeed(port, EHEA_SPEED_AUTONEG); 135 136 if (!ret) 137 ehea_info("%s: Port speed succesfully set: %dMbps " 138 "%s Duplex", 139 port->netdev->name, port->port_speed, 140 port->full_duplex == 1 ? "Full" : "Half"); 141 return ret; 142} 143 144static void ehea_get_drvinfo(struct net_device *dev, 145 struct ethtool_drvinfo *info) 146{ 147 strlcpy(info->driver, DRV_NAME, sizeof(info->driver) - 1); 148 strlcpy(info->version, DRV_VERSION, sizeof(info->version) - 1); 149} 150 151static u32 ehea_get_msglevel(struct net_device *dev) 152{ 153 struct ehea_port *port = netdev_priv(dev); 154 return port->msg_enable; 155} 156 157static void ehea_set_msglevel(struct net_device *dev, u32 value) 158{ 159 struct ehea_port *port = netdev_priv(dev); 160 port->msg_enable = value; 161} 162 163static u32 ehea_get_rx_csum(struct net_device *dev) 164{ 165 return 1; 166} 167 168static char ehea_ethtool_stats_keys[][ETH_GSTRING_LEN] = { 169 {"poll_max_processed"}, 170 {"queue_stopped"}, 171 {"min_swqe_avail"}, 172 {"poll_receive_err"}, 173 {"pkt_send"}, 174 {"pkt_xmit"}, 175 {"send_tasklet"}, 176 {"ehea_poll"}, 177 {"nwqe"}, 178 {"swqe_available_0"}, 179 {"sig_comp_iv"}, 180 {"swqe_refill_th"}, 181 {"port resets"}, 182 {"rxo"}, 183 {"rx64"}, 184 {"rx65"}, 185 {"rx128"}, 186 {"rx256"}, 187 {"rx512"}, 188 {"rx1024"}, 189 {"txo"}, 190 {"tx64"}, 191 {"tx65"}, 192 {"tx128"}, 193 {"tx256"}, 194 {"tx512"}, 195 {"tx1024"}, 196}; 197 198static void ehea_get_strings(struct net_device *dev, u32 stringset, u8 *data) 199{ 200 if (stringset == ETH_SS_STATS) { 201 memcpy(data, &ehea_ethtool_stats_keys, 202 sizeof(ehea_ethtool_stats_keys)); 203 } 204} 205 206static int ehea_get_stats_count(struct net_device *dev) 207{ 208 return ARRAY_SIZE(ehea_ethtool_stats_keys); 209} 210 211static void ehea_get_ethtool_stats(struct net_device *dev, 212 struct ethtool_stats *stats, u64 *data) 213{ 214 u64 hret; 215 int i; 216 struct ehea_port *port = netdev_priv(dev); 217 struct ehea_adapter *adapter = port->adapter; 218 struct ehea_port_res *pr = &port->port_res[0]; 219 struct port_state *p_state = &pr->p_state; 220 struct hcp_ehea_port_cb6 *cb6; 221 222 for (i = 0; i < ehea_get_stats_count(dev); i++) 223 data[i] = 0; 224 225 i = 0; 226 227 data[i++] = p_state->poll_max_processed; 228 data[i++] = p_state->queue_stopped; 229 data[i++] = p_state->min_swqe_avail; 230 data[i++] = p_state->poll_receive_errors; 231 data[i++] = p_state->pkt_send; 232 data[i++] = p_state->pkt_xmit; 233 data[i++] = p_state->send_tasklet; 234 data[i++] = p_state->ehea_poll; 235 data[i++] = p_state->nwqe; 236 data[i++] = atomic_read(&port->port_res[0].swqe_avail); 237 data[i++] = port->sig_comp_iv; 238 data[i++] = port->port_res[0].swqe_refill_th; 239 data[i++] = port->resets; 240 241 cb6 = kzalloc(PAGE_SIZE, GFP_KERNEL); 242 if (!cb6) { 243 ehea_error("no mem for cb6"); 244 return; 245 } 246 247 hret = ehea_h_query_ehea_port(adapter->handle, port->logical_port_id, 248 H_PORT_CB6, H_PORT_CB6_ALL, cb6); 249 if (netif_msg_hw(port)) 250 ehea_dump(cb6, sizeof(*cb6), "ehea_get_ethtool_stats"); 251 252 if (hret == H_SUCCESS) { 253 data[i++] = cb6->rxo; 254 data[i++] = cb6->rx64; 255 data[i++] = cb6->rx65; 256 data[i++] = cb6->rx128; 257 data[i++] = cb6->rx256; 258 data[i++] = cb6->rx512; 259 data[i++] = cb6->rx1024; 260 data[i++] = cb6->txo; 261 data[i++] = cb6->tx64; 262 data[i++] = cb6->tx65; 263 data[i++] = cb6->tx128; 264 data[i++] = cb6->tx256; 265 data[i++] = cb6->tx512; 266 data[i++] = cb6->tx1024; 267 } else 268 ehea_error("query_ehea_port failed"); 269 270 kfree(cb6); 271} 272 273const struct ethtool_ops ehea_ethtool_ops = { 274 .get_settings = ehea_get_settings, 275 .get_drvinfo = ehea_get_drvinfo, 276 .get_msglevel = ehea_get_msglevel, 277 .set_msglevel = ehea_set_msglevel, 278 .get_link = ethtool_op_get_link, 279 .get_tx_csum = ethtool_op_get_tx_csum, 280 .get_sg = ethtool_op_get_sg, 281 .get_tso = ethtool_op_get_tso, 282 .set_tso = ethtool_op_set_tso, 283 .get_strings = ehea_get_strings, 284 .get_stats_count = ehea_get_stats_count, 285 .get_ethtool_stats = ehea_get_ethtool_stats, 286 .get_rx_csum = ehea_get_rx_csum, 287 .set_settings = ehea_set_settings, 288 .nway_reset = ehea_nway_reset, /* Restart autonegotiation */ 289}; 290 291void ehea_set_ethtool_ops(struct net_device *netdev) 292{ 293 SET_ETHTOOL_OPS(netdev, &ehea_ethtool_ops); 294}