2018-01-18 06:47:45

by Lipeng

[permalink] [raw]
Subject: [PATCH net-next 0/5] add some features to hns3 driver

This patchset adds some features to hns3 driver, include the support
for ethtool command -d, -p and support for manager table.

[Patch 1/5] adds support for ethtool command -d, its ops is get_regs.
driver will send command to command queue, and get regs number and
regs value from command queue.
[Patch 2/5] adds manager table initialization for hardware.
[Patch 3/5 - 4/5] add support for ethtool command -p. Phy will control
leds for copper ports. For fiber ports, driver sends command to
command queue, and IMP will write SGPIO regs to control leds.
[Patch 4/5] adds support for net status led for fiber ports. Net status
include port speed, total rx/tx packets and link status. Driver send
the status to command queue, and IMP will write SGPIO to control leds.

Fuyun Liang (2):
net: hns3: add support for get_regs
net: hns3: add manager table initialization for hardware

Jian Shen (3):
net: hns3: add ethtool -p support for phy device
net: hns3: add ethtool -p support for fiber port
net: hns3: add net status led support for fiber port

drivers/net/ethernet/hisilicon/hns3/hnae3.h | 5 +-
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 35 ++
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 47 ++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 533 +++++++++++++++++++++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 14 +
5 files changed, 633 insertions(+), 1 deletion(-)

--
2.9.3



2018-01-18 06:45:51

by Lipeng

[permalink] [raw]
Subject: [PATCH net-next 4/5] net: hns3: add ethtool -p support for fiber port

From: Jian Shen <[email protected]>

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

Signed-off-by: Jian Shen <[email protected]>
Signed-off-by: Peng Li <[email protected]>
---
.../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


2018-01-18 06:46:08

by Lipeng

[permalink] [raw]
Subject: [PATCH net-next 3/5] net: hns3: add ethtool -p support for phy device

From: Jian Shen <[email protected]>

Add led location support for phy device. The led will keep blinking
with frequency 2HZ when locating.

Signed-off-by: Jian Shen <[email protected]>
Signed-off-by: Peng Li <[email protected]>
---
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 2 +
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 12 +++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 88 ++++++++++++++++++++++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 12 +++
4 files changed, 114 insertions(+)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index d104ce5..fd06bc7 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -405,6 +405,8 @@ struct hnae3_ae_ops {
int (*set_channels)(struct hnae3_handle *handle, u32 new_tqps_num);
void (*get_flowctrl_adv)(struct hnae3_handle *handle,
u32 *flowctrl_adv);
+ int (*set_led_id)(struct hnae3_handle *handle,
+ enum ethtool_phys_id_state status);
};

struct hnae3_dcb_ops {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index 1c8b293..7410205 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -1084,6 +1084,17 @@ static void hns3_get_regs(struct net_device *netdev,
h->ae_algo->ops->get_regs(h, &cmd->version, data);
}

+static int hns3_set_phys_id(struct net_device *netdev,
+ enum ethtool_phys_id_state state)
+{
+ struct hnae3_handle *h = hns3_get_handle(netdev);
+
+ if (!h->ae_algo || !h->ae_algo->ops || !h->ae_algo->ops->set_led_id)
+ return -EOPNOTSUPP;
+
+ return h->ae_algo->ops->set_led_id(h, state);
+}
+
static const struct ethtool_ops hns3vf_ethtool_ops = {
.get_drvinfo = hns3_get_drvinfo,
.get_ringparam = hns3_get_ringparam,
@@ -1126,6 +1137,7 @@ static const struct ethtool_ops hns3_ethtool_ops = {
.set_coalesce = hns3_set_coalesce,
.get_regs_len = hns3_get_regs_len,
.get_regs = hns3_get_regs,
+ .set_phys_id = hns3_set_phys_id,
};

void hns3_ethtool_set_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 6e64bed..73caf06 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -5819,6 +5819,93 @@ 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_phy(struct phy_device *phydev, int value)
+{
+ int ret, cur_page;
+
+ mutex_lock(&phydev->lock);
+
+ ret = phy_read(phydev, HCLGE_PHY_PAGE_REG);
+ if (ret < 0)
+ goto out;
+ else
+ cur_page = ret;
+
+ ret = phy_write(phydev, HCLGE_PHY_PAGE_REG, HCLGE_PHY_PAGE_LED);
+ if (ret)
+ goto out;
+
+ ret = phy_write(phydev, HCLGE_LED_FC_REG, value);
+ if (ret)
+ goto out;
+
+ ret = phy_write(phydev, HCLGE_PHY_PAGE_REG, cur_page);
+
+out:
+ mutex_unlock(&phydev->lock);
+ return ret;
+}
+
+static int hclge_get_led_status_phy(struct phy_device *phydev, int *value)
+{
+ int ret, cur_page;
+
+ mutex_lock(&phydev->lock);
+
+ ret = phy_read(phydev, HCLGE_PHY_PAGE_REG);
+ if (ret < 0)
+ goto out;
+ else
+ cur_page = ret;
+
+ ret = phy_write(phydev, HCLGE_PHY_PAGE_REG, HCLGE_PHY_PAGE_LED);
+ if (ret)
+ goto out;
+
+ *value = phy_read(phydev, HCLGE_LED_FC_REG);
+
+ ret = phy_write(phydev, HCLGE_PHY_PAGE_REG, cur_page);
+
+out:
+ mutex_unlock(&phydev->lock);
+ return ret;
+}
+
+static int hclge_set_led_id(struct hnae3_handle *handle,
+ enum ethtool_phys_id_state status)
+{
+#define BLINK_FREQUENCY 2
+ struct hclge_vport *vport = hclge_get_vport(handle);
+ struct hclge_dev *hdev = vport->back;
+ 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;
+ }
+
+ return ret;
+}
+
static const struct hnae3_ae_ops hclge_ops = {
.init_ae_dev = hclge_init_ae_dev,
.uninit_ae_dev = hclge_uninit_ae_dev,
@@ -5872,6 +5959,7 @@ static const struct hnae3_ae_ops hclge_ops = {
.get_flowctrl_adv = hclge_get_flowctrl_adv,
.get_regs_len = hclge_get_regs_len,
.get_regs = hclge_get_regs,
+ .set_led_id = hclge_set_led_id,
};

static struct hnae3_ae_algo ae_algo = {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index eeb6c8d..9969d3c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -63,6 +63,7 @@

#define HCLGE_PHY_PAGE_MDIX 0
#define HCLGE_PHY_PAGE_COPPER 0
+#define HCLGE_PHY_PAGE_LED 3

/* Page Selection Reg. */
#define HCLGE_PHY_PAGE_REG 22
@@ -73,6 +74,15 @@
/* Copper Specific Status Register */
#define HCLGE_PHY_CSS_REG 17

+/* LED Function Control Register */
+#define HCLGE_LED_FC_REG 16
+
+/* LED Polarity Control Register */
+#define HCLGE_LED_PC_REG 17
+
+#define HCLGE_LED_FORCE_ON 9
+#define HCLGE_LED_FORCE_OFF 8
+
#define HCLGE_PHY_MDIX_CTRL_S (5)
#define HCLGE_PHY_MDIX_CTRL_M GENMASK(6, 5)

@@ -550,6 +560,8 @@ struct hclge_dev {
bool accept_mta_mc; /* Whether accept mta filter multicast */

struct hclge_vlan_type_cfg vlan_type_cfg;
+
+ int phy_led_val;
};

/* VPort level vlan tag configuration for TX direction */
--
2.9.3


2018-01-18 06:46:40

by Lipeng

[permalink] [raw]
Subject: [PATCH net-next 2/5] net: hns3: add manager table initialization for hardware

From: Fuyun Liang <[email protected]>

The manager table is empty by default. If it is not initialized, the
management pkgs like LLDP will be dropped by hardware. Default entries
need to be added to manager table.

Signed-off-by: Fuyun Liang <[email protected]>
Signed-off-by: Peng Li <[email protected]>
---
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 22 +++++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 101 +++++++++++++++++++++
2 files changed, 123 insertions(+)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index 2561e7a..1cd28e0 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -605,6 +605,28 @@ struct hclge_mac_vlan_mask_entry_cmd {
u8 rsv2[14];
};

+#define HCLGE_MAC_MGR_MASK_VLAN_B BIT(0)
+#define HCLGE_MAC_MGR_MASK_MAC_B BIT(1)
+#define HCLGE_MAC_MGR_MASK_ETHERTYPE_B BIT(2)
+#define HCLGE_MAC_ETHERTYPE_LLDP 0x88cc
+
+struct hclge_mac_mgr_tbl_entry_cmd {
+ u8 flags;
+ u8 resp_code;
+ __le16 vlan_tag;
+ __le32 mac_addr_hi32;
+ __le16 mac_addr_lo16;
+ __le16 rsv1;
+ __le16 ethter_type;
+ __le16 egress_port;
+ __le16 egress_queue;
+ u8 sw_port_id_aware;
+ u8 rsv2;
+ u8 i_port_bitmap;
+ u8 i_port_direction;
+ u8 rsv3[2];
+};
+
#define HCLGE_CFG_MTA_MAC_SEL_S 0x0
#define HCLGE_CFG_MTA_MAC_SEL_M GENMASK(1, 0)
#define HCLGE_CFG_MTA_MAC_EN_B 0x7
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index c3d2cca..6e64bed 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -392,6 +392,16 @@ static const struct hclge_comm_stats_str g_mac_stats_string[] = {
HCLGE_MAC_STATS_FIELD_OFF(mac_rx_send_app_bad_pkt_num)}
};

+static const struct hclge_mac_mgr_tbl_entry_cmd hclge_mgr_table[] = {
+ {
+ .flags = HCLGE_MAC_MGR_MASK_VLAN_B,
+ .ethter_type = cpu_to_le16(HCLGE_MAC_ETHERTYPE_LLDP),
+ .mac_addr_hi32 = cpu_to_le32(htonl(0x0180C200)),
+ .mac_addr_lo16 = cpu_to_le16(htons(0x000E)),
+ .i_port_bitmap = 0x1,
+ },
+};
+
static int hclge_64_bit_update_stats(struct hclge_dev *hdev)
{
#define HCLGE_64_BIT_CMD_NUM 5
@@ -4249,6 +4259,91 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport,
return status;
}

+static int hclge_get_mac_ethertype_cmd_status(struct hclge_dev *hdev,
+ u16 cmdq_resp, u8 resp_code)
+{
+#define HCLGE_ETHERTYPE_SUCCESS_ADD 0
+#define HCLGE_ETHERTYPE_ALREADY_ADD 1
+#define HCLGE_ETHERTYPE_MGR_TBL_OVERFLOW 2
+#define HCLGE_ETHERTYPE_KEY_CONFLICT 3
+
+ int return_status;
+
+ if (cmdq_resp) {
+ dev_err(&hdev->pdev->dev,
+ "cmdq execute failed for get_mac_ethertype_cmd_status, status=%d.\n",
+ cmdq_resp);
+ return -EIO;
+ }
+
+ switch (resp_code) {
+ case HCLGE_ETHERTYPE_SUCCESS_ADD:
+ case HCLGE_ETHERTYPE_ALREADY_ADD:
+ return_status = 0;
+ break;
+ case HCLGE_ETHERTYPE_MGR_TBL_OVERFLOW:
+ dev_err(&hdev->pdev->dev,
+ "add mac ethertype failed for manager table overflow.\n");
+ return_status = -EIO;
+ break;
+ case HCLGE_ETHERTYPE_KEY_CONFLICT:
+ dev_err(&hdev->pdev->dev,
+ "add mac ethertype failed for key conflict.\n");
+ return_status = -EIO;
+ break;
+ default:
+ dev_err(&hdev->pdev->dev,
+ "add mac ethertype failed for undefined, code=%d.\n",
+ resp_code);
+ return_status = -EIO;
+ }
+
+ return return_status;
+}
+
+static int hclge_add_mgr_tbl(struct hclge_dev *hdev,
+ const struct hclge_mac_mgr_tbl_entry_cmd *req)
+{
+ struct hclge_desc desc;
+ u8 resp_code;
+ u16 retval;
+ int ret;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_MAC_ETHTYPE_ADD, false);
+ memcpy(desc.data, req, sizeof(struct hclge_mac_mgr_tbl_entry_cmd));
+
+ ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "add mac ethertype failed for cmd_send, ret =%d.\n",
+ ret);
+ return ret;
+ }
+
+ resp_code = (le32_to_cpu(desc.data[0]) >> 8) & 0xff;
+ retval = le16_to_cpu(desc.retval);
+
+ return hclge_get_mac_ethertype_cmd_status(hdev, retval, resp_code);
+}
+
+static int init_mgr_tbl(struct hclge_dev *hdev)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(hclge_mgr_table); i++) {
+ ret = hclge_add_mgr_tbl(hdev, &hclge_mgr_table[i]);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "add mac ethertype failed, ret =%d.\n",
+ ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static void hclge_get_mac_addr(struct hnae3_handle *handle, u8 *p)
{
struct hclge_vport *vport = hclge_get_vport(handle);
@@ -5271,6 +5366,12 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
return ret;
}

+ ret = init_mgr_tbl(hdev);
+ if (ret) {
+ dev_err(&pdev->dev, "manager table init fail, ret =%d\n", ret);
+ return ret;
+ }
+
hclge_dcb_ops_set(hdev);

timer_setup(&hdev->service_timer, hclge_service_timer, 0);
--
2.9.3


2018-01-18 06:47:02

by Lipeng

[permalink] [raw]
Subject: [PATCH net-next 1/5] net: hns3: add support for get_regs

From: Fuyun Liang <[email protected]>

This patch adds get_regs support for ethtool cmd.

Signed-off-by: Fuyun Liang <[email protected]>
Signed-off-by: Peng Li <[email protected]>
---
drivers/net/ethernet/hisilicon/hns3/hnae3.h | 3 +-
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c | 23 +++
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 4 +
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 176 +++++++++++++++++++++
4 files changed, 205 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index 634e932..d104ce5 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -356,7 +356,8 @@ struct hnae3_ae_ops {
u32 stringset, u8 *data);
int (*get_sset_count)(struct hnae3_handle *handle, int stringset);

- void (*get_regs)(struct hnae3_handle *handle, void *data);
+ void (*get_regs)(struct hnae3_handle *handle, u32 *version,
+ void *data);
int (*get_regs_len)(struct hnae3_handle *handle);

u32 (*get_rss_key_size)(struct hnae3_handle *handle);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
index 358f780..1c8b293 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
@@ -1063,6 +1063,27 @@ static int hns3_set_coalesce(struct net_device *netdev,
return 0;
}

+static int hns3_get_regs_len(struct net_device *netdev)
+{
+ struct hnae3_handle *h = hns3_get_handle(netdev);
+
+ if (!h->ae_algo->ops->get_regs_len)
+ return -EOPNOTSUPP;
+
+ return h->ae_algo->ops->get_regs_len(h);
+}
+
+static void hns3_get_regs(struct net_device *netdev,
+ struct ethtool_regs *cmd, void *data)
+{
+ struct hnae3_handle *h = hns3_get_handle(netdev);
+
+ if (!h->ae_algo->ops->get_regs)
+ return;
+
+ h->ae_algo->ops->get_regs(h, &cmd->version, data);
+}
+
static const struct ethtool_ops hns3vf_ethtool_ops = {
.get_drvinfo = hns3_get_drvinfo,
.get_ringparam = hns3_get_ringparam,
@@ -1103,6 +1124,8 @@ static const struct ethtool_ops hns3_ethtool_ops = {
.set_channels = hns3_set_channels,
.get_coalesce = hns3_get_coalesce,
.set_coalesce = hns3_set_coalesce,
+ .get_regs_len = hns3_get_regs_len,
+ .get_regs = hns3_get_regs,
};

void hns3_ethtool_set_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index 3c3159b..2561e7a 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -102,6 +102,10 @@ enum hclge_opcode_type {
HCLGE_OPC_STATS_64_BIT = 0x0030,
HCLGE_OPC_STATS_32_BIT = 0x0031,
HCLGE_OPC_STATS_MAC = 0x0032,
+
+ HCLGE_OPC_QUERY_REG_NUM = 0x0040,
+ HCLGE_OPC_QUERY_32_BIT_REG = 0x0041,
+ HCLGE_OPC_QUERY_64_BIT_REG = 0x0042,
/* Device management command */

/* MAC commond */
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 27f0ab6..c3d2cca 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -5544,6 +5544,180 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num)
return ret;
}

+static int hclge_get_regs_num(struct hclge_dev *hdev, u32 *regs_num_32_bit,
+ u32 *regs_num_64_bit)
+{
+ struct hclge_desc desc;
+ u32 total_num;
+ int ret;
+
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_REG_NUM, true);
+ ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Query register number cmd failed, ret = %d.\n", ret);
+ return ret;
+ }
+
+ *regs_num_32_bit = le32_to_cpu(desc.data[0]);
+ *regs_num_64_bit = le32_to_cpu(desc.data[1]);
+
+ total_num = *regs_num_32_bit + *regs_num_64_bit;
+ if (!total_num)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int hclge_get_32_bit_regs(struct hclge_dev *hdev, u32 regs_num,
+ void *data)
+{
+#define HCLGE_32_BIT_REG_RTN_DATANUM 8
+
+ struct hclge_desc *desc;
+ u32 *reg_val = data;
+ __le32 *desc_data;
+ int cmd_num;
+ int i, k, n;
+ int ret;
+
+ if (regs_num == 0)
+ return 0;
+
+ cmd_num = DIV_ROUND_UP(regs_num + 2, HCLGE_32_BIT_REG_RTN_DATANUM);
+ desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_32_BIT_REG, true);
+ ret = hclge_cmd_send(&hdev->hw, desc, cmd_num);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Query 32 bit register cmd failed, ret = %d.\n", ret);
+ kfree(desc);
+ return ret;
+ }
+
+ for (i = 0; i < cmd_num; i++) {
+ if (i == 0) {
+ desc_data = (__le32 *)(&desc[i].data[0]);
+ n = HCLGE_32_BIT_REG_RTN_DATANUM - 2;
+ } else {
+ desc_data = (__le32 *)(&desc[i]);
+ n = HCLGE_32_BIT_REG_RTN_DATANUM;
+ }
+ for (k = 0; k < n; k++) {
+ *reg_val++ = le32_to_cpu(*desc_data++);
+
+ regs_num--;
+ if (!regs_num)
+ break;
+ }
+ }
+
+ kfree(desc);
+ return 0;
+}
+
+static int hclge_get_64_bit_regs(struct hclge_dev *hdev, u32 regs_num,
+ void *data)
+{
+#define HCLGE_64_BIT_REG_RTN_DATANUM 4
+
+ struct hclge_desc *desc;
+ u64 *reg_val = data;
+ __le64 *desc_data;
+ int cmd_num;
+ int i, k, n;
+ int ret;
+
+ if (regs_num == 0)
+ return 0;
+
+ cmd_num = DIV_ROUND_UP(regs_num + 1, HCLGE_64_BIT_REG_RTN_DATANUM);
+ desc = kcalloc(cmd_num, sizeof(struct hclge_desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_QUERY_64_BIT_REG, true);
+ ret = hclge_cmd_send(&hdev->hw, desc, cmd_num);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Query 64 bit register cmd failed, ret = %d.\n", ret);
+ kfree(desc);
+ return ret;
+ }
+
+ for (i = 0; i < cmd_num; i++) {
+ if (i == 0) {
+ desc_data = (__le64 *)(&desc[i].data[0]);
+ n = HCLGE_64_BIT_REG_RTN_DATANUM - 1;
+ } else {
+ desc_data = (__le64 *)(&desc[i]);
+ n = HCLGE_64_BIT_REG_RTN_DATANUM;
+ }
+ for (k = 0; k < n; k++) {
+ *reg_val++ = le64_to_cpu(*desc_data++);
+
+ regs_num--;
+ if (!regs_num)
+ break;
+ }
+ }
+
+ kfree(desc);
+ return 0;
+}
+
+static int hclge_get_regs_len(struct hnae3_handle *handle)
+{
+ struct hclge_vport *vport = hclge_get_vport(handle);
+ struct hclge_dev *hdev = vport->back;
+ u32 regs_num_32_bit, regs_num_64_bit;
+ int ret;
+
+ ret = hclge_get_regs_num(hdev, &regs_num_32_bit, &regs_num_64_bit);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Get register number failed, ret = %d.\n", ret);
+ return -EOPNOTSUPP;
+ }
+
+ return regs_num_32_bit * sizeof(u32) + regs_num_64_bit * sizeof(u64);
+}
+
+static void hclge_get_regs(struct hnae3_handle *handle, u32 *version,
+ void *data)
+{
+ struct hclge_vport *vport = hclge_get_vport(handle);
+ struct hclge_dev *hdev = vport->back;
+ u32 regs_num_32_bit, regs_num_64_bit;
+ int ret;
+
+ *version = hdev->fw_version;
+
+ ret = hclge_get_regs_num(hdev, &regs_num_32_bit, &regs_num_64_bit);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Get register number failed, ret = %d.\n", ret);
+ return;
+ }
+
+ ret = hclge_get_32_bit_regs(hdev, regs_num_32_bit, data);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Get 32 bit register failed, ret = %d.\n", ret);
+ return;
+ }
+
+ data = (u32 *)data + regs_num_32_bit;
+ ret = hclge_get_64_bit_regs(hdev, regs_num_64_bit,
+ data);
+ if (ret)
+ dev_err(&hdev->pdev->dev,
+ "Get 64 bit register failed, ret = %d.\n", ret);
+}
+
static const struct hnae3_ae_ops hclge_ops = {
.init_ae_dev = hclge_init_ae_dev,
.uninit_ae_dev = hclge_uninit_ae_dev,
@@ -5595,6 +5769,8 @@ static const struct hnae3_ae_ops hclge_ops = {
.set_channels = hclge_set_channels,
.get_channels = hclge_get_channels,
.get_flowctrl_adv = hclge_get_flowctrl_adv,
+ .get_regs_len = hclge_get_regs_len,
+ .get_regs = hclge_get_regs,
};

static struct hnae3_ae_algo ae_algo = {
--
2.9.3


2018-01-18 06:48:06

by Lipeng

[permalink] [raw]
Subject: [PATCH net-next 5/5] net: hns3: add net status led support for fiber port

From: Jian Shen <[email protected]>

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 <[email protected]>
Signed-off-by: Peng Li <[email protected]>
---
.../net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 1 +
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 109 +++++++++++++++++++++
.../ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 2 +
3 files changed, 112 insertions(+)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index 122f862..3fd10a6 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -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*/
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 039c90b..f3d9332 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -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);
}

@@ -5965,6 +6005,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,
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index 9969d3c..171ac9d 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -562,6 +562,8 @@ struct hclge_dev {
struct hclge_vlan_type_cfg vlan_type_cfg;

int phy_led_val;
+ u64 rx_pkts_for_led;
+ u64 tx_pkts_for_led;
};

/* VPort level vlan tag configuration for TX direction */
--
2.9.3


2018-01-18 14:27:24

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH net-next 3/5] net: hns3: add ethtool -p support for phy device

> +static int hclge_set_led_status_phy(struct phy_device *phydev, int value)
> +{
> + int ret, cur_page;
> +
> + mutex_lock(&phydev->lock);
> +
> + ret = phy_read(phydev, HCLGE_PHY_PAGE_REG);
> + if (ret < 0)
> + goto out;
> + else
> + cur_page = ret;
> +
> + ret = phy_write(phydev, HCLGE_PHY_PAGE_REG, HCLGE_PHY_PAGE_LED);
> + if (ret)
> + goto out;
> +
> + ret = phy_write(phydev, HCLGE_LED_FC_REG, value);
> + if (ret)
> + goto out;
> +
> + ret = phy_write(phydev, HCLGE_PHY_PAGE_REG, cur_page);
> +
> +out:
> + mutex_unlock(&phydev->lock);
> + return ret;
> +}

Sorry, but NACK.

Please add an interface to phylib and the phy driver you are using to
do this.

> #define HCLGE_PHY_PAGE_MDIX 0
> #define HCLGE_PHY_PAGE_COPPER 0
> +#define HCLGE_PHY_PAGE_LED 3
>
> /* Page Selection Reg. */
> #define HCLGE_PHY_PAGE_REG 22
> @@ -73,6 +74,15 @@
> /* Copper Specific Status Register */
> #define HCLGE_PHY_CSS_REG 17
>
> +/* LED Function Control Register */
> +#define HCLGE_LED_FC_REG 16
> +
> +/* LED Polarity Control Register */
> +#define HCLGE_LED_PC_REG 17
> +
> +#define HCLGE_LED_FORCE_ON 9
> +#define HCLGE_LED_FORCE_OFF 8
> +

By the looks of these defines, you assume you have a Marvell PHY.
Please make this generic so anybody with a Marvell PHY can use it.

Andrew

2018-01-19 02:51:47

by Lipeng

[permalink] [raw]
Subject: Re: [PATCH net-next 3/5] net: hns3: add ethtool -p support for phy device



On 2018/1/18 22:25, Andrew Lunn wrote:
>> +static int hclge_set_led_status_phy(struct phy_device *phydev, int value)
>> +{
>> + int ret, cur_page;
>> +
>> + mutex_lock(&phydev->lock);
>> +
>> + ret = phy_read(phydev, HCLGE_PHY_PAGE_REG);
>> + if (ret < 0)
>> + goto out;
>> + else
>> + cur_page = ret;
>> +
>> + ret = phy_write(phydev, HCLGE_PHY_PAGE_REG, HCLGE_PHY_PAGE_LED);
>> + if (ret)
>> + goto out;
>> +
>> + ret = phy_write(phydev, HCLGE_LED_FC_REG, value);
>> + if (ret)
>> + goto out;
>> +
>> + ret = phy_write(phydev, HCLGE_PHY_PAGE_REG, cur_page);
>> +
>> +out:
>> + mutex_unlock(&phydev->lock);
>> + return ret;
>> +}
> Sorry, but NACK.
>
> Please add an interface to phylib and the phy driver you are using to
> do this.
>
>> #define HCLGE_PHY_PAGE_MDIX 0
>> #define HCLGE_PHY_PAGE_COPPER 0
>> +#define HCLGE_PHY_PAGE_LED 3
>>
>> /* Page Selection Reg. */
>> #define HCLGE_PHY_PAGE_REG 22
>> @@ -73,6 +74,15 @@
>> /* Copper Specific Status Register */
>> #define HCLGE_PHY_CSS_REG 17
>>
>> +/* LED Function Control Register */
>> +#define HCLGE_LED_FC_REG 16
>> +
>> +/* LED Polarity Control Register */
>> +#define HCLGE_LED_PC_REG 17
>> +
>> +#define HCLGE_LED_FORCE_ON 9
>> +#define HCLGE_LED_FORCE_OFF 8
>> +
> By the looks of these defines, you assume you have a Marvell PHY.
> Please make this generic so anybody with a Marvell PHY can use it.
>
> Andrew
Hi  Andrw,

As your suggestion, we need add  interface to  phylib and the phy driver.
We will consider your suggestion and push this patch after we fix your
comments.

so we will remove this patch  in V2 patch-set.

Thanks
Peng Li

> .
>