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

Commit 6871af29 authored by Jian Shen's avatar Jian Shen Committed by David S. Miller
Browse files

net: hns3: Add reset handle for flow director



When doing reset, remove all entries in TCAM block, and keep flow
director rules list. After finishing reset, restore all entries.

Signed-off-by: default avatarJian Shen <shenjian15@huawei.com>
Signed-off-by: default avatarPeng Li <lipeng321@huawei.com>
Signed-off-by: default avatarSalil Mehta <salil.mehta@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 05c2314f
Loading
Loading
Loading
Loading
+4 −0
Original line number Original line Diff line number Diff line
@@ -179,6 +179,7 @@ struct hnae3_ae_dev {
	struct list_head node;
	struct list_head node;
	u32 flag;
	u32 flag;
	enum hnae3_dev_type dev_type;
	enum hnae3_dev_type dev_type;
	enum hnae3_reset_type reset_type;
	void *priv;
	void *priv;
};
};


@@ -420,12 +421,15 @@ struct hnae3_ae_ops {
			    struct ethtool_rxnfc *cmd);
			    struct ethtool_rxnfc *cmd);
	int (*del_fd_entry)(struct hnae3_handle *handle,
	int (*del_fd_entry)(struct hnae3_handle *handle,
			    struct ethtool_rxnfc *cmd);
			    struct ethtool_rxnfc *cmd);
	void (*del_all_fd_entries)(struct hnae3_handle *handle,
				   bool clear_list);
	int (*get_fd_rule_cnt)(struct hnae3_handle *handle,
	int (*get_fd_rule_cnt)(struct hnae3_handle *handle,
			       struct ethtool_rxnfc *cmd);
			       struct ethtool_rxnfc *cmd);
	int (*get_fd_rule_info)(struct hnae3_handle *handle,
	int (*get_fd_rule_info)(struct hnae3_handle *handle,
				struct ethtool_rxnfc *cmd);
				struct ethtool_rxnfc *cmd);
	int (*get_fd_all_rules)(struct hnae3_handle *handle,
	int (*get_fd_all_rules)(struct hnae3_handle *handle,
				struct ethtool_rxnfc *cmd, u32 *rule_locs);
				struct ethtool_rxnfc *cmd, u32 *rule_locs);
	int (*restore_fd_rules)(struct hnae3_handle *handle);
};
};


struct hnae3_dcb_ops {
struct hnae3_dcb_ops {
+30 −0
Original line number Original line Diff line number Diff line
@@ -1654,6 +1654,7 @@ static int hns3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	ae_dev->pdev = pdev;
	ae_dev->pdev = pdev;
	ae_dev->flag = ent->driver_data;
	ae_dev->flag = ent->driver_data;
	ae_dev->dev_type = HNAE3_DEV_KNIC;
	ae_dev->dev_type = HNAE3_DEV_KNIC;
	ae_dev->reset_type = HNAE3_NONE_RESET;
	hns3_get_dev_capability(pdev, ae_dev);
	hns3_get_dev_capability(pdev, ae_dev);
	pci_set_drvdata(pdev, ae_dev);
	pci_set_drvdata(pdev, ae_dev);


@@ -3150,6 +3151,25 @@ static void hns3_uninit_mac_addr(struct net_device *netdev)
		h->ae_algo->ops->rm_uc_addr(h, netdev->dev_addr);
		h->ae_algo->ops->rm_uc_addr(h, netdev->dev_addr);
}
}


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);

	if (h->ae_algo->ops->del_all_fd_entries)
		h->ae_algo->ops->del_all_fd_entries(h, clear_list);
}

static void hns3_nic_set_priv_ops(struct net_device *netdev)
static void hns3_nic_set_priv_ops(struct net_device *netdev)
{
{
	struct hns3_nic_priv *priv = netdev_priv(netdev);
	struct hns3_nic_priv *priv = netdev_priv(netdev);
@@ -3561,6 +3581,8 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle)
	if (!(handle->flags & HNAE3_SUPPORT_VF))
	if (!(handle->flags & HNAE3_SUPPORT_VF))
		hns3_restore_vlan(netdev);
		hns3_restore_vlan(netdev);


	hns3_restore_fd_rules(netdev);

	/* Carrier off reporting is important to ethtool even BEFORE open */
	/* Carrier off reporting is important to ethtool even BEFORE open */
	netif_carrier_off(netdev);
	netif_carrier_off(netdev);


@@ -3581,6 +3603,7 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle)


static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
{
{
	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
	struct net_device *netdev = handle->kinfo.netdev;
	struct net_device *netdev = handle->kinfo.netdev;
	struct hns3_nic_priv *priv = netdev_priv(netdev);
	struct hns3_nic_priv *priv = netdev_priv(netdev);
	int ret;
	int ret;
@@ -3601,6 +3624,13 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)


	hns3_uninit_mac_addr(netdev);
	hns3_uninit_mac_addr(netdev);


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

	return ret;
	return ret;
}
}


+5 −0
Original line number Original line Diff line number Diff line
@@ -585,6 +585,11 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value)
	writel(value, reg_addr + reg);
	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));
}

#define hns3_write_dev(a, reg, value) \
#define hns3_write_dev(a, reg, value) \
	hns3_write_reg((a)->io_base, (reg), (value))
	hns3_write_reg((a)->io_base, (reg), (value))


+64 −0
Original line number Original line Diff line number Diff line
@@ -2513,8 +2513,13 @@ static void hclge_clear_reset_cause(struct hclge_dev *hdev)


static void hclge_reset(struct hclge_dev *hdev)
static void hclge_reset(struct hclge_dev *hdev)
{
{
	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
	struct hnae3_handle *handle;
	struct hnae3_handle *handle;


	/* 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;
	/* perform reset of the stack & ae device for a client */
	/* perform reset of the stack & ae device for a client */
	handle = &hdev->vport[0].nic;
	handle = &hdev->vport[0].nic;
	rtnl_lock();
	rtnl_lock();
@@ -2535,6 +2540,7 @@ static void hclge_reset(struct hclge_dev *hdev)
	hclge_notify_client(hdev, HNAE3_UP_CLIENT);
	hclge_notify_client(hdev, HNAE3_UP_CLIENT);
	handle->last_reset_time = jiffies;
	handle->last_reset_time = jiffies;
	rtnl_unlock();
	rtnl_unlock();
	ae_dev->reset_type = HNAE3_NONE_RESET;
}
}


static void hclge_reset_event(struct hnae3_handle *handle)
static void hclge_reset_event(struct hnae3_handle *handle)
@@ -4299,6 +4305,62 @@ static int hclge_del_fd_entry(struct hnae3_handle *handle,
					 false);
					 false);
}
}


static void hclge_del_all_fd_entries(struct hnae3_handle *handle,
				     bool clear_list)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct hclge_dev *hdev = vport->back;
	struct hclge_fd_rule *rule;
	struct hlist_node *node;

	if (!hnae3_dev_fd_supported(hdev))
		return;

	if (clear_list) {
		hlist_for_each_entry_safe(rule, node, &hdev->fd_rule_list,
					  rule_node) {
			hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true,
					     rule->location, NULL, false);
			hlist_del(&rule->rule_node);
			kfree(rule);
			hdev->hclge_fd_rule_num--;
		}
	} else {
		hlist_for_each_entry_safe(rule, node, &hdev->fd_rule_list,
					  rule_node)
			hclge_fd_tcam_config(hdev, HCLGE_FD_STAGE_1, true,
					     rule->location, NULL, false);
	}
}

static int hclge_restore_fd_entries(struct hnae3_handle *handle)
{
	struct hclge_vport *vport = hclge_get_vport(handle);
	struct hclge_dev *hdev = vport->back;
	struct hclge_fd_rule *rule;
	struct hlist_node *node;
	int ret;

	if (!hnae3_dev_fd_supported(hdev))
		return -EOPNOTSUPP;

	hlist_for_each_entry_safe(rule, node, &hdev->fd_rule_list, rule_node) {
		ret = hclge_config_action(hdev, HCLGE_FD_STAGE_1, rule);
		if (!ret)
			ret = hclge_config_key(hdev, HCLGE_FD_STAGE_1, rule);

		if (ret) {
			dev_warn(&hdev->pdev->dev,
				 "Restore rule %d failed, remove it\n",
				 rule->location);
			hlist_del(&rule->rule_node);
			kfree(rule);
			hdev->hclge_fd_rule_num--;
		}
	}
	return 0;
}

static int hclge_get_fd_rule_cnt(struct hnae3_handle *handle,
static int hclge_get_fd_rule_cnt(struct hnae3_handle *handle,
				 struct ethtool_rxnfc *cmd)
				 struct ethtool_rxnfc *cmd)
{
{
@@ -7270,9 +7332,11 @@ static const struct hnae3_ae_ops hclge_ops = {
	.get_link_mode = hclge_get_link_mode,
	.get_link_mode = hclge_get_link_mode,
	.add_fd_entry = hclge_add_fd_entry,
	.add_fd_entry = hclge_add_fd_entry,
	.del_fd_entry = hclge_del_fd_entry,
	.del_fd_entry = hclge_del_fd_entry,
	.del_all_fd_entries = hclge_del_all_fd_entries,
	.get_fd_rule_cnt = hclge_get_fd_rule_cnt,
	.get_fd_rule_cnt = hclge_get_fd_rule_cnt,
	.get_fd_rule_info = hclge_get_fd_rule_info,
	.get_fd_rule_info = hclge_get_fd_rule_info,
	.get_fd_all_rules = hclge_get_all_rules,
	.get_fd_all_rules = hclge_get_all_rules,
	.restore_fd_rules = hclge_restore_fd_entries,
};
};


static struct hnae3_ae_algo ae_algo = {
static struct hnae3_ae_algo ae_algo = {