diff options
Diffstat (limited to 'drivers/net/gianfar_ethtool.c')
-rw-r--r-- | drivers/net/gianfar_ethtool.c | 100 |
1 files changed, 65 insertions, 35 deletions
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 6c144b525b47..6d0d1714c2f2 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c | |||
@@ -7,8 +7,9 @@ | |||
7 | * | 7 | * |
8 | * Author: Andy Fleming | 8 | * Author: Andy Fleming |
9 | * Maintainer: Kumar Gala | 9 | * Maintainer: Kumar Gala |
10 | * Modifier: Sandeep Gopalpet <sandeep.kumar@freescale.com> | ||
10 | * | 11 | * |
11 | * Copyright (c) 2003,2004 Freescale Semiconductor, Inc. | 12 | * Copyright 2003-2006, 2008-2009 Freescale Semiconductor, Inc. |
12 | * | 13 | * |
13 | * This software may be used and distributed according to | 14 | * This software may be used and distributed according to |
14 | * the terms of the GNU Public License, Version 2, incorporated herein | 15 | * the terms of the GNU Public License, Version 2, incorporated herein |
@@ -41,7 +42,7 @@ | |||
41 | #include "gianfar.h" | 42 | #include "gianfar.h" |
42 | 43 | ||
43 | extern void gfar_start(struct net_device *dev); | 44 | extern void gfar_start(struct net_device *dev); |
44 | extern int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit); | 45 | extern int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit); |
45 | 46 | ||
46 | #define GFAR_MAX_COAL_USECS 0xffff | 47 | #define GFAR_MAX_COAL_USECS 0xffff |
47 | #define GFAR_MAX_COAL_FRAMES 0xff | 48 | #define GFAR_MAX_COAL_FRAMES 0xff |
@@ -197,12 +198,16 @@ static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
197 | { | 198 | { |
198 | struct gfar_private *priv = netdev_priv(dev); | 199 | struct gfar_private *priv = netdev_priv(dev); |
199 | struct phy_device *phydev = priv->phydev; | 200 | struct phy_device *phydev = priv->phydev; |
201 | struct gfar_priv_rx_q *rx_queue = NULL; | ||
202 | struct gfar_priv_tx_q *tx_queue = NULL; | ||
200 | 203 | ||
201 | if (NULL == phydev) | 204 | if (NULL == phydev) |
202 | return -ENODEV; | 205 | return -ENODEV; |
206 | tx_queue = priv->tx_queue; | ||
207 | rx_queue = priv->rx_queue; | ||
203 | 208 | ||
204 | cmd->maxtxpkt = get_icft_value(priv->txic); | 209 | cmd->maxtxpkt = get_icft_value(tx_queue->txic); |
205 | cmd->maxrxpkt = get_icft_value(priv->rxic); | 210 | cmd->maxrxpkt = get_icft_value(rx_queue->rxic); |
206 | 211 | ||
207 | return phy_ethtool_gset(phydev, cmd); | 212 | return phy_ethtool_gset(phydev, cmd); |
208 | } | 213 | } |
@@ -279,6 +284,8 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic | |||
279 | static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) | 284 | static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) |
280 | { | 285 | { |
281 | struct gfar_private *priv = netdev_priv(dev); | 286 | struct gfar_private *priv = netdev_priv(dev); |
287 | struct gfar_priv_rx_q *rx_queue = NULL; | ||
288 | struct gfar_priv_tx_q *tx_queue = NULL; | ||
282 | unsigned long rxtime; | 289 | unsigned long rxtime; |
283 | unsigned long rxcount; | 290 | unsigned long rxcount; |
284 | unsigned long txtime; | 291 | unsigned long txtime; |
@@ -290,10 +297,13 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals | |||
290 | if (NULL == priv->phydev) | 297 | if (NULL == priv->phydev) |
291 | return -ENODEV; | 298 | return -ENODEV; |
292 | 299 | ||
293 | rxtime = get_ictt_value(priv->rxic); | 300 | rx_queue = priv->rx_queue; |
294 | rxcount = get_icft_value(priv->rxic); | 301 | tx_queue = priv->tx_queue; |
295 | txtime = get_ictt_value(priv->txic); | 302 | |
296 | txcount = get_icft_value(priv->txic); | 303 | rxtime = get_ictt_value(rx_queue->rxic); |
304 | rxcount = get_icft_value(rx_queue->rxic); | ||
305 | txtime = get_ictt_value(tx_queue->txic); | ||
306 | txcount = get_icft_value(tx_queue->txic); | ||
297 | cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, rxtime); | 307 | cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, rxtime); |
298 | cvals->rx_max_coalesced_frames = rxcount; | 308 | cvals->rx_max_coalesced_frames = rxcount; |
299 | 309 | ||
@@ -339,16 +349,21 @@ static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals | |||
339 | static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) | 349 | static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals) |
340 | { | 350 | { |
341 | struct gfar_private *priv = netdev_priv(dev); | 351 | struct gfar_private *priv = netdev_priv(dev); |
352 | struct gfar_priv_tx_q *tx_queue = NULL; | ||
353 | struct gfar_priv_rx_q *rx_queue = NULL; | ||
342 | 354 | ||
343 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) | 355 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) |
344 | return -EOPNOTSUPP; | 356 | return -EOPNOTSUPP; |
345 | 357 | ||
358 | tx_queue = priv->tx_queue; | ||
359 | rx_queue = priv->rx_queue; | ||
360 | |||
346 | /* Set up rx coalescing */ | 361 | /* Set up rx coalescing */ |
347 | if ((cvals->rx_coalesce_usecs == 0) || | 362 | if ((cvals->rx_coalesce_usecs == 0) || |
348 | (cvals->rx_max_coalesced_frames == 0)) | 363 | (cvals->rx_max_coalesced_frames == 0)) |
349 | priv->rxcoalescing = 0; | 364 | rx_queue->rxcoalescing = 0; |
350 | else | 365 | else |
351 | priv->rxcoalescing = 1; | 366 | rx_queue->rxcoalescing = 1; |
352 | 367 | ||
353 | if (NULL == priv->phydev) | 368 | if (NULL == priv->phydev) |
354 | return -ENODEV; | 369 | return -ENODEV; |
@@ -366,15 +381,15 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals | |||
366 | return -EINVAL; | 381 | return -EINVAL; |
367 | } | 382 | } |
368 | 383 | ||
369 | priv->rxic = mk_ic_value(cvals->rx_max_coalesced_frames, | 384 | rx_queue->rxic = mk_ic_value(cvals->rx_max_coalesced_frames, |
370 | gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs)); | 385 | gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs)); |
371 | 386 | ||
372 | /* Set up tx coalescing */ | 387 | /* Set up tx coalescing */ |
373 | if ((cvals->tx_coalesce_usecs == 0) || | 388 | if ((cvals->tx_coalesce_usecs == 0) || |
374 | (cvals->tx_max_coalesced_frames == 0)) | 389 | (cvals->tx_max_coalesced_frames == 0)) |
375 | priv->txcoalescing = 0; | 390 | tx_queue->txcoalescing = 0; |
376 | else | 391 | else |
377 | priv->txcoalescing = 1; | 392 | tx_queue->txcoalescing = 1; |
378 | 393 | ||
379 | /* Check the bounds of the values */ | 394 | /* Check the bounds of the values */ |
380 | if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) { | 395 | if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) { |
@@ -389,16 +404,16 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals | |||
389 | return -EINVAL; | 404 | return -EINVAL; |
390 | } | 405 | } |
391 | 406 | ||
392 | priv->txic = mk_ic_value(cvals->tx_max_coalesced_frames, | 407 | tx_queue->txic = mk_ic_value(cvals->tx_max_coalesced_frames, |
393 | gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs)); | 408 | gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs)); |
394 | 409 | ||
395 | gfar_write(&priv->regs->rxic, 0); | 410 | gfar_write(&priv->regs->rxic, 0); |
396 | if (priv->rxcoalescing) | 411 | if (rx_queue->rxcoalescing) |
397 | gfar_write(&priv->regs->rxic, priv->rxic); | 412 | gfar_write(&priv->regs->rxic, rx_queue->rxic); |
398 | 413 | ||
399 | gfar_write(&priv->regs->txic, 0); | 414 | gfar_write(&priv->regs->txic, 0); |
400 | if (priv->txcoalescing) | 415 | if (tx_queue->txcoalescing) |
401 | gfar_write(&priv->regs->txic, priv->txic); | 416 | gfar_write(&priv->regs->txic, tx_queue->txic); |
402 | 417 | ||
403 | return 0; | 418 | return 0; |
404 | } | 419 | } |
@@ -409,6 +424,11 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals | |||
409 | static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) | 424 | static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rvals) |
410 | { | 425 | { |
411 | struct gfar_private *priv = netdev_priv(dev); | 426 | struct gfar_private *priv = netdev_priv(dev); |
427 | struct gfar_priv_tx_q *tx_queue = NULL; | ||
428 | struct gfar_priv_rx_q *rx_queue = NULL; | ||
429 | |||
430 | tx_queue = priv->tx_queue; | ||
431 | rx_queue = priv->rx_queue; | ||
412 | 432 | ||
413 | rvals->rx_max_pending = GFAR_RX_MAX_RING_SIZE; | 433 | rvals->rx_max_pending = GFAR_RX_MAX_RING_SIZE; |
414 | rvals->rx_mini_max_pending = GFAR_RX_MAX_RING_SIZE; | 434 | rvals->rx_mini_max_pending = GFAR_RX_MAX_RING_SIZE; |
@@ -418,10 +438,10 @@ static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rv | |||
418 | /* Values changeable by the user. The valid values are | 438 | /* Values changeable by the user. The valid values are |
419 | * in the range 1 to the "*_max_pending" counterpart above. | 439 | * in the range 1 to the "*_max_pending" counterpart above. |
420 | */ | 440 | */ |
421 | rvals->rx_pending = priv->rx_ring_size; | 441 | rvals->rx_pending = rx_queue->rx_ring_size; |
422 | rvals->rx_mini_pending = priv->rx_ring_size; | 442 | rvals->rx_mini_pending = rx_queue->rx_ring_size; |
423 | rvals->rx_jumbo_pending = priv->rx_ring_size; | 443 | rvals->rx_jumbo_pending = rx_queue->rx_ring_size; |
424 | rvals->tx_pending = priv->tx_ring_size; | 444 | rvals->tx_pending = tx_queue->tx_ring_size; |
425 | } | 445 | } |
426 | 446 | ||
427 | /* Change the current ring parameters, stopping the controller if | 447 | /* Change the current ring parameters, stopping the controller if |
@@ -431,6 +451,8 @@ static void gfar_gringparam(struct net_device *dev, struct ethtool_ringparam *rv | |||
431 | static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) | 451 | static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rvals) |
432 | { | 452 | { |
433 | struct gfar_private *priv = netdev_priv(dev); | 453 | struct gfar_private *priv = netdev_priv(dev); |
454 | struct gfar_priv_tx_q *tx_queue = NULL; | ||
455 | struct gfar_priv_rx_q *rx_queue = NULL; | ||
434 | int err = 0; | 456 | int err = 0; |
435 | 457 | ||
436 | if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE) | 458 | if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE) |
@@ -451,29 +473,32 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva | |||
451 | return -EINVAL; | 473 | return -EINVAL; |
452 | } | 474 | } |
453 | 475 | ||
476 | tx_queue = priv->tx_queue; | ||
477 | rx_queue = priv->rx_queue; | ||
478 | |||
454 | if (dev->flags & IFF_UP) { | 479 | if (dev->flags & IFF_UP) { |
455 | unsigned long flags; | 480 | unsigned long flags; |
456 | 481 | ||
457 | /* Halt TX and RX, and process the frames which | 482 | /* Halt TX and RX, and process the frames which |
458 | * have already been received */ | 483 | * have already been received */ |
459 | spin_lock_irqsave(&priv->txlock, flags); | 484 | spin_lock_irqsave(&tx_queue->txlock, flags); |
460 | spin_lock(&priv->rxlock); | 485 | spin_lock(&rx_queue->rxlock); |
461 | 486 | ||
462 | gfar_halt(dev); | 487 | gfar_halt(dev); |
463 | 488 | ||
464 | spin_unlock(&priv->rxlock); | 489 | spin_unlock(&rx_queue->rxlock); |
465 | spin_unlock_irqrestore(&priv->txlock, flags); | 490 | spin_unlock_irqrestore(&tx_queue->txlock, flags); |
466 | 491 | ||
467 | gfar_clean_rx_ring(dev, priv->rx_ring_size); | 492 | gfar_clean_rx_ring(rx_queue, rx_queue->rx_ring_size); |
468 | 493 | ||
469 | /* Now we take down the rings to rebuild them */ | 494 | /* Now we take down the rings to rebuild them */ |
470 | stop_gfar(dev); | 495 | stop_gfar(dev); |
471 | } | 496 | } |
472 | 497 | ||
473 | /* Change the size */ | 498 | /* Change the size */ |
474 | priv->rx_ring_size = rvals->rx_pending; | 499 | rx_queue->rx_ring_size = rvals->rx_pending; |
475 | priv->tx_ring_size = rvals->tx_pending; | 500 | tx_queue->tx_ring_size = rvals->tx_pending; |
476 | priv->num_txbdfree = priv->tx_ring_size; | 501 | tx_queue->num_txbdfree = tx_queue->tx_ring_size; |
477 | 502 | ||
478 | /* Rebuild the rings with the new size */ | 503 | /* Rebuild the rings with the new size */ |
479 | if (dev->flags & IFF_UP) { | 504 | if (dev->flags & IFF_UP) { |
@@ -486,24 +511,29 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva | |||
486 | static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) | 511 | static int gfar_set_rx_csum(struct net_device *dev, uint32_t data) |
487 | { | 512 | { |
488 | struct gfar_private *priv = netdev_priv(dev); | 513 | struct gfar_private *priv = netdev_priv(dev); |
514 | struct gfar_priv_rx_q *rx_queue = NULL; | ||
515 | struct gfar_priv_tx_q *tx_queue = NULL; | ||
489 | unsigned long flags; | 516 | unsigned long flags; |
490 | int err = 0; | 517 | int err = 0; |
491 | 518 | ||
492 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) | 519 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM)) |
493 | return -EOPNOTSUPP; | 520 | return -EOPNOTSUPP; |
494 | 521 | ||
522 | tx_queue = priv->tx_queue; | ||
523 | rx_queue = priv->rx_queue; | ||
524 | |||
495 | if (dev->flags & IFF_UP) { | 525 | if (dev->flags & IFF_UP) { |
496 | /* Halt TX and RX, and process the frames which | 526 | /* Halt TX and RX, and process the frames which |
497 | * have already been received */ | 527 | * have already been received */ |
498 | spin_lock_irqsave(&priv->txlock, flags); | 528 | spin_lock_irqsave(&tx_queue->txlock, flags); |
499 | spin_lock(&priv->rxlock); | 529 | spin_lock(&rx_queue->rxlock); |
500 | 530 | ||
501 | gfar_halt(dev); | 531 | gfar_halt(dev); |
502 | 532 | ||
503 | spin_unlock(&priv->rxlock); | 533 | spin_unlock(&rx_queue->rxlock); |
504 | spin_unlock_irqrestore(&priv->txlock, flags); | 534 | spin_unlock_irqrestore(&tx_queue->txlock, flags); |
505 | 535 | ||
506 | gfar_clean_rx_ring(dev, priv->rx_ring_size); | 536 | gfar_clean_rx_ring(rx_queue, rx_queue->rx_ring_size); |
507 | 537 | ||
508 | /* Now we take down the rings to rebuild them */ | 538 | /* Now we take down the rings to rebuild them */ |
509 | stop_gfar(dev); | 539 | stop_gfar(dev); |