net: hns3: add net status led support for fiber port
authorJian Shen <shenjian15@huawei.com>
Fri, 19 Jan 2018 06:41:12 +0000 (14:41 +0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 22 Jan 2018 21:05:49 +0000 (16:05 -0500)
Check the net status per second, include port speed, total rx/tx packets
and link status. Updating the led status for fiber port.

Signed-off-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h

index 122f862b6d9c2eacf6878e80177e5881c6c33c3f..3fd10a6bec5358cb1e44f1454ab7aa29257947a4 100644 (file)
@@ -115,6 +115,7 @@ enum hclge_opcode_type {
        HCLGE_OPC_QUERY_LINK_STATUS     = 0x0307,
        HCLGE_OPC_CONFIG_MAX_FRM_SIZE   = 0x0308,
        HCLGE_OPC_CONFIG_SPEED_DUP      = 0x0309,
+       HCLGE_OPC_STATS_MAC_TRAFFIC     = 0x0314,
        /* MACSEC command */
 
        /* PFC/Pause CMD*/
index 12150f26d00d2b856f128789fab9abe44f7c1397..32bc6f68e2974762d9eb6f2597d976a59f833322 100644 (file)
@@ -39,6 +39,7 @@ static int hclge_set_mta_filter_mode(struct hclge_dev *hdev,
 static int hclge_set_mtu(struct hnae3_handle *handle, int new_mtu);
 static int hclge_init_vlan_config(struct hclge_dev *hdev);
 static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev);
+static int hclge_update_led_status(struct hclge_dev *hdev);
 
 static struct hnae3_ae_algo ae_algo;
 
@@ -505,6 +506,38 @@ static int hclge_32_bit_update_stats(struct hclge_dev *hdev)
        return 0;
 }
 
+static int hclge_mac_get_traffic_stats(struct hclge_dev *hdev)
+{
+       struct hclge_mac_stats *mac_stats = &hdev->hw_stats.mac_stats;
+       struct hclge_desc desc;
+       __le64 *desc_data;
+       int ret;
+
+       /* for fiber port, need to query the total rx/tx packets statstics,
+        * used for data transferring checking.
+        */
+       if (hdev->hw.mac.media_type != HNAE3_MEDIA_TYPE_FIBER)
+               return 0;
+
+       if (test_bit(HCLGE_STATE_STATISTICS_UPDATING, &hdev->state))
+               return 0;
+
+       hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_STATS_MAC_TRAFFIC, true);
+       ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+       if (ret) {
+               dev_err(&hdev->pdev->dev,
+                       "Get MAC total pkt stats fail, ret = %d\n", ret);
+
+               return ret;
+       }
+
+       desc_data = (__le64 *)(&desc.data[0]);
+       mac_stats->mac_tx_total_pkt_num += le64_to_cpu(*desc_data++);
+       mac_stats->mac_rx_total_pkt_num += le64_to_cpu(*desc_data);
+
+       return 0;
+}
+
 static int hclge_mac_update_stats(struct hclge_dev *hdev)
 {
 #define HCLGE_MAC_CMD_NUM 21
@@ -2846,13 +2879,20 @@ static void hclge_service_task(struct work_struct *work)
        struct hclge_dev *hdev =
                container_of(work, struct hclge_dev, service_task);
 
+       /* The total rx/tx packets statstics are wanted to be updated
+        * per second. Both hclge_update_stats_for_all() and
+        * hclge_mac_get_traffic_stats() can do it.
+        */
        if (hdev->hw_stats.stats_timer >= HCLGE_STATS_TIMER_INTERVAL) {
                hclge_update_stats_for_all(hdev);
                hdev->hw_stats.stats_timer = 0;
+       } else {
+               hclge_mac_get_traffic_stats(hdev);
        }
 
        hclge_update_speed_duplex(hdev);
        hclge_update_link_status(hdev);
+       hclge_update_led_status(hdev);
        hclge_service_complete(hdev);
 }
 
@@ -5888,6 +5928,75 @@ static int hclge_set_led_id(struct hnae3_handle *handle,
        return ret;
 }
 
+enum hclge_led_port_speed {
+       HCLGE_SPEED_LED_FOR_1G,
+       HCLGE_SPEED_LED_FOR_10G,
+       HCLGE_SPEED_LED_FOR_25G,
+       HCLGE_SPEED_LED_FOR_40G,
+       HCLGE_SPEED_LED_FOR_50G,
+       HCLGE_SPEED_LED_FOR_100G,
+};
+
+static u8 hclge_led_get_speed_status(u32 speed)
+{
+       u8 speed_led;
+
+       switch (speed) {
+       case HCLGE_MAC_SPEED_1G:
+               speed_led = HCLGE_SPEED_LED_FOR_1G;
+               break;
+       case HCLGE_MAC_SPEED_10G:
+               speed_led = HCLGE_SPEED_LED_FOR_10G;
+               break;
+       case HCLGE_MAC_SPEED_25G:
+               speed_led = HCLGE_SPEED_LED_FOR_25G;
+               break;
+       case HCLGE_MAC_SPEED_40G:
+               speed_led = HCLGE_SPEED_LED_FOR_40G;
+               break;
+       case HCLGE_MAC_SPEED_50G:
+               speed_led = HCLGE_SPEED_LED_FOR_50G;
+               break;
+       case HCLGE_MAC_SPEED_100G:
+               speed_led = HCLGE_SPEED_LED_FOR_100G;
+               break;
+       default:
+               speed_led = HCLGE_LED_NO_CHANGE;
+       }
+
+       return speed_led;
+}
+
+static int hclge_update_led_status(struct hclge_dev *hdev)
+{
+       u8 port_speed_status, link_status, activity_status;
+       u64 rx_pkts, tx_pkts;
+
+       if (hdev->hw.mac.media_type != HNAE3_MEDIA_TYPE_FIBER)
+               return 0;
+
+       port_speed_status = hclge_led_get_speed_status(hdev->hw.mac.speed);
+
+       rx_pkts = hdev->hw_stats.mac_stats.mac_rx_total_pkt_num;
+       tx_pkts = hdev->hw_stats.mac_stats.mac_tx_total_pkt_num;
+       if (rx_pkts != hdev->rx_pkts_for_led ||
+           tx_pkts != hdev->tx_pkts_for_led)
+               activity_status = HCLGE_LED_ON;
+       else
+               activity_status = HCLGE_LED_OFF;
+       hdev->rx_pkts_for_led = rx_pkts;
+       hdev->tx_pkts_for_led = tx_pkts;
+
+       if (hdev->hw.mac.link)
+               link_status = HCLGE_LED_ON;
+       else
+               link_status = HCLGE_LED_OFF;
+
+       return hclge_set_led_status_sfp(hdev, port_speed_status,
+                                       activity_status, link_status,
+                                       HCLGE_LED_NO_CHANGE);
+}
+
 static const struct hnae3_ae_ops hclge_ops = {
        .init_ae_dev = hclge_init_ae_dev,
        .uninit_ae_dev = hclge_uninit_ae_dev,
index eeb6c8d66e4e67b35babe031d7e54394b24a0968..d99a76a9557cdfb90cdf988546389477e1374a48 100644 (file)
@@ -550,6 +550,9 @@ struct hclge_dev {
        bool accept_mta_mc; /* Whether accept mta filter multicast */
 
        struct hclge_vlan_type_cfg vlan_type_cfg;
+
+       u64 rx_pkts_for_led;
+       u64 tx_pkts_for_led;
 };
 
 /* VPort level vlan tag configuration for TX direction */