Commit 4849d9be authored by David S. Miller's avatar David S. Miller

Merge branch 'hns3-imp-phys'

Huazhong Tan says:

====================
net: hns3: support imp-controlled PHYs

This series adds support for imp-controlled PHYs in the HNS3
ethernet driver.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5ab6f96a b47cfe1f
...@@ -653,6 +653,10 @@ struct hnae3_ae_ops { ...@@ -653,6 +653,10 @@ struct hnae3_ae_ops {
int (*del_cls_flower)(struct hnae3_handle *handle, int (*del_cls_flower)(struct hnae3_handle *handle,
struct flow_cls_offload *cls_flower); struct flow_cls_offload *cls_flower);
bool (*cls_flower_active)(struct hnae3_handle *handle); bool (*cls_flower_active)(struct hnae3_handle *handle);
int (*get_phy_link_ksettings)(struct hnae3_handle *handle,
struct ethtool_link_ksettings *cmd);
int (*set_phy_link_ksettings)(struct hnae3_handle *handle,
const struct ethtool_link_ksettings *cmd);
}; };
struct hnae3_dcb_ops { struct hnae3_dcb_ops {
......
...@@ -365,6 +365,8 @@ static void hns3_dbg_dev_caps(struct hnae3_handle *h) ...@@ -365,6 +365,8 @@ static void hns3_dbg_dev_caps(struct hnae3_handle *h)
dev_info(&h->pdev->dev, "support PAUSE: %s\n", dev_info(&h->pdev->dev, "support PAUSE: %s\n",
test_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps) ? test_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps) ?
"yes" : "no"); "yes" : "no");
dev_info(&h->pdev->dev, "support imp-controlled PHY: %s\n",
test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, caps) ? "yes" : "no");
} }
static void hns3_dbg_dev_specs(struct hnae3_handle *h) static void hns3_dbg_dev_specs(struct hnae3_handle *h)
......
...@@ -700,6 +700,7 @@ static int hns3_get_link_ksettings(struct net_device *netdev, ...@@ -700,6 +700,7 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
struct ethtool_link_ksettings *cmd) struct ethtool_link_ksettings *cmd)
{ {
struct hnae3_handle *h = hns3_get_handle(netdev); struct hnae3_handle *h = hns3_get_handle(netdev);
struct hnae3_ae_dev *ae_dev = pci_get_drvdata(h->pdev);
const struct hnae3_ae_ops *ops; const struct hnae3_ae_ops *ops;
u8 module_type; u8 module_type;
u8 media_type; u8 media_type;
...@@ -730,7 +731,10 @@ static int hns3_get_link_ksettings(struct net_device *netdev, ...@@ -730,7 +731,10 @@ static int hns3_get_link_ksettings(struct net_device *netdev,
break; break;
case HNAE3_MEDIA_TYPE_COPPER: case HNAE3_MEDIA_TYPE_COPPER:
cmd->base.port = PORT_TP; cmd->base.port = PORT_TP;
if (!netdev->phydev) if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) &&
ops->get_phy_link_ksettings)
ops->get_phy_link_ksettings(h, cmd);
else if (!netdev->phydev)
hns3_get_ksettings(h, cmd); hns3_get_ksettings(h, cmd);
else else
phy_ethtool_ksettings_get(netdev->phydev, cmd); phy_ethtool_ksettings_get(netdev->phydev, cmd);
...@@ -823,6 +827,9 @@ static int hns3_set_link_ksettings(struct net_device *netdev, ...@@ -823,6 +827,9 @@ static int hns3_set_link_ksettings(struct net_device *netdev,
return -EINVAL; return -EINVAL;
return phy_ethtool_ksettings_set(netdev->phydev, cmd); return phy_ethtool_ksettings_set(netdev->phydev, cmd);
} else if (test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps) &&
ops->set_phy_link_ksettings) {
return ops->set_phy_link_ksettings(handle, cmd);
} }
if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2) if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)
......
...@@ -385,6 +385,8 @@ static void hclge_parse_capability(struct hclge_dev *hdev, ...@@ -385,6 +385,8 @@ static void hclge_parse_capability(struct hclge_dev *hdev,
set_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps); set_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps);
if (hnae3_get_bit(caps, HCLGE_CAP_PAUSE_B)) if (hnae3_get_bit(caps, HCLGE_CAP_PAUSE_B))
set_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps); set_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps);
if (hnae3_get_bit(caps, HCLGE_CAP_PHY_IMP_B))
set_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, ae_dev->caps);
} }
static __le32 hclge_build_api_caps(void) static __le32 hclge_build_api_caps(void)
...@@ -474,6 +476,8 @@ static int hclge_firmware_compat_config(struct hclge_dev *hdev) ...@@ -474,6 +476,8 @@ static int hclge_firmware_compat_config(struct hclge_dev *hdev)
hnae3_set_bit(compat, HCLGE_LINK_EVENT_REPORT_EN_B, 1); hnae3_set_bit(compat, HCLGE_LINK_EVENT_REPORT_EN_B, 1);
hnae3_set_bit(compat, HCLGE_NCSI_ERROR_REPORT_EN_B, 1); hnae3_set_bit(compat, HCLGE_NCSI_ERROR_REPORT_EN_B, 1);
if (hnae3_dev_phy_imp_supported(hdev))
hnae3_set_bit(compat, HCLGE_PHY_IMP_EN_B, 1);
req->compat = cpu_to_le32(compat); req->compat = cpu_to_le32(compat);
return hclge_cmd_send(&hdev->hw, &desc, 1); return hclge_cmd_send(&hdev->hw, &desc, 1);
......
...@@ -127,7 +127,7 @@ enum hclge_opcode_type { ...@@ -127,7 +127,7 @@ enum hclge_opcode_type {
HCLGE_OPC_QUERY_MAC_TNL_INT = 0x0310, HCLGE_OPC_QUERY_MAC_TNL_INT = 0x0310,
HCLGE_OPC_MAC_TNL_INT_EN = 0x0311, HCLGE_OPC_MAC_TNL_INT_EN = 0x0311,
HCLGE_OPC_CLEAR_MAC_TNL_INT = 0x0312, HCLGE_OPC_CLEAR_MAC_TNL_INT = 0x0312,
HCLGE_OPC_SERDES_LOOPBACK = 0x0315, HCLGE_OPC_COMMON_LOOPBACK = 0x0315,
HCLGE_OPC_CONFIG_FEC_MODE = 0x031A, HCLGE_OPC_CONFIG_FEC_MODE = 0x031A,
/* PFC/Pause commands */ /* PFC/Pause commands */
...@@ -303,6 +303,10 @@ enum hclge_opcode_type { ...@@ -303,6 +303,10 @@ enum hclge_opcode_type {
HCLGE_PPP_CMD1_INT_CMD = 0x2101, HCLGE_PPP_CMD1_INT_CMD = 0x2101,
HCLGE_MAC_ETHERTYPE_IDX_RD = 0x2105, HCLGE_MAC_ETHERTYPE_IDX_RD = 0x2105,
HCLGE_NCSI_INT_EN = 0x2401, HCLGE_NCSI_INT_EN = 0x2401,
/* PHY command */
HCLGE_OPC_PHY_LINK_KSETTING = 0x7025,
HCLGE_OPC_PHY_REG = 0x7026,
}; };
#define HCLGE_TQP_REG_OFFSET 0x80000 #define HCLGE_TQP_REG_OFFSET 0x80000
...@@ -960,9 +964,10 @@ struct hclge_pf_rst_done_cmd { ...@@ -960,9 +964,10 @@ struct hclge_pf_rst_done_cmd {
#define HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B BIT(0) #define HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B BIT(0)
#define HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B BIT(2) #define HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B BIT(2)
#define HCLGE_CMD_SERDES_DONE_B BIT(0) #define HCLGE_CMD_GE_PHY_INNER_LOOP_B BIT(3)
#define HCLGE_CMD_SERDES_SUCCESS_B BIT(1) #define HCLGE_CMD_COMMON_LB_DONE_B BIT(0)
struct hclge_serdes_lb_cmd { #define HCLGE_CMD_COMMON_LB_SUCCESS_B BIT(1)
struct hclge_common_lb_cmd {
u8 mask; u8 mask;
u8 enable; u8 enable;
u8 result; u8 result;
...@@ -1098,6 +1103,7 @@ struct hclge_query_ppu_pf_other_int_dfx_cmd { ...@@ -1098,6 +1103,7 @@ struct hclge_query_ppu_pf_other_int_dfx_cmd {
#define HCLGE_LINK_EVENT_REPORT_EN_B 0 #define HCLGE_LINK_EVENT_REPORT_EN_B 0
#define HCLGE_NCSI_ERROR_REPORT_EN_B 1 #define HCLGE_NCSI_ERROR_REPORT_EN_B 1
#define HCLGE_PHY_IMP_EN_B 2
struct hclge_firmware_compat_cmd { struct hclge_firmware_compat_cmd {
__le32 compat; __le32 compat;
u8 rsv[20]; u8 rsv[20];
...@@ -1139,6 +1145,36 @@ struct hclge_dev_specs_1_cmd { ...@@ -1139,6 +1145,36 @@ struct hclge_dev_specs_1_cmd {
u8 rsv1[18]; u8 rsv1[18];
}; };
#define HCLGE_PHY_LINK_SETTING_BD_NUM 2
struct hclge_phy_link_ksetting_0_cmd {
__le32 speed;
u8 duplex;
u8 autoneg;
u8 eth_tp_mdix;
u8 eth_tp_mdix_ctrl;
u8 port;
u8 transceiver;
u8 phy_address;
u8 rsv;
__le32 supported;
__le32 advertising;
__le32 lp_advertising;
};
struct hclge_phy_link_ksetting_1_cmd {
u8 master_slave_cfg;
u8 master_slave_state;
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); int hclge_cmd_init(struct hclge_dev *hdev);
static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value) static inline void hclge_write_reg(void __iomem *base, u32 reg, u32 value)
{ {
......
...@@ -1546,13 +1546,13 @@ static void hclge_dbg_dump_loopback(struct hclge_dev *hdev, ...@@ -1546,13 +1546,13 @@ static void hclge_dbg_dump_loopback(struct hclge_dev *hdev,
{ {
struct phy_device *phydev = hdev->hw.mac.phydev; struct phy_device *phydev = hdev->hw.mac.phydev;
struct hclge_config_mac_mode_cmd *req_app; struct hclge_config_mac_mode_cmd *req_app;
struct hclge_serdes_lb_cmd *req_serdes; struct hclge_common_lb_cmd *req_common;
struct hclge_desc desc; struct hclge_desc desc;
u8 loopback_en; u8 loopback_en;
int ret; int ret;
req_app = (struct hclge_config_mac_mode_cmd *)desc.data; req_app = (struct hclge_config_mac_mode_cmd *)desc.data;
req_serdes = (struct hclge_serdes_lb_cmd *)desc.data; req_common = (struct hclge_common_lb_cmd *)desc.data;
dev_info(&hdev->pdev->dev, "mac id: %u\n", hdev->hw.mac.mac_id); dev_info(&hdev->pdev->dev, "mac id: %u\n", hdev->hw.mac.mac_id);
...@@ -1569,27 +1569,33 @@ static void hclge_dbg_dump_loopback(struct hclge_dev *hdev, ...@@ -1569,27 +1569,33 @@ static void hclge_dbg_dump_loopback(struct hclge_dev *hdev,
dev_info(&hdev->pdev->dev, "app loopback: %s\n", dev_info(&hdev->pdev->dev, "app loopback: %s\n",
loopback_en ? "on" : "off"); loopback_en ? "on" : "off");
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_SERDES_LOOPBACK, true); hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_COMMON_LOOPBACK, true);
ret = hclge_cmd_send(&hdev->hw, &desc, 1); ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) { if (ret) {
dev_err(&hdev->pdev->dev, dev_err(&hdev->pdev->dev,
"failed to dump serdes loopback status, ret = %d\n", "failed to dump common loopback status, ret = %d\n",
ret); ret);
return; return;
} }
loopback_en = req_serdes->enable & HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B; loopback_en = req_common->enable & HCLGE_CMD_SERDES_SERIAL_INNER_LOOP_B;
dev_info(&hdev->pdev->dev, "serdes serial loopback: %s\n", dev_info(&hdev->pdev->dev, "serdes serial loopback: %s\n",
loopback_en ? "on" : "off"); loopback_en ? "on" : "off");
loopback_en = req_serdes->enable & loopback_en = req_common->enable &
HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B; HCLGE_CMD_SERDES_PARALLEL_INNER_LOOP_B;
dev_info(&hdev->pdev->dev, "serdes parallel loopback: %s\n", dev_info(&hdev->pdev->dev, "serdes parallel loopback: %s\n",
loopback_en ? "on" : "off"); loopback_en ? "on" : "off");
if (phydev) if (phydev) {
dev_info(&hdev->pdev->dev, "phy loopback: %s\n", dev_info(&hdev->pdev->dev, "phy loopback: %s\n",
phydev->loopback_enabled ? "on" : "off"); phydev->loopback_enabled ? "on" : "off");
} else if (hnae3_dev_phy_imp_supported(hdev)) {
loopback_en = req_common->enable &
HCLGE_CMD_GE_PHY_INNER_LOOP_B;
dev_info(&hdev->pdev->dev, "phy loopback: %s\n",
loopback_en ? "on" : "off");
}
} }
/* hclge_dbg_dump_mac_tnl_status: print message about mac tnl interrupt /* hclge_dbg_dump_mac_tnl_status: print message about mac tnl interrupt
......
...@@ -268,3 +268,42 @@ void hclge_mac_stop_phy(struct hclge_dev *hdev) ...@@ -268,3 +268,42 @@ void hclge_mac_stop_phy(struct hclge_dev *hdev)
phy_stop(phydev); 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;
}
...@@ -9,5 +9,7 @@ int hclge_mac_connect_phy(struct hnae3_handle *handle); ...@@ -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_disconnect_phy(struct hnae3_handle *handle);
void hclge_mac_start_phy(struct hclge_dev *hdev); void hclge_mac_start_phy(struct hclge_dev *hdev);
void hclge_mac_stop_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 #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment