]> git.baikalelectronics.ru Git - kernel.git/commitdiff
i40e: Minimize amount of busy-waiting during AQ send
authorJedrzej Jagielski <jedrzej.jagielski@intel.com>
Tue, 16 Nov 2021 13:13:29 +0000 (13:13 +0000)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Fri, 7 Jan 2022 17:04:21 +0000 (09:04 -0800)
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: Dawid Lukwinski <dawid.lukwinski@intel.com>
Signed-off-by: Jedrzej Jagielski <jedrzej.jagielski@intel.com>
Tested-by: Tony Brelinski <tony.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/i40e/i40e_adminq.c
drivers/net/ethernet/intel/i40e/i40e_common.c
drivers/net/ethernet/intel/i40e/i40e_prototype.h

index 593912b176099e7f2d97fa679d966f29b18b1398..7abef88801fb5f28f02d5befc12647bd98eb0385 100644 (file)
@@ -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;
-                       udelay(50);
+
+                       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 @@ asq_send_command_error:
        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)
index b4d3fed0d2f208a15ec50aa05e277a533471345b..f81a674c8d40e82256ab05763726abc009297418 100644 (file)
@@ -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;
 }
index aaea297640e09b57e576a22cef8d97258c2bb1b3..9241b6005ad3fc454fccee525f3d7baa056f71de 100644 (file)
@@ -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,
-                               struct i40e_asq_cmd_details *cmd_details);
+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,