From: Junxian Huang huangjunxian6@hisilicon.com
driver inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IAH10J
----------------------------------------------------------------------
Currently the notifier block of bonding events is in the hr_dev structure. bond_grp is dynamic allocated in the event handler. Since all these hr_dev would response bonding events, we had to add complicated filter to choose a suitable hr_dev to handle the events. Besides we also had to concern about the validity of bond_grp pointers in many concurrency cases as they may have been freed.
Refactor the bonding event handler by: 1. allocating/deallocating bond_grp structures when driver inits/exits; 2. registering notifier block of bonding events in bond_grp
Signed-off-by: Junxian Huang huangjunxian6@hisilicon.com Signed-off-by: Xinghai Cen cenxinghai@h-partners.com --- drivers/infiniband/hw/hns/hns_roce_bond.c | 415 +++++++++++--------- drivers/infiniband/hw/hns/hns_roce_bond.h | 3 + drivers/infiniband/hw/hns/hns_roce_device.h | 1 - drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 9 +- drivers/infiniband/hw/hns/hns_roce_main.c | 2 +- 5 files changed, 247 insertions(+), 183 deletions(-)
diff --git a/drivers/infiniband/hw/hns/hns_roce_bond.c b/drivers/infiniband/hw/hns/hns_roce_bond.c index 4b2b5538c918..c5b30d7dab67 100644 --- a/drivers/infiniband/hw/hns/hns_roce_bond.c +++ b/drivers/infiniband/hw/hns/hns_roce_bond.c @@ -52,32 +52,6 @@ static int get_netdev_bond_slave_id(struct net_device *net_dev, return -ENOENT; }
-static bool is_hrdev_bond_slave(struct hns_roce_dev *hr_dev, - struct net_device *upper_dev) -{ - struct hns_roce_bond_group *bond_grp; - struct net_device *net_dev; - u8 bus_num; - - if (!hr_dev || !upper_dev) - return false; - - if (!netif_is_lag_master(upper_dev)) - return false; - - net_dev = get_hr_netdev(hr_dev, 0); - bus_num = get_hr_bus_num(hr_dev); - - if (upper_dev == get_upper_dev_from_ndev(net_dev)) - return true; - - bond_grp = hns_roce_get_bond_grp(net_dev, bus_num); - if (bond_grp && upper_dev == bond_grp->upper_dev) - return true; - - return false; -} - struct hns_roce_bond_group *hns_roce_get_bond_grp(struct net_device *net_dev, u8 bus_num) { @@ -92,8 +66,10 @@ struct hns_roce_bond_group *hns_roce_get_bond_grp(struct net_device *net_dev, bond_grp = die_info->bgrps[i]; if (!bond_grp) continue; - if (get_netdev_bond_slave_id(net_dev, bond_grp) >= 0 || - (bond_grp->upper_dev == get_upper_dev_from_ndev(net_dev))) + if (get_netdev_bond_slave_id(net_dev, bond_grp) >= 0) + return bond_grp; + if (bond_grp->upper_dev && + bond_grp->upper_dev == get_upper_dev_from_ndev(net_dev)) return bond_grp; }
@@ -107,8 +83,8 @@ bool hns_roce_bond_is_active(struct hns_roce_dev *hr_dev) u8 bus_num = get_hr_bus_num(hr_dev);
bond_grp = hns_roce_get_bond_grp(net_dev, bus_num); - - if (bond_grp && bond_grp->bond_state != HNS_ROCE_BOND_NOT_BONDED) + if (bond_grp && bond_grp->bond_state != HNS_ROCE_BOND_NOT_BONDED && + bond_grp->bond_state != HNS_ROCE_BOND_NOT_ATTACHED) return true;
return false; @@ -507,39 +483,6 @@ static void hns_roce_do_bond_work(struct work_struct *work) hns_roce_queue_bond_work(bond_grp, HZ); }
-int hns_roce_bond_init(struct hns_roce_dev *hr_dev) -{ - struct net_device *net_dev = get_hr_netdev(hr_dev, 0); - struct hns_roce_v2_priv *priv = hr_dev->priv; - struct hns_roce_bond_group *bond_grp; - u8 bus_num = get_hr_bus_num(hr_dev); - int ret; - - bond_grp = hns_roce_get_bond_grp(net_dev, bus_num); - if (priv->handle->rinfo.reset_state == HNS_ROCE_STATE_RST_INIT && - bond_grp) { - bond_grp->main_hr_dev = hr_dev; - ret = hns_roce_recover_bond(bond_grp); - if (ret) { - ibdev_err(&hr_dev->ib_dev, - "failed to recover RoCE bond, ret = %d.\n", - ret); - return ret; - } - } - - hr_dev->bond_nb.notifier_call = hns_roce_bond_event; - ret = register_netdevice_notifier(&hr_dev->bond_nb); - if (ret) { - ibdev_err(&hr_dev->ib_dev, - "failed to register notifier for RoCE bond, ret = %d.\n", - ret); - hr_dev->bond_nb.notifier_call = NULL; - } - - return ret; -} - static struct hns_roce_die_info *alloc_die_info(int bus_num) { struct hns_roce_die_info *die_info; @@ -611,67 +554,116 @@ static int remove_bond_id(int bus_num, u8 bond_id) return 0; }
-int hns_roce_cleanup_bond(struct hns_roce_bond_group *bond_grp) +static int hns_roce_alloc_bond_grp(struct hns_roce_dev *hr_dev) { - bool completion_no_waiter; + struct hns_roce_bond_group *bgrps[ROCE_BOND_NUM_MAX]; + struct hns_roce_bond_group *bond_grp; int ret; + int i;
- ret = bond_grp->main_hr_dev ? - hns_roce_cmd_bond(bond_grp, HNS_ROCE_CLEAR_BOND) : -EIO; - if (ret) - BOND_ERR_LOG("failed to clear RoCE bond, ret = %d.\n", ret); - - cancel_delayed_work(&bond_grp->bond_work); - ret = remove_bond_id(bond_grp->bus_num, bond_grp->bond_id); - if (ret) - BOND_ERR_LOG("failed to remove bond id %u, ret = %d.\n", - bond_grp->bond_id, ret); + for (i = 0; i < ROCE_BOND_NUM_MAX; i++) { + bond_grp = kvzalloc(sizeof(*bond_grp), GFP_KERNEL); + if (!bond_grp) { + ret = -ENOMEM; + goto mem_err; + }
- completion_no_waiter = completion_done(&bond_grp->bond_work_done); - complete(&bond_grp->bond_work_done); - mutex_destroy(&bond_grp->bond_mutex); - if (completion_no_waiter) - kfree(bond_grp); + mutex_init(&bond_grp->bond_mutex); + INIT_DELAYED_WORK(&bond_grp->bond_work, hns_roce_do_bond_work); + init_completion(&bond_grp->bond_work_done);
- return ret; -} + bond_grp->bond_ready = false; + bond_grp->bond_state = HNS_ROCE_BOND_NOT_ATTACHED; + bond_grp->bus_num = get_hr_bus_num(hr_dev);
-static bool hns_roce_bond_lowerstate_event(struct hns_roce_dev *hr_dev, - struct hns_roce_bond_group *bond_grp, - struct netdev_notifier_changelowerstate_info *info) -{ - struct net_device *net_dev = - netdev_notifier_info_to_dev((struct netdev_notifier_info *)info); + ret = alloc_bond_id(bond_grp); + if (ret) { + ibdev_err(&hr_dev->ib_dev, + "failed to alloc bond ID, ret = %d.\n", ret); + goto alloc_id_err; + }
- if (!netif_is_lag_port(net_dev) || - (!bond_grp || hr_dev != bond_grp->main_hr_dev)) - return false; + bond_grp->bond_nb.notifier_call = hns_roce_bond_event; + ret = register_netdevice_notifier(&bond_grp->bond_nb); + if (ret) { + ibdev_err(&hr_dev->ib_dev, + "failed to register bond nb, ret = %d.\n", ret); + goto register_nb_err; + } + bgrps[i] = bond_grp; + }
- mutex_lock(&bond_grp->bond_mutex); + return 0;
- if (bond_grp->bond_ready && - bond_grp->bond_state == HNS_ROCE_BOND_IS_BONDED) - bond_grp->bond_state = HNS_ROCE_BOND_SLAVE_CHANGESTATE; +register_nb_err: + remove_bond_id(bond_grp->bus_num, bond_grp->bond_id); +alloc_id_err: + mutex_destroy(&bond_grp->bond_mutex); + kvfree(bond_grp); +mem_err: + for (i--; i >= 0; i--) { + unregister_netdevice_notifier(&bgrps[i]->bond_nb); + cancel_delayed_work_sync(&bgrps[i]->bond_work); + complete(&bgrps[i]->bond_work_done); + remove_bond_id(bgrps[i]->bus_num, bgrps[i]->bond_id); + mutex_destroy(&bgrps[i]->bond_mutex); + kvfree(bgrps[i]); + } + return ret; +}
- mutex_unlock(&bond_grp->bond_mutex); +void hns_roce_dealloc_bond_grp(void) +{ + struct hns_roce_bond_group *bond_grp; + struct hns_roce_die_info *die_info; + unsigned long id; + int i;
- return true; + xa_for_each(&roce_bond_xa, id, die_info) { + for (i = 0; i < ROCE_BOND_NUM_MAX; i++) { + bond_grp = die_info->bgrps[i]; + if (!bond_grp) + continue; + unregister_netdevice_notifier(&bond_grp->bond_nb); + cancel_delayed_work_sync(&bond_grp->bond_work); + remove_bond_id(bond_grp->bus_num, bond_grp->bond_id); + mutex_destroy(&bond_grp->bond_mutex); + kvfree(bond_grp); + } + } }
-static bool is_bond_setting_supported(struct netdev_lag_upper_info *bond_info) +int hns_roce_bond_init(struct hns_roce_dev *hr_dev) { - if (!bond_info) - return false; + struct net_device *net_dev = get_hr_netdev(hr_dev, 0); + struct hns_roce_v2_priv *priv = hr_dev->priv; + struct hns_roce_bond_group *bond_grp; + u8 bus_num = get_hr_bus_num(hr_dev); + int ret = 0;
- if (bond_info->tx_type != NETDEV_LAG_TX_TYPE_ACTIVEBACKUP && - bond_info->tx_type != NETDEV_LAG_TX_TYPE_HASH) - return false; + if (priv->handle->rinfo.reset_state == HNS_ROCE_STATE_RST_INIT) { + bond_grp = hns_roce_get_bond_grp(net_dev, bus_num); + if (!bond_grp) + return 0;
- if (bond_info->tx_type == NETDEV_LAG_TX_TYPE_HASH && - bond_info->hash_type > NETDEV_LAG_HASH_L23) - return false; + bond_grp->main_hr_dev = hr_dev; + ret = hns_roce_recover_bond(bond_grp); + if (ret) + ibdev_err(&hr_dev->ib_dev, + "failed to recover RoCE bond, ret = %d.\n", + ret); + return ret; + }
- return true; + if (!xa_load(&roce_bond_xa, bus_num)) { + ret = hns_roce_alloc_bond_grp(hr_dev); + if (ret) + ibdev_err(&hr_dev->ib_dev, + "failed to alloc RoCE bond, ret = %d.\n", + ret); + } + + return ret; }
static void hns_roce_bond_info_update(struct hns_roce_bond_group *bond_grp, @@ -716,6 +708,80 @@ static void hns_roce_bond_info_update(struct hns_roce_bond_group *bond_grp, rcu_read_unlock(); }
+static void hns_roce_attach_bond_grp(struct hns_roce_bond_group *bond_grp, + struct hns_roce_dev *hr_dev, + struct net_device *upper_dev) +{ + bond_grp->upper_dev = upper_dev; + bond_grp->main_hr_dev = hr_dev; + bond_grp->bond_state = HNS_ROCE_BOND_NOT_BONDED; + bond_grp->bond_ready = false; + hns_roce_bond_info_update(bond_grp, upper_dev, true); +} + +static void hns_roce_detach_bond_grp(struct hns_roce_bond_group *bond_grp) +{ + cancel_delayed_work(&bond_grp->bond_work); + bond_grp->upper_dev = NULL; + bond_grp->main_hr_dev = NULL; + bond_grp->bond_ready = false; + bond_grp->bond_state = HNS_ROCE_BOND_NOT_ATTACHED; + bond_grp->slave_map = 0; + bond_grp->slave_map_diff = 0; + memset(bond_grp->bond_func_info, 0, sizeof(bond_grp->bond_func_info)); +} + +int hns_roce_cleanup_bond(struct hns_roce_bond_group *bond_grp) +{ + int ret; + + ret = bond_grp->main_hr_dev ? + hns_roce_cmd_bond(bond_grp, HNS_ROCE_CLEAR_BOND) : -EIO; + if (ret) + BOND_ERR_LOG("failed to clear RoCE bond, ret = %d.\n", ret); + + hns_roce_detach_bond_grp(bond_grp); + complete(&bond_grp->bond_work_done); + + return ret; +} + +static bool hns_roce_bond_lowerstate_event(struct hns_roce_bond_group *bond_grp, + struct netdev_notifier_changelowerstate_info *info) +{ + struct net_device *net_dev = + netdev_notifier_info_to_dev((struct netdev_notifier_info *)info); + + if (!netif_is_lag_port(net_dev)) + return false; + + mutex_lock(&bond_grp->bond_mutex); + + if (bond_grp->bond_ready && + bond_grp->bond_state == HNS_ROCE_BOND_IS_BONDED) + bond_grp->bond_state = HNS_ROCE_BOND_SLAVE_CHANGESTATE; + + mutex_unlock(&bond_grp->bond_mutex); + + return true; +} + +static bool is_bond_setting_supported(struct netdev_lag_upper_info *bond_info) +{ + if (!bond_info) + return false; + + if (bond_info->tx_type != NETDEV_LAG_TX_TYPE_ACTIVEBACKUP && + bond_info->tx_type != NETDEV_LAG_TX_TYPE_HASH) + return false; + + if (bond_info->tx_type == NETDEV_LAG_TX_TYPE_HASH && + bond_info->hash_type > NETDEV_LAG_HASH_L23) + return false; + + return true; +} + static bool hns_roce_bond_upper_event(struct hns_roce_bond_group *bond_grp, struct netdev_notifier_changeupper_info *info) { @@ -755,44 +821,8 @@ static bool hns_roce_bond_upper_event(struct hns_roce_bond_group *bond_grp, return changed; }
-static struct hns_roce_bond_group *hns_roce_alloc_bond_grp(struct hns_roce_dev *main_hr_dev, - struct net_device *upper_dev) -{ - struct hns_roce_bond_group *bond_grp; - int ret; - - bond_grp = kzalloc(sizeof(*bond_grp), GFP_KERNEL); - if (!bond_grp) - return NULL; - - mutex_init(&bond_grp->bond_mutex); - - INIT_DELAYED_WORK(&bond_grp->bond_work, hns_roce_do_bond_work); - - init_completion(&bond_grp->bond_work_done); - - bond_grp->upper_dev = upper_dev; - bond_grp->main_hr_dev = main_hr_dev; - bond_grp->bond_ready = false; - bond_grp->bond_state = HNS_ROCE_BOND_NOT_BONDED; - bond_grp->bus_num = main_hr_dev->pci_dev->bus->number; - - ret = alloc_bond_id(bond_grp); - if (ret) { - ibdev_err(&main_hr_dev->ib_dev, - "failed to alloc bond ID, ret = %d.\n", ret); - mutex_destroy(&bond_grp->bond_mutex); - kfree(bond_grp); - return NULL; - } - - hns_roce_bond_info_update(bond_grp, upper_dev, true); - - return bond_grp; -} - static bool is_dev_bond_supported(struct hns_roce_bond_group *bond_grp, - struct net_device *net_dev, int bus_num) + struct net_device *net_dev) { struct hns_roce_dev *hr_dev = hns_roce_get_hrdev_by_netdev(net_dev);
@@ -810,7 +840,7 @@ static bool is_dev_bond_supported(struct hns_roce_bond_group *bond_grp, if (hr_dev->is_vf || pci_num_vf(hr_dev->pci_dev) > 0) return false;
- if (bus_num != get_hr_bus_num(hr_dev)) + if (bond_grp->bus_num != get_hr_bus_num(hr_dev)) return false;
return true; @@ -833,8 +863,7 @@ static bool check_unlinking_bond_support(struct hns_roce_bond_group *bond_grp)
static bool check_linking_bond_support(struct netdev_lag_upper_info *bond_info, struct hns_roce_bond_group *bond_grp, - struct net_device *upper_dev, - int bus_num) + struct net_device *upper_dev) { struct net_device *net_dev; u8 slave_num = 0; @@ -844,7 +873,7 @@ static bool check_linking_bond_support(struct netdev_lag_upper_info *bond_info,
rcu_read_lock(); for_each_netdev_in_bond_rcu(upper_dev, net_dev) { - if (is_dev_bond_supported(bond_grp, net_dev, bus_num)) { + if (is_dev_bond_supported(bond_grp, net_dev)) { slave_num++; } else { rcu_read_unlock(); @@ -857,19 +886,14 @@ static bool check_linking_bond_support(struct netdev_lag_upper_info *bond_info, }
static enum bond_support_type - check_bond_support(struct hns_roce_dev *hr_dev, - struct net_device **upper_dev, + check_bond_support(struct hns_roce_bond_group *bond_grp, + struct net_device *upper_dev, struct netdev_notifier_changeupper_info *info) { - struct net_device *net_dev = get_hr_netdev(hr_dev, 0); - struct hns_roce_bond_group *bond_grp; - int bus_num = get_hr_bus_num(hr_dev); bool bond_grp_exist = false; bool support;
- *upper_dev = info->upper_dev; - bond_grp = hns_roce_get_bond_grp(net_dev, bus_num); - if (bond_grp && *upper_dev == bond_grp->upper_dev) + if (upper_dev == bond_grp->upper_dev) bond_grp_exist = true;
if (!info->linking && !bond_grp_exist) @@ -877,7 +901,7 @@ static enum bond_support_type
if (info->linking) support = check_linking_bond_support(info->upper_info, bond_grp, - *upper_dev, bus_num); + upper_dev); else support = check_unlinking_bond_support(bond_grp);
@@ -887,16 +911,56 @@ static enum bond_support_type return bond_grp_exist ? BOND_EXISTING_NOT_SUPPORT : BOND_NOT_SUPPORT; }
+static bool upper_event_filter(struct netdev_notifier_changeupper_info *info, + struct hns_roce_bond_group *bond_grp, + struct net_device *net_dev) +{ + struct net_device *upper_dev = info->upper_dev; + struct hns_roce_bond_group *bond_grp_tmp; + struct hns_roce_dev *hr_dev; + u8 bus_num; + + if (!info->linking) + return bond_grp->upper_dev == upper_dev; + + hr_dev = hns_roce_get_hrdev_by_netdev(net_dev); + if (!hr_dev) + return false; + + bus_num = get_hr_bus_num(hr_dev); + if (bond_grp->bus_num != bus_num) + return false; + + bond_grp_tmp = hns_roce_get_bond_grp(net_dev, bus_num); + if (bond_grp_tmp && bond_grp_tmp != bond_grp) + return false; + + if (bond_grp->bond_state != HNS_ROCE_BOND_NOT_ATTACHED && + bond_grp->upper_dev != upper_dev) + return false; + + return true; +} + +static bool lowerstate_event_filter(struct hns_roce_bond_group *bond_grp, + struct net_device *net_dev) +{ + struct hns_roce_bond_group *bond_grp_tmp; + + bond_grp_tmp = hns_roce_get_bond_grp(net_dev, bond_grp->bus_num); + return bond_grp_tmp == bond_grp; +} + int hns_roce_bond_event(struct notifier_block *self, unsigned long event, void *ptr) { + struct hns_roce_bond_group *bond_grp = + container_of(self, struct hns_roce_bond_group, bond_nb); struct net_device *net_dev = netdev_notifier_info_to_dev(ptr); - struct hns_roce_dev *hr_dev = - container_of(self, struct hns_roce_dev, bond_nb); + struct netdev_notifier_changeupper_info *info; enum bond_support_type support = BOND_SUPPORT; - struct hns_roce_bond_group *bond_grp; - u8 bus_num = get_hr_bus_num(hr_dev); struct net_device *upper_dev; + struct hns_roce_dev *hr_dev; bool changed; int slave_id;
@@ -904,30 +968,27 @@ int hns_roce_bond_event(struct notifier_block *self, return NOTIFY_DONE;
if (event == NETDEV_CHANGEUPPER) { - support = check_bond_support(hr_dev, &upper_dev, ptr); + if (!upper_event_filter(ptr, bond_grp, net_dev)) + return NOTIFY_DONE; + info = (struct netdev_notifier_changeupper_info *)ptr; + upper_dev = info->upper_dev; + support = check_bond_support(bond_grp, upper_dev, ptr); if (support == BOND_NOT_SUPPORT) return NOTIFY_DONE; } else { + if (!lowerstate_event_filter(bond_grp, net_dev)) + return NOTIFY_DONE; upper_dev = get_upper_dev_from_ndev(net_dev); }
- if (upper_dev && !is_hrdev_bond_slave(hr_dev, upper_dev)) - return NOTIFY_DONE; - else if (!upper_dev && hr_dev != hns_roce_get_hrdev_by_netdev(net_dev)) - return NOTIFY_DONE; - - bond_grp = hns_roce_get_bond_grp(get_hr_netdev(hr_dev, 0), bus_num); if (event == NETDEV_CHANGEUPPER) { - if (!bond_grp) { - bond_grp = hns_roce_alloc_bond_grp(hr_dev, upper_dev); - if (!bond_grp) { - ibdev_err(&hr_dev->ib_dev, - "failed to alloc RoCE bond_grp!\n"); + if (bond_grp->bond_state == HNS_ROCE_BOND_NOT_ATTACHED) { + hr_dev = hns_roce_get_hrdev_by_netdev(net_dev); + if (!hr_dev) return NOTIFY_DONE; - } - } else if (hr_dev != bond_grp->main_hr_dev) { - return NOTIFY_DONE; + hns_roce_attach_bond_grp(bond_grp, hr_dev, upper_dev); } + /* In the case of netdev being unregistered, the roce * instance shouldn't be inited. */ @@ -944,7 +1005,7 @@ int hns_roce_bond_event(struct notifier_block *self, } changed = hns_roce_bond_upper_event(bond_grp, ptr); } else { - changed = hns_roce_bond_lowerstate_event(hr_dev, bond_grp, ptr); + changed = hns_roce_bond_lowerstate_event(bond_grp, ptr); } if (changed) hns_roce_queue_bond_work(bond_grp, HZ); diff --git a/drivers/infiniband/hw/hns/hns_roce_bond.h b/drivers/infiniband/hw/hns/hns_roce_bond.h index 75c9d670de7c..ba82ec12e4e5 100644 --- a/drivers/infiniband/hw/hns/hns_roce_bond.h +++ b/drivers/infiniband/hw/hns/hns_roce_bond.h @@ -33,6 +33,7 @@ enum bond_support_type { };
enum hns_roce_bond_state { + HNS_ROCE_BOND_NOT_ATTACHED, HNS_ROCE_BOND_NOT_BONDED, HNS_ROCE_BOND_IS_BONDED, HNS_ROCE_BOND_REGISTERING, @@ -72,6 +73,7 @@ struct hns_roce_bond_group { struct hns_roce_func_info bond_func_info[ROCE_BOND_FUNC_MAX]; struct delayed_work bond_work; struct completion bond_work_done; + struct notifier_block bond_nb; };
struct hns_roce_die_info { @@ -88,5 +90,6 @@ struct net_device *hns_roce_get_bond_netdev(struct hns_roce_dev *hr_dev); struct hns_roce_bond_group *hns_roce_get_bond_grp(struct net_device *net_dev, u8 bus_num); bool is_bond_slave_in_reset(struct hns_roce_bond_group *bond_grp); +void hns_roce_dealloc_bond_grp(void);
#endif diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h index 0f1b87f8c75b..8add4742c094 100644 --- a/drivers/infiniband/hw/hns/hns_roce_device.h +++ b/drivers/infiniband/hw/hns/hns_roce_device.h @@ -1154,7 +1154,6 @@ struct hns_roce_dev { struct hns_roce_dev_debugfs dbgfs; atomic64_t *dfx_cnt; struct hns_roce_scc_param *scc_param; - struct notifier_block bond_nb;
struct list_head mtr_unfree_list; /* list of unfree mtr on this dev */ struct mutex mtr_unfree_list_mutex; /* protect mtr_unfree_list */ diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 2568609edb60..54ea073db0d0 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -2388,6 +2388,9 @@ static int hns_roce_query_caps(struct hns_roce_dev *hr_dev) caps->flags |= le16_to_cpu(resp_d->cap_flags_ex) << HNS_ROCE_CAP_FLAGS_EX_SHIFT;
+ if (hr_dev->is_vf) + caps->flags &= ~HNS_ROCE_CAP_FLAG_BOND; + caps->num_cqs = 1 << hr_reg_read(resp_c, PF_CAPS_C_NUM_CQS); caps->gid_table_len[0] = hr_reg_read(resp_c, PF_CAPS_C_MAX_GID); caps->max_cqes = 1 << hr_reg_read(resp_c, PF_CAPS_C_CQ_DEPTH); @@ -7460,11 +7463,8 @@ static void hns_roce_hw_v2_uninit_instance(struct hnae3_handle *handle, if (handle->rinfo.instance_state == HNS_ROCE_STATE_BOND_UNINIT) { bond_grp = hns_roce_get_bond_grp(handle->rinfo.netdev, handle->pdev->bus->number); - if (bond_grp) { + if (bond_grp) wait_for_completion(&bond_grp->bond_work_done); - if (bond_grp->bond_state == HNS_ROCE_BOND_NOT_BONDED) - kfree(bond_grp); - } }
if (handle->rinfo.instance_state != HNS_ROCE_STATE_INITED) @@ -7705,6 +7705,7 @@ static int __init hns_roce_hw_v2_init(void)
static void __exit hns_roce_hw_v2_exit(void) { + hns_roce_dealloc_bond_grp(); hnae3_unregister_client(&hns_roce_hw_v2_client); hns_roce_cleanup_debugfs(); } diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c index 3628dbb250ab..725f2f08cb0b 100644 --- a/drivers/infiniband/hw/hns/hns_roce_main.c +++ b/drivers/infiniband/hw/hns/hns_roce_main.c @@ -856,7 +856,6 @@ static void hns_roce_unregister_device(struct hns_roce_dev *hr_dev, if (!(hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_BOND)) goto normal_unregister;
- unregister_netdevice_notifier(&hr_dev->bond_nb); bond_grp = hns_roce_get_bond_grp(net_dev, bus_num); if (!bond_grp) goto normal_unregister; @@ -866,6 +865,7 @@ static void hns_roce_unregister_device(struct hns_roce_dev *hr_dev, * is unregistered, re-initialized the remaining slaves before * the bond resources cleanup. */ + cancel_delayed_work_sync(&bond_grp->bond_work); bond_grp->bond_state = HNS_ROCE_BOND_NOT_BONDED; for (i = 0; i < ROCE_BOND_FUNC_MAX; i++) { net_dev = bond_grp->bond_func_info[i].net_dev;