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

Configure Feed

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

at v2.6.13 556 lines 15 kB view raw
1/* 2 * drivers/net/gianfar_ethtool.c 3 * 4 * Gianfar Ethernet Driver 5 * Ethtool support for Gianfar Enet 6 * Based on e1000 ethtool support 7 * 8 * Author: Andy Fleming 9 * Maintainer: Kumar Gala (kumar.gala@freescale.com) 10 * 11 * Copyright (c) 2003,2004 Freescale Semiconductor, Inc. 12 * 13 * This software may be used and distributed according to 14 * the terms of the GNU Public License, Version 2, incorporated herein 15 * by reference. 16 */ 17 18#include <linux/config.h> 19#include <linux/kernel.h> 20#include <linux/sched.h> 21#include <linux/string.h> 22#include <linux/errno.h> 23#include <linux/slab.h> 24#include <linux/interrupt.h> 25#include <linux/init.h> 26#include <linux/delay.h> 27#include <linux/netdevice.h> 28#include <linux/etherdevice.h> 29#include <linux/skbuff.h> 30#include <linux/spinlock.h> 31#include <linux/mm.h> 32 33#include <asm/io.h> 34#include <asm/irq.h> 35#include <asm/uaccess.h> 36#include <linux/module.h> 37#include <linux/version.h> 38#include <linux/crc32.h> 39#include <asm/types.h> 40#include <asm/uaccess.h> 41#include <linux/ethtool.h> 42 43#include "gianfar.h" 44 45#define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) 46 47extern int startup_gfar(struct net_device *dev); 48extern void stop_gfar(struct net_device *dev); 49extern void gfar_halt(struct net_device *dev); 50extern void gfar_start(struct net_device *dev); 51extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); 52 53static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, 54 u64 * buf); 55static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf); 56static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); 57static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals); 58static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals); 59static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals); 60static void gfar_gdrvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo); 61 62static char stat_gstrings[][ETH_GSTRING_LEN] = { 63 "rx-dropped-by-kernel", 64 "rx-large-frame-errors", 65 "rx-short-frame-errors", 66 "rx-non-octet-errors", 67 "rx-crc-errors", 68 "rx-overrun-errors", 69 "rx-busy-errors", 70 "rx-babbling-errors", 71 "rx-truncated-frames", 72 "ethernet-bus-error", 73 "tx-babbling-errors", 74 "tx-underrun-errors", 75 "rx-skb-missing-errors", 76 "tx-timeout-errors", 77 "tx-rx-64-frames", 78 "tx-rx-65-127-frames", 79 "tx-rx-128-255-frames", 80 "tx-rx-256-511-frames", 81 "tx-rx-512-1023-frames", 82 "tx-rx-1024-1518-frames", 83 "tx-rx-1519-1522-good-vlan", 84 "rx-bytes", 85 "rx-packets", 86 "rx-fcs-errors", 87 "receive-multicast-packet", 88 "receive-broadcast-packet", 89 "rx-control-frame-packets", 90 "rx-pause-frame-packets", 91 "rx-unknown-op-code", 92 "rx-alignment-error", 93 "rx-frame-length-error", 94 "rx-code-error", 95 "rx-carrier-sense-error", 96 "rx-undersize-packets", 97 "rx-oversize-packets", 98 "rx-fragmented-frames", 99 "rx-jabber-frames", 100 "rx-dropped-frames", 101 "tx-byte-counter", 102 "tx-packets", 103 "tx-multicast-packets", 104 "tx-broadcast-packets", 105 "tx-pause-control-frames", 106 "tx-deferral-packets", 107 "tx-excessive-deferral-packets", 108 "tx-single-collision-packets", 109 "tx-multiple-collision-packets", 110 "tx-late-collision-packets", 111 "tx-excessive-collision-packets", 112 "tx-total-collision", 113 "reserved", 114 "tx-dropped-frames", 115 "tx-jabber-frames", 116 "tx-fcs-errors", 117 "tx-control-frames", 118 "tx-oversize-frames", 119 "tx-undersize-frames", 120 "tx-fragmented-frames", 121}; 122 123/* Fill in a buffer with the strings which correspond to the 124 * stats */ 125static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf) 126{ 127 struct gfar_private *priv = netdev_priv(dev); 128 129 if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) 130 memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN); 131 else 132 memcpy(buf, stat_gstrings, 133 GFAR_EXTRA_STATS_LEN * ETH_GSTRING_LEN); 134} 135 136/* Fill in an array of 64-bit statistics from various sources. 137 * This array will be appended to the end of the ethtool_stats 138 * structure, and returned to user space 139 */ 140static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, u64 * buf) 141{ 142 int i; 143 struct gfar_private *priv = netdev_priv(dev); 144 u64 *extra = (u64 *) & priv->extra_stats; 145 146 if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) { 147 u32 *rmon = (u32 *) & priv->regs->rmon; 148 struct gfar_stats *stats = (struct gfar_stats *) buf; 149 150 for (i = 0; i < GFAR_RMON_LEN; i++) 151 stats->rmon[i] = (u64) (rmon[i]); 152 153 for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) 154 stats->extra[i] = extra[i]; 155 } else 156 for (i = 0; i < GFAR_EXTRA_STATS_LEN; i++) 157 buf[i] = extra[i]; 158} 159 160/* Returns the number of stats (and their corresponding strings) */ 161static int gfar_stats_count(struct net_device *dev) 162{ 163 struct gfar_private *priv = netdev_priv(dev); 164 165 if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) 166 return GFAR_STATS_LEN; 167 else 168 return GFAR_EXTRA_STATS_LEN; 169} 170 171/* Fills in the drvinfo structure with some basic info */ 172static void gfar_gdrvinfo(struct net_device *dev, struct 173 ethtool_drvinfo *drvinfo) 174{ 175 strncpy(drvinfo->driver, DRV_NAME, GFAR_INFOSTR_LEN); 176 strncpy(drvinfo->version, gfar_driver_version, GFAR_INFOSTR_LEN); 177 strncpy(drvinfo->fw_version, "N/A", GFAR_INFOSTR_LEN); 178 strncpy(drvinfo->bus_info, "N/A", GFAR_INFOSTR_LEN); 179 drvinfo->n_stats = GFAR_STATS_LEN; 180 drvinfo->testinfo_len = 0; 181 drvinfo->regdump_len = 0; 182 drvinfo->eedump_len = 0; 183} 184 185/* Return the current settings in the ethtool_cmd structure */ 186static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) 187{ 188 struct gfar_private *priv = netdev_priv(dev); 189 uint gigabit_support = 190 priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? 191 SUPPORTED_1000baseT_Full : 0; 192 uint gigabit_advert = 193 priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ? 194 ADVERTISED_1000baseT_Full: 0; 195 196 cmd->supported = (SUPPORTED_10baseT_Half 197 | SUPPORTED_100baseT_Half 198 | SUPPORTED_100baseT_Full 199 | gigabit_support | SUPPORTED_Autoneg); 200 201 /* For now, we always advertise everything */ 202 cmd->advertising = (ADVERTISED_10baseT_Half 203 | ADVERTISED_100baseT_Half 204 | ADVERTISED_100baseT_Full 205 | gigabit_advert | ADVERTISED_Autoneg); 206 207 cmd->speed = priv->mii_info->speed; 208 cmd->duplex = priv->mii_info->duplex; 209 cmd->port = PORT_MII; 210 cmd->phy_address = priv->mii_info->mii_id; 211 cmd->transceiver = XCVR_EXTERNAL; 212 cmd->autoneg = AUTONEG_ENABLE; 213 cmd->maxtxpkt = priv->txcount; 214 cmd->maxrxpkt = priv->rxcount; 215 216 return 0; 217} 218 219/* Return the length of the register structure */ 220static int gfar_reglen(struct net_device *dev) 221{ 222 return sizeof (struct gfar); 223} 224 225/* Return a dump of the GFAR register space */ 226static void gfar_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf) 227{ 228 int i; 229 struct gfar_private *priv = netdev_priv(dev); 230 u32 *theregs = (u32 *) priv->regs; 231 u32 *buf = (u32 *) regbuf; 232 233 for (i = 0; i < sizeof (struct gfar) / sizeof (u32); i++) 234 buf[i] = theregs[i]; 235} 236 237/* Convert microseconds to ethernet clock ticks, which changes 238 * depending on what speed the controller is running at */ 239static unsigned int gfar_usecs2ticks(struct gfar_private *priv, unsigned int usecs) 240{ 241 unsigned int count; 242 243 /* The timer is different, depending on the interface speed */ 244 switch (priv->mii_info->speed) { 245 case 1000: 246 count = GFAR_GBIT_TIME; 247 break; 248 case 100: 249 count = GFAR_100_TIME; 250 break; 251 case 10: 252 default: 253 count = GFAR_10_TIME; 254 break; 255 } 256 257 /* Make sure we return a number greater than 0 258 * if usecs > 0 */ 259 return ((usecs * 1000 + count - 1) / count); 260} 261 262/* Convert ethernet clock ticks to microseconds */ 263static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int ticks) 264{ 265 unsigned int count; 266 267 /* The timer is different, depending on the interface speed */ 268 switch (priv->mii_info->speed) { 269 case 1000: 270 count = GFAR_GBIT_TIME; 271 break; 272 case 100: 273 count = GFAR_100_TIME; 274 break; 275 case 10: 276 default: 277 count = GFAR_10_TIME; 278 break; 279 } 280 281 /* Make sure we return a number greater than 0 */ 282 /* if ticks is > 0 */ 283 return ((ticks * count) / 1000); 284} 285 286/* Get the coalescing parameters, and put them in the cvals 287 * structure. */ 288static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) 289{ 290 struct gfar_private *priv = netdev_priv(dev); 291 292 if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) 293 return -EOPNOTSUPP; 294 295 cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime); 296 cvals->rx_max_coalesced_frames = priv->rxcount; 297 298 cvals->tx_coalesce_usecs = gfar_ticks2usecs(priv, priv->txtime); 299 cvals->tx_max_coalesced_frames = priv->txcount; 300 301 cvals->use_adaptive_rx_coalesce = 0; 302 cvals->use_adaptive_tx_coalesce = 0; 303 304 cvals->pkt_rate_low = 0; 305 cvals->rx_coalesce_usecs_low = 0; 306 cvals->rx_max_coalesced_frames_low = 0; 307 cvals->tx_coalesce_usecs_low = 0; 308 cvals->tx_max_coalesced_frames_low = 0; 309 310 /* When the packet rate is below pkt_rate_high but above 311 * pkt_rate_low (both measured in packets per second) the 312 * normal {rx,tx}_* coalescing parameters are used. 313 */ 314 315 /* When the packet rate is (measured in packets per second) 316 * is above pkt_rate_high, the {rx,tx}_*_high parameters are 317 * used. 318 */ 319 cvals->pkt_rate_high = 0; 320 cvals->rx_coalesce_usecs_high = 0; 321 cvals->rx_max_coalesced_frames_high = 0; 322 cvals->tx_coalesce_usecs_high = 0; 323 cvals->tx_max_coalesced_frames_high = 0; 324 325 /* How often to do adaptive coalescing packet rate sampling, 326 * measured in seconds. Must not be zero. 327 */ 328 cvals->rate_sample_interval = 0; 329 330 return 0; 331} 332 333/* Change the coalescing values. 334 * Both cvals->*_usecs and cvals->*_frames have to be > 0 335 * in order for coalescing to be active 336 */ 337static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) 338{ 339 struct gfar_private *priv = netdev_priv(dev); 340 341 if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) 342 return -EOPNOTSUPP; 343 344 /* Set up rx coalescing */ 345 if ((cvals->rx_coalesce_usecs == 0) || 346 (cvals->rx_max_coalesced_frames == 0)) 347 priv->rxcoalescing = 0; 348 else 349 priv->rxcoalescing = 1; 350 351 priv->rxtime = gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs); 352 priv->rxcount = cvals->rx_max_coalesced_frames; 353 354 /* Set up tx coalescing */ 355 if ((cvals->tx_coalesce_usecs == 0) || 356 (cvals->tx_max_coalesced_frames == 0)) 357 priv->txcoalescing = 0; 358 else 359 priv->txcoalescing = 1; 360 361 priv->txtime = gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs); 362 priv->txcount = cvals->tx_max_coalesced_frames; 363 364 if (priv->rxcoalescing) 365 gfar_write(&priv->regs->rxic, 366 mk_ic_value(priv->rxcount, priv->rxtime)); 367 else 368 gfar_write(&priv->regs->rxic, 0); 369 370 if (priv->txcoalescing) 371 gfar_write(&priv->regs->txic, 372 mk_ic_value(priv->txcount, priv->txtime)); 373 else 374 gfar_write(&priv->regs->txic, 0); 375 376 return 0; 377} 378 379/* Fills in rvals with the current ring parameters. Currently, 380 * rx, rx_mini, and rx_jumbo rings are the same size, as mini and 381 * jumbo are ignored by the driver */ 382static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) 383{ 384 struct gfar_private *priv = netdev_priv(dev); 385 386 rvals->rx_max_pending = GFAR_RX_MAX_RING_SIZE; 387 rvals->rx_mini_max_pending = GFAR_RX_MAX_RING_SIZE; 388 rvals->rx_jumbo_max_pending = GFAR_RX_MAX_RING_SIZE; 389 rvals->tx_max_pending = GFAR_TX_MAX_RING_SIZE; 390 391 /* Values changeable by the user. The valid values are 392 * in the range 1 to the "*_max_pending" counterpart above. 393 */ 394 rvals->rx_pending = priv->rx_ring_size; 395 rvals->rx_mini_pending = priv->rx_ring_size; 396 rvals->rx_jumbo_pending = priv->rx_ring_size; 397 rvals->tx_pending = priv->tx_ring_size; 398} 399 400/* Change the current ring parameters, stopping the controller if 401 * necessary so that we don't mess things up while we're in 402 * motion. We wait for the ring to be clean before reallocating 403 * the rings. */ 404static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) 405{ 406 struct gfar_private *priv = netdev_priv(dev); 407 int err = 0; 408 409 if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE) 410 return -EINVAL; 411 412 if (!is_power_of_2(rvals->rx_pending)) { 413 printk("%s: Ring sizes must be a power of 2\n", 414 dev->name); 415 return -EINVAL; 416 } 417 418 if (rvals->tx_pending > GFAR_TX_MAX_RING_SIZE) 419 return -EINVAL; 420 421 if (!is_power_of_2(rvals->tx_pending)) { 422 printk("%s: Ring sizes must be a power of 2\n", 423 dev->name); 424 return -EINVAL; 425 } 426 427 if (dev->flags & IFF_UP) { 428 unsigned long flags; 429 430 /* Halt TX and RX, and process the frames which 431 * have already been received */ 432 spin_lock_irqsave(&priv->lock, flags); 433 gfar_halt(dev); 434 gfar_clean_rx_ring(dev, priv->rx_ring_size); 435 spin_unlock_irqrestore(&priv->lock, flags); 436 437 /* Now we take down the rings to rebuild them */ 438 stop_gfar(dev); 439 } 440 441 /* Change the size */ 442 priv->rx_ring_size = rvals->rx_pending; 443 priv->tx_ring_size = rvals->tx_pending; 444 445 /* Rebuild the rings with the new size */ 446 if (dev->flags & IFF_UP) 447 err = startup_gfar(dev); 448 449 return err; 450} 451 452static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) 453{ 454 struct gfar_private *priv = netdev_priv(dev); 455 int err = 0; 456 457 if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) 458 return -EOPNOTSUPP; 459 460 if (dev->flags & IFF_UP) { 461 unsigned long flags; 462 463 /* Halt TX and RX, and process the frames which 464 * have already been received */ 465 spin_lock_irqsave(&priv->lock, flags); 466 gfar_halt(dev); 467 gfar_clean_rx_ring(dev, priv->rx_ring_size); 468 spin_unlock_irqrestore(&priv->lock, flags); 469 470 /* Now we take down the rings to rebuild them */ 471 stop_gfar(dev); 472 } 473 474 priv->rx_csum_enable = data; 475 476 if (dev->flags & IFF_UP) 477 err = startup_gfar(dev); 478 479 return err; 480} 481 482static uint32_t gfar_get_rx_csum(struct net_device *dev) 483{ 484 struct gfar_private *priv = netdev_priv(dev); 485 486 if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) 487 return 0; 488 489 return priv->rx_csum_enable; 490} 491 492static int gfar_set_tx_csum(struct net_device *dev, uint32_t data) 493{ 494 unsigned long flags; 495 struct gfar_private *priv = netdev_priv(dev); 496 497 if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) 498 return -EOPNOTSUPP; 499 500 spin_lock_irqsave(&priv->lock, flags); 501 gfar_halt(dev); 502 503 if (data) 504 dev->features |= NETIF_F_IP_CSUM; 505 else 506 dev->features &= ~NETIF_F_IP_CSUM; 507 508 gfar_start(dev); 509 spin_unlock_irqrestore(&priv->lock, flags); 510 511 return 0; 512} 513 514static uint32_t gfar_get_tx_csum(struct net_device *dev) 515{ 516 struct gfar_private *priv = netdev_priv(dev); 517 518 if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) 519 return 0; 520 521 return (dev->features & NETIF_F_IP_CSUM) != 0; 522} 523 524static uint32_t gfar_get_msglevel(struct net_device *dev) 525{ 526 struct gfar_private *priv = netdev_priv(dev); 527 return priv->msg_enable; 528} 529 530static void gfar_set_msglevel(struct net_device *dev, uint32_t data) 531{ 532 struct gfar_private *priv = netdev_priv(dev); 533 priv->msg_enable = data; 534} 535 536 537struct ethtool_ops gfar_ethtool_ops = { 538 .get_settings = gfar_gsettings, 539 .get_drvinfo = gfar_gdrvinfo, 540 .get_regs_len = gfar_reglen, 541 .get_regs = gfar_get_regs, 542 .get_link = ethtool_op_get_link, 543 .get_coalesce = gfar_gcoalesce, 544 .set_coalesce = gfar_scoalesce, 545 .get_ringparam = gfar_gringparam, 546 .set_ringparam = gfar_sringparam, 547 .get_strings = gfar_gstrings, 548 .get_stats_count = gfar_stats_count, 549 .get_ethtool_stats = gfar_fill_stats, 550 .get_rx_csum = gfar_get_rx_csum, 551 .get_tx_csum = gfar_get_tx_csum, 552 .set_rx_csum = gfar_set_rx_csum, 553 .set_tx_csum = gfar_set_tx_csum, 554 .get_msglevel = gfar_get_msglevel, 555 .set_msglevel = gfar_set_msglevel, 556};