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

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
Loading
Loading
Loading
Loading
+22 −7
Original line number Diff line number Diff line
@@ -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
 *  @desc: prefilled descriptor describing the command (non DMA mem)
 *  @buff: buffer to use for indirect commands
 *  @buff_size: size of buffer for indirect commands
 *  @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
 *  queue.  It runs the queue, cleans the queue, etc
 **/
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)
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)
{
	i40e_status status = 0;
	struct i40e_dma_mem *dma_buff = NULL;
@@ -910,7 +911,12 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
			 */
			if (i40e_asq_done(hw))
				break;

			if (is_atomic_context)
				udelay(50);
			else
				usleep_range(40, 60);

			total_delay += 50;
		} while (total_delay < hw->aq.asq_cmd_timeout);
	}
@@ -967,6 +973,15 @@ i40e_status i40e_asq_send_command(struct i40e_hw *hw,
	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
 *  @desc:     pointer to the temp descriptor (non DMA mem)
+4 −2
Original line number Diff line number Diff line
@@ -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->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;
}
@@ -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->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;
}
+9 −5
Original line number Diff line number Diff line
@@ -22,11 +22,15 @@ void i40e_adminq_init_ring_data(struct i40e_hw *hw);
i40e_status i40e_clean_arq_element(struct i40e_hw *hw,
					     struct i40e_arq_event_info *e,
					     u16 *events_pending);
i40e_status i40e_asq_send_command(struct i40e_hw *hw,
				struct i40e_aq_desc *desc,
				void *buff, /* can be NULL */
				u16  buff_size,
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);
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 */
void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask,