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: Jian Shen <shenjian15@huawei.com> Signed-off-by: Peng Li <lipeng321@huawei.com> Signed-off-by: Salil Mehta <salil.mehta@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
05c2314fe6
commit
6871af29b3
@ -179,6 +179,7 @@ struct hnae3_ae_dev {
|
||||
struct list_head node;
|
||||
u32 flag;
|
||||
enum hnae3_dev_type dev_type;
|
||||
enum hnae3_reset_type reset_type;
|
||||
void *priv;
|
||||
};
|
||||
|
||||
@ -420,12 +421,15 @@ struct hnae3_ae_ops {
|
||||
struct ethtool_rxnfc *cmd);
|
||||
int (*del_fd_entry)(struct hnae3_handle *handle,
|
||||
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,
|
||||
struct ethtool_rxnfc *cmd);
|
||||
int (*get_fd_rule_info)(struct hnae3_handle *handle,
|
||||
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);
|
||||
};
|
||||
|
||||
struct hnae3_dcb_ops {
|
||||
|
@ -1654,6 +1654,7 @@ 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->dev_type = HNAE3_DEV_KNIC;
|
||||
ae_dev->reset_type = HNAE3_NONE_RESET;
|
||||
hns3_get_dev_capability(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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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))
|
||||
hns3_restore_vlan(netdev);
|
||||
|
||||
hns3_restore_fd_rules(netdev);
|
||||
|
||||
/* Carrier off reporting is important to ethtool even BEFORE open */
|
||||
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)
|
||||
{
|
||||
struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);
|
||||
struct net_device *netdev = handle->kinfo.netdev;
|
||||
struct hns3_nic_priv *priv = netdev_priv(netdev);
|
||||
int ret;
|
||||
@ -3601,6 +3624,13 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -585,6 +585,11 @@ 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));
|
||||
}
|
||||
|
||||
#define hns3_write_dev(a, reg, value) \
|
||||
hns3_write_reg((a)->io_base, (reg), (value))
|
||||
|
||||
|
@ -2513,8 +2513,13 @@ static void hclge_clear_reset_cause(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;
|
||||
|
||||
/* 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 */
|
||||
handle = &hdev->vport[0].nic;
|
||||
rtnl_lock();
|
||||
@ -2535,6 +2540,7 @@ static void hclge_reset(struct hclge_dev *hdev)
|
||||
hclge_notify_client(hdev, HNAE3_UP_CLIENT);
|
||||
handle->last_reset_time = jiffies;
|
||||
rtnl_unlock();
|
||||
ae_dev->reset_type = HNAE3_NONE_RESET;
|
||||
}
|
||||
|
||||
static void hclge_reset_event(struct hnae3_handle *handle)
|
||||
@ -4299,6 +4305,62 @@ static int hclge_del_fd_entry(struct hnae3_handle *handle,
|
||||
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,
|
||||
struct ethtool_rxnfc *cmd)
|
||||
{
|
||||
@ -7270,9 +7332,11 @@ static const struct hnae3_ae_ops hclge_ops = {
|
||||
.get_link_mode = hclge_get_link_mode,
|
||||
.add_fd_entry = hclge_add_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_info = hclge_get_fd_rule_info,
|
||||
.get_fd_all_rules = hclge_get_all_rules,
|
||||
.restore_fd_rules = hclge_restore_fd_entries,
|
||||
};
|
||||
|
||||
static struct hnae3_ae_algo ae_algo = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user