aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@vyatta.com>2009-08-14 18:36:41 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-14 18:36:41 -0400
commit0ea065e52eb6a0f029b5fa5ed2f142be1b66a153 (patch)
treef18bfc3027224f724ec00c6f4c0557e3f6861035 /drivers/net/sky2.c
parent481cea4a4d72aabe76dbb86b1a64f4e8931eca25 (diff)
sky2: fix pause negotiation
The sky2 driver combines auto speed negotiation with automatic negotiation of pause parameters; but the ethtool interface expects them to be split. This patch allows autonegotiation to be used for speed, but manually disable flow control. Signed-off-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r--drivers/net/sky2.c73
1 files changed, 47 insertions, 26 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 4944fcc6b07..6788a91d68d 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -321,7 +321,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
321 struct sky2_port *sky2 = netdev_priv(hw->dev[port]); 321 struct sky2_port *sky2 = netdev_priv(hw->dev[port]);
322 u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg; 322 u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg;
323 323
324 if (sky2->autoneg == AUTONEG_ENABLE && 324 if ( (sky2->flags & SKY2_FLAG_AUTO_SPEED) &&
325 !(hw->flags & SKY2_HW_NEWER_PHY)) { 325 !(hw->flags & SKY2_HW_NEWER_PHY)) {
326 u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); 326 u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL);
327 327
@@ -363,7 +363,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
363 ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO); 363 ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO);
364 364
365 /* downshift on PHY 88E1112 and 88E1149 is changed */ 365 /* downshift on PHY 88E1112 and 88E1149 is changed */
366 if (sky2->autoneg == AUTONEG_ENABLE 366 if ( (sky2->flags & SKY2_FLAG_AUTO_SPEED)
367 && (hw->flags & SKY2_HW_NEWER_PHY)) { 367 && (hw->flags & SKY2_HW_NEWER_PHY)) {
368 /* set downshift counter to 3x and enable downshift */ 368 /* set downshift counter to 3x and enable downshift */
369 ctrl &= ~PHY_M_PC_DSC_MSK; 369 ctrl &= ~PHY_M_PC_DSC_MSK;
@@ -408,7 +408,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
408 adv = PHY_AN_CSMA; 408 adv = PHY_AN_CSMA;
409 reg = 0; 409 reg = 0;
410 410
411 if (sky2->autoneg == AUTONEG_ENABLE) { 411 if (sky2->flags & SKY2_FLAG_AUTO_SPEED) {
412 if (sky2_is_copper(hw)) { 412 if (sky2_is_copper(hw)) {
413 if (sky2->advertising & ADVERTISED_1000baseT_Full) 413 if (sky2->advertising & ADVERTISED_1000baseT_Full)
414 ct1000 |= PHY_M_1000C_AFD; 414 ct1000 |= PHY_M_1000C_AFD;
@@ -423,14 +423,11 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
423 if (sky2->advertising & ADVERTISED_10baseT_Half) 423 if (sky2->advertising & ADVERTISED_10baseT_Half)
424 adv |= PHY_M_AN_10_HD; 424 adv |= PHY_M_AN_10_HD;
425 425
426 adv |= copper_fc_adv[sky2->flow_mode];
427 } else { /* special defines for FIBER (88E1040S only) */ 426 } else { /* special defines for FIBER (88E1040S only) */
428 if (sky2->advertising & ADVERTISED_1000baseT_Full) 427 if (sky2->advertising & ADVERTISED_1000baseT_Full)
429 adv |= PHY_M_AN_1000X_AFD; 428 adv |= PHY_M_AN_1000X_AFD;
430 if (sky2->advertising & ADVERTISED_1000baseT_Half) 429 if (sky2->advertising & ADVERTISED_1000baseT_Half)
431 adv |= PHY_M_AN_1000X_AHD; 430 adv |= PHY_M_AN_1000X_AHD;
432
433 adv |= fiber_fc_adv[sky2->flow_mode];
434 } 431 }
435 432
436 /* Restart Auto-negotiation */ 433 /* Restart Auto-negotiation */
@@ -439,8 +436,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
439 /* forced speed/duplex settings */ 436 /* forced speed/duplex settings */
440 ct1000 = PHY_M_1000C_MSE; 437 ct1000 = PHY_M_1000C_MSE;
441 438
442 /* Disable auto update for duplex flow control and speed */ 439 /* Disable auto update for duplex flow control and duplex */
443 reg |= GM_GPCR_AU_ALL_DIS; 440 reg |= GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_SPD_DIS;
444 441
445 switch (sky2->speed) { 442 switch (sky2->speed) {
446 case SPEED_1000: 443 case SPEED_1000:
@@ -458,8 +455,15 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
458 ctrl |= PHY_CT_DUP_MD; 455 ctrl |= PHY_CT_DUP_MD;
459 } else if (sky2->speed < SPEED_1000) 456 } else if (sky2->speed < SPEED_1000)
460 sky2->flow_mode = FC_NONE; 457 sky2->flow_mode = FC_NONE;
458 }
461 459
462 460 if (sky2->flags & SKY2_FLAG_AUTO_PAUSE) {
461 if (sky2_is_copper(hw))
462 adv |= copper_fc_adv[sky2->flow_mode];
463 else
464 adv |= fiber_fc_adv[sky2->flow_mode];
465 } else {
466 reg |= GM_GPCR_AU_FCT_DIS;
463 reg |= gm_fc_disable[sky2->flow_mode]; 467 reg |= gm_fc_disable[sky2->flow_mode];
464 468
465 /* Forward pause packets to GMAC? */ 469 /* Forward pause packets to GMAC? */
@@ -594,7 +598,8 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
594 /* no effect on Yukon-XL */ 598 /* no effect on Yukon-XL */
595 gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); 599 gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
596 600
597 if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { 601 if ( !(sky2->flags & SKY2_FLAG_AUTO_SPEED)
602 || sky2->speed == SPEED_100) {
598 /* turn on 100 Mbps LED (LED_LINK100) */ 603 /* turn on 100 Mbps LED (LED_LINK100) */
599 ledover |= PHY_M_LED_MO_100(MO_LED_ON); 604 ledover |= PHY_M_LED_MO_100(MO_LED_ON);
600 } 605 }
@@ -605,7 +610,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
605 } 610 }
606 611
607 /* Enable phy interrupt on auto-negotiation complete (or link up) */ 612 /* Enable phy interrupt on auto-negotiation complete (or link up) */
608 if (sky2->autoneg == AUTONEG_ENABLE) 613 if (sky2->flags & SKY2_FLAG_AUTO_SPEED)
609 gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); 614 gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL);
610 else 615 else
611 gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); 616 gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
@@ -661,7 +666,9 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port)
661 666
662 /* setup General Purpose Control Register */ 667 /* setup General Purpose Control Register */
663 gma_write16(hw, port, GM_GP_CTRL, 668 gma_write16(hw, port, GM_GP_CTRL,
664 GM_GPCR_FL_PASS | GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS); 669 GM_GPCR_FL_PASS | GM_GPCR_SPEED_100 |
670 GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |
671 GM_GPCR_AU_SPD_DIS);
665 672
666 if (hw->chip_id != CHIP_ID_YUKON_EC) { 673 if (hw->chip_id != CHIP_ID_YUKON_EC) {
667 if (hw->chip_id == CHIP_ID_YUKON_EC_U) { 674 if (hw->chip_id == CHIP_ID_YUKON_EC_U) {
@@ -1117,7 +1124,8 @@ static void rx_set_checksum(struct sky2_port *sky2)
1117 1124
1118 sky2_write32(sky2->hw, 1125 sky2_write32(sky2->hw,
1119 Q_ADDR(rxqaddr[sky2->port], Q_CSR), 1126 Q_ADDR(rxqaddr[sky2->port], Q_CSR),
1120 sky2->rx_csum ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); 1127 (sky2->flags & SKY2_FLAG_RX_CHECKSUM)
1128 ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
1121} 1129}
1122 1130
1123/* 1131/*
@@ -2087,7 +2095,7 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port)
2087 printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n", 2095 printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n",
2088 sky2->netdev->name, istatus, phystat); 2096 sky2->netdev->name, istatus, phystat);
2089 2097
2090 if (sky2->autoneg == AUTONEG_ENABLE && (istatus & PHY_M_IS_AN_COMPL)) { 2098 if (istatus & PHY_M_IS_AN_COMPL) {
2091 if (sky2_autoneg_done(sky2, phystat) == 0) 2099 if (sky2_autoneg_done(sky2, phystat) == 0)
2092 sky2_link_up(sky2); 2100 sky2_link_up(sky2);
2093 goto out; 2101 goto out;
@@ -2453,7 +2461,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
2453 2461
2454 /* This chip reports checksum status differently */ 2462 /* This chip reports checksum status differently */
2455 if (hw->flags & SKY2_HW_NEW_LE) { 2463 if (hw->flags & SKY2_HW_NEW_LE) {
2456 if (sky2->rx_csum && 2464 if ((sky2->flags & SKY2_FLAG_RX_CHECKSUM) &&
2457 (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) && 2465 (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
2458 (le->css & CSS_TCPUDPCSOK)) 2466 (le->css & CSS_TCPUDPCSOK))
2459 skb->ip_summed = CHECKSUM_UNNECESSARY; 2467 skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -2480,7 +2488,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
2480 /* fall through */ 2488 /* fall through */
2481#endif 2489#endif
2482 case OP_RXCHKS: 2490 case OP_RXCHKS:
2483 if (!sky2->rx_csum) 2491 if (!(sky2->flags & SKY2_FLAG_RX_CHECKSUM))
2484 break; 2492 break;
2485 2493
2486 /* If this happens then driver assuming wrong format */ 2494 /* If this happens then driver assuming wrong format */
@@ -2505,7 +2513,8 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do, u16 idx)
2505 printk(KERN_NOTICE PFX "%s: hardware receive " 2513 printk(KERN_NOTICE PFX "%s: hardware receive "
2506 "checksum problem (status = %#x)\n", 2514 "checksum problem (status = %#x)\n",
2507 dev->name, status); 2515 dev->name, status);
2508 sky2->rx_csum = 0; 2516 sky2->flags &= ~SKY2_FLAG_RX_CHECKSUM;
2517
2509 sky2_write32(sky2->hw, 2518 sky2_write32(sky2->hw,
2510 Q_ADDR(rxqaddr[port], Q_CSR), 2519 Q_ADDR(rxqaddr[port], Q_CSR),
2511 BMU_DIS_RX_CHKSUM); 2520 BMU_DIS_RX_CHKSUM);
@@ -3206,7 +3215,8 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
3206 } 3215 }
3207 3216
3208 ecmd->advertising = sky2->advertising; 3217 ecmd->advertising = sky2->advertising;
3209 ecmd->autoneg = sky2->autoneg; 3218 ecmd->autoneg = (sky2->flags & SKY2_FLAG_AUTO_SPEED)
3219 ? AUTONEG_ENABLE : AUTONEG_DISABLE;
3210 ecmd->duplex = sky2->duplex; 3220 ecmd->duplex = sky2->duplex;
3211 return 0; 3221 return 0;
3212} 3222}
@@ -3218,6 +3228,7 @@ static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
3218 u32 supported = sky2_supported_modes(hw); 3228 u32 supported = sky2_supported_modes(hw);
3219 3229
3220 if (ecmd->autoneg == AUTONEG_ENABLE) { 3230 if (ecmd->autoneg == AUTONEG_ENABLE) {
3231 sky2->flags |= SKY2_FLAG_AUTO_SPEED;
3221 ecmd->advertising = supported; 3232 ecmd->advertising = supported;
3222 sky2->duplex = -1; 3233 sky2->duplex = -1;
3223 sky2->speed = -1; 3234 sky2->speed = -1;
@@ -3259,9 +3270,9 @@ static int sky2_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
3259 3270
3260 sky2->speed = ecmd->speed; 3271 sky2->speed = ecmd->speed;
3261 sky2->duplex = ecmd->duplex; 3272 sky2->duplex = ecmd->duplex;
3273 sky2->flags &= ~SKY2_FLAG_AUTO_SPEED;
3262 } 3274 }
3263 3275
3264 sky2->autoneg = ecmd->autoneg;
3265 sky2->advertising = ecmd->advertising; 3276 sky2->advertising = ecmd->advertising;
3266 3277
3267 if (netif_running(dev)) { 3278 if (netif_running(dev)) {
@@ -3331,14 +3342,17 @@ static u32 sky2_get_rx_csum(struct net_device *dev)
3331{ 3342{
3332 struct sky2_port *sky2 = netdev_priv(dev); 3343 struct sky2_port *sky2 = netdev_priv(dev);
3333 3344
3334 return sky2->rx_csum; 3345 return !!(sky2->flags & SKY2_FLAG_RX_CHECKSUM);
3335} 3346}
3336 3347
3337static int sky2_set_rx_csum(struct net_device *dev, u32 data) 3348static int sky2_set_rx_csum(struct net_device *dev, u32 data)
3338{ 3349{
3339 struct sky2_port *sky2 = netdev_priv(dev); 3350 struct sky2_port *sky2 = netdev_priv(dev);
3340 3351
3341 sky2->rx_csum = data; 3352 if (data)
3353 sky2->flags |= SKY2_FLAG_RX_CHECKSUM;
3354 else
3355 sky2->flags &= ~SKY2_FLAG_RX_CHECKSUM;
3342 3356
3343 sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), 3357 sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR),
3344 data ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); 3358 data ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
@@ -3356,7 +3370,7 @@ static int sky2_nway_reset(struct net_device *dev)
3356{ 3370{
3357 struct sky2_port *sky2 = netdev_priv(dev); 3371 struct sky2_port *sky2 = netdev_priv(dev);
3358 3372
3359 if (!netif_running(dev) || sky2->autoneg != AUTONEG_ENABLE) 3373 if (!netif_running(dev) || !(sky2->flags & SKY2_FLAG_AUTO_SPEED))
3360 return -EINVAL; 3374 return -EINVAL;
3361 3375
3362 sky2_phy_reinit(sky2); 3376 sky2_phy_reinit(sky2);
@@ -3596,7 +3610,8 @@ static void sky2_get_pauseparam(struct net_device *dev,
3596 ecmd->tx_pause = ecmd->rx_pause = 1; 3610 ecmd->tx_pause = ecmd->rx_pause = 1;
3597 } 3611 }
3598 3612
3599 ecmd->autoneg = sky2->autoneg; 3613 ecmd->autoneg = (sky2->flags & SKY2_FLAG_AUTO_PAUSE)
3614 ? AUTONEG_ENABLE : AUTONEG_DISABLE;
3600} 3615}
3601 3616
3602static int sky2_set_pauseparam(struct net_device *dev, 3617static int sky2_set_pauseparam(struct net_device *dev,
@@ -3604,7 +3619,11 @@ static int sky2_set_pauseparam(struct net_device *dev,
3604{ 3619{
3605 struct sky2_port *sky2 = netdev_priv(dev); 3620 struct sky2_port *sky2 = netdev_priv(dev);
3606 3621
3607 sky2->autoneg = ecmd->autoneg; 3622 if (ecmd->autoneg == AUTONEG_ENABLE)
3623 sky2->flags |= SKY2_FLAG_AUTO_PAUSE;
3624 else
3625 sky2->flags &= ~SKY2_FLAG_AUTO_PAUSE;
3626
3608 sky2->flow_mode = sky2_flow(ecmd->rx_pause, ecmd->tx_pause); 3627 sky2->flow_mode = sky2_flow(ecmd->rx_pause, ecmd->tx_pause);
3609 3628
3610 if (netif_running(dev)) 3629 if (netif_running(dev))
@@ -4294,13 +4313,15 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
4294 sky2->msg_enable = netif_msg_init(debug, default_msg); 4313 sky2->msg_enable = netif_msg_init(debug, default_msg);
4295 4314
4296 /* Auto speed and flow control */ 4315 /* Auto speed and flow control */
4297 sky2->autoneg = AUTONEG_ENABLE; 4316 sky2->flags = SKY2_FLAG_AUTO_SPEED | SKY2_FLAG_AUTO_PAUSE;
4317 if (hw->chip_id != CHIP_ID_YUKON_XL)
4318 sky2->flags |= SKY2_FLAG_RX_CHECKSUM;
4319
4298 sky2->flow_mode = FC_BOTH; 4320 sky2->flow_mode = FC_BOTH;
4299 4321
4300 sky2->duplex = -1; 4322 sky2->duplex = -1;
4301 sky2->speed = -1; 4323 sky2->speed = -1;
4302 sky2->advertising = sky2_supported_modes(hw); 4324 sky2->advertising = sky2_supported_modes(hw);
4303 sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL);
4304 sky2->wol = wol; 4325 sky2->wol = wol;
4305 4326
4306 spin_lock_init(&sky2->phy_lock); 4327 spin_lock_init(&sky2->phy_lock);