169 lines
5.7 KiB
Diff
169 lines
5.7 KiB
Diff
From 42e18be60daee3fa262b80bf8dff791862fb1137 Mon Sep 17 00:00:00 2001
|
|
From: Guangbin Huang <huangguangbin2@huawei.com>
|
|
Date: Sat, 24 Jul 2021 15:43:50 +0800
|
|
Subject: [PATCH 058/283] net: hns3: add ioctl support for imp-controlled PHYs
|
|
|
|
mainline inclusion
|
|
from mainline-v5.13-rc1
|
|
commit 024712f51e5711d69ced729fb3398819ed6e8b53
|
|
category: feature
|
|
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I8EMQV
|
|
CVE: NA
|
|
|
|
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=024712f51e5711d69ced729fb3398819ed6e8b53
|
|
|
|
----------------------------------------------------------------------
|
|
|
|
When the imp-controlled PHYs feature is enabled, driver will not
|
|
register mdio bus. In order to support ioctl ops for phy tool to
|
|
read or write phy register in this case, the firmware implement
|
|
a new command for driver and driver implement ioctl by using this
|
|
new command.
|
|
|
|
Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
|
|
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
Reviewed-by: Yongxin Li <liyongxin1@huawei.com>
|
|
Signed-off-by: Junxin Chen <chenjunxin1@huawei.com>
|
|
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com>
|
|
Signed-off-by: Xiaodong Li <lixiaodong67@huawei.com>
|
|
---
|
|
.../hisilicon/hns3/hns3pf/hclge_cmd.h | 8 ++++
|
|
.../hisilicon/hns3/hns3pf/hclge_main.c | 26 ++++++++++++-
|
|
.../hisilicon/hns3/hns3pf/hclge_mdio.c | 39 +++++++++++++++++++
|
|
.../hisilicon/hns3/hns3pf/hclge_mdio.h | 2 +
|
|
4 files changed, 74 insertions(+), 1 deletion(-)
|
|
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
|
|
index 2922cd1bc859..88aefd3685a7 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
|
|
@@ -311,6 +311,7 @@ enum hclge_opcode_type {
|
|
|
|
/* PHY command */
|
|
HCLGE_OPC_PHY_LINK_KSETTING = 0x7025,
|
|
+ HCLGE_OPC_PHY_REG = 0x7026,
|
|
};
|
|
|
|
#define HCLGE_TQP_REG_OFFSET 0x80000
|
|
@@ -1175,6 +1176,13 @@ struct hclge_phy_link_ksetting_1_cmd {
|
|
u8 rsv[22];
|
|
};
|
|
|
|
+struct hclge_phy_reg_cmd {
|
|
+ __le16 reg_addr;
|
|
+ u8 rsv0[2];
|
|
+ __le16 reg_val;
|
|
+ u8 rsv1[18];
|
|
+};
|
|
+
|
|
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 c73348bc7706..abd79d4bc56d 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
|
|
@@ -8457,6 +8457,30 @@ static int hclge_set_mac_addr(struct hnae3_handle *handle, void *p,
|
|
return 0;
|
|
}
|
|
|
|
+static int hclge_mii_ioctl(struct hclge_dev *hdev, struct ifreq *ifr, int cmd)
|
|
+{
|
|
+ struct mii_ioctl_data *data = if_mii(ifr);
|
|
+
|
|
+ if (!hnae3_dev_phy_imp_supported(hdev))
|
|
+ return -EOPNOTSUPP;
|
|
+
|
|
+ switch (cmd) {
|
|
+ case SIOCGMIIPHY:
|
|
+ data->phy_id = hdev->hw.mac.phy_addr;
|
|
+ data->val_out = hclge_read_phy_reg(hdev, data->reg_num);
|
|
+ return 0;
|
|
+ /* this command reads phy id and register at the same time */
|
|
+ case SIOCGMIIREG:
|
|
+ data->val_out = hclge_read_phy_reg(hdev, data->reg_num);
|
|
+ return 0;
|
|
+
|
|
+ case SIOCSMIIREG:
|
|
+ return hclge_write_phy_reg(hdev, data->reg_num, data->val_in);
|
|
+ default:
|
|
+ return -EOPNOTSUPP;
|
|
+ }
|
|
+}
|
|
+
|
|
static int hclge_do_ioctl(struct hnae3_handle *handle, struct ifreq *ifr,
|
|
int cmd)
|
|
{
|
|
@@ -8464,7 +8488,7 @@ static int hclge_do_ioctl(struct hnae3_handle *handle, struct ifreq *ifr,
|
|
struct hclge_dev *hdev = vport->back;
|
|
|
|
if (!hdev->hw.mac.phydev)
|
|
- return -EOPNOTSUPP;
|
|
+ return hclge_mii_ioctl(hdev, ifr, cmd);
|
|
|
|
return phy_mii_ioctl(hdev->hw.mac.phydev, ifr, cmd);
|
|
}
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
|
|
index 3eea4870a56a..b9c81e2e60b2 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
|
|
@@ -293,3 +293,42 @@ void hclge_mac_stop_phy(struct hclge_dev *hdev)
|
|
|
|
phy_stop(phydev);
|
|
}
|
|
+
|
|
+u16 hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr)
|
|
+{
|
|
+ struct hclge_phy_reg_cmd *req;
|
|
+ struct hclge_desc desc;
|
|
+ int ret;
|
|
+
|
|
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PHY_REG, true);
|
|
+
|
|
+ req = (struct hclge_phy_reg_cmd *)desc.data;
|
|
+ req->reg_addr = cpu_to_le16(reg_addr);
|
|
+
|
|
+ ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
|
+ if (ret)
|
|
+ dev_err(&hdev->pdev->dev,
|
|
+ "failed to read phy reg, ret = %d.\n", ret);
|
|
+
|
|
+ return le16_to_cpu(req->reg_val);
|
|
+}
|
|
+
|
|
+int hclge_write_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 val)
|
|
+{
|
|
+ struct hclge_phy_reg_cmd *req;
|
|
+ struct hclge_desc desc;
|
|
+ int ret;
|
|
+
|
|
+ hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_PHY_REG, false);
|
|
+
|
|
+ req = (struct hclge_phy_reg_cmd *)desc.data;
|
|
+ req->reg_addr = cpu_to_le16(reg_addr);
|
|
+ req->reg_val = cpu_to_le16(val);
|
|
+
|
|
+ ret = hclge_cmd_send(&hdev->hw, &desc, 1);
|
|
+ if (ret)
|
|
+ dev_err(&hdev->pdev->dev,
|
|
+ "failed to write phy reg, ret = %d.\n", ret);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
|
|
index ef095d9c566f..7e019be3816a 100644
|
|
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
|
|
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.h
|
|
@@ -9,5 +9,7 @@ int hclge_mac_connect_phy(struct hnae3_handle *handle);
|
|
void hclge_mac_disconnect_phy(struct hnae3_handle *handle);
|
|
void hclge_mac_start_phy(struct hclge_dev *hdev);
|
|
void hclge_mac_stop_phy(struct hclge_dev *hdev);
|
|
+u16 hclge_read_phy_reg(struct hclge_dev *hdev, u16 reg_addr);
|
|
+int hclge_write_phy_reg(struct hclge_dev *hdev, u16 reg_addr, u16 val);
|
|
|
|
#endif
|
|
--
|
|
2.34.1
|
|
|