Commit ef39584d authored by Jedrzej Jagielski's avatar Jedrzej Jagielski Committed by Tony Nguyen

i40e: Minimize amount of busy-waiting during AQ send

The i40e_asq_send_command will now use a non blocking usleep_range if
possible (non-atomic context), instead of busy-waiting udelay. The
usleep_range function uses hrtimers to provide better performance and
removes the negative impact of busy-waiting in time-critical
environments.

1. Rename i40e_asq_send_command to i40e_asq_send_command_atomic
   and add 5th parameter to inform if called from an atomic context.
   Call inside usleep_range (if non-atomic) or udelay (if atomic).

2. Change i40e_asq_send_command to invoke
   i40e_asq_send_command_atomic(..., false).

3. Change two functions:
    - i40e_aq_set_vsi_uc_promisc_on_vlan
    - i40e_aq_set_vsi_mc_promisc_on_vlan
   to explicitly use i40e_asq_send_command_atomic(..., true)
   instead of i40e_asq_send_command, as they use spinlocks and do some
   work in an atomic context.
   All other calls to i40e_asq_send_command remain unchanged.
Signed-off-by: default avatarDawid Lukwinski <dawid.lukwinski@intel.com>
Signed-off-by: default avatarJedrzej Jagielski <jedrzej.jagielski@intel.com>
Tested-by: default avatarTony Brelinski <tony.brelinski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent cfb1d572
...@@ -769,21 +769,22 @@ static bool i40e_asq_done(struct i40e_hw *hw) ...@@ -769,21 +769,22 @@ static bool i40e_asq_done(struct i40e_hw *hw)
} }
/** /**
* i40e_asq_send_command - send command to Admin Queue * i40e_asq_send_command_atomic - send command to Admin Queue
* @hw: pointer to the hw struct * @hw: pointer to the hw struct
* @desc: prefilled descriptor describing the command (non DMA mem) * @desc: prefilled descriptor describing the command (non DMA mem)
* @buff: buffer to use for indirect commands * @buff: buffer to use for indirect commands
* @buff_size: size of buffer for indirect commands * @buff_size: size of buffer for indirect commands
* @cmd_details: pointer to command details structure * @cmd_details: pointer to command details structure
* @is_atomic_context: is the function called in an atomic context?
* *
* This is the main send command driver routine for the Admin Queue send * This is the main send command driver routine for the Admin Queue send
* queue. It runs the queue, cleans the queue, etc * queue. It runs the queue, cleans the queue, etc
**/ **/
i40e_status i40e_asq_send_command(struct i40e_hw *hw, i40e_status
struct i40e_aq_desc *desc, i40e_asq_send_command_atomic(struct i40e_hw *hw, struct i40e_aq_desc *desc,
void *buff, /* can be NULL */ void *buff, /* can be NULL */ u16 buff_size,
u16 buff_size, struct i40e_asq_cmd_details *cmd_details,
struct i40e_asq_cmd_details *cmd_details) bool is_atomic_context)
{ {
i40e_status status = 0; i40e_status status = 0;
struct i40e_dma_mem *dma_buff = NULL; struct i40e_dma_mem *dma_buff = NULL;
...@@ -910,7 +911,12 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, ...@@ -910,7 +911,12 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
*/ */
if (i40e_asq_done(hw)) if (i40e_asq_done(hw))
break; break;
if (is_atomic_context)
udelay(50); udelay(50);
else
usleep_range(40, 60);
total_delay += 50; total_delay += 50;
} while (total_delay < hw->aq.asq_cmd_timeout); } while (total_delay < hw->aq.asq_cmd_timeout);
} }
...@@ -967,6 +973,15 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw, ...@@ -967,6 +973,15 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
return status; return status;
} }
i40e_status
i40e_asq_send_command(struct i40e_hw *hw, struct i40e_aq_desc *desc,
void *buff, /* can be NULL */ u16 buff_size,
struct i40e_asq_cmd_details *cmd_details)
{
return i40e_asq_send_command_atomic(hw, desc, buff, buff_size,
cmd_details, false);
}
/** /**
* i40e_fill_default_direct_cmd_desc - AQ descriptor helper function * i40e_fill_default_direct_cmd_desc - AQ descriptor helper function
* @desc: pointer to the temp descriptor (non DMA mem) * @desc: pointer to the temp descriptor (non DMA mem)
......
...@@ -2073,7 +2073,8 @@ enum i40e_status_code i40e_aq_set_vsi_mc_promisc_on_vlan(struct i40e_hw *hw, ...@@ -2073,7 +2073,8 @@ enum i40e_status_code i40e_aq_set_vsi_mc_promisc_on_vlan(struct i40e_hw *hw,
cmd->seid = cpu_to_le16(seid); cmd->seid = cpu_to_le16(seid);
cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID); cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID);
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); status = i40e_asq_send_command_atomic(hw, &desc, NULL, 0,
cmd_details, true);
return status; return status;
} }
...@@ -2114,7 +2115,8 @@ enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw, ...@@ -2114,7 +2115,8 @@ enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw,
cmd->seid = cpu_to_le16(seid); cmd->seid = cpu_to_le16(seid);
cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID); cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID);
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); status = i40e_asq_send_command_atomic(hw, &desc, NULL, 0,
cmd_details, true);
return status; return status;
} }
......
...@@ -22,11 +22,15 @@ void i40e_adminq_init_ring_data(struct i40e_hw *hw); ...@@ -22,11 +22,15 @@ void i40e_adminq_init_ring_data(struct i40e_hw *hw);
i40e_status i40e_clean_arq_element(struct i40e_hw *hw, i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
struct i40e_arq_event_info *e, struct i40e_arq_event_info *e,
u16 *events_pending); u16 *events_pending);
i40e_status i40e_asq_send_command(struct i40e_hw *hw, i40e_status
struct i40e_aq_desc *desc, i40e_asq_send_command(struct i40e_hw *hw, struct i40e_aq_desc *desc,
void *buff, /* can be NULL */ void *buff, /* can be NULL */ u16 buff_size,
u16 buff_size,
struct i40e_asq_cmd_details *cmd_details); struct i40e_asq_cmd_details *cmd_details);
i40e_status
i40e_asq_send_command_atomic(struct i40e_hw *hw, struct i40e_aq_desc *desc,
void *buff, /* can be NULL */ u16 buff_size,
struct i40e_asq_cmd_details *cmd_details,
bool is_atomic_context);
/* debug function for adminq */ /* debug function for adminq */
void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment