From: Jian Shen <shenjia...@huawei.com>

Add led location support for fiber port. The led will keep blinking
when locating.

Signed-off-by: Jian Shen <shenjia...@huawei.com>
Signed-off-by: Peng Li <lipeng...@huawei.com>
---
 .../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h |  20 ++++
 .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c    | 101 ++++++++++++++++-----
 2 files changed, 100 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h 
b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index 1cd28e0..122f862 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -227,6 +227,9 @@ enum hclge_opcode_type {
 
        /* Mailbox cmd */
        HCLGEVF_OPC_MBX_PF_TO_VF        = 0x2000,
+
+       /* Led command */
+       HCLGE_OPC_LED_STATUS_CFG        = 0xB000,
 };
 
 #define HCLGE_TQP_REG_OFFSET           0x80000
@@ -807,6 +810,23 @@ struct hclge_reset_cmd {
 #define HCLGE_NIC_CMQ_DESC_NUM         1024
 #define HCLGE_NIC_CMQ_DESC_NUM_S       3
 
+#define HCLGE_LED_PORT_SPEED_STATE_S   0
+#define HCLGE_LED_PORT_SPEED_STATE_M   GENMASK(5, 0)
+#define HCLGE_LED_ACTIVITY_STATE_S     0
+#define HCLGE_LED_ACTIVITY_STATE_M     GENMASK(1, 0)
+#define HCLGE_LED_LINK_STATE_S         0
+#define HCLGE_LED_LINK_STATE_M         GENMASK(1, 0)
+#define HCLGE_LED_LOCATE_STATE_S       0
+#define HCLGE_LED_LOCATE_STATE_M       GENMASK(1, 0)
+
+struct hclge_set_led_state_cmd {
+       u8 port_speed_led_config;
+       u8 link_led_config;
+       u8 activity_led_config;
+       u8 locate_led_config;
+       u8 rsv[20];
+};
+
 int hclge_cmd_init(struct hclge_dev *hdev);
 static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value)
 {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c 
b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 73caf06..039c90b 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -5819,6 +5819,34 @@ static void hclge_get_regs(struct hnae3_handle *handle, 
u32 *version,
                        "Get 64 bit register failed, ret = %d.\n", ret);
 }
 
+static int hclge_set_led_status_sfp(struct hclge_dev *hdev, u8 
speed_led_status,
+                                   u8 act_led_status, u8 link_led_status,
+                                   u8 locate_led_status)
+{
+       struct hclge_set_led_state_cmd *req;
+       struct hclge_desc desc;
+       int ret;
+
+       hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_LED_STATUS_CFG, false);
+
+       req = (struct hclge_set_led_state_cmd *)desc.data;
+       hnae_set_field(req->port_speed_led_config, HCLGE_LED_PORT_SPEED_STATE_M,
+                      HCLGE_LED_PORT_SPEED_STATE_S, speed_led_status);
+       hnae_set_field(req->link_led_config, HCLGE_LED_ACTIVITY_STATE_M,
+                      HCLGE_LED_ACTIVITY_STATE_S, act_led_status);
+       hnae_set_field(req->activity_led_config, HCLGE_LED_LINK_STATE_M,
+                      HCLGE_LED_LINK_STATE_S, link_led_status);
+       hnae_set_field(req->locate_led_config, HCLGE_LED_LOCATE_STATE_M,
+                      HCLGE_LED_LOCATE_STATE_S, locate_led_status);
+
+       ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+       if (ret)
+               dev_err(&hdev->pdev->dev,
+                       "Send set led state cmd error, ret =%d\n", ret);
+
+       return ret;
+}
+
 static int hclge_set_led_status_phy(struct phy_device *phydev, int value)
 {
        int ret, cur_page;
@@ -5871,6 +5899,12 @@ static int hclge_get_led_status_phy(struct phy_device 
*phydev, int *value)
        return ret;
 }
 
+enum hclge_led_status {
+       HCLGE_LED_OFF,
+       HCLGE_LED_ON,
+       HCLGE_LED_NO_CHANGE = 0xFF,
+};
+
 static int hclge_set_led_id(struct hnae3_handle *handle,
                            enum ethtool_phys_id_state status)
 {
@@ -5880,27 +5914,52 @@ static int hclge_set_led_id(struct hnae3_handle *handle,
        struct phy_device *phydev = hdev->hw.mac.phydev;
        int ret = 0;
 
-       if (!phydev)
-               return -EOPNOTSUPP;
-
-       switch (status) {
-       case ETHTOOL_ID_ACTIVE:
-               ret = hclge_get_led_status_phy(phydev, &hdev->phy_led_val);
-               if (ret)
-                       return ret;
-               return BLINK_FREQUENCY;
-       case ETHTOOL_ID_ON:
-               ret = hclge_set_led_status_phy(phydev, HCLGE_LED_FORCE_ON);
-               break;
-       case ETHTOOL_ID_OFF:
-               ret = hclge_set_led_status_phy(phydev, HCLGE_LED_FORCE_OFF);
-               break;
-       case ETHTOOL_ID_INACTIVE:
-               ret = hclge_set_led_status_phy(phydev, hdev->phy_led_val);
-               break;
-       default:
-               ret = -EINVAL;
-               break;
+       if (phydev) {
+               switch (status) {
+               case ETHTOOL_ID_ACTIVE:
+                       ret = hclge_get_led_status_phy(phydev,
+                                                      &hdev->phy_led_val);
+                       if (ret)
+                               return ret;
+                       return BLINK_FREQUENCY;
+               case ETHTOOL_ID_ON:
+                       ret = hclge_set_led_status_phy(phydev,
+                                                      HCLGE_LED_FORCE_ON);
+                       break;
+               case ETHTOOL_ID_OFF:
+                       ret = hclge_set_led_status_phy(phydev,
+                                                      HCLGE_LED_FORCE_OFF);
+                       break;
+               case ETHTOOL_ID_INACTIVE:
+                       ret = hclge_set_led_status_phy(phydev,
+                                                      hdev->phy_led_val);
+                       break;
+               default:
+                       ret = -EINVAL;
+                       break;
+               }
+       } else if (hdev->hw.mac.media_type == HNAE3_MEDIA_TYPE_FIBER) {
+               switch (status) {
+               case ETHTOOL_ID_ACTIVE:
+                       ret = hclge_set_led_status_sfp(hdev,
+                                                      HCLGE_LED_NO_CHANGE,
+                                                      HCLGE_LED_NO_CHANGE,
+                                                      HCLGE_LED_NO_CHANGE,
+                                                      HCLGE_LED_ON);
+                       break;
+               case ETHTOOL_ID_INACTIVE:
+                       ret = hclge_set_led_status_sfp(hdev,
+                                                      HCLGE_LED_NO_CHANGE,
+                                                      HCLGE_LED_NO_CHANGE,
+                                                      HCLGE_LED_NO_CHANGE,
+                                                      HCLGE_LED_OFF);
+                       break;
+               default:
+                       ret = -EINVAL;
+                       break;
+               }
+       } else {
+               ret = -EOPNOTSUPP;
        }
 
        return ret;
-- 
2.9.3

Reply via email to