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

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
...@@ -179,6 +179,7 @@ struct hnae3_ae_dev { ...@@ -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 { ...@@ -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 {
......
...@@ -1654,6 +1654,7 @@ static int hns3_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
} }
......
...@@ -585,6 +585,11 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value) ...@@ -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))
......
...@@ -2513,8 +2513,13 @@ static void hclge_clear_reset_cause(struct hclge_dev *hdev) ...@@ -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) ...@@ -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, ...@@ -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 = { ...@@ -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 = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment