aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc/mdio_10g.c
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2008-12-13 00:50:46 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-13 00:58:17 -0500
commit04cc8cacb01c09fba2297faf1477cd570ba43f0b (patch)
treef17dbd584b072d14f1500c6f6d659be993ae35c7 /drivers/net/sfc/mdio_10g.c
parent177dfcd80f28f8fbc3e22c2d8b24d21cb86f1d97 (diff)
sfc: Implement auto-negotiation
Add infrastructure for auto-negotiation of speed, duplex and flow control. When using 10Xpress, auto-negotiate flow control. While we're at it, clean up the code to warn when partner is not 10GBASE-T capable. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/mdio_10g.c')
-rw-r--r--drivers/net/sfc/mdio_10g.c348
1 files changed, 277 insertions, 71 deletions
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
index 8d91131aa5ab..037601e0b9d7 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/sfc/mdio_10g.c
@@ -47,13 +47,16 @@ static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd,
47 if (LOOPBACK_INTERNAL(efx)) 47 if (LOOPBACK_INTERNAL(efx))
48 return 0; 48 return 0;
49 49
50 /* Read MMD STATUS2 to check it is responding. */ 50 if (mmd != MDIO_MMD_AN) {
51 status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT2); 51 /* Read MMD STATUS2 to check it is responding. */
52 if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) & 52 status = mdio_clause45_read(efx, phy_id, mmd,
53 ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) != 53 MDIO_MMDREG_STAT2);
54 MDIO_MMDREG_STAT2_PRESENT_VAL) { 54 if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) &
55 EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd); 55 ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) !=
56 return -EIO; 56 MDIO_MMDREG_STAT2_PRESENT_VAL) {
57 EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd);
58 return -EIO;
59 }
57 } 60 }
58 61
59 /* Read MMD STATUS 1 to check for fault. */ 62 /* Read MMD STATUS 1 to check for fault. */
@@ -179,12 +182,15 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
179 else if (efx->loopback_mode == LOOPBACK_PHYXS) 182 else if (efx->loopback_mode == LOOPBACK_PHYXS)
180 mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS | 183 mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS |
181 MDIO_MMDREG_DEVS_PCS | 184 MDIO_MMDREG_DEVS_PCS |
182 MDIO_MMDREG_DEVS_PMAPMD); 185 MDIO_MMDREG_DEVS_PMAPMD |
186 MDIO_MMDREG_DEVS_AN);
183 else if (efx->loopback_mode == LOOPBACK_PCS) 187 else if (efx->loopback_mode == LOOPBACK_PCS)
184 mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS | 188 mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS |
185 MDIO_MMDREG_DEVS_PMAPMD); 189 MDIO_MMDREG_DEVS_PMAPMD |
190 MDIO_MMDREG_DEVS_AN);
186 else if (efx->loopback_mode == LOOPBACK_PMAPMD) 191 else if (efx->loopback_mode == LOOPBACK_PMAPMD)
187 mmd_mask &= ~MDIO_MMDREG_DEVS_PMAPMD; 192 mmd_mask &= ~(MDIO_MMDREG_DEVS_PMAPMD |
193 MDIO_MMDREG_DEVS_AN);
188 194
189 while (mmd_mask) { 195 while (mmd_mask) {
190 if (mmd_mask & 1) { 196 if (mmd_mask & 1) {
@@ -244,6 +250,7 @@ void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
244 int low_power, unsigned int mmd_mask) 250 int low_power, unsigned int mmd_mask)
245{ 251{
246 int mmd = 0; 252 int mmd = 0;
253 mmd_mask &= ~MDIO_MMDREG_DEVS_AN;
247 while (mmd_mask) { 254 while (mmd_mask) {
248 if (mmd_mask & 1) 255 if (mmd_mask & 1)
249 mdio_clause45_set_mmd_lpower(efx, low_power, mmd); 256 mdio_clause45_set_mmd_lpower(efx, low_power, mmd);
@@ -252,103 +259,302 @@ void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
252 } 259 }
253} 260}
254 261
262static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr, u32 xnp)
263{
264 int phy_id = efx->mii.phy_id;
265 u32 result = 0;
266 int reg;
267
268 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, addr);
269 if (reg & ADVERTISE_10HALF)
270 result |= ADVERTISED_10baseT_Half;
271 if (reg & ADVERTISE_10FULL)
272 result |= ADVERTISED_10baseT_Full;
273 if (reg & ADVERTISE_100HALF)
274 result |= ADVERTISED_100baseT_Half;
275 if (reg & ADVERTISE_100FULL)
276 result |= ADVERTISED_100baseT_Full;
277 if (reg & LPA_RESV)
278 result |= xnp;
279
280 return result;
281}
282
255/** 283/**
256 * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO. 284 * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO.
257 * @efx: Efx NIC 285 * @efx: Efx NIC
258 * @ecmd: Buffer for settings 286 * @ecmd: Buffer for settings
259 * 287 *
260 * On return the 'port', 'speed', 'supported' and 'advertising' fields of 288 * On return the 'port', 'speed', 'supported' and 'advertising' fields of
261 * ecmd have been filled out based on the PMA type. 289 * ecmd have been filled out.
262 */ 290 */
263void mdio_clause45_get_settings(struct efx_nic *efx, 291void mdio_clause45_get_settings(struct efx_nic *efx,
264 struct ethtool_cmd *ecmd) 292 struct ethtool_cmd *ecmd)
265{ 293{
266 int pma_type; 294 mdio_clause45_get_settings_ext(efx, ecmd, 0, 0);
295}
267 296
268 /* If no PMA is present we are presumably talking something XAUI-ish 297/**
269 * like CX4. Which we report as FIBRE (see below) */ 298 * mdio_clause45_get_settings_ext - Read (some of) the PHY settings over MDIO.
270 if ((efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)) == 0) { 299 * @efx: Efx NIC
271 ecmd->speed = SPEED_10000; 300 * @ecmd: Buffer for settings
272 ecmd->port = PORT_FIBRE; 301 * @xnp: Advertised Extended Next Page state
273 ecmd->supported = SUPPORTED_FIBRE; 302 * @xnp_lpa: Link Partner's advertised XNP state
274 ecmd->advertising = ADVERTISED_FIBRE; 303 *
275 return; 304 * On return the 'port', 'speed', 'supported' and 'advertising' fields of
276 } 305 * ecmd have been filled out.
306 */
307void mdio_clause45_get_settings_ext(struct efx_nic *efx,
308 struct ethtool_cmd *ecmd,
309 u32 xnp, u32 xnp_lpa)
310{
311 int phy_id = efx->mii.phy_id;
312 int reg;
277 313
278 pma_type = mdio_clause45_read(efx, efx->mii.phy_id, 314 ecmd->transceiver = XCVR_INTERNAL;
279 MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL2); 315 ecmd->phy_address = phy_id;
280 pma_type &= MDIO_PMAPMD_CTRL2_TYPE_MASK;
281 316
282 switch (pma_type) { 317 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
283 /* We represent CX4 as fibre in the absence of anything 318 MDIO_MMDREG_CTRL2);
284 better. */ 319 switch (reg & MDIO_PMAPMD_CTRL2_TYPE_MASK) {
285 case MDIO_PMAPMD_CTRL2_10G_CX4:
286 ecmd->speed = SPEED_10000;
287 ecmd->port = PORT_FIBRE;
288 ecmd->supported = SUPPORTED_FIBRE;
289 ecmd->advertising = ADVERTISED_FIBRE;
290 break;
291 /* 10G Base-T */
292 case MDIO_PMAPMD_CTRL2_10G_BT: 320 case MDIO_PMAPMD_CTRL2_10G_BT:
293 ecmd->speed = SPEED_10000;
294 ecmd->port = PORT_TP;
295 ecmd->supported = SUPPORTED_TP | SUPPORTED_10000baseT_Full;
296 ecmd->advertising = (ADVERTISED_FIBRE
297 | ADVERTISED_10000baseT_Full);
298 break;
299 case MDIO_PMAPMD_CTRL2_1G_BT: 321 case MDIO_PMAPMD_CTRL2_1G_BT:
300 ecmd->speed = SPEED_1000;
301 ecmd->port = PORT_TP;
302 ecmd->supported = SUPPORTED_TP | SUPPORTED_1000baseT_Full;
303 ecmd->advertising = (ADVERTISED_FIBRE
304 | ADVERTISED_1000baseT_Full);
305 break;
306 case MDIO_PMAPMD_CTRL2_100_BT: 322 case MDIO_PMAPMD_CTRL2_100_BT:
307 ecmd->speed = SPEED_100;
308 ecmd->port = PORT_TP;
309 ecmd->supported = SUPPORTED_TP | SUPPORTED_100baseT_Full;
310 ecmd->advertising = (ADVERTISED_FIBRE
311 | ADVERTISED_100baseT_Full);
312 break;
313 case MDIO_PMAPMD_CTRL2_10_BT: 323 case MDIO_PMAPMD_CTRL2_10_BT:
314 ecmd->speed = SPEED_10;
315 ecmd->port = PORT_TP; 324 ecmd->port = PORT_TP;
316 ecmd->supported = SUPPORTED_TP | SUPPORTED_10baseT_Full; 325 ecmd->supported = SUPPORTED_TP;
317 ecmd->advertising = ADVERTISED_FIBRE | ADVERTISED_10baseT_Full; 326 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
327 MDIO_MMDREG_SPEED);
328 if (reg & (1 << MDIO_MMDREG_SPEED_10G_LBN))
329 ecmd->supported |= SUPPORTED_10000baseT_Full;
330 if (reg & (1 << MDIO_MMDREG_SPEED_1000M_LBN))
331 ecmd->supported |= (SUPPORTED_1000baseT_Full |
332 SUPPORTED_1000baseT_Half);
333 if (reg & (1 << MDIO_MMDREG_SPEED_100M_LBN))
334 ecmd->supported |= (SUPPORTED_100baseT_Full |
335 SUPPORTED_100baseT_Half);
336 if (reg & (1 << MDIO_MMDREG_SPEED_10M_LBN))
337 ecmd->supported |= (SUPPORTED_10baseT_Full |
338 SUPPORTED_10baseT_Half);
339 ecmd->advertising = ADVERTISED_TP;
318 break; 340 break;
319 /* All the other defined modes are flavours of 341
320 * 10G optical */ 342 /* We represent CX4 as fibre in the absence of anything better */
343 case MDIO_PMAPMD_CTRL2_10G_CX4:
344 /* All the other defined modes are flavours of optical */
321 default: 345 default:
322 ecmd->speed = SPEED_10000;
323 ecmd->port = PORT_FIBRE; 346 ecmd->port = PORT_FIBRE;
324 ecmd->supported = SUPPORTED_FIBRE; 347 ecmd->supported = SUPPORTED_FIBRE;
325 ecmd->advertising = ADVERTISED_FIBRE; 348 ecmd->advertising = ADVERTISED_FIBRE;
326 break; 349 break;
327 } 350 }
351
352 if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) {
353 ecmd->supported |= SUPPORTED_Autoneg;
354 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
355 MDIO_MMDREG_CTRL1);
356 if (reg & BMCR_ANENABLE) {
357 ecmd->autoneg = AUTONEG_ENABLE;
358 ecmd->advertising |=
359 ADVERTISED_Autoneg |
360 mdio_clause45_get_an(efx,
361 MDIO_AN_ADVERTISE, xnp);
362 } else
363 ecmd->autoneg = AUTONEG_DISABLE;
364 } else
365 ecmd->autoneg = AUTONEG_DISABLE;
366
367 /* If AN is enabled and complete, report best common mode */
368 if (ecmd->autoneg &&
369 (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, MDIO_MMDREG_STAT1) &
370 (1 << MDIO_AN_STATUS_AN_DONE_LBN))) {
371 u32 common, lpa;
372 lpa = mdio_clause45_get_an(efx, MDIO_AN_LPA, xnp_lpa);
373 common = ecmd->advertising & lpa;
374 if (common & ADVERTISED_10000baseT_Full) {
375 ecmd->speed = SPEED_10000;
376 ecmd->duplex = DUPLEX_FULL;
377 } else if (common & (ADVERTISED_1000baseT_Full |
378 ADVERTISED_1000baseT_Half)) {
379 ecmd->speed = SPEED_1000;
380 ecmd->duplex = !!(common & ADVERTISED_1000baseT_Full);
381 } else if (common & (ADVERTISED_100baseT_Full |
382 ADVERTISED_100baseT_Half)) {
383 ecmd->speed = SPEED_100;
384 ecmd->duplex = !!(common & ADVERTISED_100baseT_Full);
385 } else {
386 ecmd->speed = SPEED_10;
387 ecmd->duplex = !!(common & ADVERTISED_10baseT_Full);
388 }
389 } else {
390 /* Report forced settings */
391 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
392 MDIO_MMDREG_CTRL1);
393 ecmd->speed = (((reg & BMCR_SPEED1000) ? 100 : 1) *
394 ((reg & BMCR_SPEED100) ? 100 : 10));
395 ecmd->duplex = (reg & BMCR_FULLDPLX ||
396 ecmd->speed == SPEED_10000);
397 }
328} 398}
329 399
330/** 400/**
331 * mdio_clause45_set_settings - Set (some of) the PHY settings over MDIO. 401 * mdio_clause45_set_settings - Set (some of) the PHY settings over MDIO.
332 * @efx: Efx NIC 402 * @efx: Efx NIC
333 * @ecmd: New settings 403 * @ecmd: New settings
334 *
335 * Currently this just enforces that we are _not_ changing the
336 * 'port', 'speed', 'supported' or 'advertising' settings as these
337 * cannot be changed on any currently supported PHY.
338 */ 404 */
339int mdio_clause45_set_settings(struct efx_nic *efx, 405int mdio_clause45_set_settings(struct efx_nic *efx,
340 struct ethtool_cmd *ecmd) 406 struct ethtool_cmd *ecmd)
341{ 407{
342 struct ethtool_cmd tmpcmd; 408 int phy_id = efx->mii.phy_id;
343 mdio_clause45_get_settings(efx, &tmpcmd); 409 struct ethtool_cmd prev;
344 /* None of the current PHYs support more than one mode 410 u32 required;
345 * of operation (and only 10GBT ever will), so keep things 411 int ctrl1_bits, reg;
346 * simple for now */ 412
347 if ((ecmd->speed == tmpcmd.speed) && (ecmd->port == tmpcmd.port) && 413 efx->phy_op->get_settings(efx, &prev);
348 (ecmd->supported == tmpcmd.supported) && 414
349 (ecmd->advertising == tmpcmd.advertising)) 415 if (ecmd->advertising == prev.advertising &&
416 ecmd->speed == prev.speed &&
417 ecmd->duplex == prev.duplex &&
418 ecmd->port == prev.port &&
419 ecmd->autoneg == prev.autoneg)
350 return 0; 420 return 0;
351 return -EOPNOTSUPP; 421
422 /* We can only change these settings for -T PHYs */
423 if (prev.port != PORT_TP || ecmd->port != PORT_TP)
424 return -EINVAL;
425
426 /* Check that PHY supports these settings and work out the
427 * basic control bits */
428 if (ecmd->duplex) {
429 switch (ecmd->speed) {
430 case SPEED_10:
431 ctrl1_bits = BMCR_FULLDPLX;
432 required = SUPPORTED_10baseT_Full;
433 break;
434 case SPEED_100:
435 ctrl1_bits = BMCR_SPEED100 | BMCR_FULLDPLX;
436 required = SUPPORTED_100baseT_Full;
437 break;
438 case SPEED_1000:
439 ctrl1_bits = BMCR_SPEED1000 | BMCR_FULLDPLX;
440 required = SUPPORTED_1000baseT_Full;
441 break;
442 case SPEED_10000:
443 ctrl1_bits = (BMCR_SPEED1000 | BMCR_SPEED100 |
444 BMCR_FULLDPLX);
445 required = SUPPORTED_10000baseT_Full;
446 break;
447 default:
448 return -EINVAL;
449 }
450 } else {
451 switch (ecmd->speed) {
452 case SPEED_10:
453 ctrl1_bits = 0;
454 required = SUPPORTED_10baseT_Half;
455 break;
456 case SPEED_100:
457 ctrl1_bits = BMCR_SPEED100;
458 required = SUPPORTED_100baseT_Half;
459 break;
460 case SPEED_1000:
461 ctrl1_bits = BMCR_SPEED1000;
462 required = SUPPORTED_1000baseT_Half;
463 break;
464 default:
465 return -EINVAL;
466 }
467 }
468 if (ecmd->autoneg)
469 required |= SUPPORTED_Autoneg;
470 required |= ecmd->advertising;
471 if (required & ~prev.supported)
472 return -EINVAL;
473
474 /* Set the basic control bits */
475 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
476 MDIO_MMDREG_CTRL1);
477 reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | 0x003c);
478 reg |= ctrl1_bits;
479 mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL1,
480 reg);
481
482 /* Set the AN registers */
483 if (ecmd->autoneg != prev.autoneg ||
484 ecmd->advertising != prev.advertising) {
485 bool xnp = false;
486
487 if (efx->phy_op->set_xnp_advertise)
488 xnp = efx->phy_op->set_xnp_advertise(efx,
489 ecmd->advertising);
490
491 if (ecmd->autoneg) {
492 reg = 0;
493 if (ecmd->advertising & ADVERTISED_10baseT_Half)
494 reg |= ADVERTISE_10HALF;
495 if (ecmd->advertising & ADVERTISED_10baseT_Full)
496 reg |= ADVERTISE_10FULL;
497 if (ecmd->advertising & ADVERTISED_100baseT_Half)
498 reg |= ADVERTISE_100HALF;
499 if (ecmd->advertising & ADVERTISED_100baseT_Full)
500 reg |= ADVERTISE_100FULL;
501 if (xnp)
502 reg |= ADVERTISE_RESV;
503 mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
504 MDIO_AN_ADVERTISE, reg);
505 }
506
507 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
508 MDIO_MMDREG_CTRL1);
509 if (ecmd->autoneg)
510 reg |= BMCR_ANENABLE | BMCR_ANRESTART;
511 else
512 reg &= ~BMCR_ANENABLE;
513 if (xnp)
514 reg |= 1 << MDIO_AN_CTRL_XNP_LBN;
515 else
516 reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN);
517 mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
518 MDIO_MMDREG_CTRL1, reg);
519 }
520
521 return 0;
522}
523
524void mdio_clause45_set_pause(struct efx_nic *efx)
525{
526 int phy_id = efx->mii.phy_id;
527 int reg;
528
529 if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) {
530 /* Set pause capability advertising */
531 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
532 MDIO_AN_ADVERTISE);
533 reg &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
534 reg |= efx_fc_advertise(efx->wanted_fc);
535 mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
536 MDIO_AN_ADVERTISE, reg);
537
538 /* Restart auto-negotiation */
539 reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
540 MDIO_MMDREG_CTRL1);
541 if (reg & BMCR_ANENABLE) {
542 reg |= BMCR_ANRESTART;
543 mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
544 MDIO_MMDREG_CTRL1, reg);
545 }
546 }
547}
548
549enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx)
550{
551 int phy_id = efx->mii.phy_id;
552 int lpa;
553
554 if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)))
555 return efx->wanted_fc;
556 lpa = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, MDIO_AN_LPA);
557 return efx_fc_resolve(efx->wanted_fc, lpa);
352} 558}
353 559
354void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev, 560void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev,