diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/net/sfc/tenxpress.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/net/sfc/tenxpress.c')
-rw-r--r-- | drivers/net/sfc/tenxpress.c | 434 |
1 files changed, 31 insertions, 403 deletions
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index 6791be90c2fe..7b0fd89e7b85 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /**************************************************************************** | 1 | /**************************************************************************** |
2 | * Driver for Solarflare Solarstorm network controllers and boards | 2 | * Driver for Solarflare Solarstorm network controllers and boards |
3 | * Copyright 2007-2009 Solarflare Communications Inc. | 3 | * Copyright 2007-2011 Solarflare Communications Inc. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | 5 | * This program is free software; you can redistribute it and/or modify it |
6 | * under the terms of the GNU General Public License version 2 as published | 6 | * under the terms of the GNU General Public License version 2 as published |
@@ -15,14 +15,9 @@ | |||
15 | #include "mdio_10g.h" | 15 | #include "mdio_10g.h" |
16 | #include "nic.h" | 16 | #include "nic.h" |
17 | #include "phy.h" | 17 | #include "phy.h" |
18 | #include "regs.h" | ||
19 | #include "workarounds.h" | 18 | #include "workarounds.h" |
20 | #include "selftest.h" | ||
21 | 19 | ||
22 | /* We expect these MMDs to be in the package. SFT9001 also has a | 20 | /* We expect these MMDs to be in the package. */ |
23 | * clause 22 extension MMD, but since it doesn't have all the generic | ||
24 | * MMD registers it is pointless to include it here. | ||
25 | */ | ||
26 | #define TENXPRESS_REQUIRED_DEVS (MDIO_DEVS_PMAPMD | \ | 21 | #define TENXPRESS_REQUIRED_DEVS (MDIO_DEVS_PMAPMD | \ |
27 | MDIO_DEVS_PCS | \ | 22 | MDIO_DEVS_PCS | \ |
28 | MDIO_DEVS_PHYXS | \ | 23 | MDIO_DEVS_PHYXS | \ |
@@ -33,12 +28,6 @@ | |||
33 | (1 << LOOPBACK_PMAPMD) | \ | 28 | (1 << LOOPBACK_PMAPMD) | \ |
34 | (1 << LOOPBACK_PHYXS_WS)) | 29 | (1 << LOOPBACK_PHYXS_WS)) |
35 | 30 | ||
36 | #define SFT9001_LOOPBACKS ((1 << LOOPBACK_GPHY) | \ | ||
37 | (1 << LOOPBACK_PHYXS) | \ | ||
38 | (1 << LOOPBACK_PCS) | \ | ||
39 | (1 << LOOPBACK_PMAPMD) | \ | ||
40 | (1 << LOOPBACK_PHYXS_WS)) | ||
41 | |||
42 | /* We complain if we fail to see the link partner as 10G capable this many | 31 | /* We complain if we fail to see the link partner as 10G capable this many |
43 | * times in a row (must be > 1 as sampling the autoneg. registers is racy) | 32 | * times in a row (must be > 1 as sampling the autoneg. registers is racy) |
44 | */ | 33 | */ |
@@ -50,9 +39,8 @@ | |||
50 | #define PMA_PMD_EXT_GMII_EN_WIDTH 1 | 39 | #define PMA_PMD_EXT_GMII_EN_WIDTH 1 |
51 | #define PMA_PMD_EXT_CLK_OUT_LBN 2 | 40 | #define PMA_PMD_EXT_CLK_OUT_LBN 2 |
52 | #define PMA_PMD_EXT_CLK_OUT_WIDTH 1 | 41 | #define PMA_PMD_EXT_CLK_OUT_WIDTH 1 |
53 | #define PMA_PMD_LNPGA_POWERDOWN_LBN 8 /* SFX7101 only */ | 42 | #define PMA_PMD_LNPGA_POWERDOWN_LBN 8 |
54 | #define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1 | 43 | #define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1 |
55 | #define PMA_PMD_EXT_CLK312_LBN 8 /* SFT9001 only */ | ||
56 | #define PMA_PMD_EXT_CLK312_WIDTH 1 | 44 | #define PMA_PMD_EXT_CLK312_WIDTH 1 |
57 | #define PMA_PMD_EXT_LPOWER_LBN 12 | 45 | #define PMA_PMD_EXT_LPOWER_LBN 12 |
58 | #define PMA_PMD_EXT_LPOWER_WIDTH 1 | 46 | #define PMA_PMD_EXT_LPOWER_WIDTH 1 |
@@ -84,7 +72,6 @@ | |||
84 | #define PMA_PMD_LED_FLASH (3) | 72 | #define PMA_PMD_LED_FLASH (3) |
85 | #define PMA_PMD_LED_MASK 3 | 73 | #define PMA_PMD_LED_MASK 3 |
86 | /* All LEDs under hardware control */ | 74 | /* All LEDs under hardware control */ |
87 | #define SFT9001_PMA_PMD_LED_DEFAULT 0 | ||
88 | /* Green and Amber under hardware control, Red off */ | 75 | /* Green and Amber under hardware control, Red off */ |
89 | #define SFX7101_PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN) | 76 | #define SFX7101_PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN) |
90 | 77 | ||
@@ -98,31 +85,7 @@ | |||
98 | #define PMA_PMD_SPEED_LBN 4 | 85 | #define PMA_PMD_SPEED_LBN 4 |
99 | #define PMA_PMD_SPEED_WIDTH 4 | 86 | #define PMA_PMD_SPEED_WIDTH 4 |
100 | 87 | ||
101 | /* Cable diagnostics - SFT9001 only */ | 88 | /* Misc register defines */ |
102 | #define PMA_PMD_CDIAG_CTRL_REG 49213 | ||
103 | #define CDIAG_CTRL_IMMED_LBN 15 | ||
104 | #define CDIAG_CTRL_BRK_LINK_LBN 12 | ||
105 | #define CDIAG_CTRL_IN_PROG_LBN 11 | ||
106 | #define CDIAG_CTRL_LEN_UNIT_LBN 10 | ||
107 | #define CDIAG_CTRL_LEN_METRES 1 | ||
108 | #define PMA_PMD_CDIAG_RES_REG 49174 | ||
109 | #define CDIAG_RES_A_LBN 12 | ||
110 | #define CDIAG_RES_B_LBN 8 | ||
111 | #define CDIAG_RES_C_LBN 4 | ||
112 | #define CDIAG_RES_D_LBN 0 | ||
113 | #define CDIAG_RES_WIDTH 4 | ||
114 | #define CDIAG_RES_OPEN 2 | ||
115 | #define CDIAG_RES_OK 1 | ||
116 | #define CDIAG_RES_INVALID 0 | ||
117 | /* Set of 4 registers for pairs A-D */ | ||
118 | #define PMA_PMD_CDIAG_LEN_REG 49175 | ||
119 | |||
120 | /* Serdes control registers - SFT9001 only */ | ||
121 | #define PMA_PMD_CSERDES_CTRL_REG 64258 | ||
122 | /* Set the 156.25 MHz output to 312.5 MHz to drive Falcon's XMAC */ | ||
123 | #define PMA_PMD_CSERDES_DEFAULT 0x000f | ||
124 | |||
125 | /* Misc register defines - SFX7101 only */ | ||
126 | #define PCS_CLOCK_CTRL_REG 55297 | 89 | #define PCS_CLOCK_CTRL_REG 55297 |
127 | #define PLL312_RST_N_LBN 2 | 90 | #define PLL312_RST_N_LBN 2 |
128 | 91 | ||
@@ -185,121 +148,17 @@ struct tenxpress_phy_data { | |||
185 | int bad_lp_tries; | 148 | int bad_lp_tries; |
186 | }; | 149 | }; |
187 | 150 | ||
188 | static ssize_t show_phy_short_reach(struct device *dev, | ||
189 | struct device_attribute *attr, char *buf) | ||
190 | { | ||
191 | struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); | ||
192 | int reg; | ||
193 | |||
194 | reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR); | ||
195 | return sprintf(buf, "%d\n", !!(reg & MDIO_PMA_10GBT_TXPWR_SHORT)); | ||
196 | } | ||
197 | |||
198 | static ssize_t set_phy_short_reach(struct device *dev, | ||
199 | struct device_attribute *attr, | ||
200 | const char *buf, size_t count) | ||
201 | { | ||
202 | struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev)); | ||
203 | int rc; | ||
204 | |||
205 | rtnl_lock(); | ||
206 | if (efx->state != STATE_RUNNING) { | ||
207 | rc = -EBUSY; | ||
208 | } else { | ||
209 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR, | ||
210 | MDIO_PMA_10GBT_TXPWR_SHORT, | ||
211 | count != 0 && *buf != '0'); | ||
212 | rc = efx_reconfigure_port(efx); | ||
213 | } | ||
214 | rtnl_unlock(); | ||
215 | |||
216 | return rc < 0 ? rc : (ssize_t)count; | ||
217 | } | ||
218 | |||
219 | static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach, | ||
220 | set_phy_short_reach); | ||
221 | |||
222 | int sft9001_wait_boot(struct efx_nic *efx) | ||
223 | { | ||
224 | unsigned long timeout = jiffies + HZ + 1; | ||
225 | int boot_stat; | ||
226 | |||
227 | for (;;) { | ||
228 | boot_stat = efx_mdio_read(efx, MDIO_MMD_PCS, | ||
229 | PCS_BOOT_STATUS_REG); | ||
230 | if (boot_stat >= 0) { | ||
231 | netif_dbg(efx, hw, efx->net_dev, | ||
232 | "PHY boot status = %#x\n", boot_stat); | ||
233 | switch (boot_stat & | ||
234 | ((1 << PCS_BOOT_FATAL_ERROR_LBN) | | ||
235 | (3 << PCS_BOOT_PROGRESS_LBN) | | ||
236 | (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN) | | ||
237 | (1 << PCS_BOOT_CODE_STARTED_LBN))) { | ||
238 | case ((1 << PCS_BOOT_FATAL_ERROR_LBN) | | ||
239 | (PCS_BOOT_PROGRESS_CHECKSUM << | ||
240 | PCS_BOOT_PROGRESS_LBN)): | ||
241 | case ((1 << PCS_BOOT_FATAL_ERROR_LBN) | | ||
242 | (PCS_BOOT_PROGRESS_INIT << | ||
243 | PCS_BOOT_PROGRESS_LBN) | | ||
244 | (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN)): | ||
245 | return -EINVAL; | ||
246 | case ((PCS_BOOT_PROGRESS_WAIT_MDIO << | ||
247 | PCS_BOOT_PROGRESS_LBN) | | ||
248 | (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN)): | ||
249 | return (efx->phy_mode & PHY_MODE_SPECIAL) ? | ||
250 | 0 : -EIO; | ||
251 | case ((PCS_BOOT_PROGRESS_JUMP << | ||
252 | PCS_BOOT_PROGRESS_LBN) | | ||
253 | (1 << PCS_BOOT_CODE_STARTED_LBN)): | ||
254 | case ((PCS_BOOT_PROGRESS_JUMP << | ||
255 | PCS_BOOT_PROGRESS_LBN) | | ||
256 | (1 << PCS_BOOT_DOWNLOAD_WAIT_LBN) | | ||
257 | (1 << PCS_BOOT_CODE_STARTED_LBN)): | ||
258 | return (efx->phy_mode & PHY_MODE_SPECIAL) ? | ||
259 | -EIO : 0; | ||
260 | default: | ||
261 | if (boot_stat & (1 << PCS_BOOT_FATAL_ERROR_LBN)) | ||
262 | return -EIO; | ||
263 | break; | ||
264 | } | ||
265 | } | ||
266 | |||
267 | if (time_after_eq(jiffies, timeout)) | ||
268 | return -ETIMEDOUT; | ||
269 | |||
270 | msleep(50); | ||
271 | } | ||
272 | } | ||
273 | |||
274 | static int tenxpress_init(struct efx_nic *efx) | 151 | static int tenxpress_init(struct efx_nic *efx) |
275 | { | 152 | { |
276 | int reg; | 153 | /* Enable 312.5 MHz clock */ |
277 | 154 | efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG, | |
278 | if (efx->phy_type == PHY_TYPE_SFX7101) { | 155 | 1 << CLK312_EN_LBN); |
279 | /* Enable 312.5 MHz clock */ | ||
280 | efx_mdio_write(efx, MDIO_MMD_PCS, PCS_TEST_SELECT_REG, | ||
281 | 1 << CLK312_EN_LBN); | ||
282 | } else { | ||
283 | /* Enable 312.5 MHz clock and GMII */ | ||
284 | reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG); | ||
285 | reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) | | ||
286 | (1 << PMA_PMD_EXT_CLK_OUT_LBN) | | ||
287 | (1 << PMA_PMD_EXT_CLK312_LBN) | | ||
288 | (1 << PMA_PMD_EXT_ROBUST_LBN)); | ||
289 | |||
290 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); | ||
291 | efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, | ||
292 | GPHY_XCONTROL_REG, 1 << GPHY_ISOLATE_LBN, | ||
293 | false); | ||
294 | } | ||
295 | 156 | ||
296 | /* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */ | 157 | /* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */ |
297 | if (efx->phy_type == PHY_TYPE_SFX7101) { | 158 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG, |
298 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG, | 159 | 1 << PMA_PMA_LED_ACTIVITY_LBN, true); |
299 | 1 << PMA_PMA_LED_ACTIVITY_LBN, true); | 160 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, |
300 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG, | 161 | SFX7101_PMA_PMD_LED_DEFAULT); |
301 | SFX7101_PMA_PMD_LED_DEFAULT); | ||
302 | } | ||
303 | 162 | ||
304 | return 0; | 163 | return 0; |
305 | } | 164 | } |
@@ -307,7 +166,6 @@ static int tenxpress_init(struct efx_nic *efx) | |||
307 | static int tenxpress_phy_probe(struct efx_nic *efx) | 166 | static int tenxpress_phy_probe(struct efx_nic *efx) |
308 | { | 167 | { |
309 | struct tenxpress_phy_data *phy_data; | 168 | struct tenxpress_phy_data *phy_data; |
310 | int rc; | ||
311 | 169 | ||
312 | /* Allocate phy private storage */ | 170 | /* Allocate phy private storage */ |
313 | phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); | 171 | phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); |
@@ -316,42 +174,15 @@ static int tenxpress_phy_probe(struct efx_nic *efx) | |||
316 | efx->phy_data = phy_data; | 174 | efx->phy_data = phy_data; |
317 | phy_data->phy_mode = efx->phy_mode; | 175 | phy_data->phy_mode = efx->phy_mode; |
318 | 176 | ||
319 | /* Create any special files */ | 177 | efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; |
320 | if (efx->phy_type == PHY_TYPE_SFT9001B) { | 178 | efx->mdio.mode_support = MDIO_SUPPORTS_C45; |
321 | rc = device_create_file(&efx->pci_dev->dev, | ||
322 | &dev_attr_phy_short_reach); | ||
323 | if (rc) | ||
324 | goto fail; | ||
325 | } | ||
326 | |||
327 | if (efx->phy_type == PHY_TYPE_SFX7101) { | ||
328 | efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; | ||
329 | efx->mdio.mode_support = MDIO_SUPPORTS_C45; | ||
330 | |||
331 | efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS; | ||
332 | 179 | ||
333 | efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | | 180 | efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS; |
334 | ADVERTISED_10000baseT_Full); | ||
335 | } else { | ||
336 | efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; | ||
337 | efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; | ||
338 | 181 | ||
339 | efx->loopback_modes = (SFT9001_LOOPBACKS | | 182 | efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | |
340 | FALCON_XMAC_LOOPBACKS | | 183 | ADVERTISED_10000baseT_Full); |
341 | FALCON_GMAC_LOOPBACKS); | ||
342 | |||
343 | efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | | ||
344 | ADVERTISED_10000baseT_Full | | ||
345 | ADVERTISED_1000baseT_Full | | ||
346 | ADVERTISED_100baseT_Full); | ||
347 | } | ||
348 | 184 | ||
349 | return 0; | 185 | return 0; |
350 | |||
351 | fail: | ||
352 | kfree(efx->phy_data); | ||
353 | efx->phy_data = NULL; | ||
354 | return rc; | ||
355 | } | 186 | } |
356 | 187 | ||
357 | static int tenxpress_phy_init(struct efx_nic *efx) | 188 | static int tenxpress_phy_init(struct efx_nic *efx) |
@@ -361,21 +192,11 @@ static int tenxpress_phy_init(struct efx_nic *efx) | |||
361 | falcon_board(efx)->type->init_phy(efx); | 192 | falcon_board(efx)->type->init_phy(efx); |
362 | 193 | ||
363 | if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { | 194 | if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { |
364 | if (efx->phy_type == PHY_TYPE_SFT9001A) { | ||
365 | int reg; | ||
366 | reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, | ||
367 | PMA_PMD_XCONTROL_REG); | ||
368 | reg |= (1 << PMA_PMD_EXT_SSR_LBN); | ||
369 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, | ||
370 | PMA_PMD_XCONTROL_REG, reg); | ||
371 | mdelay(200); | ||
372 | } | ||
373 | |||
374 | rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); | 195 | rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); |
375 | if (rc < 0) | 196 | if (rc < 0) |
376 | return rc; | 197 | return rc; |
377 | 198 | ||
378 | rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); | 199 | rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS); |
379 | if (rc < 0) | 200 | if (rc < 0) |
380 | return rc; | 201 | return rc; |
381 | } | 202 | } |
@@ -403,7 +224,7 @@ static int tenxpress_special_reset(struct efx_nic *efx) | |||
403 | { | 224 | { |
404 | int rc, reg; | 225 | int rc, reg; |
405 | 226 | ||
406 | /* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so | 227 | /* The XGMAC clock is driven from the SFX7101 312MHz clock, so |
407 | * a special software reset can glitch the XGMAC sufficiently for stats | 228 | * a special software reset can glitch the XGMAC sufficiently for stats |
408 | * requests to fail. */ | 229 | * requests to fail. */ |
409 | falcon_stop_nic_stats(efx); | 230 | falcon_stop_nic_stats(efx); |
@@ -484,53 +305,18 @@ static bool sfx7101_link_ok(struct efx_nic *efx) | |||
484 | MDIO_DEVS_PHYXS); | 305 | MDIO_DEVS_PHYXS); |
485 | } | 306 | } |
486 | 307 | ||
487 | static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd) | ||
488 | { | ||
489 | u32 reg; | ||
490 | |||
491 | if (efx_phy_mode_disabled(efx->phy_mode)) | ||
492 | return false; | ||
493 | else if (efx->loopback_mode == LOOPBACK_GPHY) | ||
494 | return true; | ||
495 | else if (efx->loopback_mode) | ||
496 | return efx_mdio_links_ok(efx, | ||
497 | MDIO_DEVS_PMAPMD | | ||
498 | MDIO_DEVS_PHYXS); | ||
499 | |||
500 | /* We must use the same definition of link state as LASI, | ||
501 | * otherwise we can miss a link state transition | ||
502 | */ | ||
503 | if (ecmd->speed == 10000) { | ||
504 | reg = efx_mdio_read(efx, MDIO_MMD_PCS, MDIO_PCS_10GBRT_STAT1); | ||
505 | return reg & MDIO_PCS_10GBRT_STAT1_BLKLK; | ||
506 | } else { | ||
507 | reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_STATUS_REG); | ||
508 | return reg & (1 << C22EXT_STATUS_LINK_LBN); | ||
509 | } | ||
510 | } | ||
511 | |||
512 | static void tenxpress_ext_loopback(struct efx_nic *efx) | 308 | static void tenxpress_ext_loopback(struct efx_nic *efx) |
513 | { | 309 | { |
514 | efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, PHYXS_TEST1, | 310 | efx_mdio_set_flag(efx, MDIO_MMD_PHYXS, PHYXS_TEST1, |
515 | 1 << LOOPBACK_NEAR_LBN, | 311 | 1 << LOOPBACK_NEAR_LBN, |
516 | efx->loopback_mode == LOOPBACK_PHYXS); | 312 | efx->loopback_mode == LOOPBACK_PHYXS); |
517 | if (efx->phy_type != PHY_TYPE_SFX7101) | ||
518 | efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, GPHY_XCONTROL_REG, | ||
519 | 1 << GPHY_LOOPBACK_NEAR_LBN, | ||
520 | efx->loopback_mode == LOOPBACK_GPHY); | ||
521 | } | 313 | } |
522 | 314 | ||
523 | static void tenxpress_low_power(struct efx_nic *efx) | 315 | static void tenxpress_low_power(struct efx_nic *efx) |
524 | { | 316 | { |
525 | if (efx->phy_type == PHY_TYPE_SFX7101) | 317 | efx_mdio_set_mmds_lpower( |
526 | efx_mdio_set_mmds_lpower( | 318 | efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER), |
527 | efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER), | 319 | TENXPRESS_REQUIRED_DEVS); |
528 | TENXPRESS_REQUIRED_DEVS); | ||
529 | else | ||
530 | efx_mdio_set_flag( | ||
531 | efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, | ||
532 | 1 << PMA_PMD_EXT_LPOWER_LBN, | ||
533 | !!(efx->phy_mode & PHY_MODE_LOW_POWER)); | ||
534 | } | 320 | } |
535 | 321 | ||
536 | static int tenxpress_phy_reconfigure(struct efx_nic *efx) | 322 | static int tenxpress_phy_reconfigure(struct efx_nic *efx) |
@@ -550,12 +336,7 @@ static int tenxpress_phy_reconfigure(struct efx_nic *efx) | |||
550 | 336 | ||
551 | if (loop_reset || phy_mode_change) { | 337 | if (loop_reset || phy_mode_change) { |
552 | tenxpress_special_reset(efx); | 338 | tenxpress_special_reset(efx); |
553 | 339 | falcon_reset_xaui(efx); | |
554 | /* Reset XAUI if we were in 10G, and are staying | ||
555 | * in 10G. If we're moving into and out of 10G | ||
556 | * then xaui will be reset anyway */ | ||
557 | if (EFX_IS10G(efx)) | ||
558 | falcon_reset_xaui(efx); | ||
559 | } | 340 | } |
560 | 341 | ||
561 | tenxpress_low_power(efx); | 342 | tenxpress_low_power(efx); |
@@ -578,29 +359,12 @@ static bool tenxpress_phy_poll(struct efx_nic *efx) | |||
578 | { | 359 | { |
579 | struct efx_link_state old_state = efx->link_state; | 360 | struct efx_link_state old_state = efx->link_state; |
580 | 361 | ||
581 | if (efx->phy_type == PHY_TYPE_SFX7101) { | 362 | efx->link_state.up = sfx7101_link_ok(efx); |
582 | efx->link_state.up = sfx7101_link_ok(efx); | 363 | efx->link_state.speed = 10000; |
583 | efx->link_state.speed = 10000; | 364 | efx->link_state.fd = true; |
584 | efx->link_state.fd = true; | 365 | efx->link_state.fc = efx_mdio_get_pause(efx); |
585 | efx->link_state.fc = efx_mdio_get_pause(efx); | ||
586 | |||
587 | sfx7101_check_bad_lp(efx, efx->link_state.up); | ||
588 | } else { | ||
589 | struct ethtool_cmd ecmd; | ||
590 | |||
591 | /* Check the LASI alarm first */ | ||
592 | if (efx->loopback_mode == LOOPBACK_NONE && | ||
593 | !(efx_mdio_read(efx, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT) & | ||
594 | MDIO_PMA_LASI_LSALARM)) | ||
595 | return false; | ||
596 | 366 | ||
597 | tenxpress_get_settings(efx, &ecmd); | 367 | sfx7101_check_bad_lp(efx, efx->link_state.up); |
598 | |||
599 | efx->link_state.up = sft9001_link_ok(efx, &ecmd); | ||
600 | efx->link_state.speed = ecmd.speed; | ||
601 | efx->link_state.fd = (ecmd.duplex == DUPLEX_FULL); | ||
602 | efx->link_state.fc = efx_mdio_get_pause(efx); | ||
603 | } | ||
604 | 368 | ||
605 | return !efx_link_state_equal(&efx->link_state, &old_state); | 369 | return !efx_link_state_equal(&efx->link_state, &old_state); |
606 | } | 370 | } |
@@ -621,10 +385,6 @@ static void sfx7101_phy_fini(struct efx_nic *efx) | |||
621 | 385 | ||
622 | static void tenxpress_phy_remove(struct efx_nic *efx) | 386 | static void tenxpress_phy_remove(struct efx_nic *efx) |
623 | { | 387 | { |
624 | if (efx->phy_type == PHY_TYPE_SFT9001B) | ||
625 | device_remove_file(&efx->pci_dev->dev, | ||
626 | &dev_attr_phy_short_reach); | ||
627 | |||
628 | kfree(efx->phy_data); | 388 | kfree(efx->phy_data); |
629 | efx->phy_data = NULL; | 389 | efx->phy_data = NULL; |
630 | } | 390 | } |
@@ -647,10 +407,7 @@ void tenxpress_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) | |||
647 | (PMA_PMD_LED_ON << PMA_PMD_LED_LINK_LBN); | 407 | (PMA_PMD_LED_ON << PMA_PMD_LED_LINK_LBN); |
648 | break; | 408 | break; |
649 | default: | 409 | default: |
650 | if (efx->phy_type == PHY_TYPE_SFX7101) | 410 | reg = SFX7101_PMA_PMD_LED_DEFAULT; |
651 | reg = SFX7101_PMA_PMD_LED_DEFAULT; | ||
652 | else | ||
653 | reg = SFT9001_PMA_PMD_LED_DEFAULT; | ||
654 | break; | 411 | break; |
655 | } | 412 | } |
656 | 413 | ||
@@ -685,102 +442,12 @@ sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags) | |||
685 | return rc; | 442 | return rc; |
686 | } | 443 | } |
687 | 444 | ||
688 | static const char *const sft9001_test_names[] = { | ||
689 | "bist", | ||
690 | "cable.pairA.status", | ||
691 | "cable.pairB.status", | ||
692 | "cable.pairC.status", | ||
693 | "cable.pairD.status", | ||
694 | "cable.pairA.length", | ||
695 | "cable.pairB.length", | ||
696 | "cable.pairC.length", | ||
697 | "cable.pairD.length", | ||
698 | }; | ||
699 | |||
700 | static const char *sft9001_test_name(struct efx_nic *efx, unsigned int index) | ||
701 | { | ||
702 | if (index < ARRAY_SIZE(sft9001_test_names)) | ||
703 | return sft9001_test_names[index]; | ||
704 | return NULL; | ||
705 | } | ||
706 | |||
707 | static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags) | ||
708 | { | ||
709 | int rc = 0, rc2, i, ctrl_reg, res_reg; | ||
710 | |||
711 | /* Initialise cable diagnostic results to unknown failure */ | ||
712 | for (i = 1; i < 9; ++i) | ||
713 | results[i] = -1; | ||
714 | |||
715 | /* Run cable diagnostics; wait up to 5 seconds for them to complete. | ||
716 | * A cable fault is not a self-test failure, but a timeout is. */ | ||
717 | ctrl_reg = ((1 << CDIAG_CTRL_IMMED_LBN) | | ||
718 | (CDIAG_CTRL_LEN_METRES << CDIAG_CTRL_LEN_UNIT_LBN)); | ||
719 | if (flags & ETH_TEST_FL_OFFLINE) { | ||
720 | /* Break the link in order to run full diagnostics. We | ||
721 | * must reset the PHY to resume normal service. */ | ||
722 | ctrl_reg |= (1 << CDIAG_CTRL_BRK_LINK_LBN); | ||
723 | } | ||
724 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG, | ||
725 | ctrl_reg); | ||
726 | i = 0; | ||
727 | while (efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_CTRL_REG) & | ||
728 | (1 << CDIAG_CTRL_IN_PROG_LBN)) { | ||
729 | if (++i == 50) { | ||
730 | rc = -ETIMEDOUT; | ||
731 | goto out; | ||
732 | } | ||
733 | msleep(100); | ||
734 | } | ||
735 | res_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_CDIAG_RES_REG); | ||
736 | for (i = 0; i < 4; i++) { | ||
737 | int pair_res = | ||
738 | (res_reg >> (CDIAG_RES_A_LBN - i * CDIAG_RES_WIDTH)) | ||
739 | & ((1 << CDIAG_RES_WIDTH) - 1); | ||
740 | int len_reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, | ||
741 | PMA_PMD_CDIAG_LEN_REG + i); | ||
742 | if (pair_res == CDIAG_RES_OK) | ||
743 | results[1 + i] = 1; | ||
744 | else if (pair_res == CDIAG_RES_INVALID) | ||
745 | results[1 + i] = -1; | ||
746 | else | ||
747 | results[1 + i] = -pair_res; | ||
748 | if (pair_res != CDIAG_RES_INVALID && | ||
749 | pair_res != CDIAG_RES_OPEN && | ||
750 | len_reg != 0xffff) | ||
751 | results[5 + i] = len_reg; | ||
752 | } | ||
753 | |||
754 | out: | ||
755 | if (flags & ETH_TEST_FL_OFFLINE) { | ||
756 | /* Reset, running the BIST and then resuming normal service. */ | ||
757 | rc2 = tenxpress_special_reset(efx); | ||
758 | results[0] = rc2 ? -1 : 1; | ||
759 | if (!rc) | ||
760 | rc = rc2; | ||
761 | |||
762 | efx_mdio_an_reconfigure(efx); | ||
763 | } | ||
764 | |||
765 | return rc; | ||
766 | } | ||
767 | |||
768 | static void | 445 | static void |
769 | tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) | 446 | tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) |
770 | { | 447 | { |
771 | u32 adv = 0, lpa = 0; | 448 | u32 adv = 0, lpa = 0; |
772 | int reg; | 449 | int reg; |
773 | 450 | ||
774 | if (efx->phy_type != PHY_TYPE_SFX7101) { | ||
775 | reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL); | ||
776 | if (reg & (1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN)) | ||
777 | adv |= ADVERTISED_1000baseT_Full; | ||
778 | reg = efx_mdio_read(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_STATUS); | ||
779 | if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_HD_LBN)) | ||
780 | lpa |= ADVERTISED_1000baseT_Half; | ||
781 | if (reg & (1 << C22EXT_MSTSLV_STATUS_LP_1000_FD_LBN)) | ||
782 | lpa |= ADVERTISED_1000baseT_Full; | ||
783 | } | ||
784 | reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL); | 451 | reg = efx_mdio_read(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL); |
785 | if (reg & MDIO_AN_10GBT_CTRL_ADV10G) | 452 | if (reg & MDIO_AN_10GBT_CTRL_ADV10G) |
786 | adv |= ADVERTISED_10000baseT_Full; | 453 | adv |= ADVERTISED_10000baseT_Full; |
@@ -790,24 +457,10 @@ tenxpress_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) | |||
790 | 457 | ||
791 | mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa); | 458 | mdio45_ethtool_gset_npage(&efx->mdio, ecmd, adv, lpa); |
792 | 459 | ||
793 | if (efx->phy_type != PHY_TYPE_SFX7101) { | ||
794 | ecmd->supported |= (SUPPORTED_100baseT_Full | | ||
795 | SUPPORTED_1000baseT_Full); | ||
796 | if (ecmd->speed != SPEED_10000) { | ||
797 | ecmd->eth_tp_mdix = | ||
798 | (efx_mdio_read(efx, MDIO_MMD_PMAPMD, | ||
799 | PMA_PMD_XSTATUS_REG) & | ||
800 | (1 << PMA_PMD_XSTAT_MDIX_LBN)) | ||
801 | ? ETH_TP_MDI_X : ETH_TP_MDI; | ||
802 | } | ||
803 | } | ||
804 | |||
805 | /* In loopback, the PHY automatically brings up the correct interface, | 460 | /* In loopback, the PHY automatically brings up the correct interface, |
806 | * but doesn't advertise the correct speed. So override it */ | 461 | * but doesn't advertise the correct speed. So override it */ |
807 | if (efx->loopback_mode == LOOPBACK_GPHY) | 462 | if (LOOPBACK_EXTERNAL(efx)) |
808 | ecmd->speed = SPEED_1000; | 463 | ethtool_cmd_speed_set(ecmd, SPEED_10000); |
809 | else if (LOOPBACK_EXTERNAL(efx)) | ||
810 | ecmd->speed = SPEED_10000; | ||
811 | } | 464 | } |
812 | 465 | ||
813 | static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) | 466 | static int tenxpress_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) |
@@ -825,17 +478,7 @@ static void sfx7101_set_npage_adv(struct efx_nic *efx, u32 advertising) | |||
825 | advertising & ADVERTISED_10000baseT_Full); | 478 | advertising & ADVERTISED_10000baseT_Full); |
826 | } | 479 | } |
827 | 480 | ||
828 | static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising) | 481 | const struct efx_phy_operations falcon_sfx7101_phy_ops = { |
829 | { | ||
830 | efx_mdio_set_flag(efx, MDIO_MMD_C22EXT, C22EXT_MSTSLV_CTRL, | ||
831 | 1 << C22EXT_MSTSLV_CTRL_ADV_1000_FD_LBN, | ||
832 | advertising & ADVERTISED_1000baseT_Full); | ||
833 | efx_mdio_set_flag(efx, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL, | ||
834 | MDIO_AN_10GBT_CTRL_ADV10G, | ||
835 | advertising & ADVERTISED_10000baseT_Full); | ||
836 | } | ||
837 | |||
838 | struct efx_phy_operations falcon_sfx7101_phy_ops = { | ||
839 | .probe = tenxpress_phy_probe, | 482 | .probe = tenxpress_phy_probe, |
840 | .init = tenxpress_phy_init, | 483 | .init = tenxpress_phy_init, |
841 | .reconfigure = tenxpress_phy_reconfigure, | 484 | .reconfigure = tenxpress_phy_reconfigure, |
@@ -849,18 +492,3 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = { | |||
849 | .test_name = sfx7101_test_name, | 492 | .test_name = sfx7101_test_name, |
850 | .run_tests = sfx7101_run_tests, | 493 | .run_tests = sfx7101_run_tests, |
851 | }; | 494 | }; |
852 | |||
853 | struct efx_phy_operations falcon_sft9001_phy_ops = { | ||
854 | .probe = tenxpress_phy_probe, | ||
855 | .init = tenxpress_phy_init, | ||
856 | .reconfigure = tenxpress_phy_reconfigure, | ||
857 | .poll = tenxpress_phy_poll, | ||
858 | .fini = efx_port_dummy_op_void, | ||
859 | .remove = tenxpress_phy_remove, | ||
860 | .get_settings = tenxpress_get_settings, | ||
861 | .set_settings = tenxpress_set_settings, | ||
862 | .set_npage_adv = sft9001_set_npage_adv, | ||
863 | .test_alive = efx_mdio_test_alive, | ||
864 | .test_name = sft9001_test_name, | ||
865 | .run_tests = sft9001_run_tests, | ||
866 | }; | ||