diff options
author | David Daney <ddaney@caviumnetworks.com> | 2009-10-14 15:04:42 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2009-12-16 20:57:00 -0500 |
commit | f6ed1b3b3579db5c8c3aaf6fd3010c706973a35d (patch) | |
tree | 82957dab3ed4653fe83236fa839fe639294672ff /drivers | |
parent | d6aa60a10b2f5068e331ca2936b1e6c248ae37c1 (diff) |
Staging: octeon-ethernet: Convert to use PHY Abstraction Layer.
The octeon-ethernet driver shares an mdio bus with the octeon-mgmt
driver. Here we convert the octeon-ethernet driver to use the PHY
Abstraction Layer.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/octeon/Kconfig | 3 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet-mdio.c | 204 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet-mdio.h | 2 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet-proc.c | 112 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet-rgmii.c | 52 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet-sgmii.c | 2 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet-xaui.c | 2 | ||||
-rw-r--r-- | drivers/staging/octeon/ethernet.c | 23 | ||||
-rw-r--r-- | drivers/staging/octeon/octeon-ethernet.h | 6 |
9 files changed, 125 insertions, 281 deletions
diff --git a/drivers/staging/octeon/Kconfig b/drivers/staging/octeon/Kconfig index 536e2382de54..638ad6b35891 100644 --- a/drivers/staging/octeon/Kconfig +++ b/drivers/staging/octeon/Kconfig | |||
@@ -1,7 +1,8 @@ | |||
1 | config OCTEON_ETHERNET | 1 | config OCTEON_ETHERNET |
2 | tristate "Cavium Networks Octeon Ethernet support" | 2 | tristate "Cavium Networks Octeon Ethernet support" |
3 | depends on CPU_CAVIUM_OCTEON | 3 | depends on CPU_CAVIUM_OCTEON |
4 | select MII | 4 | select PHYLIB |
5 | select MDIO_OCTEON | ||
5 | help | 6 | help |
6 | This driver supports the builtin ethernet ports on Cavium | 7 | This driver supports the builtin ethernet ports on Cavium |
7 | Networks' products in the Octeon family. This driver supports the | 8 | Networks' products in the Octeon family. This driver supports the |
diff --git a/drivers/staging/octeon/ethernet-mdio.c b/drivers/staging/octeon/ethernet-mdio.c index 31a58e508924..05a5cc0f43ed 100644 --- a/drivers/staging/octeon/ethernet-mdio.c +++ b/drivers/staging/octeon/ethernet-mdio.c | |||
@@ -26,7 +26,8 @@ | |||
26 | **********************************************************************/ | 26 | **********************************************************************/ |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/ethtool.h> | 28 | #include <linux/ethtool.h> |
29 | #include <linux/mii.h> | 29 | #include <linux/phy.h> |
30 | |||
30 | #include <net/dst.h> | 31 | #include <net/dst.h> |
31 | 32 | ||
32 | #include <asm/octeon/octeon.h> | 33 | #include <asm/octeon/octeon.h> |
@@ -34,86 +35,12 @@ | |||
34 | #include "ethernet-defines.h" | 35 | #include "ethernet-defines.h" |
35 | #include "octeon-ethernet.h" | 36 | #include "octeon-ethernet.h" |
36 | #include "ethernet-mdio.h" | 37 | #include "ethernet-mdio.h" |
38 | #include "ethernet-util.h" | ||
37 | 39 | ||
38 | #include "cvmx-helper-board.h" | 40 | #include "cvmx-helper-board.h" |
39 | 41 | ||
40 | #include "cvmx-smix-defs.h" | 42 | #include "cvmx-smix-defs.h" |
41 | 43 | ||
42 | DECLARE_MUTEX(mdio_sem); | ||
43 | |||
44 | /** | ||
45 | * Perform an MII read. Called by the generic MII routines | ||
46 | * | ||
47 | * @dev: Device to perform read for | ||
48 | * @phy_id: The MII phy id | ||
49 | * @location: Register location to read | ||
50 | * Returns Result from the read or zero on failure | ||
51 | */ | ||
52 | static int cvm_oct_mdio_read(struct net_device *dev, int phy_id, int location) | ||
53 | { | ||
54 | union cvmx_smix_cmd smi_cmd; | ||
55 | union cvmx_smix_rd_dat smi_rd; | ||
56 | |||
57 | smi_cmd.u64 = 0; | ||
58 | smi_cmd.s.phy_op = 1; | ||
59 | smi_cmd.s.phy_adr = phy_id; | ||
60 | smi_cmd.s.reg_adr = location; | ||
61 | cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); | ||
62 | |||
63 | do { | ||
64 | if (!in_interrupt()) | ||
65 | yield(); | ||
66 | smi_rd.u64 = cvmx_read_csr(CVMX_SMIX_RD_DAT(0)); | ||
67 | } while (smi_rd.s.pending); | ||
68 | |||
69 | if (smi_rd.s.val) | ||
70 | return smi_rd.s.dat; | ||
71 | else | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | static int cvm_oct_mdio_dummy_read(struct net_device *dev, int phy_id, | ||
76 | int location) | ||
77 | { | ||
78 | return 0xffff; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * Perform an MII write. Called by the generic MII routines | ||
83 | * | ||
84 | * @dev: Device to perform write for | ||
85 | * @phy_id: The MII phy id | ||
86 | * @location: Register location to write | ||
87 | * @val: Value to write | ||
88 | */ | ||
89 | static void cvm_oct_mdio_write(struct net_device *dev, int phy_id, int location, | ||
90 | int val) | ||
91 | { | ||
92 | union cvmx_smix_cmd smi_cmd; | ||
93 | union cvmx_smix_wr_dat smi_wr; | ||
94 | |||
95 | smi_wr.u64 = 0; | ||
96 | smi_wr.s.dat = val; | ||
97 | cvmx_write_csr(CVMX_SMIX_WR_DAT(0), smi_wr.u64); | ||
98 | |||
99 | smi_cmd.u64 = 0; | ||
100 | smi_cmd.s.phy_op = 0; | ||
101 | smi_cmd.s.phy_adr = phy_id; | ||
102 | smi_cmd.s.reg_adr = location; | ||
103 | cvmx_write_csr(CVMX_SMIX_CMD(0), smi_cmd.u64); | ||
104 | |||
105 | do { | ||
106 | if (!in_interrupt()) | ||
107 | yield(); | ||
108 | smi_wr.u64 = cvmx_read_csr(CVMX_SMIX_WR_DAT(0)); | ||
109 | } while (smi_wr.s.pending); | ||
110 | } | ||
111 | |||
112 | static void cvm_oct_mdio_dummy_write(struct net_device *dev, int phy_id, | ||
113 | int location, int val) | ||
114 | { | ||
115 | } | ||
116 | |||
117 | static void cvm_oct_get_drvinfo(struct net_device *dev, | 44 | static void cvm_oct_get_drvinfo(struct net_device *dev, |
118 | struct ethtool_drvinfo *info) | 45 | struct ethtool_drvinfo *info) |
119 | { | 46 | { |
@@ -125,49 +52,37 @@ static void cvm_oct_get_drvinfo(struct net_device *dev, | |||
125 | static int cvm_oct_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 52 | static int cvm_oct_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
126 | { | 53 | { |
127 | struct octeon_ethernet *priv = netdev_priv(dev); | 54 | struct octeon_ethernet *priv = netdev_priv(dev); |
128 | int ret; | ||
129 | 55 | ||
130 | down(&mdio_sem); | 56 | if (priv->phydev) |
131 | ret = mii_ethtool_gset(&priv->mii_info, cmd); | 57 | return phy_ethtool_gset(priv->phydev, cmd); |
132 | up(&mdio_sem); | ||
133 | 58 | ||
134 | return ret; | 59 | return -EINVAL; |
135 | } | 60 | } |
136 | 61 | ||
137 | static int cvm_oct_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 62 | static int cvm_oct_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
138 | { | 63 | { |
139 | struct octeon_ethernet *priv = netdev_priv(dev); | 64 | struct octeon_ethernet *priv = netdev_priv(dev); |
140 | int ret; | ||
141 | 65 | ||
142 | down(&mdio_sem); | 66 | if (!capable(CAP_NET_ADMIN)) |
143 | ret = mii_ethtool_sset(&priv->mii_info, cmd); | 67 | return -EPERM; |
144 | up(&mdio_sem); | 68 | |
69 | if (priv->phydev) | ||
70 | return phy_ethtool_sset(priv->phydev, cmd); | ||
145 | 71 | ||
146 | return ret; | 72 | return -EINVAL; |
147 | } | 73 | } |
148 | 74 | ||
149 | static int cvm_oct_nway_reset(struct net_device *dev) | 75 | static int cvm_oct_nway_reset(struct net_device *dev) |
150 | { | 76 | { |
151 | struct octeon_ethernet *priv = netdev_priv(dev); | 77 | struct octeon_ethernet *priv = netdev_priv(dev); |
152 | int ret; | ||
153 | 78 | ||
154 | down(&mdio_sem); | 79 | if (!capable(CAP_NET_ADMIN)) |
155 | ret = mii_nway_restart(&priv->mii_info); | 80 | return -EPERM; |
156 | up(&mdio_sem); | ||
157 | 81 | ||
158 | return ret; | 82 | if (priv->phydev) |
159 | } | 83 | return phy_start_aneg(priv->phydev); |
160 | 84 | ||
161 | static u32 cvm_oct_get_link(struct net_device *dev) | 85 | return -EINVAL; |
162 | { | ||
163 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
164 | u32 ret; | ||
165 | |||
166 | down(&mdio_sem); | ||
167 | ret = mii_link_ok(&priv->mii_info); | ||
168 | up(&mdio_sem); | ||
169 | |||
170 | return ret; | ||
171 | } | 86 | } |
172 | 87 | ||
173 | const struct ethtool_ops cvm_oct_ethtool_ops = { | 88 | const struct ethtool_ops cvm_oct_ethtool_ops = { |
@@ -175,7 +90,7 @@ const struct ethtool_ops cvm_oct_ethtool_ops = { | |||
175 | .get_settings = cvm_oct_get_settings, | 90 | .get_settings = cvm_oct_get_settings, |
176 | .set_settings = cvm_oct_set_settings, | 91 | .set_settings = cvm_oct_set_settings, |
177 | .nway_reset = cvm_oct_nway_reset, | 92 | .nway_reset = cvm_oct_nway_reset, |
178 | .get_link = cvm_oct_get_link, | 93 | .get_link = ethtool_op_get_link, |
179 | .get_sg = ethtool_op_get_sg, | 94 | .get_sg = ethtool_op_get_sg, |
180 | .get_tx_csum = ethtool_op_get_tx_csum, | 95 | .get_tx_csum = ethtool_op_get_tx_csum, |
181 | }; | 96 | }; |
@@ -191,41 +106,78 @@ const struct ethtool_ops cvm_oct_ethtool_ops = { | |||
191 | int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 106 | int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) |
192 | { | 107 | { |
193 | struct octeon_ethernet *priv = netdev_priv(dev); | 108 | struct octeon_ethernet *priv = netdev_priv(dev); |
194 | struct mii_ioctl_data *data = if_mii(rq); | ||
195 | unsigned int duplex_chg; | ||
196 | int ret; | ||
197 | 109 | ||
198 | down(&mdio_sem); | 110 | if (!netif_running(dev)) |
199 | ret = generic_mii_ioctl(&priv->mii_info, data, cmd, &duplex_chg); | 111 | return -EINVAL; |
200 | up(&mdio_sem); | 112 | |
113 | if (!priv->phydev) | ||
114 | return -EINVAL; | ||
115 | |||
116 | return phy_mii_ioctl(priv->phydev, if_mii(rq), cmd); | ||
117 | } | ||
201 | 118 | ||
202 | return ret; | 119 | static void cvm_oct_adjust_link(struct net_device *dev) |
120 | { | ||
121 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
122 | cvmx_helper_link_info_t link_info; | ||
123 | |||
124 | if (priv->last_link != priv->phydev->link) { | ||
125 | priv->last_link = priv->phydev->link; | ||
126 | link_info.u64 = 0; | ||
127 | link_info.s.link_up = priv->last_link ? 1 : 0; | ||
128 | link_info.s.full_duplex = priv->phydev->duplex ? 1 : 0; | ||
129 | link_info.s.speed = priv->phydev->speed; | ||
130 | cvmx_helper_link_set( priv->port, link_info); | ||
131 | if (priv->last_link) { | ||
132 | netif_carrier_on(dev); | ||
133 | if (priv->queue != -1) | ||
134 | DEBUGPRINT("%s: %u Mbps %s duplex, " | ||
135 | "port %2d, queue %2d\n", | ||
136 | dev->name, priv->phydev->speed, | ||
137 | priv->phydev->duplex ? | ||
138 | "Full" : "Half", | ||
139 | priv->port, priv->queue); | ||
140 | else | ||
141 | DEBUGPRINT("%s: %u Mbps %s duplex, " | ||
142 | "port %2d, POW\n", | ||
143 | dev->name, priv->phydev->speed, | ||
144 | priv->phydev->duplex ? | ||
145 | "Full" : "Half", | ||
146 | priv->port); | ||
147 | } else { | ||
148 | netif_carrier_off(dev); | ||
149 | DEBUGPRINT("%s: Link down\n", dev->name); | ||
150 | } | ||
151 | } | ||
203 | } | 152 | } |
204 | 153 | ||
154 | |||
205 | /** | 155 | /** |
206 | * Setup the MDIO device structures | 156 | * Setup the PHY |
207 | * | 157 | * |
208 | * @dev: Device to setup | 158 | * @dev: Device to setup |
209 | * | 159 | * |
210 | * Returns Zero on success, negative on failure | 160 | * Returns Zero on success, negative on failure |
211 | */ | 161 | */ |
212 | int cvm_oct_mdio_setup_device(struct net_device *dev) | 162 | int cvm_oct_phy_setup_device(struct net_device *dev) |
213 | { | 163 | { |
214 | struct octeon_ethernet *priv = netdev_priv(dev); | 164 | struct octeon_ethernet *priv = netdev_priv(dev); |
215 | int phy_id = cvmx_helper_board_get_mii_address(priv->port); | 165 | |
216 | if (phy_id != -1) { | 166 | int phy_addr = cvmx_helper_board_get_mii_address(priv->port); |
217 | priv->mii_info.dev = dev; | 167 | if (phy_addr != -1) { |
218 | priv->mii_info.phy_id = phy_id; | 168 | char phy_id[20]; |
219 | priv->mii_info.phy_id_mask = 0xff; | 169 | |
220 | priv->mii_info.supports_gmii = 1; | 170 | snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, "0", phy_addr); |
221 | priv->mii_info.reg_num_mask = 0x1f; | 171 | |
222 | priv->mii_info.mdio_read = cvm_oct_mdio_read; | 172 | priv->phydev = phy_connect(dev, phy_id, cvm_oct_adjust_link, 0, |
223 | priv->mii_info.mdio_write = cvm_oct_mdio_write; | 173 | PHY_INTERFACE_MODE_GMII); |
224 | } else { | 174 | |
225 | /* Supply dummy MDIO routines so the kernel won't crash | 175 | if (IS_ERR(priv->phydev)) { |
226 | if the user tries to read them */ | 176 | priv->phydev = NULL; |
227 | priv->mii_info.mdio_read = cvm_oct_mdio_dummy_read; | 177 | return -1; |
228 | priv->mii_info.mdio_write = cvm_oct_mdio_dummy_write; | 178 | } |
179 | priv->last_link = 0; | ||
180 | phy_start_aneg(priv->phydev); | ||
229 | } | 181 | } |
230 | return 0; | 182 | return 0; |
231 | } | 183 | } |
diff --git a/drivers/staging/octeon/ethernet-mdio.h b/drivers/staging/octeon/ethernet-mdio.h index b3328aeec2df..55d0614a7cd9 100644 --- a/drivers/staging/octeon/ethernet-mdio.h +++ b/drivers/staging/octeon/ethernet-mdio.h | |||
@@ -43,4 +43,4 @@ | |||
43 | 43 | ||
44 | extern const struct ethtool_ops cvm_oct_ethtool_ops; | 44 | extern const struct ethtool_ops cvm_oct_ethtool_ops; |
45 | int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); | 45 | int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); |
46 | int cvm_oct_mdio_setup_device(struct net_device *dev); | 46 | int cvm_oct_phy_setup_device(struct net_device *dev); |
diff --git a/drivers/staging/octeon/ethernet-proc.c b/drivers/staging/octeon/ethernet-proc.c index 8fa88fc419b7..16308d484d3b 100644 --- a/drivers/staging/octeon/ethernet-proc.c +++ b/drivers/staging/octeon/ethernet-proc.c | |||
@@ -25,7 +25,6 @@ | |||
25 | * Contact Cavium Networks for more information | 25 | * Contact Cavium Networks for more information |
26 | **********************************************************************/ | 26 | **********************************************************************/ |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/mii.h> | ||
29 | #include <linux/seq_file.h> | 28 | #include <linux/seq_file.h> |
30 | #include <linux/proc_fs.h> | 29 | #include <linux/proc_fs.h> |
31 | #include <net/dst.h> | 30 | #include <net/dst.h> |
@@ -38,112 +37,6 @@ | |||
38 | #include "cvmx-helper.h" | 37 | #include "cvmx-helper.h" |
39 | #include "cvmx-pip.h" | 38 | #include "cvmx-pip.h" |
40 | 39 | ||
41 | static unsigned long long cvm_oct_stats_read_switch(struct net_device *dev, | ||
42 | int phy_id, int offset) | ||
43 | { | ||
44 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
45 | |||
46 | priv->mii_info.mdio_write(dev, phy_id, 0x1d, 0xcc00 | offset); | ||
47 | return ((uint64_t) priv->mii_info. | ||
48 | mdio_read(dev, phy_id, | ||
49 | 0x1e) << 16) | (uint64_t) priv->mii_info. | ||
50 | mdio_read(dev, phy_id, 0x1f); | ||
51 | } | ||
52 | |||
53 | static int cvm_oct_stats_switch_show(struct seq_file *m, void *v) | ||
54 | { | ||
55 | static const int ports[] = { 0, 1, 2, 3, 9, -1 }; | ||
56 | struct net_device *dev = cvm_oct_device[0]; | ||
57 | int index = 0; | ||
58 | |||
59 | while (ports[index] != -1) { | ||
60 | |||
61 | /* Latch port */ | ||
62 | struct octeon_ethernet *priv = netdev_priv(dev); | ||
63 | |||
64 | priv->mii_info.mdio_write(dev, 0x1b, 0x1d, | ||
65 | 0xdc00 | ports[index]); | ||
66 | seq_printf(m, "\nSwitch Port %d\n", ports[index]); | ||
67 | seq_printf(m, "InGoodOctets: %12llu\t" | ||
68 | "OutOctets: %12llu\t" | ||
69 | "64 Octets: %12llu\n", | ||
70 | cvm_oct_stats_read_switch(dev, 0x1b, | ||
71 | 0x00) | | ||
72 | (cvm_oct_stats_read_switch(dev, 0x1b, 0x01) << 32), | ||
73 | cvm_oct_stats_read_switch(dev, 0x1b, | ||
74 | 0x0E) | | ||
75 | (cvm_oct_stats_read_switch(dev, 0x1b, 0x0F) << 32), | ||
76 | cvm_oct_stats_read_switch(dev, 0x1b, 0x08)); | ||
77 | |||
78 | seq_printf(m, "InBadOctets: %12llu\t" | ||
79 | "OutUnicast: %12llu\t" | ||
80 | "65-127 Octets: %12llu\n", | ||
81 | cvm_oct_stats_read_switch(dev, 0x1b, 0x02), | ||
82 | cvm_oct_stats_read_switch(dev, 0x1b, 0x10), | ||
83 | cvm_oct_stats_read_switch(dev, 0x1b, 0x09)); | ||
84 | |||
85 | seq_printf(m, "InUnicast: %12llu\t" | ||
86 | "OutBroadcasts: %12llu\t" | ||
87 | "128-255 Octets: %12llu\n", | ||
88 | cvm_oct_stats_read_switch(dev, 0x1b, 0x04), | ||
89 | cvm_oct_stats_read_switch(dev, 0x1b, 0x13), | ||
90 | cvm_oct_stats_read_switch(dev, 0x1b, 0x0A)); | ||
91 | |||
92 | seq_printf(m, "InBroadcasts: %12llu\t" | ||
93 | "OutMulticasts: %12llu\t" | ||
94 | "256-511 Octets: %12llu\n", | ||
95 | cvm_oct_stats_read_switch(dev, 0x1b, 0x06), | ||
96 | cvm_oct_stats_read_switch(dev, 0x1b, 0x12), | ||
97 | cvm_oct_stats_read_switch(dev, 0x1b, 0x0B)); | ||
98 | |||
99 | seq_printf(m, "InMulticasts: %12llu\t" | ||
100 | "OutPause: %12llu\t" | ||
101 | "512-1023 Octets:%12llu\n", | ||
102 | cvm_oct_stats_read_switch(dev, 0x1b, 0x07), | ||
103 | cvm_oct_stats_read_switch(dev, 0x1b, 0x15), | ||
104 | cvm_oct_stats_read_switch(dev, 0x1b, 0x0C)); | ||
105 | |||
106 | seq_printf(m, "InPause: %12llu\t" | ||
107 | "Excessive: %12llu\t" | ||
108 | "1024-Max Octets:%12llu\n", | ||
109 | cvm_oct_stats_read_switch(dev, 0x1b, 0x16), | ||
110 | cvm_oct_stats_read_switch(dev, 0x1b, 0x11), | ||
111 | cvm_oct_stats_read_switch(dev, 0x1b, 0x0D)); | ||
112 | |||
113 | seq_printf(m, "InUndersize: %12llu\t" | ||
114 | "Collisions: %12llu\n", | ||
115 | cvm_oct_stats_read_switch(dev, 0x1b, 0x18), | ||
116 | cvm_oct_stats_read_switch(dev, 0x1b, 0x1E)); | ||
117 | |||
118 | seq_printf(m, "InFragments: %12llu\t" | ||
119 | "Deferred: %12llu\n", | ||
120 | cvm_oct_stats_read_switch(dev, 0x1b, 0x19), | ||
121 | cvm_oct_stats_read_switch(dev, 0x1b, 0x05)); | ||
122 | |||
123 | seq_printf(m, "InOversize: %12llu\t" | ||
124 | "Single: %12llu\n", | ||
125 | cvm_oct_stats_read_switch(dev, 0x1b, 0x1A), | ||
126 | cvm_oct_stats_read_switch(dev, 0x1b, 0x14)); | ||
127 | |||
128 | seq_printf(m, "InJabber: %12llu\t" | ||
129 | "Multiple: %12llu\n", | ||
130 | cvm_oct_stats_read_switch(dev, 0x1b, 0x1B), | ||
131 | cvm_oct_stats_read_switch(dev, 0x1b, 0x17)); | ||
132 | |||
133 | seq_printf(m, "In RxErr: %12llu\t" | ||
134 | "OutFCSErr: %12llu\n", | ||
135 | cvm_oct_stats_read_switch(dev, 0x1b, 0x1C), | ||
136 | cvm_oct_stats_read_switch(dev, 0x1b, 0x03)); | ||
137 | |||
138 | seq_printf(m, "InFCSErr: %12llu\t" | ||
139 | "Late: %12llu\n", | ||
140 | cvm_oct_stats_read_switch(dev, 0x1b, 0x1D), | ||
141 | cvm_oct_stats_read_switch(dev, 0x1b, 0x1F)); | ||
142 | index++; | ||
143 | } | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | /** | 40 | /** |
148 | * User is reading /proc/octeon_ethernet_stats | 41 | * User is reading /proc/octeon_ethernet_stats |
149 | * | 42 | * |
@@ -215,11 +108,6 @@ static int cvm_oct_stats_show(struct seq_file *m, void *v) | |||
215 | } | 108 | } |
216 | } | 109 | } |
217 | 110 | ||
218 | if (cvm_oct_device[0]) { | ||
219 | priv = netdev_priv(cvm_oct_device[0]); | ||
220 | if (priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII) | ||
221 | cvm_oct_stats_switch_show(m, v); | ||
222 | } | ||
223 | return 0; | 111 | return 0; |
224 | } | 112 | } |
225 | 113 | ||
diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c index fbaa465d2fac..3820f1ec11d1 100644 --- a/drivers/staging/octeon/ethernet-rgmii.c +++ b/drivers/staging/octeon/ethernet-rgmii.c | |||
@@ -147,32 +147,36 @@ static void cvm_oct_rgmii_poll(struct net_device *dev) | |||
147 | cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), | 147 | cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface), |
148 | gmxx_rxx_int_reg.u64); | 148 | gmxx_rxx_int_reg.u64); |
149 | } | 149 | } |
150 | 150 | if (priv->phydev == NULL) { | |
151 | link_info = cvmx_helper_link_autoconf(priv->port); | 151 | link_info = cvmx_helper_link_autoconf(priv->port); |
152 | priv->link_info = link_info.u64; | 152 | priv->link_info = link_info.u64; |
153 | } | ||
153 | spin_unlock_irqrestore(&global_register_lock, flags); | 154 | spin_unlock_irqrestore(&global_register_lock, flags); |
154 | 155 | ||
155 | /* Tell Linux */ | 156 | if (priv->phydev == NULL) { |
156 | if (link_info.s.link_up) { | 157 | /* Tell core. */ |
157 | 158 | if (link_info.s.link_up) { | |
158 | if (!netif_carrier_ok(dev)) | 159 | if (!netif_carrier_ok(dev)) |
159 | netif_carrier_on(dev); | 160 | netif_carrier_on(dev); |
160 | if (priv->queue != -1) | 161 | if (priv->queue != -1) |
161 | DEBUGPRINT | 162 | DEBUGPRINT("%s: %u Mbps %s duplex, " |
162 | ("%s: %u Mbps %s duplex, port %2d, queue %2d\n", | 163 | "port %2d, queue %2d\n", |
163 | dev->name, link_info.s.speed, | 164 | dev->name, link_info.s.speed, |
164 | (link_info.s.full_duplex) ? "Full" : "Half", | 165 | (link_info.s.full_duplex) ? |
165 | priv->port, priv->queue); | 166 | "Full" : "Half", |
166 | else | 167 | priv->port, priv->queue); |
167 | DEBUGPRINT("%s: %u Mbps %s duplex, port %2d, POW\n", | 168 | else |
168 | dev->name, link_info.s.speed, | 169 | DEBUGPRINT("%s: %u Mbps %s duplex, " |
169 | (link_info.s.full_duplex) ? "Full" : "Half", | 170 | "port %2d, POW\n", |
170 | priv->port); | 171 | dev->name, link_info.s.speed, |
171 | } else { | 172 | (link_info.s.full_duplex) ? |
172 | 173 | "Full" : "Half", | |
173 | if (netif_carrier_ok(dev)) | 174 | priv->port); |
174 | netif_carrier_off(dev); | 175 | } else { |
175 | DEBUGPRINT("%s: Link down\n", dev->name); | 176 | if (netif_carrier_ok(dev)) |
177 | netif_carrier_off(dev); | ||
178 | DEBUGPRINT("%s: Link down\n", dev->name); | ||
179 | } | ||
176 | } | 180 | } |
177 | } | 181 | } |
178 | 182 | ||
diff --git a/drivers/staging/octeon/ethernet-sgmii.c b/drivers/staging/octeon/ethernet-sgmii.c index 2b54996bd85d..6061d01eca2d 100644 --- a/drivers/staging/octeon/ethernet-sgmii.c +++ b/drivers/staging/octeon/ethernet-sgmii.c | |||
@@ -113,7 +113,7 @@ int cvm_oct_sgmii_init(struct net_device *dev) | |||
113 | struct octeon_ethernet *priv = netdev_priv(dev); | 113 | struct octeon_ethernet *priv = netdev_priv(dev); |
114 | cvm_oct_common_init(dev); | 114 | cvm_oct_common_init(dev); |
115 | dev->netdev_ops->ndo_stop(dev); | 115 | dev->netdev_ops->ndo_stop(dev); |
116 | if (!octeon_is_simulation()) | 116 | if (!octeon_is_simulation() && priv->phydev == NULL) |
117 | priv->poll = cvm_oct_sgmii_poll; | 117 | priv->poll = cvm_oct_sgmii_poll; |
118 | 118 | ||
119 | /* FIXME: Need autoneg logic */ | 119 | /* FIXME: Need autoneg logic */ |
diff --git a/drivers/staging/octeon/ethernet-xaui.c b/drivers/staging/octeon/ethernet-xaui.c index 0c2e7cc40f35..ee3dc41b2c53 100644 --- a/drivers/staging/octeon/ethernet-xaui.c +++ b/drivers/staging/octeon/ethernet-xaui.c | |||
@@ -112,7 +112,7 @@ int cvm_oct_xaui_init(struct net_device *dev) | |||
112 | struct octeon_ethernet *priv = netdev_priv(dev); | 112 | struct octeon_ethernet *priv = netdev_priv(dev); |
113 | cvm_oct_common_init(dev); | 113 | cvm_oct_common_init(dev); |
114 | dev->netdev_ops->ndo_stop(dev); | 114 | dev->netdev_ops->ndo_stop(dev); |
115 | if (!octeon_is_simulation()) | 115 | if (!octeon_is_simulation() && priv->phydev == NULL) |
116 | priv->poll = cvm_oct_xaui_poll; | 116 | priv->poll = cvm_oct_xaui_poll; |
117 | 117 | ||
118 | return 0; | 118 | return 0; |
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c index 492c5029992d..4cfd4b136b32 100644 --- a/drivers/staging/octeon/ethernet.c +++ b/drivers/staging/octeon/ethernet.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/netdevice.h> | 30 | #include <linux/netdevice.h> |
31 | #include <linux/etherdevice.h> | 31 | #include <linux/etherdevice.h> |
32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
33 | #include <linux/mii.h> | 33 | #include <linux/phy.h> |
34 | 34 | ||
35 | #include <net/dst.h> | 35 | #include <net/dst.h> |
36 | 36 | ||
@@ -132,8 +132,6 @@ static struct timer_list cvm_oct_poll_timer; | |||
132 | */ | 132 | */ |
133 | struct net_device *cvm_oct_device[TOTAL_NUMBER_OF_PORTS]; | 133 | struct net_device *cvm_oct_device[TOTAL_NUMBER_OF_PORTS]; |
134 | 134 | ||
135 | extern struct semaphore mdio_sem; | ||
136 | |||
137 | /** | 135 | /** |
138 | * Periodic timer tick for slow management operations | 136 | * Periodic timer tick for slow management operations |
139 | * | 137 | * |
@@ -160,13 +158,8 @@ static void cvm_do_timer(unsigned long arg) | |||
160 | goto out; | 158 | goto out; |
161 | 159 | ||
162 | priv = netdev_priv(cvm_oct_device[port]); | 160 | priv = netdev_priv(cvm_oct_device[port]); |
163 | if (priv->poll) { | 161 | if (priv->poll) |
164 | /* skip polling if we don't get the lock */ | 162 | priv->poll(cvm_oct_device[port]); |
165 | if (!down_trylock(&mdio_sem)) { | ||
166 | priv->poll(cvm_oct_device[port]); | ||
167 | up(&mdio_sem); | ||
168 | } | ||
169 | } | ||
170 | 163 | ||
171 | queues_per_port = cvmx_pko_get_num_queues(port); | 164 | queues_per_port = cvmx_pko_get_num_queues(port); |
172 | /* Drain any pending packets in the free list */ | 165 | /* Drain any pending packets in the free list */ |
@@ -524,7 +517,7 @@ int cvm_oct_common_init(struct net_device *dev) | |||
524 | dev->features |= NETIF_F_LLTX; | 517 | dev->features |= NETIF_F_LLTX; |
525 | SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops); | 518 | SET_ETHTOOL_OPS(dev, &cvm_oct_ethtool_ops); |
526 | 519 | ||
527 | cvm_oct_mdio_setup_device(dev); | 520 | cvm_oct_phy_setup_device(dev); |
528 | dev->netdev_ops->ndo_set_mac_address(dev, &sa); | 521 | dev->netdev_ops->ndo_set_mac_address(dev, &sa); |
529 | dev->netdev_ops->ndo_change_mtu(dev, dev->mtu); | 522 | dev->netdev_ops->ndo_change_mtu(dev, dev->mtu); |
530 | 523 | ||
@@ -540,7 +533,10 @@ int cvm_oct_common_init(struct net_device *dev) | |||
540 | 533 | ||
541 | void cvm_oct_common_uninit(struct net_device *dev) | 534 | void cvm_oct_common_uninit(struct net_device *dev) |
542 | { | 535 | { |
543 | /* Currently nothing to do */ | 536 | struct octeon_ethernet *priv = netdev_priv(dev); |
537 | |||
538 | if (priv->phydev) | ||
539 | phy_disconnect(priv->phydev); | ||
544 | } | 540 | } |
545 | 541 | ||
546 | static const struct net_device_ops cvm_oct_npi_netdev_ops = { | 542 | static const struct net_device_ops cvm_oct_npi_netdev_ops = { |
@@ -627,6 +623,8 @@ static const struct net_device_ops cvm_oct_pow_netdev_ops = { | |||
627 | #endif | 623 | #endif |
628 | }; | 624 | }; |
629 | 625 | ||
626 | extern void octeon_mdiobus_force_mod_depencency(void); | ||
627 | |||
630 | /** | 628 | /** |
631 | * Module/ driver initialization. Creates the linux network | 629 | * Module/ driver initialization. Creates the linux network |
632 | * devices. | 630 | * devices. |
@@ -640,6 +638,7 @@ static int __init cvm_oct_init_module(void) | |||
640 | int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE; | 638 | int fau = FAU_NUM_PACKET_BUFFERS_TO_FREE; |
641 | int qos; | 639 | int qos; |
642 | 640 | ||
641 | octeon_mdiobus_force_mod_depencency(); | ||
643 | pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION); | 642 | pr_notice("cavium-ethernet %s\n", OCTEON_ETHERNET_VERSION); |
644 | 643 | ||
645 | if (OCTEON_IS_MODEL(OCTEON_CN52XX)) | 644 | if (OCTEON_IS_MODEL(OCTEON_CN52XX)) |
diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h index 3aef9878fc0a..402a15b9bb0e 100644 --- a/drivers/staging/octeon/octeon-ethernet.h +++ b/drivers/staging/octeon/octeon-ethernet.h | |||
@@ -50,9 +50,9 @@ struct octeon_ethernet { | |||
50 | /* List of outstanding tx buffers per queue */ | 50 | /* List of outstanding tx buffers per queue */ |
51 | struct sk_buff_head tx_free_list[16]; | 51 | struct sk_buff_head tx_free_list[16]; |
52 | /* Device statistics */ | 52 | /* Device statistics */ |
53 | struct net_device_stats stats | 53 | struct net_device_stats stats; |
54 | ; /* Generic MII info structure */ | 54 | struct phy_device *phydev; |
55 | struct mii_if_info mii_info; | 55 | unsigned int last_link; |
56 | /* Last negotiated link state */ | 56 | /* Last negotiated link state */ |
57 | uint64_t link_info; | 57 | uint64_t link_info; |
58 | /* Called periodically to check link status */ | 58 | /* Called periodically to check link status */ |