diff --git a/drivers/infiniband/hw/hns/hns_roce_ah.c b/drivers/infiniband/hw/hns/hns_roce_ah.c index c92179da38bda5f6f6954000efeb9316a8937e38..f4ceaeba5601b9081d667a93848882a4c20ab25d 100644 --- a/drivers/infiniband/hw/hns/hns_roce_ah.c +++ b/drivers/infiniband/hw/hns/hns_roce_ah.c @@ -30,7 +30,6 @@ * SOFTWARE. */ -#include #include #include #include "hnae3.h" diff --git a/drivers/infiniband/hw/hns/hns_roce_bond.c b/drivers/infiniband/hw/hns/hns_roce_bond.c index 9f642b0adcb73e1dcf20239d501d7097d9710351..2f92ed730b78a4375ddf97af686c7503697ad1e5 100644 --- a/drivers/infiniband/hw/hns/hns_roce_bond.c +++ b/drivers/infiniband/hw/hns/hns_roce_bond.c @@ -3,7 +3,6 @@ * Copyright (c) 2022 Hisilicon Limited. */ -#include #include "hnae3.h" #include "hns_roce_device.h" #include "hns_roce_hw_v2.h" @@ -38,25 +37,27 @@ static struct net_device *get_upper_dev_from_ndev(struct net_device *net_dev) return upper_dev; } -static bool is_netdev_bond_slave(struct net_device *net_dev, - struct hns_roce_bond_group *bond_grp) +static int get_netdev_bond_slave_id(struct net_device *net_dev, + struct hns_roce_bond_group *bond_grp) { int i; if (!net_dev || !bond_grp) - return false; + return -ENODEV; for (i = 0; i < ROCE_BOND_FUNC_MAX; i++) if (net_dev == bond_grp->bond_func_info[i].net_dev) - return true; + return i; - return false; + 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; @@ -64,20 +65,23 @@ static bool is_hrdev_bond_slave(struct hns_roce_dev *hr_dev, if (!netif_is_lag_master(upper_dev)) return false; - if (upper_dev == get_upper_dev_from_ndev(hr_dev->iboe.netdevs[0])) + 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(hr_dev); + 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 hns_roce_dev *hr_dev) +struct hns_roce_bond_group *hns_roce_get_bond_grp(struct net_device *net_dev, + u8 bus_num) { - struct hns_roce_die_info *die_info = - xa_load(&roce_bond_xa, hr_dev->pci_dev->bus->number); + struct hns_roce_die_info *die_info = xa_load(&roce_bond_xa, bus_num); struct hns_roce_bond_group *bond_grp; int i; @@ -88,9 +92,8 @@ struct hns_roce_bond_group *hns_roce_get_bond_grp(struct hns_roce_dev *hr_dev) bond_grp = die_info->bgrps[i]; if (!bond_grp) continue; - if (is_netdev_bond_slave(hr_dev->iboe.netdevs[0], bond_grp) || - bond_grp->upper_dev == - get_upper_dev_from_ndev(hr_dev->iboe.netdevs[0])) + if (get_netdev_bond_slave_id(net_dev, bond_grp) >= 0 || + (bond_grp->upper_dev == get_upper_dev_from_ndev(net_dev))) return bond_grp; } @@ -99,7 +102,11 @@ struct hns_roce_bond_group *hns_roce_get_bond_grp(struct hns_roce_dev *hr_dev) bool hns_roce_bond_is_active(struct hns_roce_dev *hr_dev) { - struct hns_roce_bond_group *bond_grp = hns_roce_get_bond_grp(hr_dev); + struct net_device *net_dev = get_hr_netdev(hr_dev, 0); + struct hns_roce_bond_group *bond_grp; + 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) return true; @@ -118,13 +125,15 @@ static inline bool is_active_slave(struct net_device *net_dev, struct net_device *hns_roce_get_bond_netdev(struct hns_roce_dev *hr_dev) { - struct hns_roce_bond_group *bond_grp = hns_roce_get_bond_grp(hr_dev); - struct net_device *net_dev = NULL; + struct net_device *net_dev = get_hr_netdev(hr_dev, 0); + struct hns_roce_bond_group *bond_grp; + u8 bus_num = get_hr_bus_num(hr_dev); int i; if (!(hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_BOND)) return NULL; + bond_grp = hns_roce_get_bond_grp(net_dev, bus_num); if (!bond_grp) return NULL; @@ -145,9 +154,10 @@ struct net_device *hns_roce_get_bond_netdev(struct hns_roce_dev *hr_dev) for (i = 0; i < ROCE_BOND_FUNC_MAX; i++) { net_dev = bond_grp->bond_func_info[i].net_dev; if (net_dev && get_port_state(net_dev) == IB_PORT_ACTIVE) - break; + goto out; } + net_dev = NULL; out: mutex_unlock(&bond_grp->bond_mutex); @@ -207,6 +217,7 @@ static void hns_roce_set_bond(struct hns_roce_bond_group *bond_grp) } bond_grp->bond_state = HNS_ROCE_BOND_REGISTERING; + bond_grp->main_hr_dev = NULL; for (i = 0; i < ROCE_BOND_FUNC_MAX; i++) { net_dev = bond_grp->bond_func_info[i].net_dev; @@ -218,19 +229,21 @@ static void hns_roce_set_bond(struct hns_roce_bond_group *bond_grp) } } } - if (!hr_dev) - return; bond_grp->slave_map_diff = 0; hns_roce_bond_get_active_slave(bond_grp); - ret = hns_roce_cmd_bond(bond_grp, HNS_ROCE_SET_BOND); - if (ret) { - ibdev_err(&hr_dev->ib_dev, "failed to set RoCE bond!\n"); - return; - } + + ret = bond_grp->main_hr_dev ? + hns_roce_cmd_bond(bond_grp, HNS_ROCE_SET_BOND) : -EIO; bond_grp->bond_state = HNS_ROCE_BOND_IS_BONDED; - ibdev_info(&hr_dev->ib_dev, "RoCE set bond finished!\n"); + complete(&bond_grp->bond_work_done); + + if (ret) + BOND_ERR_LOG("failed to set RoCE bond, ret = %d.\n", ret); + else + ibdev_info(&bond_grp->main_hr_dev->ib_dev, + "RoCE set bond finished!\n"); } static void hns_roce_clear_bond(struct hns_roce_bond_group *bond_grp) @@ -238,23 +251,30 @@ static void hns_roce_clear_bond(struct hns_roce_bond_group *bond_grp) u8 main_func_idx = PCI_FUNC(bond_grp->main_hr_dev->pci_dev->devfn); struct hns_roce_dev *hr_dev; struct net_device *net_dev; - int i; + int i, ret; + + if (bond_grp->bond_state == HNS_ROCE_BOND_NOT_BONDED) + goto out; bond_grp->bond_state = HNS_ROCE_BOND_NOT_BONDED; + bond_grp->main_hr_dev = NULL; hns_roce_bond_uninit_client(bond_grp, main_func_idx); for (i = 0; i < ROCE_BOND_FUNC_MAX; i++) { net_dev = bond_grp->bond_func_info[i].net_dev; - if (net_dev) + if (net_dev) { hr_dev = hns_roce_bond_init_client(bond_grp, i); + if (hr_dev) + bond_grp->main_hr_dev = hr_dev; + } } - if (!hr_dev) - return; - bond_grp->main_hr_dev = hr_dev; - hns_roce_cleanup_bond(bond_grp); - ibdev_info(&hr_dev->ib_dev, "RoCE clear bond finished!\n"); +out: + ret = hns_roce_cleanup_bond(bond_grp); + if (!ret) + ibdev_info(&bond_grp->main_hr_dev->ib_dev, + "RoCE clear bond finished!\n"); } static void hns_roce_slave_changestate(struct hns_roce_bond_group *bond_grp) @@ -264,15 +284,17 @@ static void hns_roce_slave_changestate(struct hns_roce_bond_group *bond_grp) hns_roce_bond_get_active_slave(bond_grp); ret = hns_roce_cmd_bond(bond_grp, HNS_ROCE_CHANGE_BOND); - if (ret) { - ibdev_err(&bond_grp->main_hr_dev->ib_dev, - "failed to change RoCE bond slave state!\n"); - return; - } bond_grp->bond_state = HNS_ROCE_BOND_IS_BONDED; - ibdev_info(&bond_grp->main_hr_dev->ib_dev, - "RoCE slave changestate finished!\n"); + complete(&bond_grp->bond_work_done); + + if (ret) + ibdev_err(&bond_grp->main_hr_dev->ib_dev, + "failed to change RoCE bond slave state, ret = %d.\n", + ret); + else + ibdev_info(&bond_grp->main_hr_dev->ib_dev, + "RoCE slave changestate finished!\n"); } static void hns_roce_slave_inc(struct hns_roce_bond_group *bond_grp) @@ -290,16 +312,18 @@ static void hns_roce_slave_inc(struct hns_roce_bond_group *bond_grp) bond_grp->slave_map_diff = 0; hns_roce_bond_get_active_slave(bond_grp); + ret = hns_roce_cmd_bond(bond_grp, HNS_ROCE_CHANGE_BOND); - if (ret) { - ibdev_err(&bond_grp->main_hr_dev->ib_dev, - "failed to increase RoCE bond slave!\n"); - return; - } bond_grp->bond_state = HNS_ROCE_BOND_IS_BONDED; - ibdev_info(&bond_grp->main_hr_dev->ib_dev, - "RoCE slave increase finished!\n"); + complete(&bond_grp->bond_work_done); + + if (ret) + ibdev_err(&bond_grp->main_hr_dev->ib_dev, + "failed to increase slave, ret = %d.\n", ret); + else + ibdev_info(&bond_grp->main_hr_dev->ib_dev, + "RoCE slave increase finished!\n"); } static void hns_roce_slave_dec(struct hns_roce_bond_group *bond_grp) @@ -313,6 +337,7 @@ static void hns_roce_slave_dec(struct hns_roce_bond_group *bond_grp) int i; if (dec_slave_map & (1 << main_func_idx)) { + bond_grp->main_hr_dev = NULL; hns_roce_bond_uninit_client(bond_grp, main_func_idx); for (i = 0; i < ROCE_BOND_FUNC_MAX; i++) { net_dev = bond_grp->bond_func_info[i].net_dev; @@ -338,16 +363,19 @@ static void hns_roce_slave_dec(struct hns_roce_bond_group *bond_grp) bond_grp->slave_map_diff = 0; hns_roce_bond_get_active_slave(bond_grp); - ret = hns_roce_cmd_bond(bond_grp, HNS_ROCE_CHANGE_BOND); - if (ret) { - ibdev_err(&bond_grp->main_hr_dev->ib_dev, - "failed to decrease RoCE bond slave!\n"); - return; - } + + ret = bond_grp->main_hr_dev ? + hns_roce_cmd_bond(bond_grp, HNS_ROCE_CHANGE_BOND) : -EIO; bond_grp->bond_state = HNS_ROCE_BOND_IS_BONDED; - ibdev_info(&bond_grp->main_hr_dev->ib_dev, - "RoCE slave decrease finished!\n"); + complete(&bond_grp->bond_work_done); + + if (ret) + BOND_ERR_LOG("failed to decrease RoCE bond slave, ret = %d.\n", + ret); + else + ibdev_info(&bond_grp->main_hr_dev->ib_dev, + "RoCE slave decrease finished!\n"); } static void hns_roce_do_bond(struct hns_roce_bond_group *bond_grp) @@ -362,16 +390,29 @@ static void hns_roce_do_bond(struct hns_roce_bond_group *bond_grp) "do_bond: bond_ready - %d, bond_state - %d.\n", bond_ready, bond_grp->bond_state); - if (bond_ready && bond_state == HNS_ROCE_BOND_NOT_BONDED) + reinit_completion(&bond_grp->bond_work_done); + + if (!bond_ready) { + hns_roce_clear_bond(bond_grp); + return; + } + + switch (bond_state) { + case HNS_ROCE_BOND_NOT_BONDED: hns_roce_set_bond(bond_grp); - else if (bond_ready && bond_state == HNS_ROCE_BOND_SLAVE_CHANGESTATE) + return; + case HNS_ROCE_BOND_SLAVE_CHANGESTATE: hns_roce_slave_changestate(bond_grp); - else if (bond_ready && bond_state == HNS_ROCE_BOND_SLAVE_INC) + return; + case HNS_ROCE_BOND_SLAVE_INC: hns_roce_slave_inc(bond_grp); - else if (bond_ready && bond_state == HNS_ROCE_BOND_SLAVE_DEC) + return; + case HNS_ROCE_BOND_SLAVE_DEC: hns_roce_slave_dec(bond_grp); - else if (!bond_ready && bond_state != HNS_ROCE_BOND_NOT_BONDED) - hns_roce_clear_bond(bond_grp); + return; + default: + return; + } } void hns_roce_do_bond_work(struct work_struct *work) @@ -395,10 +436,13 @@ void hns_roce_do_bond_work(struct work_struct *work) int hns_roce_bond_init(struct hns_roce_dev *hr_dev) { - struct hns_roce_bond_group *bond_grp = hns_roce_get_bond_grp(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; @@ -444,7 +488,7 @@ static struct hns_roce_die_info *alloc_die_info(int bus_num) static int alloc_bond_id(struct hns_roce_bond_group *bond_grp) { - int bus_num = bond_grp->main_hr_dev->pci_dev->bus->number; + u8 bus_num = bond_grp->bus_num; struct hns_roce_die_info *die_info = xa_load(&roce_bond_xa, bus_num); int i; @@ -491,23 +535,28 @@ static int remove_bond_id(int bus_num, u8 bond_id) return 0; } -void hns_roce_cleanup_bond(struct hns_roce_bond_group *bond_grp) +int hns_roce_cleanup_bond(struct hns_roce_bond_group *bond_grp) { + bool completion_no_waiter; int ret; - ret = hns_roce_cmd_bond(bond_grp, HNS_ROCE_CLEAR_BOND); + ret = bond_grp->main_hr_dev ? + hns_roce_cmd_bond(bond_grp, HNS_ROCE_CLEAR_BOND) : -EIO; if (ret) - ibdev_err(&bond_grp->main_hr_dev->ib_dev, - "failed to clear RoCE bond!\n"); + 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->main_hr_dev->pci_dev->bus->number, - bond_grp->bond_id); + ret = remove_bond_id(bond_grp->bus_num, bond_grp->bond_id); if (ret) - ibdev_err(&bond_grp->main_hr_dev->ib_dev, - "failed to remove bond ID %d, ret = %d.\n", - bond_grp->bond_id, ret); - kfree(bond_grp); + BOND_ERR_LOG("failed to remove bond id %d, ret = %d.\n", + bond_grp->bond_id, ret); + + completion_no_waiter = completion_done(&bond_grp->bond_work_done); + complete(&bond_grp->bond_work_done); + if (completion_no_waiter) + kfree(bond_grp); + + return ret; } static bool hns_roce_bond_lowerstate_event(struct hns_roce_dev *hr_dev, @@ -636,10 +685,13 @@ static struct hns_roce_bond_group *hns_roce_alloc_bond_grp(struct hns_roce_dev * 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) { @@ -659,15 +711,16 @@ static enum bond_support_type struct net_device **upper_dev, struct netdev_notifier_changeupper_info *info) { - struct hns_roce_bond_group *bond_grp = hns_roce_get_bond_grp(hr_dev); + struct net_device *net_dev = get_hr_netdev(hr_dev, 0); struct netdev_lag_upper_info *bond_upper_info = NULL; + struct hns_roce_bond_group *bond_grp; + int bus_num = get_hr_bus_num(hr_dev); bool bond_grp_exist = false; - struct net_device *net_dev; bool support = true; u8 slave_num = 0; - int bus_num = -1; *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) bond_grp_exist = true; @@ -681,20 +734,21 @@ static enum bond_support_type !hns_roce_bond_mode_is_supported(bond_upper_info->tx_type)) return BOND_NOT_SUPPORT; + bus_num = -1; rcu_read_lock(); for_each_netdev_in_bond_rcu(*upper_dev, net_dev) { if (!info->linking && bond_grp_exist) { - if (is_netdev_bond_slave(net_dev, bond_grp)) + if (get_netdev_bond_slave_id(net_dev, bond_grp) >= 0) slave_num++; } else { hr_dev = hns_roce_get_hrdev_by_netdev(net_dev); if (hr_dev) { slave_num++; if (bus_num == -1) - bus_num = hr_dev->pci_dev->bus->number; + bus_num = get_hr_bus_num(hr_dev); if (hr_dev->is_vf || pci_num_vf(hr_dev->pci_dev) > 0 || - bus_num != hr_dev->pci_dev->bus->number) { + bus_num != get_hr_bus_num(hr_dev)) { support = false; break; } @@ -719,8 +773,10 @@ int hns_roce_bond_event(struct notifier_block *self, container_of(self, struct hns_roce_dev, bond_nb); 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; bool changed; + int slave_id; if (event != NETDEV_CHANGEUPPER && event != NETDEV_CHANGELOWERSTATE) return NOTIFY_DONE; @@ -738,7 +794,7 @@ int hns_roce_bond_event(struct notifier_block *self, else if (!upper_dev && hr_dev != hns_roce_get_hrdev_by_netdev(net_dev)) return NOTIFY_DONE; - bond_grp = hns_roce_get_bond_grp(hr_dev); + 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); @@ -750,6 +806,15 @@ int hns_roce_bond_event(struct notifier_block *self, } else if (hr_dev != bond_grp->main_hr_dev) { return NOTIFY_DONE; } + /* In the case of netdev being unregistered, the roce + * instance shouldn't be inited. + */ + if (net_dev->reg_state >= NETREG_UNREGISTERING) { + slave_id = get_netdev_bond_slave_id(net_dev, bond_grp); + if (slave_id >= 0) + bond_grp->bond_func_info[slave_id].handle = NULL; + } + if (support == BOND_EXISTING_NOT_SUPPORT) { bond_grp->bond_ready = false; 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 8f637b551f251f893cc83667d7535cc1ff57b860..c9de9315d0da221e7118e3284b3086767f778b6d 100644 --- a/drivers/infiniband/hw/hns/hns_roce_bond.h +++ b/drivers/infiniband/hw/hns/hns_roce_bond.h @@ -14,6 +14,9 @@ #define BOND_ID(id) BIT(id) +#define BOND_ERR_LOG(fmt, ...) \ + pr_err("HNS RoCE Bonding: " fmt, ##__VA_ARGS__) \ + enum { BOND_MODE_1, BOND_MODE_2_4, @@ -57,6 +60,7 @@ struct hns_roce_bond_group { u32 active_slave_map; u32 slave_map_diff; u8 bond_id; + u8 bus_num; struct bonding *bond; bool bond_ready; enum hns_roce_bond_state bond_state; @@ -67,6 +71,7 @@ struct hns_roce_bond_group { struct mutex bond_mutex; struct hns_roce_func_info bond_func_info[ROCE_BOND_FUNC_MAX]; struct delayed_work bond_work; + struct completion bond_work_done; }; struct hns_roce_die_info { @@ -77,9 +82,10 @@ struct hns_roce_die_info { int hns_roce_bond_init(struct hns_roce_dev *hr_dev); int hns_roce_bond_event(struct notifier_block *self, unsigned long event, void *ptr); -void hns_roce_cleanup_bond(struct hns_roce_bond_group *bond_grp); +int hns_roce_cleanup_bond(struct hns_roce_bond_group *bond_grp); bool hns_roce_bond_is_active(struct hns_roce_dev *hr_dev); 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 hns_roce_dev *hr_dev); +struct hns_roce_bond_group *hns_roce_get_bond_grp(struct net_device *net_dev, + u8 bus_num); #endif diff --git a/drivers/infiniband/hw/hns/hns_roce_device.h b/drivers/infiniband/hw/hns/hns_roce_device.h index 6df342ae34e39d77c4b7f4be9f2c6c23c9f201d4..148b8920925f696d9a8ce430b1a781b79a9a56d5 100644 --- a/drivers/infiniband/hw/hns/hns_roce_device.h +++ b/drivers/infiniband/hw/hns/hns_roce_device.h @@ -33,6 +33,7 @@ #ifndef _HNS_ROCE_DEVICE_H #define _HNS_ROCE_DEVICE_H +#include #include #include #include "hns_roce_bond.h" @@ -185,6 +186,7 @@ enum hns_roce_instance_state { HNS_ROCE_STATE_INIT, HNS_ROCE_STATE_INITED, HNS_ROCE_STATE_UNINIT, + HNS_ROCE_STATE_BOND_UNINIT, }; enum { @@ -1269,6 +1271,17 @@ static inline enum ib_port_state get_port_state(struct net_device *net_dev) IB_PORT_ACTIVE : IB_PORT_DOWN; } +static inline struct net_device *get_hr_netdev(struct hns_roce_dev *hr_dev, + u8 port) +{ + return hr_dev->iboe.netdevs[port]; +} + +static inline u8 get_hr_bus_num(struct hns_roce_dev *hr_dev) +{ + return hr_dev->pci_dev->bus->number; +} + void hns_roce_init_uar_table(struct hns_roce_dev *dev); int hns_roce_uar_alloc(struct hns_roce_dev *dev, struct hns_roce_uar *uar); diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 10488d1f9bebd29be17ad8e28dab9d554c7db57b..e905d26bb3e5190fbd91aa0ced5aed2f5b258a29 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -7231,7 +7231,8 @@ static bool check_vf_support(struct pci_dev *vf) if (!hr_dev) return false; - bond_grp = hns_roce_get_bond_grp(hr_dev); + bond_grp = hns_roce_get_bond_grp(get_hr_netdev(hr_dev, 0), + pf->bus->number); if (bond_grp) return false; @@ -7361,6 +7362,19 @@ static int hns_roce_hw_v2_init_instance(struct hnae3_handle *handle) static void hns_roce_hw_v2_uninit_instance(struct hnae3_handle *handle, bool reset) { + struct hns_roce_bond_group *bond_grp; + + /* Wait for the completion of bond work to avoid concurrency */ + 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) { + 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) return; @@ -7379,6 +7393,9 @@ struct hns_roce_dev int ret; handle = bond_grp->bond_func_info[func_idx].handle; + if (!handle || !handle->client) + return NULL; + ret = hns_roce_hw_v2_init_instance(handle); if (ret) return NULL; @@ -7394,7 +7411,7 @@ void hns_roce_bond_uninit_client(struct hns_roce_bond_group *bond_grp, if (handle->rinfo.instance_state != HNS_ROCE_STATE_INITED) return; - handle->rinfo.instance_state = HNS_ROCE_STATE_UNINIT; + handle->rinfo.instance_state = HNS_ROCE_STATE_BOND_UNINIT; __hns_roce_hw_v2_uninit_instance(handle, false, false); @@ -7509,9 +7526,11 @@ static void hns_roce_hw_v2_link_status_change(struct hnae3_handle *handle, struct net_device *netdev = handle->rinfo.netdev; struct hns_roce_dev *hr_dev = handle->priv; struct hns_roce_bond_group *bond_grp; + struct net_device *hr_net_dev; struct ib_event event; unsigned long flags; u8 phy_port; + u8 bus_num; if (linkup || !hr_dev) return; @@ -7521,12 +7540,14 @@ static void hns_roce_hw_v2_link_status_change(struct hnae3_handle *handle, * netdev but not only one. So bond device cannot get a correct * link status from this path. */ - bond_grp = hns_roce_get_bond_grp(hr_dev); + hr_net_dev = get_hr_netdev(hr_dev, 0); + bus_num = get_hr_bus_num(hr_dev); + bond_grp = hns_roce_get_bond_grp(hr_net_dev, bus_num); if (bond_grp) return; for (phy_port = 0; phy_port < hr_dev->caps.num_ports; phy_port++) - if (netdev == hr_dev->iboe.netdevs[phy_port]) + if (netdev == get_hr_netdev(hr_dev, phy_port)) break; if (phy_port == hr_dev->caps.num_ports) diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c index 1dc747454e00fb2da06e3343a68b890cb1606972..4a16200ab950336b1cf7501db60b7dc55af1dc5e 100644 --- a/drivers/infiniband/hw/hns/hns_roce_main.c +++ b/drivers/infiniband/hw/hns/hns_roce_main.c @@ -32,7 +32,6 @@ */ #include #include -#include #include #include #include @@ -61,7 +60,7 @@ static struct net_device *hns_roce_get_netdev(struct ib_device *ib_dev, rcu_read_lock(); if (!ndev) - ndev = hr_dev->iboe.netdevs[port_num - 1]; + ndev = get_hr_netdev(hr_dev, port_num - 1); if (ndev) dev_hold(ndev); @@ -120,10 +119,12 @@ static int hns_roce_del_gid(const struct ib_gid_attr *attr, void **context) static enum ib_port_state get_upper_port_state(struct hns_roce_dev *hr_dev) { + struct net_device *net_dev = get_hr_netdev(hr_dev, 0); struct hns_roce_bond_group *bond_grp; + u8 bus_num = get_hr_bus_num(hr_dev); struct net_device *upper; - bond_grp = hns_roce_get_bond_grp(hr_dev); + bond_grp = hns_roce_get_bond_grp(net_dev, bus_num); upper = bond_grp ? bond_grp->upper_dev : NULL; if (upper) return get_port_state(upper); @@ -198,7 +199,8 @@ static int hns_roce_netdev_event(struct notifier_block *self, hr_dev = container_of(self, struct hns_roce_dev, iboe.nb); iboe = &hr_dev->iboe; if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_BOND) { - bond_grp = hns_roce_get_bond_grp(hr_dev); + bond_grp = hns_roce_get_bond_grp(get_hr_netdev(hr_dev, 0), + get_hr_bus_num(hr_dev)); upper = bond_grp ? bond_grp->upper_dev : NULL; } @@ -217,14 +219,14 @@ static int hns_roce_netdev_event(struct notifier_block *self, static int hns_roce_setup_mtu_mac(struct hns_roce_dev *hr_dev) { + struct net_device *net_dev; int ret; u8 i; for (i = 0; i < hr_dev->caps.num_ports; i++) { hr_dev->iboe.port_state[i] = IB_PORT_DOWN; - - ret = hns_roce_set_mac(hr_dev, i, - hr_dev->iboe.netdevs[i]->dev_addr); + net_dev = get_hr_netdev(hr_dev, i); + ret = hns_roce_set_mac(hr_dev, i, net_dev->dev_addr); if (ret) return ret; } @@ -310,7 +312,7 @@ static int hns_roce_query_port(struct ib_device *ib_dev, u8 port_num, net_dev = hr_dev->hw->get_bond_netdev(hr_dev); if (!net_dev) - net_dev = hr_dev->iboe.netdevs[port]; + net_dev = get_hr_netdev(hr_dev, port); if (!net_dev) { spin_unlock_irqrestore(&hr_dev->iboe.lock, flags); dev_err(dev, "Find netdev %u failed!\n", port); @@ -851,22 +853,39 @@ static int hns_roce_get_hw_stats(struct ib_device *device, static void hns_roce_unregister_device(struct hns_roce_dev *hr_dev, bool bond_cleanup) { + struct net_device *net_dev = get_hr_netdev(hr_dev, 0); struct hns_roce_ib_iboe *iboe = &hr_dev->iboe; 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 i; - if (hr_dev->caps.flags & HNS_ROCE_CAP_FLAG_BOND) { - unregister_netdevice_notifier(&hr_dev->bond_nb); - bond_grp = hns_roce_get_bond_grp(hr_dev); - if (bond_grp) { - if (bond_cleanup) - hns_roce_cleanup_bond(bond_grp); - else if (priv->handle->rinfo.reset_state == - HNS_ROCE_STATE_RST_UNINIT) - bond_grp->main_hr_dev = NULL; + 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; + + if (bond_cleanup) { + /* To avoid the loss of other slave devices when main_hr_dev + * is unregistered, re-initialized the remaining slaves before + * the bond resources cleanup. + */ + 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; + if (net_dev && net_dev != iboe->netdevs[0]) + hns_roce_bond_init_client(bond_grp, i); } + hns_roce_cleanup_bond(bond_grp); + } else if (priv->handle->rinfo.reset_state == + HNS_ROCE_STATE_RST_UNINIT) { + bond_grp->main_hr_dev = NULL; } +normal_unregister: hr_dev->active = false; unregister_netdevice_notifier(&iboe->nb); ib_unregister_device(&hr_dev->ib_dev); @@ -961,11 +980,12 @@ static const struct ib_device_ops hns_roce_dev_restrack_ops = { static int hns_roce_register_device(struct hns_roce_dev *hr_dev) { - int ret; struct hns_roce_ib_iboe *iboe = NULL; - struct ib_device *ib_dev = NULL; struct device *dev = hr_dev->dev; + struct ib_device *ib_dev = NULL; + struct net_device *net_dev; unsigned int i; + int ret; iboe = &hr_dev->iboe; spin_lock_init(&iboe->lock); @@ -1049,11 +1069,11 @@ static int hns_roce_register_device(struct hns_roce_dev *hr_dev) ib_dev->driver_def = hns_roce_uapi_defs; for (i = 0; i < hr_dev->caps.num_ports; i++) { - if (!hr_dev->iboe.netdevs[i]) + net_dev = get_hr_netdev(hr_dev, i); + if (!net_dev) continue; - ret = ib_device_set_netdev(ib_dev, hr_dev->iboe.netdevs[i], - i + 1); + ret = ib_device_set_netdev(ib_dev, net_dev, i + 1); if (ret) return ret; } diff --git a/drivers/infiniband/hw/hns/hns_roce_pd.c b/drivers/infiniband/hw/hns/hns_roce_pd.c index 7399963dc2945dcf5ba4d48836252ef982215785..6c69e095aa01151f8ee57f8411687783d40b5396 100644 --- a/drivers/infiniband/hw/hns/hns_roce_pd.c +++ b/drivers/infiniband/hw/hns/hns_roce_pd.c @@ -30,7 +30,6 @@ * SOFTWARE. */ -#include #include "hns_roce_device.h" void hns_roce_init_pd_table(struct hns_roce_dev *hr_dev) diff --git a/drivers/infiniband/hw/hns/hns_roce_qp.c b/drivers/infiniband/hw/hns/hns_roce_qp.c index 4d0c9332f8964df27272e8cc09fc084748a4fe04..00f82f4b19f6d57ce8d5a484e7544e180ab9d018 100644 --- a/drivers/infiniband/hw/hns/hns_roce_qp.c +++ b/drivers/infiniband/hw/hns/hns_roce_qp.c @@ -31,7 +31,6 @@ * SOFTWARE. */ -#include #include #include #include @@ -1410,11 +1409,13 @@ static int check_mtu_validate(struct hns_roce_dev *hr_dev, struct hns_roce_qp *hr_qp, struct ib_qp_attr *attr, int attr_mask) { + struct net_device *net_dev; enum ib_mtu active_mtu; int p; p = attr_mask & IB_QP_PORT ? (attr->port_num - 1) : hr_qp->port; - active_mtu = iboe_get_mtu(hr_dev->iboe.netdevs[p]->mtu); + net_dev = get_hr_netdev(hr_dev, p); + active_mtu = iboe_get_mtu(net_dev->mtu); if ((hr_dev->caps.max_mtu >= IB_MTU_2048 && attr->path_mtu > hr_dev->caps.max_mtu) || diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c index 320aaa24be01f01cd1d9eb7e79afa0e95add39a2..511e0f79e9d7ae1e83f9a5ab775b993a32c50090 100644 --- a/drivers/infiniband/hw/hns/hns_roce_srq.c +++ b/drivers/infiniband/hw/hns/hns_roce_srq.c @@ -3,7 +3,6 @@ * Copyright (c) 2018 Hisilicon Limited. */ -#include #include #include "hns_roce_device.h" #include "hns_roce_cmd.h"