diff --git a/drivers/infiniband/hw/hns/hns_roce_bond.c b/drivers/infiniband/hw/hns/hns_roce_bond.c index 200d12c3ff2de1a5992b51e40ed842e2315e55db..a82ecebac5a15a5d9c9f8daef0b54e9a7f7da3f4 100644 --- a/drivers/infiniband/hw/hns/hns_roce_bond.c +++ b/drivers/infiniband/hw/hns/hns_roce_bond.c @@ -101,9 +101,7 @@ 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); - if (bond_grp && - (bond_grp->bond_state == HNS_ROCE_BOND_REGISTERING || - bond_grp->bond_state == HNS_ROCE_BOND_IS_BONDED)) + if (bond_grp && bond_grp->bond_state != HNS_ROCE_BOND_NOT_BONDED) return true; return false; @@ -155,6 +153,7 @@ static void hns_roce_queue_bond_work(struct hns_roce_bond_group *bond_grp, static void hns_roce_bond_get_active_slave(struct hns_roce_bond_group *bond_grp) { + struct netdev_lag_lower_state_info *state; struct net_device *net_dev; u32 active_slave_map = 0; u8 active_slave_num = 0; @@ -163,14 +162,27 @@ static void hns_roce_bond_get_active_slave(struct hns_roce_bond_group *bond_grp) for (i = 0; i < ROCE_BOND_FUNC_MAX; i++) { net_dev = bond_grp->bond_func_info[i].net_dev; - if (net_dev) { - active = (bond_grp->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) ? - bond_grp->bond_func_info[i].state.tx_enabled : - bond_grp->bond_func_info[i].state.link_up; - if (active) { - active_slave_num++; - active_slave_map |= (1 << i); - } + state = &bond_grp->bond_func_info[i].state; + if (!net_dev) + continue; + + state->tx_enabled = (bond_grp->bond->curr_active_slave && + (net_dev == bond_grp->bond->curr_active_slave->dev)) ? + 1 : 0; + state->link_up = + (get_port_state(net_dev) == IB_PORT_ACTIVE) ? 1 : 0; + + /* + * For bond mode 1(active-backup), only the tx-enabled slave is + * considered active. For other bond mode, all the link-up + * slaves are considered active. + */ + active = (bond_grp->tx_type == NETDEV_LAG_TX_TYPE_ACTIVEBACKUP) ? + bond_grp->bond_func_info[i].state.tx_enabled : + bond_grp->bond_func_info[i].state.link_up; + if (active) { + active_slave_num++; + active_slave_map |= (1 << i); } } @@ -178,6 +190,13 @@ static void hns_roce_bond_get_active_slave(struct hns_roce_bond_group *bond_grp) bond_grp->active_slave_map = active_slave_map; } +static int hns_roce_recover_bond(struct hns_roce_bond_group *bond_grp) +{ + hns_roce_bond_get_active_slave(bond_grp); + + return hns_roce_cmd_bond(bond_grp, HNS_ROCE_SET_BOND); +} + static void hns_roce_set_bond(struct hns_roce_bond_group *bond_grp) { struct hns_roce_dev *hr_dev = NULL; @@ -337,6 +356,9 @@ static void hns_roce_do_bond(struct hns_roce_bond_group *bond_grp) enum hns_roce_bond_state bond_state = bond_grp->bond_state; bool bond_ready = bond_grp->bond_ready; + if (!bond_grp->main_hr_dev) + return; + ibdev_info(&bond_grp->main_hr_dev->ib_dev, "do_bond: bond_ready - %d, bond_state - %d.\n", bond_ready, bond_grp->bond_state); @@ -374,13 +396,29 @@ 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 hns_roce_v2_priv *priv = hr_dev->priv; int ret; + 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; + } + bond_grp->bond_state = HNS_ROCE_BOND_IS_BONDED; + } + 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!\n"); + "failed to register notifier for RoCE bond, ret = %d.\n", + ret); hr_dev->bond_nb.notifier_call = NULL; } diff --git a/drivers/infiniband/hw/hns/hns_roce_main.c b/drivers/infiniband/hw/hns/hns_roce_main.c index 1d95297cc517c3eaf61e3335df60851574ef8d07..d8d402627b1421e33108b7fa442128af82971d1e 100644 --- a/drivers/infiniband/hw/hns/hns_roce_main.c +++ b/drivers/infiniband/hw/hns/hns_roce_main.c @@ -826,13 +826,19 @@ static void hns_roce_unregister_device(struct hns_roce_dev *hr_dev, bool bond_cleanup) { 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; 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 && bond_cleanup) - hns_roce_cleanup_bond(bond_grp); + 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; + } } hr_dev->active = false;