diff options
Diffstat (limited to 'drivers/net/ixgbevf/ethtool.c')
-rw-r--r-- | drivers/net/ixgbevf/ethtool.c | 183 |
1 files changed, 97 insertions, 86 deletions
diff --git a/drivers/net/ixgbevf/ethtool.c b/drivers/net/ixgbevf/ethtool.c index 4680b069b84f..deee3754b1f7 100644 --- a/drivers/net/ixgbevf/ethtool.c +++ b/drivers/net/ixgbevf/ethtool.c | |||
@@ -104,11 +104,13 @@ static int ixgbevf_get_settings(struct net_device *netdev, | |||
104 | hw->mac.ops.check_link(hw, &link_speed, &link_up, false); | 104 | hw->mac.ops.check_link(hw, &link_speed, &link_up, false); |
105 | 105 | ||
106 | if (link_up) { | 106 | if (link_up) { |
107 | ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? | 107 | ethtool_cmd_speed_set( |
108 | SPEED_10000 : SPEED_1000; | 108 | ecmd, |
109 | (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? | ||
110 | SPEED_10000 : SPEED_1000); | ||
109 | ecmd->duplex = DUPLEX_FULL; | 111 | ecmd->duplex = DUPLEX_FULL; |
110 | } else { | 112 | } else { |
111 | ecmd->speed = -1; | 113 | ethtool_cmd_speed_set(ecmd, -1); |
112 | ecmd->duplex = -1; | 114 | ecmd->duplex = -1; |
113 | } | 115 | } |
114 | 116 | ||
@@ -172,7 +174,7 @@ static char *ixgbevf_reg_names[] = { | |||
172 | "IXGBE_VFSTATUS", | 174 | "IXGBE_VFSTATUS", |
173 | "IXGBE_VFLINKS", | 175 | "IXGBE_VFLINKS", |
174 | "IXGBE_VFRXMEMWRAP", | 176 | "IXGBE_VFRXMEMWRAP", |
175 | "IXGBE_VFRTIMER", | 177 | "IXGBE_VFFRTIMER", |
176 | "IXGBE_VTEICR", | 178 | "IXGBE_VTEICR", |
177 | "IXGBE_VTEICS", | 179 | "IXGBE_VTEICS", |
178 | "IXGBE_VTEIMS", | 180 | "IXGBE_VTEIMS", |
@@ -240,7 +242,7 @@ static void ixgbevf_get_regs(struct net_device *netdev, | |||
240 | regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_VFSTATUS); | 242 | regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_VFSTATUS); |
241 | regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_VFLINKS); | 243 | regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_VFLINKS); |
242 | regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_VFRXMEMWRAP); | 244 | regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_VFRXMEMWRAP); |
243 | regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_VFRTIMER); | 245 | regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_VFFRTIMER); |
244 | 246 | ||
245 | /* Interrupt */ | 247 | /* Interrupt */ |
246 | /* don't read EICR because it can clear interrupt causes, instead | 248 | /* don't read EICR because it can clear interrupt causes, instead |
@@ -330,10 +332,8 @@ static int ixgbevf_set_ringparam(struct net_device *netdev, | |||
330 | { | 332 | { |
331 | struct ixgbevf_adapter *adapter = netdev_priv(netdev); | 333 | struct ixgbevf_adapter *adapter = netdev_priv(netdev); |
332 | struct ixgbevf_ring *tx_ring = NULL, *rx_ring = NULL; | 334 | struct ixgbevf_ring *tx_ring = NULL, *rx_ring = NULL; |
333 | int i, err; | 335 | int i, err = 0; |
334 | u32 new_rx_count, new_tx_count; | 336 | u32 new_rx_count, new_tx_count; |
335 | bool need_tx_update = false; | ||
336 | bool need_rx_update = false; | ||
337 | 337 | ||
338 | if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) | 338 | if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) |
339 | return -EINVAL; | 339 | return -EINVAL; |
@@ -355,89 +355,96 @@ static int ixgbevf_set_ringparam(struct net_device *netdev, | |||
355 | while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state)) | 355 | while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state)) |
356 | msleep(1); | 356 | msleep(1); |
357 | 357 | ||
358 | if (new_tx_count != adapter->tx_ring_count) { | 358 | /* |
359 | tx_ring = kcalloc(adapter->num_tx_queues, | 359 | * If the adapter isn't up and running then just set the |
360 | sizeof(struct ixgbevf_ring), GFP_KERNEL); | 360 | * new parameters and scurry for the exits. |
361 | if (!tx_ring) { | 361 | */ |
362 | err = -ENOMEM; | 362 | if (!netif_running(adapter->netdev)) { |
363 | goto err_setup; | 363 | for (i = 0; i < adapter->num_tx_queues; i++) |
364 | } | 364 | adapter->tx_ring[i].count = new_tx_count; |
365 | memcpy(tx_ring, adapter->tx_ring, | 365 | for (i = 0; i < adapter->num_rx_queues; i++) |
366 | adapter->num_tx_queues * sizeof(struct ixgbevf_ring)); | 366 | adapter->rx_ring[i].count = new_rx_count; |
367 | for (i = 0; i < adapter->num_tx_queues; i++) { | 367 | adapter->tx_ring_count = new_tx_count; |
368 | tx_ring[i].count = new_tx_count; | 368 | adapter->rx_ring_count = new_rx_count; |
369 | err = ixgbevf_setup_tx_resources(adapter, | 369 | goto clear_reset; |
370 | &tx_ring[i]); | ||
371 | if (err) { | ||
372 | while (i) { | ||
373 | i--; | ||
374 | ixgbevf_free_tx_resources(adapter, | ||
375 | &tx_ring[i]); | ||
376 | } | ||
377 | kfree(tx_ring); | ||
378 | goto err_setup; | ||
379 | } | ||
380 | tx_ring[i].v_idx = adapter->tx_ring[i].v_idx; | ||
381 | } | ||
382 | need_tx_update = true; | ||
383 | } | 370 | } |
384 | 371 | ||
385 | if (new_rx_count != adapter->rx_ring_count) { | 372 | tx_ring = kcalloc(adapter->num_tx_queues, |
386 | rx_ring = kcalloc(adapter->num_rx_queues, | 373 | sizeof(struct ixgbevf_ring), GFP_KERNEL); |
387 | sizeof(struct ixgbevf_ring), GFP_KERNEL); | 374 | if (!tx_ring) { |
388 | if ((!rx_ring) && (need_tx_update)) { | 375 | err = -ENOMEM; |
389 | err = -ENOMEM; | 376 | goto clear_reset; |
390 | goto err_rx_setup; | ||
391 | } | ||
392 | memcpy(rx_ring, adapter->rx_ring, | ||
393 | adapter->num_rx_queues * sizeof(struct ixgbevf_ring)); | ||
394 | for (i = 0; i < adapter->num_rx_queues; i++) { | ||
395 | rx_ring[i].count = new_rx_count; | ||
396 | err = ixgbevf_setup_rx_resources(adapter, | ||
397 | &rx_ring[i]); | ||
398 | if (err) { | ||
399 | while (i) { | ||
400 | i--; | ||
401 | ixgbevf_free_rx_resources(adapter, | ||
402 | &rx_ring[i]); | ||
403 | } | ||
404 | kfree(rx_ring); | ||
405 | goto err_rx_setup; | ||
406 | } | ||
407 | rx_ring[i].v_idx = adapter->rx_ring[i].v_idx; | ||
408 | } | ||
409 | need_rx_update = true; | ||
410 | } | 377 | } |
411 | 378 | ||
412 | err_rx_setup: | 379 | rx_ring = kcalloc(adapter->num_rx_queues, |
413 | /* if rings need to be updated, here's the place to do it in one shot */ | 380 | sizeof(struct ixgbevf_ring), GFP_KERNEL); |
414 | if (need_tx_update || need_rx_update) { | 381 | if (!rx_ring) { |
415 | if (netif_running(netdev)) | 382 | err = -ENOMEM; |
416 | ixgbevf_down(adapter); | 383 | goto err_rx_setup; |
417 | } | 384 | } |
418 | 385 | ||
419 | /* tx */ | 386 | ixgbevf_down(adapter); |
420 | if (need_tx_update) { | 387 | |
421 | kfree(adapter->tx_ring); | 388 | memcpy(tx_ring, adapter->tx_ring, |
422 | adapter->tx_ring = tx_ring; | 389 | adapter->num_tx_queues * sizeof(struct ixgbevf_ring)); |
423 | tx_ring = NULL; | 390 | for (i = 0; i < adapter->num_tx_queues; i++) { |
424 | adapter->tx_ring_count = new_tx_count; | 391 | tx_ring[i].count = new_tx_count; |
392 | err = ixgbevf_setup_tx_resources(adapter, &tx_ring[i]); | ||
393 | if (err) { | ||
394 | while (i) { | ||
395 | i--; | ||
396 | ixgbevf_free_tx_resources(adapter, | ||
397 | &tx_ring[i]); | ||
398 | } | ||
399 | goto err_tx_ring_setup; | ||
400 | } | ||
401 | tx_ring[i].v_idx = adapter->tx_ring[i].v_idx; | ||
425 | } | 402 | } |
426 | 403 | ||
427 | /* rx */ | 404 | memcpy(rx_ring, adapter->rx_ring, |
428 | if (need_rx_update) { | 405 | adapter->num_rx_queues * sizeof(struct ixgbevf_ring)); |
429 | kfree(adapter->rx_ring); | 406 | for (i = 0; i < adapter->num_rx_queues; i++) { |
430 | adapter->rx_ring = rx_ring; | 407 | rx_ring[i].count = new_rx_count; |
431 | rx_ring = NULL; | 408 | err = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]); |
432 | adapter->rx_ring_count = new_rx_count; | 409 | if (err) { |
410 | while (i) { | ||
411 | i--; | ||
412 | ixgbevf_free_rx_resources(adapter, | ||
413 | &rx_ring[i]); | ||
414 | } | ||
415 | goto err_rx_ring_setup; | ||
416 | } | ||
417 | rx_ring[i].v_idx = adapter->rx_ring[i].v_idx; | ||
433 | } | 418 | } |
434 | 419 | ||
420 | /* | ||
421 | * Only switch to new rings if all the prior allocations | ||
422 | * and ring setups have succeeded. | ||
423 | */ | ||
424 | kfree(adapter->tx_ring); | ||
425 | adapter->tx_ring = tx_ring; | ||
426 | adapter->tx_ring_count = new_tx_count; | ||
427 | |||
428 | kfree(adapter->rx_ring); | ||
429 | adapter->rx_ring = rx_ring; | ||
430 | adapter->rx_ring_count = new_rx_count; | ||
431 | |||
435 | /* success! */ | 432 | /* success! */ |
436 | err = 0; | 433 | ixgbevf_up(adapter); |
437 | if (netif_running(netdev)) | ||
438 | ixgbevf_up(adapter); | ||
439 | 434 | ||
440 | err_setup: | 435 | goto clear_reset; |
436 | |||
437 | err_rx_ring_setup: | ||
438 | for(i = 0; i < adapter->num_tx_queues; i++) | ||
439 | ixgbevf_free_tx_resources(adapter, &tx_ring[i]); | ||
440 | |||
441 | err_tx_ring_setup: | ||
442 | kfree(rx_ring); | ||
443 | |||
444 | err_rx_setup: | ||
445 | kfree(tx_ring); | ||
446 | |||
447 | clear_reset: | ||
441 | clear_bit(__IXGBEVF_RESETTING, &adapter->state); | 448 | clear_bit(__IXGBEVF_RESETTING, &adapter->state); |
442 | return err; | 449 | return err; |
443 | } | 450 | } |
@@ -539,7 +546,7 @@ struct ixgbevf_reg_test { | |||
539 | #define TABLE64_TEST_HI 6 | 546 | #define TABLE64_TEST_HI 6 |
540 | 547 | ||
541 | /* default VF register test */ | 548 | /* default VF register test */ |
542 | static struct ixgbevf_reg_test reg_test_vf[] = { | 549 | static const struct ixgbevf_reg_test reg_test_vf[] = { |
543 | { IXGBE_VFRDBAL(0), 2, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 }, | 550 | { IXGBE_VFRDBAL(0), 2, PATTERN_TEST, 0xFFFFFF80, 0xFFFFFF80 }, |
544 | { IXGBE_VFRDBAH(0), 2, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, | 551 | { IXGBE_VFRDBAH(0), 2, PATTERN_TEST, 0xFFFFFFFF, 0xFFFFFFFF }, |
545 | { IXGBE_VFRDLEN(0), 2, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, | 552 | { IXGBE_VFRDLEN(0), 2, PATTERN_TEST, 0x000FFF80, 0x000FFFFF }, |
@@ -552,19 +559,23 @@ static struct ixgbevf_reg_test reg_test_vf[] = { | |||
552 | { 0, 0, 0, 0 } | 559 | { 0, 0, 0, 0 } |
553 | }; | 560 | }; |
554 | 561 | ||
562 | static const u32 register_test_patterns[] = { | ||
563 | 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF | ||
564 | }; | ||
565 | |||
555 | #define REG_PATTERN_TEST(R, M, W) \ | 566 | #define REG_PATTERN_TEST(R, M, W) \ |
556 | { \ | 567 | { \ |
557 | u32 pat, val, before; \ | 568 | u32 pat, val, before; \ |
558 | const u32 _test[] = {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; \ | 569 | for (pat = 0; pat < ARRAY_SIZE(register_test_patterns); pat++) { \ |
559 | for (pat = 0; pat < ARRAY_SIZE(_test); pat++) { \ | ||
560 | before = readl(adapter->hw.hw_addr + R); \ | 570 | before = readl(adapter->hw.hw_addr + R); \ |
561 | writel((_test[pat] & W), (adapter->hw.hw_addr + R)); \ | 571 | writel((register_test_patterns[pat] & W), \ |
572 | (adapter->hw.hw_addr + R)); \ | ||
562 | val = readl(adapter->hw.hw_addr + R); \ | 573 | val = readl(adapter->hw.hw_addr + R); \ |
563 | if (val != (_test[pat] & W & M)) { \ | 574 | if (val != (register_test_patterns[pat] & W & M)) { \ |
564 | hw_dbg(&adapter->hw, \ | 575 | hw_dbg(&adapter->hw, \ |
565 | "pattern test reg %04X failed: got " \ | 576 | "pattern test reg %04X failed: got " \ |
566 | "0x%08X expected 0x%08X\n", \ | 577 | "0x%08X expected 0x%08X\n", \ |
567 | R, val, (_test[pat] & W & M)); \ | 578 | R, val, (register_test_patterns[pat] & W & M)); \ |
568 | *data = R; \ | 579 | *data = R; \ |
569 | writel(before, adapter->hw.hw_addr + R); \ | 580 | writel(before, adapter->hw.hw_addr + R); \ |
570 | return 1; \ | 581 | return 1; \ |
@@ -591,7 +602,7 @@ static struct ixgbevf_reg_test reg_test_vf[] = { | |||
591 | 602 | ||
592 | static int ixgbevf_reg_test(struct ixgbevf_adapter *adapter, u64 *data) | 603 | static int ixgbevf_reg_test(struct ixgbevf_adapter *adapter, u64 *data) |
593 | { | 604 | { |
594 | struct ixgbevf_reg_test *test; | 605 | const struct ixgbevf_reg_test *test; |
595 | u32 i; | 606 | u32 i; |
596 | 607 | ||
597 | test = reg_test_vf; | 608 | test = reg_test_vf; |