]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
hinic3: Add HW event handler
authorFan Gong <gongfan1@huawei.com>
Wed, 14 Jan 2026 08:38:28 +0000 (16:38 +0800)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 20 Jan 2026 09:34:31 +0000 (10:34 +0100)
Add HINIC3_INIT_UP flags to trace netdev open status.
Add port module event handler.
Add link status event type(FAULT, PCIE link down, heart lost, mgmt
watchdog).

Co-developed-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Fan Gong <gongfan1@huawei.com>
Link: https://patch.msgid.link/53a2b928136998f740d597bbd45ca1740b95538f.1768375903.git.zhuyikai1@h-partners.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h
drivers/net/ethernet/huawei/hinic3/hinic3_irq.c
drivers/net/ethernet/huawei/hinic3/hinic3_main.c
drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h

index 58bc561f95b33e750b3278c8c96a78eb86238053..9686c2600b4677ed23718dd04bfcbf543571796b 100644 (file)
@@ -17,6 +17,15 @@ enum hinic3_event_service_type {
        HINIC3_EVENT_SRV_NIC  = 1
 };
 
+enum hinic3_comm_event_type {
+       HINIC3_COMM_EVENT_PCIE_LINK_DOWN = 0,
+       HINIC3_COMM_EVENT_HEART_LOST = 1,
+       HINIC3_COMM_EVENT_FAULT = 2,
+       HINIC3_COMM_EVENT_SRIOV_STATE_CHANGE = 3,
+       HINIC3_COMM_EVENT_CARD_REMOVE = 4,
+       HINIC3_COMM_EVENT_MGMT_WATCHDOG = 5,
+};
+
 enum hinic3_fault_err_level {
        HINIC3_FAULT_LEVEL_SERIOUS_FLR = 3,
 };
index 63932a1fa8eeb5bb1647df9b491e9009625557d9..6950ee4d037bb769ee4505b09eae63762cfd3b85 100644 (file)
@@ -19,7 +19,8 @@ static void hinic3_net_dim(struct hinic3_nic_dev *nic_dev,
        struct hinic3_rxq *rxq = irq_cfg->rxq;
        struct dim_sample sample = {};
 
-       if (!nic_dev->adaptive_rx_coal)
+       if (!test_bit(HINIC3_INTF_UP, &nic_dev->flags) ||
+           !nic_dev->adaptive_rx_coal)
                return;
 
        dim_update_sample(irq_cfg->total_events, rxq->rxq_stats.packets,
index 2c16ec2b461632b9ee4d938358f510e4548e0895..a33f86675954b78a020466dd51d2d1f16a604fa4 100644 (file)
@@ -331,6 +331,44 @@ static void hinic3_link_status_change(struct net_device *netdev,
        }
 }
 
+static void hinic3_port_module_event_handler(struct net_device *netdev,
+                                            struct hinic3_event_info *event)
+{
+       const char *g_hinic3_module_link_err[LINK_ERR_NUM] = {
+               "Unrecognized module"
+       };
+       struct hinic3_port_module_event *module_event;
+       enum port_module_event_type type;
+       enum link_err_type err_type;
+
+       module_event = (struct hinic3_port_module_event *)event->event_data;
+       type = module_event->type;
+       err_type = module_event->err_type;
+
+       switch (type) {
+       case HINIC3_PORT_MODULE_CABLE_PLUGGED:
+       case HINIC3_PORT_MODULE_CABLE_UNPLUGGED:
+               netdev_info(netdev, "Port module event: Cable %s\n",
+                           type == HINIC3_PORT_MODULE_CABLE_PLUGGED ?
+                           "plugged" : "unplugged");
+               break;
+       case HINIC3_PORT_MODULE_LINK_ERR:
+               if (err_type >= LINK_ERR_NUM) {
+                       netdev_info(netdev, "Link failed, Unknown error type: 0x%x\n",
+                                   err_type);
+               } else {
+                       netdev_info(netdev,
+                                   "Link failed, error type: 0x%x: %s\n",
+                                   err_type,
+                                   g_hinic3_module_link_err[err_type]);
+               }
+               break;
+       default:
+               netdev_err(netdev, "Unknown port module type %d\n", type);
+               break;
+       }
+}
+
 static void hinic3_nic_event(struct auxiliary_device *adev,
                             struct hinic3_event_info *event)
 {
@@ -344,8 +382,20 @@ static void hinic3_nic_event(struct auxiliary_device *adev,
                                   HINIC3_NIC_EVENT_LINK_UP):
                hinic3_link_status_change(netdev, true);
                break;
+       case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_NIC,
+                                  HINIC3_NIC_EVENT_PORT_MODULE_EVENT):
+               hinic3_port_module_event_handler(netdev, event);
+               break;
        case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_NIC,
                                   HINIC3_NIC_EVENT_LINK_DOWN):
+       case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_COMM,
+                                  HINIC3_COMM_EVENT_FAULT):
+       case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_COMM,
+                                  HINIC3_COMM_EVENT_PCIE_LINK_DOWN):
+       case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_COMM,
+                                  HINIC3_COMM_EVENT_HEART_LOST):
+       case HINIC3_SRV_EVENT_TYPE(HINIC3_EVENT_SRV_COMM,
+                                  HINIC3_COMM_EVENT_MGMT_WATCHDOG):
                hinic3_link_status_change(netdev, false);
                break;
        default:
index 58629a24d45893899c1acf1d2a45d784ae7ad146..75adfe897e81f2f164e7d9717579811cfaad1b44 100644 (file)
@@ -432,6 +432,11 @@ static int hinic3_open(struct net_device *netdev)
        struct hinic3_dyna_qp_params qp_params;
        int err;
 
+       if (test_bit(HINIC3_INTF_UP, &nic_dev->flags)) {
+               netdev_dbg(netdev, "Netdev already open, do nothing\n");
+               return 0;
+       }
+
        err = hinic3_init_nicio_res(nic_dev);
        if (err) {
                netdev_err(netdev, "Failed to init nicio resources\n");
@@ -459,6 +464,8 @@ static int hinic3_open(struct net_device *netdev)
        if (err)
                goto err_close_channel;
 
+       set_bit(HINIC3_INTF_UP, &nic_dev->flags);
+
        return 0;
 
 err_close_channel:
@@ -479,6 +486,11 @@ static int hinic3_close(struct net_device *netdev)
        struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
        struct hinic3_dyna_qp_params qp_params;
 
+       if (!test_and_clear_bit(HINIC3_INTF_UP, &nic_dev->flags)) {
+               netdev_dbg(netdev, "Netdev already close, do nothing\n");
+               return 0;
+       }
+
        hinic3_vport_down(netdev);
        hinic3_close_channel(netdev);
        hinic3_uninit_qps(nic_dev, &qp_params);
index f83913e74cb5232964f46218b87ddb38fe5c6b39..c32eaa886e179027b82913e08f2fc72ebb95f9f9 100644 (file)
@@ -22,6 +22,7 @@ struct hinic3_nic_dev;
 enum hinic3_nic_event_type {
        HINIC3_NIC_EVENT_LINK_DOWN = 0,
        HINIC3_NIC_EVENT_LINK_UP   = 1,
+       HINIC3_NIC_EVENT_PORT_MODULE_EVENT = 2,
 };
 
 struct hinic3_sq_attr {
@@ -51,6 +52,23 @@ struct mag_cmd_set_port_enable {
        u8                   rsvd1[3];
 };
 
+enum link_err_type {
+       LINK_ERR_MODULE_UNRECOGENIZED,
+       LINK_ERR_NUM,
+};
+
+enum port_module_event_type {
+       HINIC3_PORT_MODULE_CABLE_PLUGGED,
+       HINIC3_PORT_MODULE_CABLE_UNPLUGGED,
+       HINIC3_PORT_MODULE_LINK_ERR,
+       HINIC3_PORT_MODULE_MAX_EVENT,
+};
+
+struct hinic3_port_module_event {
+       enum port_module_event_type type;
+       enum link_err_type          err_type;
+};
+
 int hinic3_get_nic_feature_from_hw(struct hinic3_nic_dev *nic_dev);
 int hinic3_set_nic_feature_to_hw(struct hinic3_nic_dev *nic_dev);
 bool hinic3_test_support(struct hinic3_nic_dev *nic_dev,
index 9bd46541b3e31301e78e353d0c984a8d3205354d..29189241f446ca2fdd97dbe380f9abcd3acfcc20 100644 (file)
@@ -16,6 +16,7 @@
        (VLAN_N_VID / HINIC3_VLAN_BITMAP_BYTE_SIZE(nic_dev))
 
 enum hinic3_flags {
+       HINIC3_INTF_UP,
        HINIC3_MAC_FILTER_CHANGED,
        HINIC3_RSS_ENABLE,
        HINIC3_UPDATE_MAC_FILTER,