return retval;
 }
 
+/**
+ * i40e_aqc_del_filters - Request firmware to delete a set of filters
+ * @vsi: ptr to the VSI
+ * @vsi_name: name to display in messages
+ * @list: the list of filters to send to firmware
+ * @num_del: the number of filters to delete
+ * @retval: Set to -EIO on failure to delete
+ *
+ * Send a request to firmware via AdminQ to delete a set of filters. Uses
+ * *retval instead of a return value so that success does not force ret_val to
+ * be set to 0. This ensures that a sequence of calls to this function
+ * preserve the previous value of *retval on successful delete.
+ */
+static
+void i40e_aqc_del_filters(struct i40e_vsi *vsi, const char *vsi_name,
+                         struct i40e_aqc_remove_macvlan_element_data *list,
+                         int num_del, int *retval)
+{
+       struct i40e_hw *hw = &vsi->back->hw;
+       i40e_status aq_ret;
+       int aq_err;
+
+       aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid, list, num_del, NULL);
+       aq_err = hw->aq.asq_last_status;
+
+       /* Explicitly ignore and do not report when firmware returns ENOENT */
+       if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) {
+               *retval = -EIO;
+               dev_info(&vsi->back->pdev->dev,
+                        "ignoring delete macvlan error on %s, err %s, aq_err %s\n",
+                        vsi_name, i40e_stat_str(hw, aq_ret),
+                        i40e_aq_str(hw, aq_err));
+       }
+}
+
+/**
+ * i40e_aqc_add_filters - Request firmware to add a set of filters
+ * @vsi: ptr to the VSI
+ * @vsi_name: name to display in messages
+ * @list: the list of filters to send to firmware
+ * @add_head: Position in the add hlist
+ * @num_add: the number of filters to add
+ * @promisc_change: set to true on exit if promiscuous mode was forced on
+ *
+ * Send a request to firmware via AdminQ to add a chunk of filters. Will set
+ * promisc_changed to true if the firmware has run out of space for more
+ * filters.
+ */
+static
+void i40e_aqc_add_filters(struct i40e_vsi *vsi, const char *vsi_name,
+                         struct i40e_aqc_add_macvlan_element_data *list,
+                         struct i40e_mac_filter *add_head,
+                         int num_add, bool *promisc_changed)
+{
+       struct i40e_hw *hw = &vsi->back->hw;
+       i40e_status aq_ret;
+       int aq_err, fcnt;
+
+       aq_ret = i40e_aq_add_macvlan(hw, vsi->seid, list, num_add, NULL);
+       aq_err = hw->aq.asq_last_status;
+       fcnt = i40e_update_filter_state(num_add, list, add_head, aq_ret);
+       vsi->active_filters += fcnt;
+
+       if (fcnt != num_add) {
+               *promisc_changed = true;
+               set_bit(__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state);
+               vsi->promisc_threshold = (vsi->active_filters * 3) / 4;
+               dev_warn(&vsi->back->pdev->dev,
+                        "Error %s adding RX filters on %s, promiscuous mode forced on\n",
+                        i40e_aq_str(hw, aq_err),
+                        vsi_name);
+       }
+}
+
 /**
  * i40e_sync_vsi_filters - Update the VSI filter list to the HW
  * @vsi: ptr to the VSI
        int num_add = 0;
        int num_del = 0;
        int retval = 0;
-       int aq_err = 0;
        u16 cmd_flags;
        int list_size;
-       int fcnt;
        int bkt;
 
        /* empty array typed pointers, kcalloc later */
 
                        /* flush a full buffer */
                        if (num_del == filter_list_len) {
-                               aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid,
-                                                               del_list,
-                                                               num_del, NULL);
-                               aq_err = hw->aq.asq_last_status;
-                               num_del = 0;
+                               i40e_aqc_del_filters(vsi, vsi_name, del_list,
+                                                    num_del, &retval);
                                memset(del_list, 0, list_size);
-
-                               /* Explicitly ignore and do not report when
-                                * firmware returns ENOENT.
-                                */
-                               if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) {
-                                       retval = -EIO;
-                                       dev_info(&pf->pdev->dev,
-                                                "ignoring delete macvlan error on %s, err %s, aq_err %s\n",
-                                                vsi_name,
-                                                i40e_stat_str(hw, aq_ret),
-                                                i40e_aq_str(hw, aq_err));
-                               }
+                               num_del = 0;
                        }
                        /* Release memory for MAC filter entries which were
                         * synced up with HW.
                }
 
                if (num_del) {
-                       aq_ret = i40e_aq_remove_macvlan(hw, vsi->seid, del_list,
-                                                       num_del, NULL);
-                       aq_err = hw->aq.asq_last_status;
-                       num_del = 0;
-
-                       /* Explicitly ignore and do not report when firmware
-                        * returns ENOENT.
-                        */
-                       if (aq_ret && !(aq_err == I40E_AQ_RC_ENOENT)) {
-                               retval = -EIO;
-                               dev_info(&pf->pdev->dev,
-                                        "ignoring delete macvlan error on %s, err %s aq_err %s\n",
-                                        vsi_name,
-                                        i40e_stat_str(hw, aq_ret),
-                                        i40e_aq_str(hw, aq_err));
-                       }
+                       i40e_aqc_del_filters(vsi, vsi_name, del_list,
+                                            num_del, &retval);
                }
 
                kfree(del_list);
 
                        /* flush a full buffer */
                        if (num_add == filter_list_len) {
-                               aq_ret = i40e_aq_add_macvlan(hw, vsi->seid,
-                                                            add_list, num_add,
-                                                            NULL);
-                               aq_err = hw->aq.asq_last_status;
-                               fcnt = i40e_update_filter_state(num_add,
-                                                               add_list,
-                                                               add_head,
-                                                               aq_ret);
-                               vsi->active_filters += fcnt;
-
-                               if (fcnt != num_add) {
-                                       promisc_changed = true;
-                                       set_bit(__I40E_FILTER_OVERFLOW_PROMISC,
-                                               &vsi->state);
-                                       vsi->promisc_threshold =
-                                               (vsi->active_filters * 3) / 4;
-                                       dev_warn(&pf->pdev->dev,
-                                                "Error %s adding RX filters on %s, promiscuous mode forced on\n",
-                                                i40e_aq_str(hw, aq_err),
-                                                vsi_name);
-                               }
+                               i40e_aqc_add_filters(vsi, vsi_name, add_list,
+                                                    add_head, num_add,
+                                                    &promisc_changed);
                                memset(add_list, 0, list_size);
                                num_add = 0;
                        }
                }
                if (num_add) {
-                       aq_ret = i40e_aq_add_macvlan(hw, vsi->seid,
-                                                    add_list, num_add, NULL);
-                       aq_err = hw->aq.asq_last_status;
-                       fcnt = i40e_update_filter_state(num_add, add_list,
-                                                       add_head, aq_ret);
-                       vsi->active_filters += fcnt;
-                       if (fcnt != num_add) {
-                               promisc_changed = true;
-                               set_bit(__I40E_FILTER_OVERFLOW_PROMISC,
-                                       &vsi->state);
-                               vsi->promisc_threshold =
-                                               (vsi->active_filters * 3) / 4;
-                               dev_warn(&pf->pdev->dev,
-                                        "Error %s adding RX filters on %s, promiscuous mode forced on\n",
-                                        i40e_aq_str(hw, aq_err), vsi_name);
-                       }
+                       i40e_aqc_add_filters(vsi, vsi_name, add_list, add_head,
+                                            num_add, &promisc_changed);
                }
                /* Now move all of the filters from the temp add list back to
                 * the VSI's list.