Commit 953d7e86 authored by Junxian Huang's avatar Junxian Huang Committed by Ge Hu
Browse files

RDMA/hns: Register notifier block of bonding events in bond_grp

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: default avatarJunxian Huang <huangjunxian6@hisilicon.com>
Signed-off-by: default avatarXinghai Cen <cenxinghai@h-partners.com>
parent e65c0786
Loading
Loading
Loading
Loading
+238 −177
Original line number Diff line number Diff line
@@ -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);
	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;
		}

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

	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);
		bond_grp->bond_ready = false;
		bond_grp->bond_state = HNS_ROCE_BOND_NOT_ATTACHED;
		bond_grp->bus_num = get_hr_bus_num(hr_dev);

	return ret;
		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;
		}

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

	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");
				return NOTIFY_DONE;
			}
		} else if (hr_dev != bond_grp->main_hr_dev) {
		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;
			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);
+3 −0
Original line number Diff line number Diff line
@@ -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
+0 −1
Original line number Diff line number Diff line
@@ -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 */
+5 −4
Original line number Diff line number Diff line
@@ -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();
}
+1 −1
Original line number Diff line number Diff line
@@ -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;