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

ixgbevf: Refactor ring parameter re-size

The function to resize the Tx/Rx rings had the potential to
dereference a NULL pointer and the code would attempt to resize
the Tx ring even if the Rx ring allocation had failed. This
would cause some confusion in the return code semantics. Fixed
up to just unwind the allocations if any of them fail and return
an error.

Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
Tested-by: Emil Tantilov <emil.s.tantilov@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Greg Rose and committed by
David S. Miller
bba50b99 543876c9

+84 -79
+84 -79
drivers/net/ixgbevf/ethtool.c
··· 330 330 { 331 331 struct ixgbevf_adapter *adapter = netdev_priv(netdev); 332 332 struct ixgbevf_ring *tx_ring = NULL, *rx_ring = NULL; 333 - int i, err; 333 + int i, err = 0; 334 334 u32 new_rx_count, new_tx_count; 335 - bool need_tx_update = false; 336 - bool need_rx_update = false; 337 335 338 336 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) 339 337 return -EINVAL; ··· 353 355 while (test_and_set_bit(__IXGBEVF_RESETTING, &adapter->state)) 354 356 msleep(1); 355 357 356 - if (new_tx_count != adapter->tx_ring_count) { 357 - tx_ring = kcalloc(adapter->num_tx_queues, 358 - sizeof(struct ixgbevf_ring), GFP_KERNEL); 359 - if (!tx_ring) { 360 - err = -ENOMEM; 361 - goto err_setup; 362 - } 363 - memcpy(tx_ring, adapter->tx_ring, 364 - adapter->num_tx_queues * sizeof(struct ixgbevf_ring)); 365 - for (i = 0; i < adapter->num_tx_queues; i++) { 366 - tx_ring[i].count = new_tx_count; 367 - err = ixgbevf_setup_tx_resources(adapter, 368 - &tx_ring[i]); 369 - if (err) { 370 - while (i) { 371 - i--; 372 - ixgbevf_free_tx_resources(adapter, 373 - &tx_ring[i]); 374 - } 375 - kfree(tx_ring); 376 - goto err_setup; 377 - } 378 - tx_ring[i].v_idx = adapter->tx_ring[i].v_idx; 379 - } 380 - need_tx_update = true; 381 - } 382 - 383 - if (new_rx_count != adapter->rx_ring_count) { 384 - rx_ring = kcalloc(adapter->num_rx_queues, 385 - sizeof(struct ixgbevf_ring), GFP_KERNEL); 386 - if ((!rx_ring) && (need_tx_update)) { 387 - err = -ENOMEM; 388 - goto err_rx_setup; 389 - } 390 - memcpy(rx_ring, adapter->rx_ring, 391 - adapter->num_rx_queues * sizeof(struct ixgbevf_ring)); 392 - for (i = 0; i < adapter->num_rx_queues; i++) { 393 - rx_ring[i].count = new_rx_count; 394 - err = ixgbevf_setup_rx_resources(adapter, 395 - &rx_ring[i]); 396 - if (err) { 397 - while (i) { 398 - i--; 399 - ixgbevf_free_rx_resources(adapter, 400 - &rx_ring[i]); 401 - } 402 - kfree(rx_ring); 403 - goto err_rx_setup; 404 - } 405 - rx_ring[i].v_idx = adapter->rx_ring[i].v_idx; 406 - } 407 - need_rx_update = true; 408 - } 409 - 410 - err_rx_setup: 411 - /* if rings need to be updated, here's the place to do it in one shot */ 412 - if (need_tx_update || need_rx_update) { 413 - if (netif_running(netdev)) 414 - ixgbevf_down(adapter); 415 - } 416 - 417 - /* tx */ 418 - if (need_tx_update) { 419 - kfree(adapter->tx_ring); 420 - adapter->tx_ring = tx_ring; 421 - tx_ring = NULL; 358 + /* 359 + * If the adapter isn't up and running then just set the 360 + * new parameters and scurry for the exits. 361 + */ 362 + if (!netif_running(adapter->netdev)) { 363 + for (i = 0; i < adapter->num_tx_queues; i++) 364 + adapter->tx_ring[i].count = new_tx_count; 365 + for (i = 0; i < adapter->num_rx_queues; i++) 366 + adapter->rx_ring[i].count = new_rx_count; 422 367 adapter->tx_ring_count = new_tx_count; 368 + adapter->rx_ring_count = new_rx_count; 369 + goto clear_reset; 423 370 } 424 371 425 - /* rx */ 426 - if (need_rx_update) { 427 - kfree(adapter->rx_ring); 428 - adapter->rx_ring = rx_ring; 429 - rx_ring = NULL; 430 - adapter->rx_ring_count = new_rx_count; 372 + tx_ring = kcalloc(adapter->num_tx_queues, 373 + sizeof(struct ixgbevf_ring), GFP_KERNEL); 374 + if (!tx_ring) { 375 + err = -ENOMEM; 376 + goto clear_reset; 431 377 } 378 + 379 + rx_ring = kcalloc(adapter->num_rx_queues, 380 + sizeof(struct ixgbevf_ring), GFP_KERNEL); 381 + if (!rx_ring) { 382 + err = -ENOMEM; 383 + goto err_rx_setup; 384 + } 385 + 386 + ixgbevf_down(adapter); 387 + 388 + memcpy(tx_ring, adapter->tx_ring, 389 + adapter->num_tx_queues * sizeof(struct ixgbevf_ring)); 390 + for (i = 0; i < adapter->num_tx_queues; i++) { 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; 402 + } 403 + 404 + memcpy(rx_ring, adapter->rx_ring, 405 + adapter->num_rx_queues * sizeof(struct ixgbevf_ring)); 406 + for (i = 0; i < adapter->num_rx_queues; i++) { 407 + rx_ring[i].count = new_rx_count; 408 + err = ixgbevf_setup_rx_resources(adapter, &rx_ring[i]); 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; 418 + } 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; 432 431 433 432 /* success! */ 434 - err = 0; 435 - if (netif_running(netdev)) 436 - ixgbevf_up(adapter); 433 + ixgbevf_up(adapter); 437 434 438 - 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: 439 448 clear_bit(__IXGBEVF_RESETTING, &adapter->state); 440 449 return err; 441 450 }