Commit 83af0039 authored by Henry Tieman's avatar Henry Tieman Committed by Jeff Kirsher
Browse files

ice: Restore filters following reset



Following a reset, Flow Director filters are cleared from the hardware.
Rebuild the filters using the software structures containing the filter
rules.

Signed-off-by: default avatarHenry Tieman <henry.w.tieman@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 2c57ffcb
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -566,6 +566,8 @@ int
ice_get_fdir_fltr_ids(struct ice_hw *hw, struct ethtool_rxnfc *cmd,
		      u32 *rule_locs);
void ice_fdir_release_flows(struct ice_hw *hw);
void ice_fdir_replay_flows(struct ice_hw *hw);
void ice_fdir_replay_fltrs(struct ice_pf *pf);
int ice_fdir_create_dflt_rules(struct ice_pf *pf);
int ice_open(struct net_device *netdev);
int ice_stop(struct net_device *netdev);
+65 −0
Original line number Diff line number Diff line
@@ -348,6 +348,53 @@ void ice_fdir_release_flows(struct ice_hw *hw)
		ice_fdir_erase_flow_from_hw(hw, ICE_BLK_FD, flow);
}

/**
 * ice_fdir_replay_flows - replay HW Flow Director filter info
 * @hw: pointer to HW instance
 */
void ice_fdir_replay_flows(struct ice_hw *hw)
{
	int flow;

	for (flow = 0; flow < ICE_FLTR_PTYPE_MAX; flow++) {
		int tun;

		if (!hw->fdir_prof[flow] || !hw->fdir_prof[flow]->cnt)
			continue;
		for (tun = 0; tun < ICE_FD_HW_SEG_MAX; tun++) {
			struct ice_flow_prof *hw_prof;
			struct ice_fd_hw_prof *prof;
			u64 prof_id;
			int j;

			prof = hw->fdir_prof[flow];
			prof_id = flow + tun * ICE_FLTR_PTYPE_MAX;
			ice_flow_add_prof(hw, ICE_BLK_FD, ICE_FLOW_RX, prof_id,
					  prof->fdir_seg[tun], TNL_SEG_CNT(tun),
					  &hw_prof);
			for (j = 0; j < prof->cnt; j++) {
				enum ice_flow_priority prio;
				u64 entry_h = 0;
				int err;

				prio = ICE_FLOW_PRIO_NORMAL;
				err = ice_flow_add_entry(hw, ICE_BLK_FD,
							 prof_id,
							 prof->vsi_h[0],
							 prof->vsi_h[j],
							 prio, prof->fdir_seg,
							 &entry_h);
				if (err) {
					dev_err(ice_hw_to_dev(hw), "Could not replay Flow Director, flow type %d\n",
						flow);
					continue;
				}
				prof->entry_h[j][tun] = entry_h;
			}
		}
	}
}

/**
 * ice_parse_rx_flow_user_data - deconstruct user-defined data
 * @fsp: pointer to ethtool Rx flow specification
@@ -1225,6 +1272,24 @@ ice_fdir_write_all_fltr(struct ice_pf *pf, struct ice_fdir_fltr *input,
	return 0;
}

/**
 * ice_fdir_replay_fltrs - replay filters from the HW filter list
 * @pf: board private structure
 */
void ice_fdir_replay_fltrs(struct ice_pf *pf)
{
	struct ice_fdir_fltr *f_rule;
	struct ice_hw *hw = &pf->hw;

	list_for_each_entry(f_rule, &hw->fdir_list_head, fltr_node) {
		int err = ice_fdir_write_all_fltr(pf, f_rule, true);

		if (err)
			dev_dbg(ice_pf_to_dev(pf), "Flow Director error %d, could not reprogram filter %d\n",
				err, f_rule->fltr_id);
	}
}

/**
 * ice_fdir_create_dflt_rules - create default perfect filters
 * @pf: PF data structure
+11 −6
Original line number Diff line number Diff line
@@ -2748,6 +2748,8 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
		goto err_vsi;

	ice_vsi_get_qs(vsi);

	ice_alloc_fd_res(vsi);
	ice_vsi_set_tc_cfg(vsi);

	/* Initialize VSI struct elements and create VSI in FW */
@@ -2756,6 +2758,7 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
		goto err_vsi;

	switch (vsi->type) {
	case ICE_VSI_CTRL:
	case ICE_VSI_PF:
		ret = ice_vsi_alloc_q_vectors(vsi);
		if (ret)
@@ -2780,9 +2783,11 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
			if (ret)
				goto err_vectors;
		}
		/* Do not exit if configuring RSS had an issue, at least
		 * receive traffic on first queue. Hence no need to capture
		 * return value
		/* ICE_VSI_CTRL does not need RSS so skip RSS processing */
		if (vsi->type != ICE_VSI_CTRL)
			/* Do not exit if configuring RSS had an issue, at
			 * least receive traffic on first queue. Hence no
			 * need to capture return value
			 */
			if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
				ice_vsi_cfg_rss_lut_key(vsi);
+31 −0
Original line number Diff line number Diff line
@@ -4895,6 +4895,21 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
		goto err_sched_init_port;
	}

	if (test_bit(ICE_FLAG_FD_ENA, pf->flags)) {
		wr32(hw, PFQF_FD_ENA, PFQF_FD_ENA_FD_ENA_M);
		if (!rd32(hw, PFQF_FD_SIZE)) {
			u16 unused, guar, b_effort;

			guar = hw->func_caps.fd_fltr_guar;
			b_effort = hw->func_caps.fd_fltr_best_effort;

			/* force guaranteed filter pool for PF */
			ice_alloc_fd_guar_item(hw, &unused, guar);
			/* force shared filter pool for PF */
			ice_alloc_fd_shrd_item(hw, &unused, b_effort);
		}
	}

	if (test_bit(ICE_FLAG_DCB_ENA, pf->flags))
		ice_dcb_rebuild(pf);

@@ -4913,6 +4928,22 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
		}
	}

	/* If Flow Director is active */
	if (test_bit(ICE_FLAG_FD_ENA, pf->flags)) {
		err = ice_vsi_rebuild_by_type(pf, ICE_VSI_CTRL);
		if (err) {
			dev_err(dev, "control VSI rebuild failed: %d\n", err);
			goto err_vsi_rebuild;
		}

		/* replay HW Flow Director recipes */
		if (hw->fdir_prof)
			ice_fdir_replay_flows(hw);

		/* replay Flow Director filters */
		ice_fdir_replay_fltrs(pf);
	}

	ice_update_pf_netdev_link(pf);

	/* tell the firmware we are up */