From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: 4472
-----------------------------------------------------------------------
Set the fault device link down so that the bond device can fail over to the backup device.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Zengweiliang zengweiliang.zengweiliang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_hw.h | 4 +- .../net/ethernet/huawei/hinic/hinic_hwdev.c | 22 +++-- drivers/net/ethernet/huawei/hinic/hinic_lld.c | 83 +++++++++++++++++-- .../net/ethernet/huawei/hinic/hinic_main.c | 8 ++ 4 files changed, 100 insertions(+), 17 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw.h b/drivers/net/ethernet/huawei/hinic/hinic_hw.h index 6afe31c9b80e..c4d48ccf8f2a 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw.h @@ -565,7 +565,8 @@ union hinic_fault_hw_mgmt { struct hinic_fault_event { /* enum hinic_fault_type */ u8 type; - u8 rsvd0[3]; + u8 fault_level; /* sdk write fault level for uld event */ + u8 rsvd0[2]; union hinic_fault_hw_mgmt event; };
@@ -653,6 +654,7 @@ enum hinic_event_type { HINIC_EVENT_MCTP_GET_HOST_INFO, HINIC_EVENT_MULTI_HOST_MGMT, HINIC_EVENT_INIT_MIGRATE_PF, + HINIC_EVENT_MGMT_WATCHDOG_EVENT, };
struct hinic_event_info { diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c index 058939d05346..2d6a547c4d34 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c @@ -3537,9 +3537,10 @@ static void fault_event_handler(struct hinic_hwdev *hwdev, void *buf_in, struct hinic_cmd_fault_event *fault_event; struct hinic_event_info event_info; struct hinic_fault_info_node *fault_node; + u8 fault_level;
if (in_size != sizeof(*fault_event)) { - sdk_err(hwdev->dev_hdl, "Invalid fault event report, length: %d, should be %ld.\n", + sdk_err(hwdev->dev_hdl, "Invalid fault event report, length: %d, should be %ld\n", in_size, sizeof(*fault_event)); return; } @@ -3547,11 +3548,16 @@ static void fault_event_handler(struct hinic_hwdev *hwdev, void *buf_in, fault_event = buf_in; fault_report_show(hwdev, &fault_event->event);
+ if (fault_event->event.type == HINIC_FAULT_SRC_HW_MGMT_CHIP) + fault_level = fault_event->event.event.chip.err_level; + else + fault_level = FAULT_LEVEL_FATAL; + if (hwdev->event_callback) { event_info.type = HINIC_EVENT_FAULT; memcpy(&event_info.info, &fault_event->event, sizeof(event_info.info)); - + event_info.info.fault_level = fault_level; hwdev->event_callback(hwdev->event_pri_handle, &event_info); }
@@ -3567,11 +3573,7 @@ static void fault_event_handler(struct hinic_hwdev *hwdev, void *buf_in, else if (fault_event->event.type == FAULT_TYPE_PHY_FAULT) fault_node->info.fault_src = HINIC_FAULT_SRC_HW_PHY_FAULT;
- if (fault_node->info.fault_src == HINIC_FAULT_SRC_HW_MGMT_CHIP) - fault_node->info.fault_lev = - fault_event->event.event.chip.err_level; - else - fault_node->info.fault_lev = FAULT_LEVEL_FATAL; + fault_node->info.fault_lev = fault_level;
memcpy(&fault_node->info.fault_data.hw_mgmt, &fault_event->event.event, sizeof(union hinic_fault_hw_mgmt)); @@ -3811,10 +3813,16 @@ static void mgmt_watchdog_timeout_event_handler(struct hinic_hwdev *hwdev, void *buf_out, u16 *out_size) { struct hinic_fault_info_node *fault_node; + struct hinic_event_info event_info = { 0 };
sw_watchdog_timeout_info_show(hwdev, buf_in, in_size, buf_out, out_size);
+ if (hwdev->event_callback) { + event_info.type = HINIC_EVENT_MGMT_WATCHDOG_EVENT; + hwdev->event_callback(hwdev->event_pri_handle, &event_info); + } + /* refresh history fault info */ fault_node = kzalloc(sizeof(*fault_node), GFP_KERNEL); if (!fault_node) { diff --git a/drivers/net/ethernet/huawei/hinic/hinic_lld.c b/drivers/net/ethernet/huawei/hinic/hinic_lld.c index 044d0df996e5..412f4c8a93ea 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_lld.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_lld.c @@ -1793,18 +1793,11 @@ static void __multi_host_mgmt(struct hinic_pcidev *dev, } }
-void hinic_event_process(void *adapter, struct hinic_event_info *event) +static void send_uld_dev_event(struct hinic_pcidev *dev, + struct hinic_event_info *event) { - struct hinic_pcidev *dev = adapter; enum hinic_service_type type;
- if (event->type == HINIC_EVENT_FMW_ACT_NTC) - return hinic_sync_time_to_fmw(dev); - else if (event->type == HINIC_EVENT_MCTP_GET_HOST_INFO) - return __mctp_get_host_info(dev, &event->mctp_info); - else if (event->type == HINIC_EVENT_MULTI_HOST_MGMT) - return __multi_host_mgmt(dev, &event->mhost_mgmt); - for (type = SERVICE_T_NIC; type < SERVICE_T_MAX; type++) { if (test_and_set_bit(type, &dev->state)) { sdk_warn(&dev->pcidev->dev, "Event: 0x%x can't handler, %s is in detach\n", @@ -1819,6 +1812,78 @@ void hinic_event_process(void *adapter, struct hinic_event_info *event) } }
+static void send_event_to_all_pf(struct hinic_pcidev *dev, + struct hinic_event_info *event) +{ + struct hinic_pcidev *des_dev = NULL; + + lld_dev_hold(); + list_for_each_entry(des_dev, &dev->chip_node->func_list, node) { + if (test_bit(HINIC_FUNC_IN_REMOVE, &des_dev->flag)) + continue; + + if (hinic_func_type(des_dev->hwdev) == TYPE_VF) + continue; + + send_uld_dev_event(des_dev, event); + } + lld_dev_put(); +} + +static void send_event_to_dst_pf(struct hinic_pcidev *dev, u16 func_id, + struct hinic_event_info *event) +{ + struct hinic_pcidev *des_dev = NULL; + + lld_dev_hold(); + list_for_each_entry(des_dev, &dev->chip_node->func_list, node) { + if (test_bit(HINIC_FUNC_IN_REMOVE, &des_dev->flag)) + continue; + + if (hinic_func_type(des_dev->hwdev) == TYPE_VF) + continue; + + if (hinic_global_func_id(des_dev->hwdev) == func_id) { + send_uld_dev_event(des_dev, event); + break; + } + } + lld_dev_put(); +} + +void hinic_event_process(void *adapter, struct hinic_event_info *event) +{ + struct hinic_pcidev *dev = adapter; + u16 func_id; + + switch (event->type) { + case HINIC_EVENT_FMW_ACT_NTC: + hinic_sync_time_to_fmw(dev); + break; + case HINIC_EVENT_MCTP_GET_HOST_INFO: + __mctp_get_host_info(dev, &event->mctp_info); + break; + case HINIC_EVENT_MULTI_HOST_MGMT: + __multi_host_mgmt(dev, &event->mhost_mgmt); + break; + case HINIC_EVENT_FAULT: + if (event->info.fault_level == FAULT_LEVEL_SERIOUS_FLR && + event->info.event.chip.func_id < HINIC_MAX_PF_NUM) { + func_id = event->info.event.chip.func_id; + send_event_to_dst_pf(adapter, func_id, event); + } else { + send_uld_dev_event(adapter, event); + } + break; + case HINIC_EVENT_MGMT_WATCHDOG_EVENT: + send_event_to_all_pf(adapter, event); + break; + default: + send_uld_dev_event(adapter, event); + break; + } +} + static int mapping_bar(struct pci_dev *pdev, struct hinic_pcidev *pci_adapter) { u32 db_dwqe_size; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index 8dc7b555f0bf..e0635287bf05 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -3026,8 +3026,13 @@ void nic_event(struct hinic_lld_dev *lld_dev, void *adapter, break; case HINIC_EVENT_HEART_LOST: hinic_heart_lost(nic_dev); + hinic_link_status_change(nic_dev, false); break; case HINIC_EVENT_FAULT: + if (event->info.fault_level == FAULT_LEVEL_SERIOUS_FLR && + event->info.event.chip.func_id == + hinic_global_func_id(lld_dev->hwdev)) + hinic_link_status_change(nic_dev, false); break; case HINIC_EVENT_DCB_STATE_CHANGE: if (nic_dev->default_cos_id == event->dcb_state.default_cos) @@ -3047,6 +3052,9 @@ void nic_event(struct hinic_lld_dev *lld_dev, void *adapter, case HINIC_EVENT_PORT_MODULE_EVENT: hinic_port_module_event_handler(nic_dev, event); break; + case HINIC_EVENT_MGMT_WATCHDOG_EVENT: + hinic_link_status_change(nic_dev, false); + break; default: break; }