aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000e/netdev.c
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2009-06-02 07:29:18 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-03 05:46:34 -0400
commita4f58f5455ba0efda36fb33c37074922d1527a10 (patch)
tree98aa6d14824b7c1b7907e703abedd80219e0abda /drivers/net/e1000e/netdev.c
parent2adc55c959940fc680074392eddbd5585a76f3d9 (diff)
e1000e: add support for 82577/82578 GbE LOM parts
This patch provides support for the next generation Intel desktop and mobile gigabit ethernet LOM adapters. These adapters are the follow-on parts to the LOMs tied to the prior ICH chipsets and are comprised of a MAC in the PCH chipset and an external PHY (82577 for mobile and 82578 for desktop versions). New features consist of PHY wakeup to save power by completely turning off the MAC while in Sx state, and 4K jumbo frames. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/e1000e/netdev.c')
-rw-r--r--drivers/net/e1000e/netdev.c206
1 files changed, 193 insertions, 13 deletions
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 4072fbb6493d..2cb704dd9546 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -62,6 +62,7 @@ static const struct e1000_info *e1000_info_tbl[] = {
62 [board_ich8lan] = &e1000_ich8_info, 62 [board_ich8lan] = &e1000_ich8_info,
63 [board_ich9lan] = &e1000_ich9_info, 63 [board_ich9lan] = &e1000_ich9_info,
64 [board_ich10lan] = &e1000_ich10_info, 64 [board_ich10lan] = &e1000_ich10_info,
65 [board_pchlan] = &e1000_pch_info,
65}; 66};
66 67
67#ifdef DEBUG 68#ifdef DEBUG
@@ -2308,6 +2309,23 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
2308 if (adapter->flags2 & FLAG2_CRC_STRIPPING) 2309 if (adapter->flags2 & FLAG2_CRC_STRIPPING)
2309 rctl |= E1000_RCTL_SECRC; 2310 rctl |= E1000_RCTL_SECRC;
2310 2311
2312 /* Workaround Si errata on 82577 PHY - configure IPG for jumbos */
2313 if ((hw->phy.type == e1000_phy_82577) && (rctl & E1000_RCTL_LPE)) {
2314 u16 phy_data;
2315
2316 e1e_rphy(hw, PHY_REG(770, 26), &phy_data);
2317 phy_data &= 0xfff8;
2318 phy_data |= (1 << 2);
2319 e1e_wphy(hw, PHY_REG(770, 26), phy_data);
2320
2321 e1e_rphy(hw, 22, &phy_data);
2322 phy_data &= 0x0fff;
2323 phy_data |= (1 << 14);
2324 e1e_wphy(hw, 0x10, 0x2823);
2325 e1e_wphy(hw, 0x11, 0x0003);
2326 e1e_wphy(hw, 22, phy_data);
2327 }
2328
2311 /* Setup buffer sizes */ 2329 /* Setup buffer sizes */
2312 rctl &= ~E1000_RCTL_SZ_4096; 2330 rctl &= ~E1000_RCTL_SZ_4096;
2313 rctl |= E1000_RCTL_BSEX; 2331 rctl |= E1000_RCTL_BSEX;
@@ -2789,6 +2807,8 @@ void e1000e_reset(struct e1000_adapter *adapter)
2789 e1000_get_hw_control(adapter); 2807 e1000_get_hw_control(adapter);
2790 2808
2791 ew32(WUC, 0); 2809 ew32(WUC, 0);
2810 if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP)
2811 e1e_wphy(&adapter->hw, BM_WUC, 0);
2792 2812
2793 if (mac->ops.init_hw(hw)) 2813 if (mac->ops.init_hw(hw))
2794 e_err("Hardware Error\n"); 2814 e_err("Hardware Error\n");
@@ -3269,6 +3289,7 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
3269{ 3289{
3270 struct e1000_hw *hw = &adapter->hw; 3290 struct e1000_hw *hw = &adapter->hw;
3271 struct pci_dev *pdev = adapter->pdev; 3291 struct pci_dev *pdev = adapter->pdev;
3292 u16 phy_data;
3272 3293
3273 /* 3294 /*
3274 * Prevent stats update while adapter is being reset, or if the pci 3295 * Prevent stats update while adapter is being reset, or if the pci
@@ -3288,11 +3309,34 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
3288 adapter->stats.roc += er32(ROC); 3309 adapter->stats.roc += er32(ROC);
3289 3310
3290 adapter->stats.mpc += er32(MPC); 3311 adapter->stats.mpc += er32(MPC);
3291 adapter->stats.scc += er32(SCC); 3312 if ((hw->phy.type == e1000_phy_82578) ||
3292 adapter->stats.ecol += er32(ECOL); 3313 (hw->phy.type == e1000_phy_82577)) {
3293 adapter->stats.mcc += er32(MCC); 3314 e1e_rphy(hw, HV_SCC_UPPER, &phy_data);
3294 adapter->stats.latecol += er32(LATECOL); 3315 e1e_rphy(hw, HV_SCC_LOWER, &phy_data);
3295 adapter->stats.dc += er32(DC); 3316 adapter->stats.scc += phy_data;
3317
3318 e1e_rphy(hw, HV_ECOL_UPPER, &phy_data);
3319 e1e_rphy(hw, HV_ECOL_LOWER, &phy_data);
3320 adapter->stats.ecol += phy_data;
3321
3322 e1e_rphy(hw, HV_MCC_UPPER, &phy_data);
3323 e1e_rphy(hw, HV_MCC_LOWER, &phy_data);
3324 adapter->stats.mcc += phy_data;
3325
3326 e1e_rphy(hw, HV_LATECOL_UPPER, &phy_data);
3327 e1e_rphy(hw, HV_LATECOL_LOWER, &phy_data);
3328 adapter->stats.latecol += phy_data;
3329
3330 e1e_rphy(hw, HV_DC_UPPER, &phy_data);
3331 e1e_rphy(hw, HV_DC_LOWER, &phy_data);
3332 adapter->stats.dc += phy_data;
3333 } else {
3334 adapter->stats.scc += er32(SCC);
3335 adapter->stats.ecol += er32(ECOL);
3336 adapter->stats.mcc += er32(MCC);
3337 adapter->stats.latecol += er32(LATECOL);
3338 adapter->stats.dc += er32(DC);
3339 }
3296 adapter->stats.xonrxc += er32(XONRXC); 3340 adapter->stats.xonrxc += er32(XONRXC);
3297 adapter->stats.xontxc += er32(XONTXC); 3341 adapter->stats.xontxc += er32(XONTXC);
3298 adapter->stats.xoffrxc += er32(XOFFRXC); 3342 adapter->stats.xoffrxc += er32(XOFFRXC);
@@ -3310,13 +3354,28 @@ void e1000e_update_stats(struct e1000_adapter *adapter)
3310 3354
3311 hw->mac.tx_packet_delta = er32(TPT); 3355 hw->mac.tx_packet_delta = er32(TPT);
3312 adapter->stats.tpt += hw->mac.tx_packet_delta; 3356 adapter->stats.tpt += hw->mac.tx_packet_delta;
3313 hw->mac.collision_delta = er32(COLC); 3357 if ((hw->phy.type == e1000_phy_82578) ||
3358 (hw->phy.type == e1000_phy_82577)) {
3359 e1e_rphy(hw, HV_COLC_UPPER, &phy_data);
3360 e1e_rphy(hw, HV_COLC_LOWER, &phy_data);
3361 hw->mac.collision_delta = phy_data;
3362 } else {
3363 hw->mac.collision_delta = er32(COLC);
3364 }
3314 adapter->stats.colc += hw->mac.collision_delta; 3365 adapter->stats.colc += hw->mac.collision_delta;
3315 3366
3316 adapter->stats.algnerrc += er32(ALGNERRC); 3367 adapter->stats.algnerrc += er32(ALGNERRC);
3317 adapter->stats.rxerrc += er32(RXERRC); 3368 adapter->stats.rxerrc += er32(RXERRC);
3318 if ((hw->mac.type != e1000_82574) && (hw->mac.type != e1000_82583)) 3369 if ((hw->phy.type == e1000_phy_82578) ||
3319 adapter->stats.tncrs += er32(TNCRS); 3370 (hw->phy.type == e1000_phy_82577)) {
3371 e1e_rphy(hw, HV_TNCRS_UPPER, &phy_data);
3372 e1e_rphy(hw, HV_TNCRS_LOWER, &phy_data);
3373 adapter->stats.tncrs += phy_data;
3374 } else {
3375 if ((hw->mac.type != e1000_82574) &&
3376 (hw->mac.type != e1000_82583))
3377 adapter->stats.tncrs += er32(TNCRS);
3378 }
3320 adapter->stats.cexterr += er32(CEXTERR); 3379 adapter->stats.cexterr += er32(CEXTERR);
3321 adapter->stats.tsctc += er32(TSCTC); 3380 adapter->stats.tsctc += er32(TSCTC);
3322 adapter->stats.tsctfc += er32(TSCTFC); 3381 adapter->stats.tsctfc += er32(TSCTFC);
@@ -4342,6 +4401,81 @@ static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
4342 } 4401 }
4343} 4402}
4344 4403
4404static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
4405{
4406 struct e1000_hw *hw = &adapter->hw;
4407 u32 i, mac_reg;
4408 u16 phy_reg;
4409 int retval = 0;
4410
4411 /* copy MAC RARs to PHY RARs */
4412 for (i = 0; i < adapter->hw.mac.rar_entry_count; i++) {
4413 mac_reg = er32(RAL(i));
4414 e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF));
4415 e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF));
4416 mac_reg = er32(RAH(i));
4417 e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF));
4418 e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0xFFFF));
4419 }
4420
4421 /* copy MAC MTA to PHY MTA */
4422 for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) {
4423 mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i);
4424 e1e_wphy(hw, BM_MTA(i), (u16)(mac_reg & 0xFFFF));
4425 e1e_wphy(hw, BM_MTA(i) + 1, (u16)((mac_reg >> 16) & 0xFFFF));
4426 }
4427
4428 /* configure PHY Rx Control register */
4429 e1e_rphy(&adapter->hw, BM_RCTL, &phy_reg);
4430 mac_reg = er32(RCTL);
4431 if (mac_reg & E1000_RCTL_UPE)
4432 phy_reg |= BM_RCTL_UPE;
4433 if (mac_reg & E1000_RCTL_MPE)
4434 phy_reg |= BM_RCTL_MPE;
4435 phy_reg &= ~(BM_RCTL_MO_MASK);
4436 if (mac_reg & E1000_RCTL_MO_3)
4437 phy_reg |= (((mac_reg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT)
4438 << BM_RCTL_MO_SHIFT);
4439 if (mac_reg & E1000_RCTL_BAM)
4440 phy_reg |= BM_RCTL_BAM;
4441 if (mac_reg & E1000_RCTL_PMCF)
4442 phy_reg |= BM_RCTL_PMCF;
4443 mac_reg = er32(CTRL);
4444 if (mac_reg & E1000_CTRL_RFCE)
4445 phy_reg |= BM_RCTL_RFCE;
4446 e1e_wphy(&adapter->hw, BM_RCTL, phy_reg);
4447
4448 /* enable PHY wakeup in MAC register */
4449 ew32(WUFC, wufc);
4450 ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN);
4451
4452 /* configure and enable PHY wakeup in PHY registers */
4453 e1e_wphy(&adapter->hw, BM_WUFC, wufc);
4454 e1e_wphy(&adapter->hw, BM_WUC, E1000_WUC_PME_EN);
4455
4456 /* activate PHY wakeup */
4457 retval = hw->phy.ops.acquire_phy(hw);
4458 if (retval) {
4459 e_err("Could not acquire PHY\n");
4460 return retval;
4461 }
4462 e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
4463 (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
4464 retval = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
4465 if (retval) {
4466 e_err("Could not read PHY page 769\n");
4467 goto out;
4468 }
4469 phy_reg |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT;
4470 retval = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
4471 if (retval)
4472 e_err("Could not set PHY Host Wakeup bit\n");
4473out:
4474 hw->phy.ops.release_phy(hw);
4475
4476 return retval;
4477}
4478
4345static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake) 4479static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
4346{ 4480{
4347 struct net_device *netdev = pci_get_drvdata(pdev); 4481 struct net_device *netdev = pci_get_drvdata(pdev);
@@ -4384,8 +4518,9 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
4384 #define E1000_CTRL_ADVD3WUC 0x00100000 4518 #define E1000_CTRL_ADVD3WUC 0x00100000
4385 /* phy power management enable */ 4519 /* phy power management enable */
4386 #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 4520 #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000
4387 ctrl |= E1000_CTRL_ADVD3WUC | 4521 ctrl |= E1000_CTRL_ADVD3WUC;
4388 E1000_CTRL_EN_PHY_PWR_MGMT; 4522 if (!(adapter->flags2 & FLAG2_HAS_PHY_WAKEUP))
4523 ctrl |= E1000_CTRL_EN_PHY_PWR_MGMT;
4389 ew32(CTRL, ctrl); 4524 ew32(CTRL, ctrl);
4390 4525
4391 if (adapter->hw.phy.media_type == e1000_media_type_fiber || 4526 if (adapter->hw.phy.media_type == e1000_media_type_fiber ||
@@ -4403,8 +4538,17 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake)
4403 /* Allow time for pending master requests to run */ 4538 /* Allow time for pending master requests to run */
4404 e1000e_disable_pcie_master(&adapter->hw); 4539 e1000e_disable_pcie_master(&adapter->hw);
4405 4540
4406 ew32(WUC, E1000_WUC_PME_EN); 4541 if ((adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) &&
4407 ew32(WUFC, wufc); 4542 !(hw->mac.ops.check_mng_mode(hw))) {
4543 /* enable wakeup by the PHY */
4544 retval = e1000_init_phy_wakeup(adapter, wufc);
4545 if (retval)
4546 return retval;
4547 } else {
4548 /* enable wakeup by the MAC */
4549 ew32(WUFC, wufc);
4550 ew32(WUC, E1000_WUC_PME_EN);
4551 }
4408 } else { 4552 } else {
4409 ew32(WUC, 0); 4553 ew32(WUC, 0);
4410 ew32(WUFC, 0); 4554 ew32(WUFC, 0);
@@ -4547,8 +4691,37 @@ static int e1000_resume(struct pci_dev *pdev)
4547 } 4691 }
4548 4692
4549 e1000e_power_up_phy(adapter); 4693 e1000e_power_up_phy(adapter);
4694
4695 /* report the system wakeup cause from S3/S4 */
4696 if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) {
4697 u16 phy_data;
4698
4699 e1e_rphy(&adapter->hw, BM_WUS, &phy_data);
4700 if (phy_data) {
4701 e_info("PHY Wakeup cause - %s\n",
4702 phy_data & E1000_WUS_EX ? "Unicast Packet" :
4703 phy_data & E1000_WUS_MC ? "Multicast Packet" :
4704 phy_data & E1000_WUS_BC ? "Broadcast Packet" :
4705 phy_data & E1000_WUS_MAG ? "Magic Packet" :
4706 phy_data & E1000_WUS_LNKC ? "Link Status "
4707 " Change" : "other");
4708 }
4709 e1e_wphy(&adapter->hw, BM_WUS, ~0);
4710 } else {
4711 u32 wus = er32(WUS);
4712 if (wus) {
4713 e_info("MAC Wakeup cause - %s\n",
4714 wus & E1000_WUS_EX ? "Unicast Packet" :
4715 wus & E1000_WUS_MC ? "Multicast Packet" :
4716 wus & E1000_WUS_BC ? "Broadcast Packet" :
4717 wus & E1000_WUS_MAG ? "Magic Packet" :
4718 wus & E1000_WUS_LNKC ? "Link Status Change" :
4719 "other");
4720 }
4721 ew32(WUS, ~0);
4722 }
4723
4550 e1000e_reset(adapter); 4724 e1000e_reset(adapter);
4551 ew32(WUS, ~0);
4552 4725
4553 e1000_init_manageability(adapter); 4726 e1000_init_manageability(adapter);
4554 4727
@@ -4994,6 +5167,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
4994 /* APME bit in EEPROM is mapped to WUC.APME */ 5167 /* APME bit in EEPROM is mapped to WUC.APME */
4995 eeprom_data = er32(WUC); 5168 eeprom_data = er32(WUC);
4996 eeprom_apme_mask = E1000_WUC_APME; 5169 eeprom_apme_mask = E1000_WUC_APME;
5170 if (eeprom_data & E1000_WUC_PHY_WAKE)
5171 adapter->flags2 |= FLAG2_HAS_PHY_WAKEUP;
4997 } else if (adapter->flags & FLAG_APME_IN_CTRL3) { 5172 } else if (adapter->flags & FLAG_APME_IN_CTRL3) {
4998 if (adapter->flags & FLAG_APME_CHECK_PORT_B && 5173 if (adapter->flags & FLAG_APME_CHECK_PORT_B &&
4999 (adapter->hw.bus.func == 1)) 5174 (adapter->hw.bus.func == 1))
@@ -5195,6 +5370,11 @@ static struct pci_device_id e1000_pci_tbl[] = {
5195 { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich10lan }, 5370 { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich10lan },
5196 { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich10lan }, 5371 { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich10lan },
5197 5372
5373 { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LM), board_pchlan },
5374 { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LC), board_pchlan },
5375 { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DM), board_pchlan },
5376 { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DC), board_pchlan },
5377
5198 { } /* terminate list */ 5378 { } /* terminate list */
5199}; 5379};
5200MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); 5380MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);