diff options
author | David S. Miller <davem@davemloft.net> | 2010-01-11 01:55:03 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-01-11 01:55:03 -0500 |
commit | d4a66e752d0b19934dd208884f8605fe385aaaa9 (patch) | |
tree | 72fb727be1d7636aae9cddfe9aa93ac9dec75daf /drivers/net/sfc | |
parent | bdbec4b86ee99b020e159f9bd604003a3ae3b0ab (diff) | |
parent | fa15e99b6bb44aa86b241a43ca8c509e91f80153 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/benet/be_cmds.h
include/linux/sysctl.h
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r-- | drivers/net/sfc/efx.c | 6 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 1 | ||||
-rw-r--r-- | drivers/net/sfc/falcon_xmac.c | 38 | ||||
-rw-r--r-- | drivers/net/sfc/mcdi_phy.c | 93 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 1 | ||||
-rw-r--r-- | drivers/net/sfc/nic.c | 2 | ||||
-rw-r--r-- | drivers/net/sfc/qt202x_phy.c | 238 | ||||
-rw-r--r-- | drivers/net/sfc/siena.c | 1 | ||||
-rw-r--r-- | drivers/net/sfc/tenxpress.c | 138 | ||||
-rw-r--r-- | drivers/net/sfc/tx.c | 4 |
10 files changed, 369 insertions, 153 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 3591cc9c39c8..62d5cd51a9dd 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -741,14 +741,14 @@ static int efx_probe_port(struct efx_nic *efx) | |||
741 | 741 | ||
742 | EFX_LOG(efx, "create port\n"); | 742 | EFX_LOG(efx, "create port\n"); |
743 | 743 | ||
744 | if (phy_flash_cfg) | ||
745 | efx->phy_mode = PHY_MODE_SPECIAL; | ||
746 | |||
744 | /* Connect up MAC/PHY operations table */ | 747 | /* Connect up MAC/PHY operations table */ |
745 | rc = efx->type->probe_port(efx); | 748 | rc = efx->type->probe_port(efx); |
746 | if (rc) | 749 | if (rc) |
747 | goto err; | 750 | goto err; |
748 | 751 | ||
749 | if (phy_flash_cfg) | ||
750 | efx->phy_mode = PHY_MODE_SPECIAL; | ||
751 | |||
752 | /* Sanity check MAC address */ | 752 | /* Sanity check MAC address */ |
753 | if (is_valid_ether_addr(efx->mac_address)) { | 753 | if (is_valid_ether_addr(efx->mac_address)) { |
754 | memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN); | 754 | memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN); |
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 17afcd26e870..9d009c46e962 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
@@ -925,6 +925,7 @@ static int falcon_probe_port(struct efx_nic *efx) | |||
925 | 925 | ||
926 | static void falcon_remove_port(struct efx_nic *efx) | 926 | static void falcon_remove_port(struct efx_nic *efx) |
927 | { | 927 | { |
928 | efx->phy_op->remove(efx); | ||
928 | efx_nic_free_buffer(efx, &efx->stats_buffer); | 929 | efx_nic_free_buffer(efx, &efx->stats_buffer); |
929 | } | 930 | } |
930 | 931 | ||
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index 3da933f8f079..8ccab2c67a20 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c | |||
@@ -111,16 +111,12 @@ static void falcon_mask_status_intr(struct efx_nic *efx, bool enable) | |||
111 | efx_writeo(efx, ®, FR_AB_XM_MGT_INT_MASK); | 111 | efx_writeo(efx, ®, FR_AB_XM_MGT_INT_MASK); |
112 | } | 112 | } |
113 | 113 | ||
114 | /* Get status of XAUI link */ | 114 | static bool falcon_xgxs_link_ok(struct efx_nic *efx) |
115 | static bool falcon_xaui_link_ok(struct efx_nic *efx) | ||
116 | { | 115 | { |
117 | efx_oword_t reg; | 116 | efx_oword_t reg; |
118 | bool align_done, link_ok = false; | 117 | bool align_done, link_ok = false; |
119 | int sync_status; | 118 | int sync_status; |
120 | 119 | ||
121 | if (LOOPBACK_INTERNAL(efx)) | ||
122 | return true; | ||
123 | |||
124 | /* Read link status */ | 120 | /* Read link status */ |
125 | efx_reado(efx, ®, FR_AB_XX_CORE_STAT); | 121 | efx_reado(efx, ®, FR_AB_XX_CORE_STAT); |
126 | 122 | ||
@@ -135,14 +131,24 @@ static bool falcon_xaui_link_ok(struct efx_nic *efx) | |||
135 | EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_DISPERR, FFE_AB_XX_STAT_ALL_LANES); | 131 | EFX_SET_OWORD_FIELD(reg, FRF_AB_XX_DISPERR, FFE_AB_XX_STAT_ALL_LANES); |
136 | efx_writeo(efx, ®, FR_AB_XX_CORE_STAT); | 132 | efx_writeo(efx, ®, FR_AB_XX_CORE_STAT); |
137 | 133 | ||
138 | /* If the link is up, then check the phy side of the xaui link */ | ||
139 | if (efx->link_state.up && link_ok) | ||
140 | if (efx->mdio.mmds & (1 << MDIO_MMD_PHYXS)) | ||
141 | link_ok = efx_mdio_phyxgxs_lane_sync(efx); | ||
142 | |||
143 | return link_ok; | 134 | return link_ok; |
144 | } | 135 | } |
145 | 136 | ||
137 | static bool falcon_xmac_link_ok(struct efx_nic *efx) | ||
138 | { | ||
139 | /* | ||
140 | * Check MAC's XGXS link status except when using XGMII loopback | ||
141 | * which bypasses the XGXS block. | ||
142 | * If possible, check PHY's XGXS link status except when using | ||
143 | * MAC loopback. | ||
144 | */ | ||
145 | return (efx->loopback_mode == LOOPBACK_XGMII || | ||
146 | falcon_xgxs_link_ok(efx)) && | ||
147 | (!(efx->mdio.mmds & (1 << MDIO_MMD_PHYXS)) || | ||
148 | LOOPBACK_INTERNAL(efx) || | ||
149 | efx_mdio_phyxgxs_lane_sync(efx)); | ||
150 | } | ||
151 | |||
146 | void falcon_reconfigure_xmac_core(struct efx_nic *efx) | 152 | void falcon_reconfigure_xmac_core(struct efx_nic *efx) |
147 | { | 153 | { |
148 | unsigned int max_frame_len; | 154 | unsigned int max_frame_len; |
@@ -245,9 +251,9 @@ static void falcon_reconfigure_xgxs_core(struct efx_nic *efx) | |||
245 | 251 | ||
246 | 252 | ||
247 | /* Try to bring up the Falcon side of the Falcon-Phy XAUI link */ | 253 | /* Try to bring up the Falcon side of the Falcon-Phy XAUI link */ |
248 | static bool falcon_check_xaui_link_up(struct efx_nic *efx, int tries) | 254 | static bool falcon_xmac_link_ok_retry(struct efx_nic *efx, int tries) |
249 | { | 255 | { |
250 | bool mac_up = falcon_xaui_link_ok(efx); | 256 | bool mac_up = falcon_xmac_link_ok(efx); |
251 | 257 | ||
252 | if (LOOPBACK_MASK(efx) & LOOPBACKS_EXTERNAL(efx) & LOOPBACKS_WS || | 258 | if (LOOPBACK_MASK(efx) & LOOPBACKS_EXTERNAL(efx) & LOOPBACKS_WS || |
253 | efx_phy_mode_disabled(efx->phy_mode)) | 259 | efx_phy_mode_disabled(efx->phy_mode)) |
@@ -261,7 +267,7 @@ static bool falcon_check_xaui_link_up(struct efx_nic *efx, int tries) | |||
261 | falcon_reset_xaui(efx); | 267 | falcon_reset_xaui(efx); |
262 | udelay(200); | 268 | udelay(200); |
263 | 269 | ||
264 | mac_up = falcon_xaui_link_ok(efx); | 270 | mac_up = falcon_xmac_link_ok(efx); |
265 | --tries; | 271 | --tries; |
266 | } | 272 | } |
267 | 273 | ||
@@ -272,7 +278,7 @@ static bool falcon_check_xaui_link_up(struct efx_nic *efx, int tries) | |||
272 | 278 | ||
273 | static bool falcon_xmac_check_fault(struct efx_nic *efx) | 279 | static bool falcon_xmac_check_fault(struct efx_nic *efx) |
274 | { | 280 | { |
275 | return !falcon_check_xaui_link_up(efx, 5); | 281 | return !falcon_xmac_link_ok_retry(efx, 5); |
276 | } | 282 | } |
277 | 283 | ||
278 | static int falcon_reconfigure_xmac(struct efx_nic *efx) | 284 | static int falcon_reconfigure_xmac(struct efx_nic *efx) |
@@ -284,7 +290,7 @@ static int falcon_reconfigure_xmac(struct efx_nic *efx) | |||
284 | 290 | ||
285 | falcon_reconfigure_mac_wrapper(efx); | 291 | falcon_reconfigure_mac_wrapper(efx); |
286 | 292 | ||
287 | efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 5); | 293 | efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 5); |
288 | falcon_mask_status_intr(efx, true); | 294 | falcon_mask_status_intr(efx, true); |
289 | 295 | ||
290 | return 0; | 296 | return 0; |
@@ -357,7 +363,7 @@ void falcon_poll_xmac(struct efx_nic *efx) | |||
357 | return; | 363 | return; |
358 | 364 | ||
359 | falcon_mask_status_intr(efx, false); | 365 | falcon_mask_status_intr(efx, false); |
360 | efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 1); | 366 | efx->xmac_poll_required = !falcon_xmac_link_ok_retry(efx, 1); |
361 | falcon_mask_status_intr(efx, true); | 367 | falcon_mask_status_intr(efx, true); |
362 | } | 368 | } |
363 | 369 | ||
diff --git a/drivers/net/sfc/mcdi_phy.c b/drivers/net/sfc/mcdi_phy.c index 0e1bcc5a0d52..eb694af7a473 100644 --- a/drivers/net/sfc/mcdi_phy.c +++ b/drivers/net/sfc/mcdi_phy.c | |||
@@ -304,31 +304,47 @@ static u32 mcdi_to_ethtool_media(u32 media) | |||
304 | 304 | ||
305 | static int efx_mcdi_phy_probe(struct efx_nic *efx) | 305 | static int efx_mcdi_phy_probe(struct efx_nic *efx) |
306 | { | 306 | { |
307 | struct efx_mcdi_phy_cfg *phy_cfg; | 307 | struct efx_mcdi_phy_cfg *phy_data; |
308 | u8 outbuf[MC_CMD_GET_LINK_OUT_LEN]; | ||
309 | u32 caps; | ||
308 | int rc; | 310 | int rc; |
309 | 311 | ||
310 | /* TODO: Move phy_data initialisation to | 312 | /* Initialise and populate phy_data */ |
311 | * phy_op->probe/remove, rather than init/fini */ | 313 | phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); |
312 | phy_cfg = kzalloc(sizeof(*phy_cfg), GFP_KERNEL); | 314 | if (phy_data == NULL) |
313 | if (phy_cfg == NULL) { | 315 | return -ENOMEM; |
314 | rc = -ENOMEM; | 316 | |
315 | goto fail_alloc; | 317 | rc = efx_mcdi_get_phy_cfg(efx, phy_data); |
316 | } | ||
317 | rc = efx_mcdi_get_phy_cfg(efx, phy_cfg); | ||
318 | if (rc != 0) | 318 | if (rc != 0) |
319 | goto fail; | 319 | goto fail; |
320 | 320 | ||
321 | efx->phy_type = phy_cfg->type; | 321 | /* Read initial link advertisement */ |
322 | BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0); | ||
323 | rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, | ||
324 | outbuf, sizeof(outbuf), NULL); | ||
325 | if (rc) | ||
326 | goto fail; | ||
327 | |||
328 | /* Fill out nic state */ | ||
329 | efx->phy_data = phy_data; | ||
330 | efx->phy_type = phy_data->type; | ||
322 | 331 | ||
323 | efx->mdio_bus = phy_cfg->channel; | 332 | efx->mdio_bus = phy_data->channel; |
324 | efx->mdio.prtad = phy_cfg->port; | 333 | efx->mdio.prtad = phy_data->port; |
325 | efx->mdio.mmds = phy_cfg->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22); | 334 | efx->mdio.mmds = phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22); |
326 | efx->mdio.mode_support = 0; | 335 | efx->mdio.mode_support = 0; |
327 | if (phy_cfg->mmd_mask & (1 << MC_CMD_MMD_CLAUSE22)) | 336 | if (phy_data->mmd_mask & (1 << MC_CMD_MMD_CLAUSE22)) |
328 | efx->mdio.mode_support |= MDIO_SUPPORTS_C22; | 337 | efx->mdio.mode_support |= MDIO_SUPPORTS_C22; |
329 | if (phy_cfg->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22)) | 338 | if (phy_data->mmd_mask & ~(1 << MC_CMD_MMD_CLAUSE22)) |
330 | efx->mdio.mode_support |= MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; | 339 | efx->mdio.mode_support |= MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; |
331 | 340 | ||
341 | caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP); | ||
342 | if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN)) | ||
343 | efx->link_advertising = | ||
344 | mcdi_to_ethtool_cap(phy_data->media, caps); | ||
345 | else | ||
346 | phy_data->forced_cap = caps; | ||
347 | |||
332 | /* Assert that we can map efx -> mcdi loopback modes */ | 348 | /* Assert that we can map efx -> mcdi loopback modes */ |
333 | BUILD_BUG_ON(LOOPBACK_NONE != MC_CMD_LOOPBACK_NONE); | 349 | BUILD_BUG_ON(LOOPBACK_NONE != MC_CMD_LOOPBACK_NONE); |
334 | BUILD_BUG_ON(LOOPBACK_DATA != MC_CMD_LOOPBACK_DATA); | 350 | BUILD_BUG_ON(LOOPBACK_DATA != MC_CMD_LOOPBACK_DATA); |
@@ -365,46 +381,6 @@ static int efx_mcdi_phy_probe(struct efx_nic *efx) | |||
365 | * but by convention we don't */ | 381 | * but by convention we don't */ |
366 | efx->loopback_modes &= ~(1 << LOOPBACK_NONE); | 382 | efx->loopback_modes &= ~(1 << LOOPBACK_NONE); |
367 | 383 | ||
368 | kfree(phy_cfg); | ||
369 | |||
370 | return 0; | ||
371 | |||
372 | fail: | ||
373 | kfree(phy_cfg); | ||
374 | fail_alloc: | ||
375 | return rc; | ||
376 | } | ||
377 | |||
378 | static int efx_mcdi_phy_init(struct efx_nic *efx) | ||
379 | { | ||
380 | struct efx_mcdi_phy_cfg *phy_data; | ||
381 | u8 outbuf[MC_CMD_GET_LINK_OUT_LEN]; | ||
382 | u32 caps; | ||
383 | int rc; | ||
384 | |||
385 | phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); | ||
386 | if (phy_data == NULL) | ||
387 | return -ENOMEM; | ||
388 | |||
389 | rc = efx_mcdi_get_phy_cfg(efx, phy_data); | ||
390 | if (rc != 0) | ||
391 | goto fail; | ||
392 | |||
393 | efx->phy_data = phy_data; | ||
394 | |||
395 | BUILD_BUG_ON(MC_CMD_GET_LINK_IN_LEN != 0); | ||
396 | rc = efx_mcdi_rpc(efx, MC_CMD_GET_LINK, NULL, 0, | ||
397 | outbuf, sizeof(outbuf), NULL); | ||
398 | if (rc) | ||
399 | goto fail; | ||
400 | |||
401 | caps = MCDI_DWORD(outbuf, GET_LINK_OUT_CAP); | ||
402 | if (caps & (1 << MC_CMD_PHY_CAP_AN_LBN)) | ||
403 | efx->link_advertising = | ||
404 | mcdi_to_ethtool_cap(phy_data->media, caps); | ||
405 | else | ||
406 | phy_data->forced_cap = caps; | ||
407 | |||
408 | return 0; | 384 | return 0; |
409 | 385 | ||
410 | fail: | 386 | fail: |
@@ -504,7 +480,7 @@ static bool efx_mcdi_phy_poll(struct efx_nic *efx) | |||
504 | return !efx_link_state_equal(&efx->link_state, &old_state); | 480 | return !efx_link_state_equal(&efx->link_state, &old_state); |
505 | } | 481 | } |
506 | 482 | ||
507 | static void efx_mcdi_phy_fini(struct efx_nic *efx) | 483 | static void efx_mcdi_phy_remove(struct efx_nic *efx) |
508 | { | 484 | { |
509 | struct efx_mcdi_phy_data *phy_data = efx->phy_data; | 485 | struct efx_mcdi_phy_data *phy_data = efx->phy_data; |
510 | 486 | ||
@@ -586,10 +562,11 @@ static int efx_mcdi_phy_set_settings(struct efx_nic *efx, struct ethtool_cmd *ec | |||
586 | 562 | ||
587 | struct efx_phy_operations efx_mcdi_phy_ops = { | 563 | struct efx_phy_operations efx_mcdi_phy_ops = { |
588 | .probe = efx_mcdi_phy_probe, | 564 | .probe = efx_mcdi_phy_probe, |
589 | .init = efx_mcdi_phy_init, | 565 | .init = efx_port_dummy_op_int, |
590 | .reconfigure = efx_mcdi_phy_reconfigure, | 566 | .reconfigure = efx_mcdi_phy_reconfigure, |
591 | .poll = efx_mcdi_phy_poll, | 567 | .poll = efx_mcdi_phy_poll, |
592 | .fini = efx_mcdi_phy_fini, | 568 | .fini = efx_port_dummy_op_void, |
569 | .remove = efx_mcdi_phy_remove, | ||
593 | .get_settings = efx_mcdi_phy_get_settings, | 570 | .get_settings = efx_mcdi_phy_get_settings, |
594 | .set_settings = efx_mcdi_phy_set_settings, | 571 | .set_settings = efx_mcdi_phy_set_settings, |
595 | .run_tests = NULL, | 572 | .run_tests = NULL, |
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 34c381f009b7..d5aab5b3fa06 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -524,6 +524,7 @@ struct efx_phy_operations { | |||
524 | int (*probe) (struct efx_nic *efx); | 524 | int (*probe) (struct efx_nic *efx); |
525 | int (*init) (struct efx_nic *efx); | 525 | int (*init) (struct efx_nic *efx); |
526 | void (*fini) (struct efx_nic *efx); | 526 | void (*fini) (struct efx_nic *efx); |
527 | void (*remove) (struct efx_nic *efx); | ||
527 | int (*reconfigure) (struct efx_nic *efx); | 528 | int (*reconfigure) (struct efx_nic *efx); |
528 | bool (*poll) (struct efx_nic *efx); | 529 | bool (*poll) (struct efx_nic *efx); |
529 | void (*get_settings) (struct efx_nic *efx, | 530 | void (*get_settings) (struct efx_nic *efx, |
diff --git a/drivers/net/sfc/nic.c b/drivers/net/sfc/nic.c index a577be227862..db44224ed2ca 100644 --- a/drivers/net/sfc/nic.c +++ b/drivers/net/sfc/nic.c | |||
@@ -1576,6 +1576,8 @@ void efx_nic_init_common(struct efx_nic *efx) | |||
1576 | EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_SOFT_EVT_EN, 1); | 1576 | EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_SOFT_EVT_EN, 1); |
1577 | /* Prefetch threshold 2 => fetch when descriptor cache half empty */ | 1577 | /* Prefetch threshold 2 => fetch when descriptor cache half empty */ |
1578 | EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_PREF_THRESHOLD, 2); | 1578 | EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_PREF_THRESHOLD, 2); |
1579 | /* Disable hardware watchdog which can misfire */ | ||
1580 | EFX_SET_OWORD_FIELD(temp, FRF_AZ_TX_PREF_WD_TMR, 0x3fffff); | ||
1579 | /* Squash TX of packets of 16 bytes or less */ | 1581 | /* Squash TX of packets of 16 bytes or less */ |
1580 | if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) | 1582 | if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) |
1581 | EFX_SET_OWORD_FIELD(temp, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1); | 1583 | EFX_SET_OWORD_FIELD(temp, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1); |
diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c index 3800fc791b2f..ff8f0a417fa3 100644 --- a/drivers/net/sfc/qt202x_phy.c +++ b/drivers/net/sfc/qt202x_phy.c | |||
@@ -33,6 +33,9 @@ | |||
33 | #define PCS_FW_HEARTBEAT_REG 0xd7ee | 33 | #define PCS_FW_HEARTBEAT_REG 0xd7ee |
34 | #define PCS_FW_HEARTB_LBN 0 | 34 | #define PCS_FW_HEARTB_LBN 0 |
35 | #define PCS_FW_HEARTB_WIDTH 8 | 35 | #define PCS_FW_HEARTB_WIDTH 8 |
36 | #define PCS_FW_PRODUCT_CODE_1 0xd7f0 | ||
37 | #define PCS_FW_VERSION_1 0xd7f3 | ||
38 | #define PCS_FW_BUILD_1 0xd7f6 | ||
36 | #define PCS_UC8051_STATUS_REG 0xd7fd | 39 | #define PCS_UC8051_STATUS_REG 0xd7fd |
37 | #define PCS_UC_STATUS_LBN 0 | 40 | #define PCS_UC_STATUS_LBN 0 |
38 | #define PCS_UC_STATUS_WIDTH 8 | 41 | #define PCS_UC_STATUS_WIDTH 8 |
@@ -52,14 +55,24 @@ void falcon_qt202x_set_led(struct efx_nic *p, int led, int mode) | |||
52 | 55 | ||
53 | struct qt202x_phy_data { | 56 | struct qt202x_phy_data { |
54 | enum efx_phy_mode phy_mode; | 57 | enum efx_phy_mode phy_mode; |
58 | bool bug17190_in_bad_state; | ||
59 | unsigned long bug17190_timer; | ||
60 | u32 firmware_ver; | ||
55 | }; | 61 | }; |
56 | 62 | ||
57 | #define QT2022C2_MAX_RESET_TIME 500 | 63 | #define QT2022C2_MAX_RESET_TIME 500 |
58 | #define QT2022C2_RESET_WAIT 10 | 64 | #define QT2022C2_RESET_WAIT 10 |
59 | 65 | ||
60 | static int qt2025c_wait_reset(struct efx_nic *efx) | 66 | #define QT2025C_MAX_HEARTB_TIME (5 * HZ) |
67 | #define QT2025C_HEARTB_WAIT 100 | ||
68 | #define QT2025C_MAX_FWSTART_TIME (25 * HZ / 10) | ||
69 | #define QT2025C_FWSTART_WAIT 100 | ||
70 | |||
71 | #define BUG17190_INTERVAL (2 * HZ) | ||
72 | |||
73 | static int qt2025c_wait_heartbeat(struct efx_nic *efx) | ||
61 | { | 74 | { |
62 | unsigned long timeout = jiffies + 10 * HZ; | 75 | unsigned long timeout = jiffies + QT2025C_MAX_HEARTB_TIME; |
63 | int reg, old_counter = 0; | 76 | int reg, old_counter = 0; |
64 | 77 | ||
65 | /* Wait for firmware heartbeat to start */ | 78 | /* Wait for firmware heartbeat to start */ |
@@ -74,11 +87,25 @@ static int qt2025c_wait_reset(struct efx_nic *efx) | |||
74 | old_counter = counter; | 87 | old_counter = counter; |
75 | else if (counter != old_counter) | 88 | else if (counter != old_counter) |
76 | break; | 89 | break; |
77 | if (time_after(jiffies, timeout)) | 90 | if (time_after(jiffies, timeout)) { |
91 | /* Some cables have EEPROMs that conflict with the | ||
92 | * PHY's on-board EEPROM so it cannot load firmware */ | ||
93 | EFX_ERR(efx, "If an SFP+ direct attach cable is" | ||
94 | " connected, please check that it complies" | ||
95 | " with the SFP+ specification\n"); | ||
78 | return -ETIMEDOUT; | 96 | return -ETIMEDOUT; |
79 | msleep(10); | 97 | } |
98 | msleep(QT2025C_HEARTB_WAIT); | ||
80 | } | 99 | } |
81 | 100 | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int qt2025c_wait_fw_status_good(struct efx_nic *efx) | ||
105 | { | ||
106 | unsigned long timeout = jiffies + QT2025C_MAX_FWSTART_TIME; | ||
107 | int reg; | ||
108 | |||
82 | /* Wait for firmware status to look good */ | 109 | /* Wait for firmware status to look good */ |
83 | for (;;) { | 110 | for (;;) { |
84 | reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG); | 111 | reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG); |
@@ -90,7 +117,178 @@ static int qt2025c_wait_reset(struct efx_nic *efx) | |||
90 | break; | 117 | break; |
91 | if (time_after(jiffies, timeout)) | 118 | if (time_after(jiffies, timeout)) |
92 | return -ETIMEDOUT; | 119 | return -ETIMEDOUT; |
120 | msleep(QT2025C_FWSTART_WAIT); | ||
121 | } | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static void qt2025c_restart_firmware(struct efx_nic *efx) | ||
127 | { | ||
128 | /* Restart microcontroller execution of firmware from RAM */ | ||
129 | efx_mdio_write(efx, 3, 0xe854, 0x00c0); | ||
130 | efx_mdio_write(efx, 3, 0xe854, 0x0040); | ||
131 | msleep(50); | ||
132 | } | ||
133 | |||
134 | static int qt2025c_wait_reset(struct efx_nic *efx) | ||
135 | { | ||
136 | int rc; | ||
137 | |||
138 | rc = qt2025c_wait_heartbeat(efx); | ||
139 | if (rc != 0) | ||
140 | return rc; | ||
141 | |||
142 | rc = qt2025c_wait_fw_status_good(efx); | ||
143 | if (rc == -ETIMEDOUT) { | ||
144 | /* Bug 17689: occasionally heartbeat starts but firmware status | ||
145 | * code never progresses beyond 0x00. Try again, once, after | ||
146 | * restarting execution of the firmware image. */ | ||
147 | EFX_LOG(efx, "bashing QT2025C microcontroller\n"); | ||
148 | qt2025c_restart_firmware(efx); | ||
149 | rc = qt2025c_wait_heartbeat(efx); | ||
150 | if (rc != 0) | ||
151 | return rc; | ||
152 | rc = qt2025c_wait_fw_status_good(efx); | ||
153 | } | ||
154 | |||
155 | return rc; | ||
156 | } | ||
157 | |||
158 | static void qt2025c_firmware_id(struct efx_nic *efx) | ||
159 | { | ||
160 | struct qt202x_phy_data *phy_data = efx->phy_data; | ||
161 | u8 firmware_id[9]; | ||
162 | size_t i; | ||
163 | |||
164 | for (i = 0; i < sizeof(firmware_id); i++) | ||
165 | firmware_id[i] = efx_mdio_read(efx, MDIO_MMD_PCS, | ||
166 | PCS_FW_PRODUCT_CODE_1 + i); | ||
167 | EFX_INFO(efx, "QT2025C firmware %xr%d v%d.%d.%d.%d [20%02d-%02d-%02d]\n", | ||
168 | (firmware_id[0] << 8) | firmware_id[1], firmware_id[2], | ||
169 | firmware_id[3] >> 4, firmware_id[3] & 0xf, | ||
170 | firmware_id[4], firmware_id[5], | ||
171 | firmware_id[6], firmware_id[7], firmware_id[8]); | ||
172 | phy_data->firmware_ver = ((firmware_id[3] & 0xf0) << 20) | | ||
173 | ((firmware_id[3] & 0x0f) << 16) | | ||
174 | (firmware_id[4] << 8) | firmware_id[5]; | ||
175 | } | ||
176 | |||
177 | static void qt2025c_bug17190_workaround(struct efx_nic *efx) | ||
178 | { | ||
179 | struct qt202x_phy_data *phy_data = efx->phy_data; | ||
180 | |||
181 | /* The PHY can get stuck in a state where it reports PHY_XS and PMA/PMD | ||
182 | * layers up, but PCS down (no block_lock). If we notice this state | ||
183 | * persisting for a couple of seconds, we switch PMA/PMD loopback | ||
184 | * briefly on and then off again, which is normally sufficient to | ||
185 | * recover it. | ||
186 | */ | ||
187 | if (efx->link_state.up || | ||
188 | !efx_mdio_links_ok(efx, MDIO_DEVS_PMAPMD | MDIO_DEVS_PHYXS)) { | ||
189 | phy_data->bug17190_in_bad_state = false; | ||
190 | return; | ||
191 | } | ||
192 | |||
193 | if (!phy_data->bug17190_in_bad_state) { | ||
194 | phy_data->bug17190_in_bad_state = true; | ||
195 | phy_data->bug17190_timer = jiffies + BUG17190_INTERVAL; | ||
196 | return; | ||
197 | } | ||
198 | |||
199 | if (time_after_eq(jiffies, phy_data->bug17190_timer)) { | ||
200 | EFX_LOG(efx, "bashing QT2025C PMA/PMD\n"); | ||
201 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1, | ||
202 | MDIO_PMA_CTRL1_LOOPBACK, true); | ||
93 | msleep(100); | 203 | msleep(100); |
204 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_CTRL1, | ||
205 | MDIO_PMA_CTRL1_LOOPBACK, false); | ||
206 | phy_data->bug17190_timer = jiffies + BUG17190_INTERVAL; | ||
207 | } | ||
208 | } | ||
209 | |||
210 | static int qt2025c_select_phy_mode(struct efx_nic *efx) | ||
211 | { | ||
212 | struct qt202x_phy_data *phy_data = efx->phy_data; | ||
213 | struct falcon_board *board = falcon_board(efx); | ||
214 | int reg, rc, i; | ||
215 | uint16_t phy_op_mode; | ||
216 | |||
217 | /* Only 2.0.1.0+ PHY firmware supports the more optimal SFP+ | ||
218 | * Self-Configure mode. Don't attempt any switching if we encounter | ||
219 | * older firmware. */ | ||
220 | if (phy_data->firmware_ver < 0x02000100) | ||
221 | return 0; | ||
222 | |||
223 | /* In general we will get optimal behaviour in "SFP+ Self-Configure" | ||
224 | * mode; however, that powers down most of the PHY when no module is | ||
225 | * present, so we must use a different mode (any fixed mode will do) | ||
226 | * to be sure that loopbacks will work. */ | ||
227 | phy_op_mode = (efx->loopback_mode == LOOPBACK_NONE) ? 0x0038 : 0x0020; | ||
228 | |||
229 | /* Only change mode if really necessary */ | ||
230 | reg = efx_mdio_read(efx, 1, 0xc319); | ||
231 | if ((reg & 0x0038) == phy_op_mode) | ||
232 | return 0; | ||
233 | EFX_LOG(efx, "Switching PHY to mode 0x%04x\n", phy_op_mode); | ||
234 | |||
235 | /* This sequence replicates the register writes configured in the boot | ||
236 | * EEPROM (including the differences between board revisions), except | ||
237 | * that the operating mode is changed, and the PHY is prevented from | ||
238 | * unnecessarily reloading the main firmware image again. */ | ||
239 | efx_mdio_write(efx, 1, 0xc300, 0x0000); | ||
240 | /* (Note: this portion of the boot EEPROM sequence, which bit-bashes 9 | ||
241 | * STOPs onto the firmware/module I2C bus to reset it, varies across | ||
242 | * board revisions, as the bus is connected to different GPIO/LED | ||
243 | * outputs on the PHY.) */ | ||
244 | if (board->major == 0 && board->minor < 2) { | ||
245 | efx_mdio_write(efx, 1, 0xc303, 0x4498); | ||
246 | for (i = 0; i < 9; i++) { | ||
247 | efx_mdio_write(efx, 1, 0xc303, 0x4488); | ||
248 | efx_mdio_write(efx, 1, 0xc303, 0x4480); | ||
249 | efx_mdio_write(efx, 1, 0xc303, 0x4490); | ||
250 | efx_mdio_write(efx, 1, 0xc303, 0x4498); | ||
251 | } | ||
252 | } else { | ||
253 | efx_mdio_write(efx, 1, 0xc303, 0x0920); | ||
254 | efx_mdio_write(efx, 1, 0xd008, 0x0004); | ||
255 | for (i = 0; i < 9; i++) { | ||
256 | efx_mdio_write(efx, 1, 0xc303, 0x0900); | ||
257 | efx_mdio_write(efx, 1, 0xd008, 0x0005); | ||
258 | efx_mdio_write(efx, 1, 0xc303, 0x0920); | ||
259 | efx_mdio_write(efx, 1, 0xd008, 0x0004); | ||
260 | } | ||
261 | efx_mdio_write(efx, 1, 0xc303, 0x4900); | ||
262 | } | ||
263 | efx_mdio_write(efx, 1, 0xc303, 0x4900); | ||
264 | efx_mdio_write(efx, 1, 0xc302, 0x0004); | ||
265 | efx_mdio_write(efx, 1, 0xc316, 0x0013); | ||
266 | efx_mdio_write(efx, 1, 0xc318, 0x0054); | ||
267 | efx_mdio_write(efx, 1, 0xc319, phy_op_mode); | ||
268 | efx_mdio_write(efx, 1, 0xc31a, 0x0098); | ||
269 | efx_mdio_write(efx, 3, 0x0026, 0x0e00); | ||
270 | efx_mdio_write(efx, 3, 0x0027, 0x0013); | ||
271 | efx_mdio_write(efx, 3, 0x0028, 0xa528); | ||
272 | efx_mdio_write(efx, 1, 0xd006, 0x000a); | ||
273 | efx_mdio_write(efx, 1, 0xd007, 0x0009); | ||
274 | efx_mdio_write(efx, 1, 0xd008, 0x0004); | ||
275 | /* This additional write is not present in the boot EEPROM. It | ||
276 | * prevents the PHY's internal boot ROM doing another pointless (and | ||
277 | * slow) reload of the firmware image (the microcontroller's code | ||
278 | * memory is not affected by the microcontroller reset). */ | ||
279 | efx_mdio_write(efx, 1, 0xc317, 0x00ff); | ||
280 | efx_mdio_write(efx, 1, 0xc300, 0x0002); | ||
281 | msleep(20); | ||
282 | |||
283 | /* Restart microcontroller execution of firmware from RAM */ | ||
284 | qt2025c_restart_firmware(efx); | ||
285 | |||
286 | /* Wait for the microcontroller to be ready again */ | ||
287 | rc = qt2025c_wait_reset(efx); | ||
288 | if (rc < 0) { | ||
289 | EFX_ERR(efx, "PHY microcontroller reset during mode switch " | ||
290 | "timed out\n"); | ||
291 | return rc; | ||
94 | } | 292 | } |
95 | 293 | ||
96 | return 0; | 294 | return 0; |
@@ -137,6 +335,16 @@ static int qt202x_reset_phy(struct efx_nic *efx) | |||
137 | 335 | ||
138 | static int qt202x_phy_probe(struct efx_nic *efx) | 336 | static int qt202x_phy_probe(struct efx_nic *efx) |
139 | { | 337 | { |
338 | struct qt202x_phy_data *phy_data; | ||
339 | |||
340 | phy_data = kzalloc(sizeof(struct qt202x_phy_data), GFP_KERNEL); | ||
341 | if (!phy_data) | ||
342 | return -ENOMEM; | ||
343 | efx->phy_data = phy_data; | ||
344 | phy_data->phy_mode = efx->phy_mode; | ||
345 | phy_data->bug17190_in_bad_state = false; | ||
346 | phy_data->bug17190_timer = 0; | ||
347 | |||
140 | efx->mdio.mmds = QT202X_REQUIRED_DEVS; | 348 | efx->mdio.mmds = QT202X_REQUIRED_DEVS; |
141 | efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; | 349 | efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; |
142 | efx->loopback_modes = QT202X_LOOPBACKS | FALCON_XMAC_LOOPBACKS; | 350 | efx->loopback_modes = QT202X_LOOPBACKS | FALCON_XMAC_LOOPBACKS; |
@@ -145,7 +353,6 @@ static int qt202x_phy_probe(struct efx_nic *efx) | |||
145 | 353 | ||
146 | static int qt202x_phy_init(struct efx_nic *efx) | 354 | static int qt202x_phy_init(struct efx_nic *efx) |
147 | { | 355 | { |
148 | struct qt202x_phy_data *phy_data; | ||
149 | u32 devid; | 356 | u32 devid; |
150 | int rc; | 357 | int rc; |
151 | 358 | ||
@@ -155,17 +362,14 @@ static int qt202x_phy_init(struct efx_nic *efx) | |||
155 | return rc; | 362 | return rc; |
156 | } | 363 | } |
157 | 364 | ||
158 | phy_data = kzalloc(sizeof(struct qt202x_phy_data), GFP_KERNEL); | ||
159 | if (!phy_data) | ||
160 | return -ENOMEM; | ||
161 | efx->phy_data = phy_data; | ||
162 | |||
163 | devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS); | 365 | devid = efx_mdio_read_id(efx, MDIO_MMD_PHYXS); |
164 | EFX_INFO(efx, "PHY ID reg %x (OUI %06x model %02x revision %x)\n", | 366 | EFX_INFO(efx, "PHY ID reg %x (OUI %06x model %02x revision %x)\n", |
165 | devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid), | 367 | devid, efx_mdio_id_oui(devid), efx_mdio_id_model(devid), |
166 | efx_mdio_id_rev(devid)); | 368 | efx_mdio_id_rev(devid)); |
167 | 369 | ||
168 | phy_data->phy_mode = efx->phy_mode; | 370 | if (efx->phy_type == PHY_TYPE_QT2025C) |
371 | qt2025c_firmware_id(efx); | ||
372 | |||
169 | return 0; | 373 | return 0; |
170 | } | 374 | } |
171 | 375 | ||
@@ -183,6 +387,9 @@ static bool qt202x_phy_poll(struct efx_nic *efx) | |||
183 | efx->link_state.fd = true; | 387 | efx->link_state.fd = true; |
184 | efx->link_state.fc = efx->wanted_fc; | 388 | efx->link_state.fc = efx->wanted_fc; |
185 | 389 | ||
390 | if (efx->phy_type == PHY_TYPE_QT2025C) | ||
391 | qt2025c_bug17190_workaround(efx); | ||
392 | |||
186 | return efx->link_state.up != was_up; | 393 | return efx->link_state.up != was_up; |
187 | } | 394 | } |
188 | 395 | ||
@@ -191,6 +398,10 @@ static int qt202x_phy_reconfigure(struct efx_nic *efx) | |||
191 | struct qt202x_phy_data *phy_data = efx->phy_data; | 398 | struct qt202x_phy_data *phy_data = efx->phy_data; |
192 | 399 | ||
193 | if (efx->phy_type == PHY_TYPE_QT2025C) { | 400 | if (efx->phy_type == PHY_TYPE_QT2025C) { |
401 | int rc = qt2025c_select_phy_mode(efx); | ||
402 | if (rc) | ||
403 | return rc; | ||
404 | |||
194 | /* There are several different register bits which can | 405 | /* There are several different register bits which can |
195 | * disable TX (and save power) on direct-attach cables | 406 | * disable TX (and save power) on direct-attach cables |
196 | * or optical transceivers, varying somewhat between | 407 | * or optical transceivers, varying somewhat between |
@@ -224,7 +435,7 @@ static void qt202x_phy_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecm | |||
224 | mdio45_ethtool_gset(&efx->mdio, ecmd); | 435 | mdio45_ethtool_gset(&efx->mdio, ecmd); |
225 | } | 436 | } |
226 | 437 | ||
227 | static void qt202x_phy_fini(struct efx_nic *efx) | 438 | static void qt202x_phy_remove(struct efx_nic *efx) |
228 | { | 439 | { |
229 | /* Free the context block */ | 440 | /* Free the context block */ |
230 | kfree(efx->phy_data); | 441 | kfree(efx->phy_data); |
@@ -236,7 +447,8 @@ struct efx_phy_operations falcon_qt202x_phy_ops = { | |||
236 | .init = qt202x_phy_init, | 447 | .init = qt202x_phy_init, |
237 | .reconfigure = qt202x_phy_reconfigure, | 448 | .reconfigure = qt202x_phy_reconfigure, |
238 | .poll = qt202x_phy_poll, | 449 | .poll = qt202x_phy_poll, |
239 | .fini = qt202x_phy_fini, | 450 | .fini = efx_port_dummy_op_void, |
451 | .remove = qt202x_phy_remove, | ||
240 | .get_settings = qt202x_phy_get_settings, | 452 | .get_settings = qt202x_phy_get_settings, |
241 | .set_settings = efx_mdio_set_settings, | 453 | .set_settings = efx_mdio_set_settings, |
242 | }; | 454 | }; |
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index de07a4f031b2..f8c6771e66d8 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c | |||
@@ -133,6 +133,7 @@ static int siena_probe_port(struct efx_nic *efx) | |||
133 | 133 | ||
134 | void siena_remove_port(struct efx_nic *efx) | 134 | void siena_remove_port(struct efx_nic *efx) |
135 | { | 135 | { |
136 | efx->phy_op->remove(efx); | ||
136 | efx_nic_free_buffer(efx, &efx->stats_buffer); | 137 | efx_nic_free_buffer(efx, &efx->stats_buffer); |
137 | } | 138 | } |
138 | 139 | ||
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index ca11572a49a9..3009c297c135 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c | |||
@@ -202,10 +202,14 @@ static ssize_t set_phy_short_reach(struct device *dev, | |||
202 | int rc; | 202 | int rc; |
203 | 203 | ||
204 | rtnl_lock(); | 204 | rtnl_lock(); |
205 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR, | 205 | if (efx->state != STATE_RUNNING) { |
206 | MDIO_PMA_10GBT_TXPWR_SHORT, | 206 | rc = -EBUSY; |
207 | count != 0 && *buf != '0'); | 207 | } else { |
208 | rc = efx_reconfigure_port(efx); | 208 | efx_mdio_set_flag(efx, MDIO_MMD_PMAPMD, MDIO_PMA_10GBT_TXPWR, |
209 | MDIO_PMA_10GBT_TXPWR_SHORT, | ||
210 | count != 0 && *buf != '0'); | ||
211 | rc = efx_reconfigure_port(efx); | ||
212 | } | ||
209 | rtnl_unlock(); | 213 | rtnl_unlock(); |
210 | 214 | ||
211 | return rc < 0 ? rc : (ssize_t)count; | 215 | return rc < 0 ? rc : (ssize_t)count; |
@@ -298,36 +302,62 @@ static int tenxpress_init(struct efx_nic *efx) | |||
298 | return 0; | 302 | return 0; |
299 | } | 303 | } |
300 | 304 | ||
301 | static int sfx7101_phy_probe(struct efx_nic *efx) | 305 | static int tenxpress_phy_probe(struct efx_nic *efx) |
302 | { | 306 | { |
303 | efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; | 307 | struct tenxpress_phy_data *phy_data; |
304 | efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; | 308 | int rc; |
305 | efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS; | 309 | |
306 | return 0; | 310 | /* Allocate phy private storage */ |
307 | } | 311 | phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); |
312 | if (!phy_data) | ||
313 | return -ENOMEM; | ||
314 | efx->phy_data = phy_data; | ||
315 | phy_data->phy_mode = efx->phy_mode; | ||
316 | |||
317 | /* Create any special files */ | ||
318 | if (efx->phy_type == PHY_TYPE_SFT9001B) { | ||
319 | rc = device_create_file(&efx->pci_dev->dev, | ||
320 | &dev_attr_phy_short_reach); | ||
321 | if (rc) | ||
322 | goto fail; | ||
323 | } | ||
324 | |||
325 | if (efx->phy_type == PHY_TYPE_SFX7101) { | ||
326 | efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; | ||
327 | efx->mdio.mode_support = MDIO_SUPPORTS_C45; | ||
328 | |||
329 | efx->loopback_modes = SFX7101_LOOPBACKS | FALCON_XMAC_LOOPBACKS; | ||
330 | |||
331 | efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | | ||
332 | ADVERTISED_10000baseT_Full); | ||
333 | } else { | ||
334 | efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; | ||
335 | efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; | ||
336 | |||
337 | efx->loopback_modes = (SFT9001_LOOPBACKS | | ||
338 | FALCON_XMAC_LOOPBACKS | | ||
339 | FALCON_GMAC_LOOPBACKS); | ||
340 | |||
341 | efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | | ||
342 | ADVERTISED_10000baseT_Full | | ||
343 | ADVERTISED_1000baseT_Full | | ||
344 | ADVERTISED_100baseT_Full); | ||
345 | } | ||
308 | 346 | ||
309 | static int sft9001_phy_probe(struct efx_nic *efx) | ||
310 | { | ||
311 | efx->mdio.mmds = TENXPRESS_REQUIRED_DEVS; | ||
312 | efx->mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_EMULATE_C22; | ||
313 | efx->loopback_modes = (SFT9001_LOOPBACKS | FALCON_XMAC_LOOPBACKS | | ||
314 | FALCON_GMAC_LOOPBACKS); | ||
315 | return 0; | 347 | return 0; |
348 | |||
349 | fail: | ||
350 | kfree(efx->phy_data); | ||
351 | efx->phy_data = NULL; | ||
352 | return rc; | ||
316 | } | 353 | } |
317 | 354 | ||
318 | static int tenxpress_phy_init(struct efx_nic *efx) | 355 | static int tenxpress_phy_init(struct efx_nic *efx) |
319 | { | 356 | { |
320 | struct tenxpress_phy_data *phy_data; | 357 | int rc; |
321 | int rc = 0; | ||
322 | 358 | ||
323 | falcon_board(efx)->type->init_phy(efx); | 359 | falcon_board(efx)->type->init_phy(efx); |
324 | 360 | ||
325 | phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL); | ||
326 | if (!phy_data) | ||
327 | return -ENOMEM; | ||
328 | efx->phy_data = phy_data; | ||
329 | phy_data->phy_mode = efx->phy_mode; | ||
330 | |||
331 | if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { | 361 | if (!(efx->phy_mode & PHY_MODE_SPECIAL)) { |
332 | if (efx->phy_type == PHY_TYPE_SFT9001A) { | 362 | if (efx->phy_type == PHY_TYPE_SFT9001A) { |
333 | int reg; | 363 | int reg; |
@@ -341,44 +371,27 @@ static int tenxpress_phy_init(struct efx_nic *efx) | |||
341 | 371 | ||
342 | rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); | 372 | rc = efx_mdio_wait_reset_mmds(efx, TENXPRESS_REQUIRED_DEVS); |
343 | if (rc < 0) | 373 | if (rc < 0) |
344 | goto fail; | 374 | return rc; |
345 | 375 | ||
346 | rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); | 376 | rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); |
347 | if (rc < 0) | 377 | if (rc < 0) |
348 | goto fail; | 378 | return rc; |
349 | } | 379 | } |
350 | 380 | ||
351 | rc = tenxpress_init(efx); | 381 | rc = tenxpress_init(efx); |
352 | if (rc < 0) | 382 | if (rc < 0) |
353 | goto fail; | 383 | return rc; |
354 | 384 | ||
355 | /* Initialise advertising flags */ | 385 | /* Reinitialise flow control settings */ |
356 | efx->link_advertising = (ADVERTISED_TP | ADVERTISED_Autoneg | | ||
357 | ADVERTISED_10000baseT_Full); | ||
358 | if (efx->phy_type != PHY_TYPE_SFX7101) | ||
359 | efx->link_advertising |= (ADVERTISED_1000baseT_Full | | ||
360 | ADVERTISED_100baseT_Full); | ||
361 | efx_link_set_wanted_fc(efx, efx->wanted_fc); | 386 | efx_link_set_wanted_fc(efx, efx->wanted_fc); |
362 | efx_mdio_an_reconfigure(efx); | 387 | efx_mdio_an_reconfigure(efx); |
363 | 388 | ||
364 | if (efx->phy_type == PHY_TYPE_SFT9001B) { | ||
365 | rc = device_create_file(&efx->pci_dev->dev, | ||
366 | &dev_attr_phy_short_reach); | ||
367 | if (rc) | ||
368 | goto fail; | ||
369 | } | ||
370 | |||
371 | schedule_timeout_uninterruptible(HZ / 5); /* 200ms */ | 389 | schedule_timeout_uninterruptible(HZ / 5); /* 200ms */ |
372 | 390 | ||
373 | /* Let XGXS and SerDes out of reset */ | 391 | /* Let XGXS and SerDes out of reset */ |
374 | falcon_reset_xaui(efx); | 392 | falcon_reset_xaui(efx); |
375 | 393 | ||
376 | return 0; | 394 | return 0; |
377 | |||
378 | fail: | ||
379 | kfree(efx->phy_data); | ||
380 | efx->phy_data = NULL; | ||
381 | return rc; | ||
382 | } | 395 | } |
383 | 396 | ||
384 | /* Perform a "special software reset" on the PHY. The caller is | 397 | /* Perform a "special software reset" on the PHY. The caller is |
@@ -589,25 +602,26 @@ static bool tenxpress_phy_poll(struct efx_nic *efx) | |||
589 | return !efx_link_state_equal(&efx->link_state, &old_state); | 602 | return !efx_link_state_equal(&efx->link_state, &old_state); |
590 | } | 603 | } |
591 | 604 | ||
592 | static void tenxpress_phy_fini(struct efx_nic *efx) | 605 | static void sfx7101_phy_fini(struct efx_nic *efx) |
593 | { | 606 | { |
594 | int reg; | 607 | int reg; |
595 | 608 | ||
609 | /* Power down the LNPGA */ | ||
610 | reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); | ||
611 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); | ||
612 | |||
613 | /* Waiting here ensures that the board fini, which can turn | ||
614 | * off the power to the PHY, won't get run until the LNPGA | ||
615 | * powerdown has been given long enough to complete. */ | ||
616 | schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */ | ||
617 | } | ||
618 | |||
619 | static void tenxpress_phy_remove(struct efx_nic *efx) | ||
620 | { | ||
596 | if (efx->phy_type == PHY_TYPE_SFT9001B) | 621 | if (efx->phy_type == PHY_TYPE_SFT9001B) |
597 | device_remove_file(&efx->pci_dev->dev, | 622 | device_remove_file(&efx->pci_dev->dev, |
598 | &dev_attr_phy_short_reach); | 623 | &dev_attr_phy_short_reach); |
599 | 624 | ||
600 | if (efx->phy_type == PHY_TYPE_SFX7101) { | ||
601 | /* Power down the LNPGA */ | ||
602 | reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN); | ||
603 | efx_mdio_write(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG, reg); | ||
604 | |||
605 | /* Waiting here ensures that the board fini, which can turn | ||
606 | * off the power to the PHY, won't get run until the LNPGA | ||
607 | * powerdown has been given long enough to complete. */ | ||
608 | schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */ | ||
609 | } | ||
610 | |||
611 | kfree(efx->phy_data); | 625 | kfree(efx->phy_data); |
612 | efx->phy_data = NULL; | 626 | efx->phy_data = NULL; |
613 | } | 627 | } |
@@ -819,11 +833,12 @@ static void sft9001_set_npage_adv(struct efx_nic *efx, u32 advertising) | |||
819 | } | 833 | } |
820 | 834 | ||
821 | struct efx_phy_operations falcon_sfx7101_phy_ops = { | 835 | struct efx_phy_operations falcon_sfx7101_phy_ops = { |
822 | .probe = sfx7101_phy_probe, | 836 | .probe = tenxpress_phy_probe, |
823 | .init = tenxpress_phy_init, | 837 | .init = tenxpress_phy_init, |
824 | .reconfigure = tenxpress_phy_reconfigure, | 838 | .reconfigure = tenxpress_phy_reconfigure, |
825 | .poll = tenxpress_phy_poll, | 839 | .poll = tenxpress_phy_poll, |
826 | .fini = tenxpress_phy_fini, | 840 | .fini = sfx7101_phy_fini, |
841 | .remove = tenxpress_phy_remove, | ||
827 | .get_settings = tenxpress_get_settings, | 842 | .get_settings = tenxpress_get_settings, |
828 | .set_settings = tenxpress_set_settings, | 843 | .set_settings = tenxpress_set_settings, |
829 | .set_npage_adv = sfx7101_set_npage_adv, | 844 | .set_npage_adv = sfx7101_set_npage_adv, |
@@ -832,11 +847,12 @@ struct efx_phy_operations falcon_sfx7101_phy_ops = { | |||
832 | }; | 847 | }; |
833 | 848 | ||
834 | struct efx_phy_operations falcon_sft9001_phy_ops = { | 849 | struct efx_phy_operations falcon_sft9001_phy_ops = { |
835 | .probe = sft9001_phy_probe, | 850 | .probe = tenxpress_phy_probe, |
836 | .init = tenxpress_phy_init, | 851 | .init = tenxpress_phy_init, |
837 | .reconfigure = tenxpress_phy_reconfigure, | 852 | .reconfigure = tenxpress_phy_reconfigure, |
838 | .poll = tenxpress_phy_poll, | 853 | .poll = tenxpress_phy_poll, |
839 | .fini = tenxpress_phy_fini, | 854 | .fini = efx_port_dummy_op_void, |
855 | .remove = tenxpress_phy_remove, | ||
840 | .get_settings = tenxpress_get_settings, | 856 | .get_settings = tenxpress_get_settings, |
841 | .set_settings = tenxpress_set_settings, | 857 | .set_settings = tenxpress_set_settings, |
842 | .set_npage_adv = sft9001_set_npage_adv, | 858 | .set_npage_adv = sft9001_set_npage_adv, |
diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c index e669f94e821b..a8b70ef6d817 100644 --- a/drivers/net/sfc/tx.c +++ b/drivers/net/sfc/tx.c | |||
@@ -821,8 +821,6 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) | |||
821 | EFX_TXQ_MASK]; | 821 | EFX_TXQ_MASK]; |
822 | efx_tsoh_free(tx_queue, buffer); | 822 | efx_tsoh_free(tx_queue, buffer); |
823 | EFX_BUG_ON_PARANOID(buffer->skb); | 823 | EFX_BUG_ON_PARANOID(buffer->skb); |
824 | buffer->len = 0; | ||
825 | buffer->continuation = true; | ||
826 | if (buffer->unmap_len) { | 824 | if (buffer->unmap_len) { |
827 | unmap_addr = (buffer->dma_addr + buffer->len - | 825 | unmap_addr = (buffer->dma_addr + buffer->len - |
828 | buffer->unmap_len); | 826 | buffer->unmap_len); |
@@ -836,6 +834,8 @@ static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) | |||
836 | PCI_DMA_TODEVICE); | 834 | PCI_DMA_TODEVICE); |
837 | buffer->unmap_len = 0; | 835 | buffer->unmap_len = 0; |
838 | } | 836 | } |
837 | buffer->len = 0; | ||
838 | buffer->continuation = true; | ||
839 | } | 839 | } |
840 | } | 840 | } |
841 | 841 | ||