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

IB/mlx4: Optimize do_slave_init

There is little chance our memory allocation will fail, so we can
combine initializing the work structs with allocating them instead of
looping through all of them once to allocate and again to initialize.
Then when we need to actually find out if our device is up or in the
process of going down, have all of our work structs batched up, take the
spin_lock once and only once, and do all of the batch under the one
spin_lock invocation instead of incurring all of the locked memory cycles
we would otherwise incur to take/release the spin_lock over and over
again.

Signed-off-by: Doug Ledford <dledford@redhat.com>

+9 -7
+9 -7
drivers/infiniband/hw/mlx4/main.c
··· 2681 2681 kfree(dm[i]); 2682 2682 goto out; 2683 2683 } 2684 - } 2685 - /* initialize or tear down tunnel QPs for the slave */ 2686 - for (i = 0; i < ports; i++) { 2687 2684 INIT_WORK(&dm[i]->work, mlx4_ib_tunnels_update_work); 2688 2685 dm[i]->port = first_port + i + 1; 2689 2686 dm[i]->slave = slave; 2690 2687 dm[i]->do_init = do_init; 2691 2688 dm[i]->dev = ibdev; 2692 - spin_lock_irqsave(&ibdev->sriov.going_down_lock, flags); 2693 - if (!ibdev->sriov.is_going_down) 2689 + } 2690 + /* initialize or tear down tunnel QPs for the slave */ 2691 + spin_lock_irqsave(&ibdev->sriov.going_down_lock, flags); 2692 + if (!ibdev->sriov.is_going_down) { 2693 + for (i = 0; i < ports; i++) 2694 2694 queue_work(ibdev->sriov.demux[i].ud_wq, &dm[i]->work); 2695 - else 2696 - kfree(dm[i]); 2697 2695 spin_unlock_irqrestore(&ibdev->sriov.going_down_lock, flags); 2696 + } else { 2697 + spin_unlock_irqrestore(&ibdev->sriov.going_down_lock, flags); 2698 + for (i = 0; i < ports; i++) 2699 + kfree(dm[i]); 2698 2700 } 2699 2701 out: 2700 2702 kfree(dm);