Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d70f9a3c authored by Guojia Liao's avatar Guojia Liao Committed by Greg Kroah-Hartman
Browse files

net: hns3: fix aRFS FD rules leftover after add a user FD rule



[ Upstream commit efe3fa45f770f1d66e2734ee7a3523c75694ff04 ]

When user had created a FD rule, all the aRFS rules should be clear up.
HNS3 process flow as below:
1.get spin lock of fd_ruls_list
2.clear up all aRFS rules
3.release lock
4.get spin lock of fd_ruls_list
5.creat a rules
6.release lock;

There is a short period of time between step 3 and step 4, which would
creatting some new aRFS FD rules if driver was receiving packet.
So refactor the fd_rule_lock to fix it.

Fixes: 44122887 ("net: hns3: refine the flow director handle")
Signed-off-by: default avatarGuojia Liao <liaoguojia@huawei.com>
Signed-off-by: default avatarHuazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 475b8d61
Loading
Loading
Loading
Loading
+15 −13
Original line number Diff line number Diff line
@@ -5627,9 +5627,9 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle,
	/* to avoid rule conflict, when user configure rule by ethtool,
	 * we need to clear all arfs rules
	 */
	spin_lock_bh(&hdev->fd_rule_lock);
	hclge_clear_arfs_rules(handle);

	spin_lock_bh(&hdev->fd_rule_lock);
	ret = hclge_fd_config_rule(hdev, rule);

	spin_unlock_bh(&hdev->fd_rule_lock);
@@ -5672,6 +5672,7 @@ static int hclge_del_fd_entry(struct hnae3_handle *handle,
	return ret;
}

/* make sure being called after lock up with fd_rule_lock */
static void hclge_del_all_fd_entries(struct hnae3_handle *handle,
				     bool clear_list)
{
@@ -5684,7 +5685,6 @@ static void hclge_del_all_fd_entries(struct hnae3_handle *handle,
	if (!hnae3_dev_fd_supported(hdev))
		return;

	spin_lock_bh(&hdev->fd_rule_lock);
	for_each_set_bit(location, hdev->fd_bmap,
			 hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1])
		hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true, location,
@@ -5701,8 +5701,6 @@ static void hclge_del_all_fd_entries(struct hnae3_handle *handle,
		bitmap_zero(hdev->fd_bmap,
			    hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1]);
	}

	spin_unlock_bh(&hdev->fd_rule_lock);
}

static int hclge_restore_fd_entries(struct hnae3_handle *handle)
@@ -6069,7 +6067,7 @@ static int hclge_add_fd_entry_by_arfs(struct hnae3_handle *handle, u16 queue_id,
				      u16 flow_id, struct flow_keys *fkeys)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct hclge_fd_rule_tuples new_tuples;
	struct hclge_fd_rule_tuples new_tuples = {};
	struct hclge_dev *hdev = vport->back;
	struct hclge_fd_rule *rule;
	u16 tmp_queue_id;
@@ -6079,20 +6077,18 @@ static int hclge_add_fd_entry_by_arfs(struct hnae3_handle *handle, u16 queue_id,
	if (!hnae3_dev_fd_supported(hdev))
		return -EOPNOTSUPP;

	memset(&new_tuples, 0, sizeof(new_tuples));
	hclge_fd_get_flow_tuples(fkeys, &new_tuples);

	spin_lock_bh(&hdev->fd_rule_lock);

	/* when there is already fd rule existed add by user,
	 * arfs should not work
	 */
	spin_lock_bh(&hdev->fd_rule_lock);
	if (hdev->fd_active_type == HCLGE_FD_EP_ACTIVE) {
		spin_unlock_bh(&hdev->fd_rule_lock);

		return -EOPNOTSUPP;
	}

	hclge_fd_get_flow_tuples(fkeys, &new_tuples);

	/* check is there flow director filter existed for this flow,
	 * if not, create a new filter for it;
	 * if filter exist with different queue id, modify the filter;
@@ -6177,6 +6173,7 @@ static void hclge_rfs_filter_expire(struct hclge_dev *hdev)
#endif
}

/* make sure being called after lock up with fd_rule_lock */
static void hclge_clear_arfs_rules(struct hnae3_handle *handle)
{
#ifdef CONFIG_RFS_ACCEL
@@ -6221,11 +6218,15 @@ static void hclge_enable_fd(struct hnae3_handle *handle, bool enable)

	hdev->fd_en = enable;
	clear = hdev->fd_active_type == HCLGE_FD_ARFS_ACTIVE;
	if (!enable)

	if (!enable) {
		spin_lock_bh(&hdev->fd_rule_lock);
		hclge_del_all_fd_entries(handle, clear);
	else
		spin_unlock_bh(&hdev->fd_rule_lock);
	} else {
		hclge_restore_fd_entries(handle);
	}
}

static void hclge_cfg_mac_mode(struct hclge_dev *hdev, bool enable)
{
@@ -6678,8 +6679,9 @@ static void hclge_ae_stop(struct hnae3_handle *handle)
	int i;

	set_bit(HCLGE_STATE_DOWN, &hdev->state);

	spin_lock_bh(&hdev->fd_rule_lock);
	hclge_clear_arfs_rules(handle);
	spin_unlock_bh(&hdev->fd_rule_lock);

	/* If it is not PF reset, the firmware will disable the MAC,
	 * so it only need to stop phy here.