Commit 039ba863 authored by Jian Shen's avatar Jian Shen Committed by David S. Miller
Browse files

net: hns3: optimize the filter table entries handling when resetting



Currently, the PF driver removes all (including its VFs') MAC/VLAN
flow director table entries when resetting, and restores them after
reset completed.

In fact, the hardware will clear all table entries only in IMP
reset and global reset. So driver only needs to restore the table
entries in these cases, and needs do nothing when PF reset, FLR
or other function level reset.

This patch optimizes it by removing unnecessary table entries clear
and restoring handling in the reset flow, and doing the restoring
after reset completed.

Signed-off-by: default avatarJian Shen <shenjian15@huawei.com>
Signed-off-by: default avatarHuazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7d0b3451
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ enum HCLGE_MBX_OPCODE {
	HCLGE_MBX_GET_MEDIA_TYPE,       /* (VF -> PF) get media type */
	HCLGE_MBX_PUSH_PROMISC_INFO,	/* (PF -> VF) push vf promisc info */
	HCLGE_MBX_VF_UNINIT,            /* (VF -> PF) vf is unintializing */
	HCLGE_MBX_HANDLE_VF_TBL,	/* (VF -> PF) store/clear hw table */

	HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf flr status */
	HCLGE_MBX_PUSH_LINK_STATUS,	/* (M7 -> PF) get port link status */
@@ -70,6 +71,10 @@ enum hclge_mbx_vlan_cfg_subcode {
	HCLGE_MBX_GET_PORT_BASE_VLAN_STATE,	/* get port based vlan state */
};

enum hclge_mbx_tbl_cfg_subcode {
	HCLGE_MBX_VPORT_LIST_CLEAR,
};

#define HCLGE_MBX_MAX_MSG_SIZE	14
#define HCLGE_MBX_MAX_RESP_DATA_SIZE	8U
#define HCLGE_MBX_MAX_RING_CHAIN_PARAM_NUM	4
+0 −5
Original line number Diff line number Diff line
@@ -233,7 +233,6 @@ struct hnae3_ae_dev {
	struct list_head node;
	u32 flag;
	unsigned long hw_err_reset_req;
	enum hnae3_reset_type reset_type;
	void *priv;
};

@@ -356,8 +355,6 @@ struct hnae3_ae_dev {
 *   Set vlan filter config of Ports
 * set_vf_vlan_filter()
 *   Set vlan filter config of vf
 * restore_vlan_table()
 *   Restore vlan filter entries after reset
 * enable_hw_strip_rxvtag()
 *   Enable/disable hardware strip vlan tag of packets received
 * set_gro_en
@@ -528,7 +525,6 @@ struct hnae3_ae_ops {
				struct ethtool_rxnfc *cmd);
	int (*get_fd_all_rules)(struct hnae3_handle *handle,
				struct ethtool_rxnfc *cmd, u32 *rule_locs);
	int (*restore_fd_rules)(struct hnae3_handle *handle);
	void (*enable_fd)(struct hnae3_handle *handle, bool enable);
	int (*add_arfs_entry)(struct hnae3_handle *handle, u16 queue_id,
			      u16 flow_id, struct flow_keys *fkeys);
@@ -542,7 +538,6 @@ struct hnae3_ae_ops {
	void (*set_timer_task)(struct hnae3_handle *handle, bool enable);
	int (*mac_connect_phy)(struct hnae3_handle *handle);
	void (*mac_disconnect_phy)(struct hnae3_handle *handle);
	void (*restore_vlan_table)(struct hnae3_handle *handle);
	int (*get_vf_config)(struct hnae3_handle *handle, int vf,
			     struct ifla_vf_info *ivf);
	int (*set_vf_link_state)(struct hnae3_handle *handle, int vf,
+0 −33
Original line number Diff line number Diff line
@@ -2102,7 +2102,6 @@ static int hns3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)

	ae_dev->pdev = pdev;
	ae_dev->flag = ent->driver_data;
	ae_dev->reset_type = HNAE3_NONE_RESET;
	hns3_get_dev_capability(pdev, ae_dev);
	pci_set_drvdata(pdev, ae_dev);

@@ -3936,17 +3935,6 @@ static void hns3_uninit_phy(struct net_device *netdev)
		h->ae_algo->ops->mac_disconnect_phy(h);
}

static int hns3_restore_fd_rules(struct net_device *netdev)
{
	struct hnae3_handle *h = hns3_get_handle(netdev);
	int ret = 0;

	if (h->ae_algo->ops->restore_fd_rules)
		ret = h->ae_algo->ops->restore_fd_rules(h);

	return ret;
}

static void hns3_del_all_fd_rules(struct net_device *netdev, bool clear_list)
{
	struct hnae3_handle *h = hns3_get_handle(netdev);
@@ -4346,7 +4334,6 @@ static void hns3_restore_coal(struct hns3_nic_priv *priv)

static int hns3_reset_notify_down_enet(struct hnae3_handle *handle)
{
	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
	struct net_device *ndev = kinfo->netdev;
	struct hns3_nic_priv *priv = netdev_priv(ndev);
@@ -4354,13 +4341,6 @@ static int hns3_reset_notify_down_enet(struct hnae3_handle *handle)
	if (test_and_set_bit(HNS3_NIC_STATE_RESETTING, &priv->state))
		return 0;

	/* it is cumbersome for hardware to pick-and-choose entries for deletion
	 * from table space. Hence, for function reset software intervention is
	 * required to delete the entries
	 */
	if (hns3_dev_ongoing_func_reset(ae_dev))
		hns3_del_all_fd_rules(ndev, false);

	if (!netif_running(ndev))
		return 0;

@@ -4455,16 +4435,6 @@ err_put_ring:
	return ret;
}

static int hns3_reset_notify_restore_enet(struct hnae3_handle *handle)
{
	struct net_device *netdev = handle->kinfo.netdev;

	if (handle->ae_algo->ops->restore_vlan_table)
		handle->ae_algo->ops->restore_vlan_table(handle);

	return hns3_restore_fd_rules(netdev);
}

static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
{
	struct net_device *netdev = handle->kinfo.netdev;
@@ -4514,9 +4484,6 @@ static int hns3_reset_notify(struct hnae3_handle *handle,
	case HNAE3_UNINIT_CLIENT:
		ret = hns3_reset_notify_uninit_enet(handle);
		break;
	case HNAE3_RESTORE_CLIENT:
		ret = hns3_reset_notify_restore_enet(handle);
		break;
	default:
		break;
	}
+0 −9
Original line number Diff line number Diff line
@@ -576,15 +576,6 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value)
	writel(value, reg_addr + reg);
}

static inline bool hns3_dev_ongoing_func_reset(struct hnae3_ae_dev *ae_dev)
{
	return (ae_dev && (ae_dev->reset_type == HNAE3_FUNC_RESET ||
			   ae_dev->reset_type == HNAE3_FLR_RESET ||
			   ae_dev->reset_type == HNAE3_VF_FUNC_RESET ||
			   ae_dev->reset_type == HNAE3_VF_FULL_RESET ||
			   ae_dev->reset_type == HNAE3_VF_PF_FUNC_RESET));
}

#define hns3_read_dev(a, reg) \
	hns3_read_reg((a)->io_base, (reg))

+45 −44
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ static enum hnae3_reset_type hclge_get_reset_level(struct hnae3_ae_dev *ae_dev,
static int hclge_set_default_loopback(struct hclge_dev *hdev);

static void hclge_sync_mac_table(struct hclge_dev *hdev);
static void hclge_restore_hw_table(struct hclge_dev *hdev);
static void hclge_sync_promisc_mode(struct hclge_dev *hdev);

static struct hnae3_ae_algo ae_algo;
@@ -3731,22 +3732,13 @@ static int hclge_reset_stack(struct hclge_dev *hdev)
	if (ret)
		return ret;

	ret = hclge_notify_client(hdev, HNAE3_INIT_CLIENT);
	if (ret)
		return ret;

	return hclge_notify_client(hdev, HNAE3_RESTORE_CLIENT);
	return hclge_notify_client(hdev, HNAE3_INIT_CLIENT);
}

static int hclge_reset_prepare(struct hclge_dev *hdev)
{
	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
	int ret;

	/* Initialize ae_dev reset status as well, in case enet layer wants to
	 * know if device is undergoing reset
	 */
	ae_dev->reset_type = hdev->reset_type;
	hdev->rst_stats.reset_cnt++;
	/* perform reset of the stack & ae device for a client */
	ret = hclge_notify_roce_client(hdev, HNAE3_DOWN_CLIENT);
@@ -3808,7 +3800,6 @@ static int hclge_reset_rebuild(struct hclge_dev *hdev)
	hdev->last_reset_time = jiffies;
	hdev->rst_stats.reset_fail_cnt = 0;
	hdev->rst_stats.reset_done_cnt++;
	ae_dev->reset_type = HNAE3_NONE_RESET;
	clear_bit(HCLGE_STATE_RST_FAIL, &hdev->state);

	/* if default_reset_request has a higher level reset request,
@@ -6942,8 +6933,14 @@ int hclge_vport_start(struct hclge_vport *vport)
	set_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state);
	vport->last_active_jiffies = jiffies;

	if (test_bit(vport->vport_id, hdev->vport_config_block))
	if (test_bit(vport->vport_id, hdev->vport_config_block)) {
		if (vport->vport_id) {
			hclge_restore_mac_table_common(vport);
			hclge_restore_vport_vlan_table(vport);
		} else {
			hclge_restore_hw_table(hdev);
		}
	}

	clear_bit(vport->vport_id, hdev->vport_config_block);

@@ -8789,39 +8786,34 @@ void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev)
	}
}

static void hclge_restore_vlan_table(struct hnae3_handle *handle)
void hclge_restore_vport_vlan_table(struct hclge_vport *vport)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct hclge_vport_vlan_cfg *vlan, *tmp;
	struct hclge_dev *hdev = vport->back;
	u16 vlan_proto;
	u16 state, vlan_id;
	int i;
	u16 vlan_id;
	u16 state;
	int ret;

	for (i = 0; i < hdev->num_alloc_vport; i++) {
		vport = &hdev->vport[i];
	vlan_proto = vport->port_base_vlan_cfg.vlan_info.vlan_proto;
	vlan_id = vport->port_base_vlan_cfg.vlan_info.vlan_tag;
	state = vport->port_base_vlan_cfg.state;

	if (state != HNAE3_PORT_BASE_VLAN_DISABLE) {
		clear_bit(vport->vport_id, hdev->vlan_table[vlan_id]);
		hclge_set_vlan_filter_hw(hdev, htons(vlan_proto),
					 vport->vport_id, vlan_id,
					 false);
			continue;
		return;
	}

	list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
			int ret;

			if (!vlan->hd_tbl_status)
				continue;
		ret = hclge_set_vlan_filter_hw(hdev, htons(ETH_P_8021Q),
					       vport->vport_id,
					       vlan->vlan_id, false);
		if (ret)
			break;
		}
		vlan->hd_tbl_status = true;
	}
}

@@ -8856,6 +8848,18 @@ void hclge_restore_mac_table_common(struct hclge_vport *vport)
	spin_unlock_bh(&vport->mac_list_lock);
}

static void hclge_restore_hw_table(struct hclge_dev *hdev)
{
	struct hclge_vport *vport = &hdev->vport[0];
	struct hnae3_handle *handle = &vport->nic;

	hclge_restore_mac_table_common(vport);
	hclge_restore_vport_vlan_table(vport);
	set_bit(HCLGE_STATE_PROMISC_CHANGED, &hdev->state);

	hclge_restore_fd_entries(handle);
}

int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
@@ -10352,13 +10356,12 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev)
	 */
	if (hdev->reset_type == HNAE3_IMP_RESET ||
	    hdev->reset_type == HNAE3_GLOBAL_RESET) {
		memset(hdev->vlan_table, 0, sizeof(hdev->vlan_table));
		memset(hdev->vf_vlan_full, 0, sizeof(hdev->vf_vlan_full));
		bitmap_set(hdev->vport_config_block, 0, hdev->num_alloc_vport);
		hclge_reset_umv_space(hdev);
	}

	memset(hdev->vlan_table, 0, sizeof(hdev->vlan_table));
	memset(hdev->vf_vlan_full, 0, sizeof(hdev->vf_vlan_full));

	ret = hclge_cmd_init(hdev);
	if (ret) {
		dev_err(&pdev->dev, "Cmd queue init failed\n");
@@ -11191,7 +11194,6 @@ static const struct hnae3_ae_ops hclge_ops = {
	.get_fd_rule_cnt = hclge_get_fd_rule_cnt,
	.get_fd_rule_info = hclge_get_fd_rule_info,
	.get_fd_all_rules = hclge_get_all_rules,
	.restore_fd_rules = hclge_restore_fd_entries,
	.enable_fd = hclge_enable_fd,
	.add_arfs_entry = hclge_add_fd_entry_by_arfs,
	.dbg_run_cmd = hclge_dbg_run_cmd,
@@ -11204,7 +11206,6 @@ static const struct hnae3_ae_ops hclge_ops = {
	.set_timer_task = hclge_set_timer_task,
	.mac_connect_phy = hclge_mac_connect_phy,
	.mac_disconnect_phy = hclge_mac_disconnect_phy,
	.restore_vlan_table = hclge_restore_vlan_table,
	.get_vf_config = hclge_get_vf_config,
	.set_vf_link_state = hclge_set_vf_link_state,
	.set_vf_spoofchk = hclge_set_vf_spoofchk,
Loading