lkml.org 
[lkml]   [2020]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 518/639] i40e: reduce stack usage in i40e_set_fc
    Date
    From: Arnd Bergmann <arnd@arndb.de>

    [ Upstream commit 33b165684ab70867d4545643f550a5d48d3ddc57 ]

    The functions i40e_aq_get_phy_abilities_resp() and i40e_set_fc() both
    have giant structure on the stack, which makes each one use stack frames
    larger than 500 bytes.

    As clang decides one function into the other, we get a warning for
    exceeding the frame size limit on 32-bit architectures:

    drivers/net/ethernet/intel/i40e/i40e_common.c:1654:23: error: stack frame size of 1116 bytes in function 'i40e_set_fc' [-Werror,-Wframe-larger-than=]

    When building with gcc, the inlining does not happen, but i40e_set_fc()
    calls i40e_aq_get_phy_abilities_resp() anyway, so they add up on the
    kernel stack just as much.

    The parts that actually use large stacks don't overlap, so make sure
    each one is a separate function, and mark them as noinline_for_stack to
    prevent the compilers from combining them again.

    Fixes: 0a862b43acc6 ("i40e/i40evf: Add module_types and update_link_info")
    Signed-off-by: Arnd Bergmann <arnd@arndb.de>
    Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
    Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    drivers/net/ethernet/intel/i40e/i40e_common.c | 91 +++++++++++--------
    1 file changed, 51 insertions(+), 40 deletions(-)

    diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
    index 85f75b5978fca..eb0ae6ab01e26 100644
    --- a/drivers/net/ethernet/intel/i40e/i40e_common.c
    +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
    @@ -1668,25 +1668,15 @@ enum i40e_status_code i40e_aq_set_phy_config(struct i40e_hw *hw,
    return status;
    }

    -/**
    - * i40e_set_fc
    - * @hw: pointer to the hw struct
    - * @aq_failures: buffer to return AdminQ failure information
    - * @atomic_restart: whether to enable atomic link restart
    - *
    - * Set the requested flow control mode using set_phy_config.
    - **/
    -enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
    - bool atomic_restart)
    +static noinline_for_stack enum i40e_status_code
    +i40e_set_fc_status(struct i40e_hw *hw,
    + struct i40e_aq_get_phy_abilities_resp *abilities,
    + bool atomic_restart)
    {
    - enum i40e_fc_mode fc_mode = hw->fc.requested_mode;
    - struct i40e_aq_get_phy_abilities_resp abilities;
    struct i40e_aq_set_phy_config config;
    - enum i40e_status_code status;
    + enum i40e_fc_mode fc_mode = hw->fc.requested_mode;
    u8 pause_mask = 0x0;

    - *aq_failures = 0x0;
    -
    switch (fc_mode) {
    case I40E_FC_FULL:
    pause_mask |= I40E_AQ_PHY_FLAG_PAUSE_TX;
    @@ -1702,6 +1692,48 @@ enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
    break;
    }

    + memset(&config, 0, sizeof(struct i40e_aq_set_phy_config));
    + /* clear the old pause settings */
    + config.abilities = abilities->abilities & ~(I40E_AQ_PHY_FLAG_PAUSE_TX) &
    + ~(I40E_AQ_PHY_FLAG_PAUSE_RX);
    + /* set the new abilities */
    + config.abilities |= pause_mask;
    + /* If the abilities have changed, then set the new config */
    + if (config.abilities == abilities->abilities)
    + return 0;
    +
    + /* Auto restart link so settings take effect */
    + if (atomic_restart)
    + config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
    + /* Copy over all the old settings */
    + config.phy_type = abilities->phy_type;
    + config.phy_type_ext = abilities->phy_type_ext;
    + config.link_speed = abilities->link_speed;
    + config.eee_capability = abilities->eee_capability;
    + config.eeer = abilities->eeer_val;
    + config.low_power_ctrl = abilities->d3_lpan;
    + config.fec_config = abilities->fec_cfg_curr_mod_ext_info &
    + I40E_AQ_PHY_FEC_CONFIG_MASK;
    +
    + return i40e_aq_set_phy_config(hw, &config, NULL);
    +}
    +
    +/**
    + * i40e_set_fc
    + * @hw: pointer to the hw struct
    + * @aq_failures: buffer to return AdminQ failure information
    + * @atomic_restart: whether to enable atomic link restart
    + *
    + * Set the requested flow control mode using set_phy_config.
    + **/
    +enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
    + bool atomic_restart)
    +{
    + struct i40e_aq_get_phy_abilities_resp abilities;
    + enum i40e_status_code status;
    +
    + *aq_failures = 0x0;
    +
    /* Get the current phy config */
    status = i40e_aq_get_phy_capabilities(hw, false, false, &abilities,
    NULL);
    @@ -1710,31 +1742,10 @@ enum i40e_status_code i40e_set_fc(struct i40e_hw *hw, u8 *aq_failures,
    return status;
    }

    - memset(&config, 0, sizeof(struct i40e_aq_set_phy_config));
    - /* clear the old pause settings */
    - config.abilities = abilities.abilities & ~(I40E_AQ_PHY_FLAG_PAUSE_TX) &
    - ~(I40E_AQ_PHY_FLAG_PAUSE_RX);
    - /* set the new abilities */
    - config.abilities |= pause_mask;
    - /* If the abilities have changed, then set the new config */
    - if (config.abilities != abilities.abilities) {
    - /* Auto restart link so settings take effect */
    - if (atomic_restart)
    - config.abilities |= I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
    - /* Copy over all the old settings */
    - config.phy_type = abilities.phy_type;
    - config.phy_type_ext = abilities.phy_type_ext;
    - config.link_speed = abilities.link_speed;
    - config.eee_capability = abilities.eee_capability;
    - config.eeer = abilities.eeer_val;
    - config.low_power_ctrl = abilities.d3_lpan;
    - config.fec_config = abilities.fec_cfg_curr_mod_ext_info &
    - I40E_AQ_PHY_FEC_CONFIG_MASK;
    - status = i40e_aq_set_phy_config(hw, &config, NULL);
    + status = i40e_set_fc_status(hw, &abilities, atomic_restart);
    + if (status)
    + *aq_failures |= I40E_SET_FC_AQ_FAIL_SET;

    - if (status)
    - *aq_failures |= I40E_SET_FC_AQ_FAIL_SET;
    - }
    /* Update the link info */
    status = i40e_update_link_info(hw);
    if (status) {
    @@ -2563,7 +2574,7 @@ i40e_status i40e_get_link_status(struct i40e_hw *hw, bool *link_up)
    * i40e_updatelink_status - update status of the HW network link
    * @hw: pointer to the hw struct
    **/
    -i40e_status i40e_update_link_info(struct i40e_hw *hw)
    +noinline_for_stack i40e_status i40e_update_link_info(struct i40e_hw *hw)
    {
    struct i40e_aq_get_phy_abilities_resp abilities;
    i40e_status status = 0;
    --
    2.20.1


    \
     
     \ /
      Last update: 2020-01-24 12:29    [W:4.188 / U:0.184 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site