Commit 5e6a024bebea5bad6b787cf2c0ee28116b4147f0
Committed by
David S. Miller
1 parent
32f784b50e
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
drivers: net: xgene: Add SGMII based 1GbE ethtool support
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com> Signed-off-by: Keyur Chudgar <kchudgar@apm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 17 additions and 8 deletions Inline Diff
drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
1 | /* Applied Micro X-Gene SoC Ethernet Driver | 1 | /* Applied Micro X-Gene SoC Ethernet Driver |
2 | * | 2 | * |
3 | * Copyright (c) 2014, Applied Micro Circuits Corporation | 3 | * Copyright (c) 2014, Applied Micro Circuits Corporation |
4 | * Authors: Iyappan Subramanian <isubramanian@apm.com> | 4 | * Authors: Iyappan Subramanian <isubramanian@apm.com> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 7 | * under the terms of the GNU General Public License as published by the |
8 | * Free Software Foundation; either version 2 of the License, or (at your | 8 | * Free Software Foundation; either version 2 of the License, or (at your |
9 | * option) any later version. | 9 | * option) any later version. |
10 | * | 10 | * |
11 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | * | 15 | * |
16 | * You should have received a copy of the GNU General Public License | 16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/ethtool.h> | 20 | #include <linux/ethtool.h> |
21 | #include "xgene_enet_main.h" | 21 | #include "xgene_enet_main.h" |
22 | 22 | ||
23 | struct xgene_gstrings_stats { | 23 | struct xgene_gstrings_stats { |
24 | char name[ETH_GSTRING_LEN]; | 24 | char name[ETH_GSTRING_LEN]; |
25 | int offset; | 25 | int offset; |
26 | }; | 26 | }; |
27 | 27 | ||
28 | #define XGENE_STAT(m) { #m, offsetof(struct xgene_enet_pdata, stats.m) } | 28 | #define XGENE_STAT(m) { #m, offsetof(struct xgene_enet_pdata, stats.m) } |
29 | 29 | ||
30 | static const struct xgene_gstrings_stats gstrings_stats[] = { | 30 | static const struct xgene_gstrings_stats gstrings_stats[] = { |
31 | XGENE_STAT(rx_packets), | 31 | XGENE_STAT(rx_packets), |
32 | XGENE_STAT(tx_packets), | 32 | XGENE_STAT(tx_packets), |
33 | XGENE_STAT(rx_bytes), | 33 | XGENE_STAT(rx_bytes), |
34 | XGENE_STAT(tx_bytes), | 34 | XGENE_STAT(tx_bytes), |
35 | XGENE_STAT(rx_errors), | 35 | XGENE_STAT(rx_errors), |
36 | XGENE_STAT(tx_errors), | 36 | XGENE_STAT(tx_errors), |
37 | XGENE_STAT(rx_length_errors), | 37 | XGENE_STAT(rx_length_errors), |
38 | XGENE_STAT(rx_crc_errors), | 38 | XGENE_STAT(rx_crc_errors), |
39 | XGENE_STAT(rx_frame_errors), | 39 | XGENE_STAT(rx_frame_errors), |
40 | XGENE_STAT(rx_fifo_errors) | 40 | XGENE_STAT(rx_fifo_errors) |
41 | }; | 41 | }; |
42 | 42 | ||
43 | #define XGENE_STATS_LEN ARRAY_SIZE(gstrings_stats) | 43 | #define XGENE_STATS_LEN ARRAY_SIZE(gstrings_stats) |
44 | 44 | ||
45 | static void xgene_get_drvinfo(struct net_device *ndev, | 45 | static void xgene_get_drvinfo(struct net_device *ndev, |
46 | struct ethtool_drvinfo *info) | 46 | struct ethtool_drvinfo *info) |
47 | { | 47 | { |
48 | struct xgene_enet_pdata *pdata = netdev_priv(ndev); | 48 | struct xgene_enet_pdata *pdata = netdev_priv(ndev); |
49 | struct platform_device *pdev = pdata->pdev; | 49 | struct platform_device *pdev = pdata->pdev; |
50 | 50 | ||
51 | strcpy(info->driver, "xgene_enet"); | 51 | strcpy(info->driver, "xgene_enet"); |
52 | strcpy(info->version, XGENE_DRV_VERSION); | 52 | strcpy(info->version, XGENE_DRV_VERSION); |
53 | snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A"); | 53 | snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A"); |
54 | sprintf(info->bus_info, "%s", pdev->name); | 54 | sprintf(info->bus_info, "%s", pdev->name); |
55 | } | 55 | } |
56 | 56 | ||
57 | static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) | 57 | static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) |
58 | { | 58 | { |
59 | struct xgene_enet_pdata *pdata = netdev_priv(ndev); | 59 | struct xgene_enet_pdata *pdata = netdev_priv(ndev); |
60 | struct phy_device *phydev = pdata->phy_dev; | 60 | struct phy_device *phydev = pdata->phy_dev; |
61 | 61 | ||
62 | if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) { | 62 | if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) { |
63 | if (phydev == NULL) | 63 | if (phydev == NULL) |
64 | return -ENODEV; | 64 | return -ENODEV; |
65 | 65 | ||
66 | return phy_ethtool_gset(phydev, cmd); | 66 | return phy_ethtool_gset(phydev, cmd); |
67 | } else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) { | ||
68 | cmd->supported = SUPPORTED_1000baseT_Full | | ||
69 | SUPPORTED_Autoneg | SUPPORTED_MII; | ||
70 | cmd->advertising = cmd->supported; | ||
71 | ethtool_cmd_speed_set(cmd, SPEED_1000); | ||
72 | cmd->duplex = DUPLEX_FULL; | ||
73 | cmd->port = PORT_MII; | ||
74 | cmd->transceiver = XCVR_INTERNAL; | ||
75 | cmd->autoneg = AUTONEG_ENABLE; | ||
76 | } else { | ||
77 | cmd->supported = SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE; | ||
78 | cmd->advertising = cmd->supported; | ||
79 | ethtool_cmd_speed_set(cmd, SPEED_10000); | ||
80 | cmd->duplex = DUPLEX_FULL; | ||
81 | cmd->port = PORT_FIBRE; | ||
82 | cmd->transceiver = XCVR_INTERNAL; | ||
83 | cmd->autoneg = AUTONEG_DISABLE; | ||
67 | } | 84 | } |
68 | |||
69 | cmd->supported = SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE; | ||
70 | cmd->advertising = cmd->supported; | ||
71 | ethtool_cmd_speed_set(cmd, SPEED_10000); | ||
72 | cmd->duplex = DUPLEX_FULL; | ||
73 | cmd->port = PORT_FIBRE; | ||
74 | cmd->transceiver = XCVR_EXTERNAL; | ||
75 | cmd->autoneg = AUTONEG_DISABLE; | ||
76 | 85 | ||
77 | return 0; | 86 | return 0; |
78 | } | 87 | } |
79 | 88 | ||
80 | static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) | 89 | static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) |
81 | { | 90 | { |
82 | struct xgene_enet_pdata *pdata = netdev_priv(ndev); | 91 | struct xgene_enet_pdata *pdata = netdev_priv(ndev); |
83 | struct phy_device *phydev = pdata->phy_dev; | 92 | struct phy_device *phydev = pdata->phy_dev; |
84 | 93 | ||
85 | if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) { | 94 | if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) { |
86 | if (phydev == NULL) | 95 | if (phydev == NULL) |
87 | return -ENODEV; | 96 | return -ENODEV; |
88 | 97 | ||
89 | return phy_ethtool_sset(phydev, cmd); | 98 | return phy_ethtool_sset(phydev, cmd); |
90 | } | 99 | } |
91 | 100 | ||
92 | return -EINVAL; | 101 | return -EINVAL; |
93 | } | 102 | } |
94 | 103 | ||
95 | static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data) | 104 | static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data) |
96 | { | 105 | { |
97 | int i; | 106 | int i; |
98 | u8 *p = data; | 107 | u8 *p = data; |
99 | 108 | ||
100 | if (stringset != ETH_SS_STATS) | 109 | if (stringset != ETH_SS_STATS) |
101 | return; | 110 | return; |
102 | 111 | ||
103 | for (i = 0; i < XGENE_STATS_LEN; i++) { | 112 | for (i = 0; i < XGENE_STATS_LEN; i++) { |
104 | memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN); | 113 | memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN); |
105 | p += ETH_GSTRING_LEN; | 114 | p += ETH_GSTRING_LEN; |
106 | } | 115 | } |
107 | } | 116 | } |
108 | 117 | ||
109 | static int xgene_get_sset_count(struct net_device *ndev, int sset) | 118 | static int xgene_get_sset_count(struct net_device *ndev, int sset) |
110 | { | 119 | { |
111 | if (sset != ETH_SS_STATS) | 120 | if (sset != ETH_SS_STATS) |
112 | return -EINVAL; | 121 | return -EINVAL; |
113 | 122 | ||
114 | return XGENE_STATS_LEN; | 123 | return XGENE_STATS_LEN; |
115 | } | 124 | } |
116 | 125 | ||
117 | static void xgene_get_ethtool_stats(struct net_device *ndev, | 126 | static void xgene_get_ethtool_stats(struct net_device *ndev, |
118 | struct ethtool_stats *dummy, | 127 | struct ethtool_stats *dummy, |
119 | u64 *data) | 128 | u64 *data) |
120 | { | 129 | { |
121 | void *pdata = netdev_priv(ndev); | 130 | void *pdata = netdev_priv(ndev); |
122 | int i; | 131 | int i; |
123 | 132 | ||
124 | for (i = 0; i < XGENE_STATS_LEN; i++) | 133 | for (i = 0; i < XGENE_STATS_LEN; i++) |
125 | *data++ = *(u64 *)(pdata + gstrings_stats[i].offset); | 134 | *data++ = *(u64 *)(pdata + gstrings_stats[i].offset); |
126 | } | 135 | } |
127 | 136 | ||
128 | static const struct ethtool_ops xgene_ethtool_ops = { | 137 | static const struct ethtool_ops xgene_ethtool_ops = { |
129 | .get_drvinfo = xgene_get_drvinfo, | 138 | .get_drvinfo = xgene_get_drvinfo, |
130 | .get_settings = xgene_get_settings, | 139 | .get_settings = xgene_get_settings, |
131 | .set_settings = xgene_set_settings, | 140 | .set_settings = xgene_set_settings, |
132 | .get_link = ethtool_op_get_link, | 141 | .get_link = ethtool_op_get_link, |
133 | .get_strings = xgene_get_strings, | 142 | .get_strings = xgene_get_strings, |
134 | .get_sset_count = xgene_get_sset_count, | 143 | .get_sset_count = xgene_get_sset_count, |