From: Chiqijun <chiqijun(a)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(a)huawei.com>
Reviewed-by: Zengweiliang <zengweiliang.zengweiliang(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)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;
}
--
2.25.1