diff options
author | David S. Miller <davem@davemloft.net> | 2008-10-08 17:56:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-10-08 17:56:41 -0400 |
commit | 4dd565134ece7e5d528d4c5288879310c54419e9 (patch) | |
tree | e08910d2d0feae0c030f8f01acc9b03eb760ad9a /drivers/net/e1000e | |
parent | 071d7ab6649eb34a873a53e71635186e9117101d (diff) | |
parent | 69849375d6b13e94d08cdc94b49b11fbab454a0e (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/e1000e/ich8lan.c
drivers/net/e1000e/netdev.c
Diffstat (limited to 'drivers/net/e1000e')
-rw-r--r-- | drivers/net/e1000e/e1000.h | 5 | ||||
-rw-r--r-- | drivers/net/e1000e/ethtool.c | 9 | ||||
-rw-r--r-- | drivers/net/e1000e/ich8lan.c | 78 | ||||
-rw-r--r-- | drivers/net/e1000e/netdev.c | 68 | ||||
-rw-r--r-- | drivers/net/e1000e/param.c | 30 |
5 files changed, 153 insertions, 37 deletions
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 0a1916b0419d..c55de1c027af 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h | |||
@@ -270,7 +270,6 @@ struct e1000_adapter { | |||
270 | struct net_device *netdev; | 270 | struct net_device *netdev; |
271 | struct pci_dev *pdev; | 271 | struct pci_dev *pdev; |
272 | struct net_device_stats net_stats; | 272 | struct net_device_stats net_stats; |
273 | spinlock_t stats_lock; /* prevent concurrent stats updates */ | ||
274 | 273 | ||
275 | /* structs defined in e1000_hw.h */ | 274 | /* structs defined in e1000_hw.h */ |
276 | struct e1000_hw hw; | 275 | struct e1000_hw hw; |
@@ -300,6 +299,8 @@ struct e1000_adapter { | |||
300 | unsigned long led_status; | 299 | unsigned long led_status; |
301 | 300 | ||
302 | unsigned int flags; | 301 | unsigned int flags; |
302 | struct work_struct downshift_task; | ||
303 | struct work_struct update_phy_task; | ||
303 | }; | 304 | }; |
304 | 305 | ||
305 | struct e1000_info { | 306 | struct e1000_info { |
@@ -321,6 +322,7 @@ struct e1000_info { | |||
321 | #define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5) | 322 | #define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5) |
322 | #define FLAG_HAS_SWSM_ON_LOAD (1 << 6) | 323 | #define FLAG_HAS_SWSM_ON_LOAD (1 << 6) |
323 | #define FLAG_HAS_JUMBO_FRAMES (1 << 7) | 324 | #define FLAG_HAS_JUMBO_FRAMES (1 << 7) |
325 | #define FLAG_READ_ONLY_NVM (1 << 8) | ||
324 | #define FLAG_IS_ICH (1 << 9) | 326 | #define FLAG_IS_ICH (1 << 9) |
325 | #define FLAG_HAS_MSIX (1 << 10) | 327 | #define FLAG_HAS_MSIX (1 << 10) |
326 | #define FLAG_HAS_SMART_POWER_DOWN (1 << 11) | 328 | #define FLAG_HAS_SMART_POWER_DOWN (1 << 11) |
@@ -406,6 +408,7 @@ extern bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw); | |||
406 | extern bool e1000e_get_laa_state_82571(struct e1000_hw *hw); | 408 | extern bool e1000e_get_laa_state_82571(struct e1000_hw *hw); |
407 | extern void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state); | 409 | extern void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state); |
408 | 410 | ||
411 | extern void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw); | ||
409 | extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, | 412 | extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, |
410 | bool state); | 413 | bool state); |
411 | extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); | 414 | extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); |
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 52b762eb1745..70c11c811a08 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c | |||
@@ -432,6 +432,10 @@ static void e1000_get_regs(struct net_device *netdev, | |||
432 | regs_buff[11] = er32(TIDV); | 432 | regs_buff[11] = er32(TIDV); |
433 | 433 | ||
434 | regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */ | 434 | regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */ |
435 | |||
436 | /* ethtool doesn't use anything past this point, so all this | ||
437 | * code is likely legacy junk for apps that may or may not | ||
438 | * exist */ | ||
435 | if (hw->phy.type == e1000_phy_m88) { | 439 | if (hw->phy.type == e1000_phy_m88) { |
436 | e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); | 440 | e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); |
437 | regs_buff[13] = (u32)phy_data; /* cable length */ | 441 | regs_buff[13] = (u32)phy_data; /* cable length */ |
@@ -447,7 +451,7 @@ static void e1000_get_regs(struct net_device *netdev, | |||
447 | regs_buff[22] = adapter->phy_stats.receive_errors; | 451 | regs_buff[22] = adapter->phy_stats.receive_errors; |
448 | regs_buff[23] = regs_buff[13]; /* mdix mode */ | 452 | regs_buff[23] = regs_buff[13]; /* mdix mode */ |
449 | } | 453 | } |
450 | regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */ | 454 | regs_buff[21] = 0; /* was idle_errors */ |
451 | e1e_rphy(hw, PHY_1000T_STATUS, &phy_data); | 455 | e1e_rphy(hw, PHY_1000T_STATUS, &phy_data); |
452 | regs_buff[24] = (u32)phy_data; /* phy local receiver status */ | 456 | regs_buff[24] = (u32)phy_data; /* phy local receiver status */ |
453 | regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ | 457 | regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ |
@@ -529,6 +533,9 @@ static int e1000_set_eeprom(struct net_device *netdev, | |||
529 | if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16))) | 533 | if (eeprom->magic != (adapter->pdev->vendor | (adapter->pdev->device << 16))) |
530 | return -EFAULT; | 534 | return -EFAULT; |
531 | 535 | ||
536 | if (adapter->flags & FLAG_READ_ONLY_NVM) | ||
537 | return -EINVAL; | ||
538 | |||
532 | max_len = hw->nvm.word_size * 2; | 539 | max_len = hw->nvm.word_size * 2; |
533 | 540 | ||
534 | first_word = eeprom->offset >> 1; | 541 | first_word = eeprom->offset >> 1; |
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 692251b60915..523b9716a543 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c | |||
@@ -60,6 +60,7 @@ | |||
60 | #define ICH_FLASH_HSFCTL 0x0006 | 60 | #define ICH_FLASH_HSFCTL 0x0006 |
61 | #define ICH_FLASH_FADDR 0x0008 | 61 | #define ICH_FLASH_FADDR 0x0008 |
62 | #define ICH_FLASH_FDATA0 0x0010 | 62 | #define ICH_FLASH_FDATA0 0x0010 |
63 | #define ICH_FLASH_PR0 0x0074 | ||
63 | 64 | ||
64 | #define ICH_FLASH_READ_COMMAND_TIMEOUT 500 | 65 | #define ICH_FLASH_READ_COMMAND_TIMEOUT 500 |
65 | #define ICH_FLASH_WRITE_COMMAND_TIMEOUT 500 | 66 | #define ICH_FLASH_WRITE_COMMAND_TIMEOUT 500 |
@@ -152,6 +153,19 @@ union ich8_hws_flash_regacc { | |||
152 | u16 regval; | 153 | u16 regval; |
153 | }; | 154 | }; |
154 | 155 | ||
156 | /* ICH Flash Protected Region */ | ||
157 | union ich8_flash_protected_range { | ||
158 | struct ich8_pr { | ||
159 | u32 base:13; /* 0:12 Protected Range Base */ | ||
160 | u32 reserved1:2; /* 13:14 Reserved */ | ||
161 | u32 rpe:1; /* 15 Read Protection Enable */ | ||
162 | u32 limit:13; /* 16:28 Protected Range Limit */ | ||
163 | u32 reserved2:2; /* 29:30 Reserved */ | ||
164 | u32 wpe:1; /* 31 Write Protection Enable */ | ||
165 | } range; | ||
166 | u32 regval; | ||
167 | }; | ||
168 | |||
155 | static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw); | 169 | static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw); |
156 | static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); | 170 | static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); |
157 | static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); | 171 | static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); |
@@ -371,6 +385,9 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) | |||
371 | return 0; | 385 | return 0; |
372 | } | 386 | } |
373 | 387 | ||
388 | static DEFINE_MUTEX(nvm_mutex); | ||
389 | static pid_t nvm_owner = -1; | ||
390 | |||
374 | /** | 391 | /** |
375 | * e1000_acquire_swflag_ich8lan - Acquire software control flag | 392 | * e1000_acquire_swflag_ich8lan - Acquire software control flag |
376 | * @hw: pointer to the HW structure | 393 | * @hw: pointer to the HW structure |
@@ -384,6 +401,15 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) | |||
384 | u32 extcnf_ctrl; | 401 | u32 extcnf_ctrl; |
385 | u32 timeout = PHY_CFG_TIMEOUT; | 402 | u32 timeout = PHY_CFG_TIMEOUT; |
386 | 403 | ||
404 | might_sleep(); | ||
405 | |||
406 | if (!mutex_trylock(&nvm_mutex)) { | ||
407 | WARN(1, KERN_ERR "e1000e mutex contention. Owned by pid %d\n", | ||
408 | nvm_owner); | ||
409 | mutex_lock(&nvm_mutex); | ||
410 | } | ||
411 | nvm_owner = current->pid; | ||
412 | |||
387 | while (timeout) { | 413 | while (timeout) { |
388 | extcnf_ctrl = er32(EXTCNF_CTRL); | 414 | extcnf_ctrl = er32(EXTCNF_CTRL); |
389 | extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; | 415 | extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; |
@@ -400,6 +426,8 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) | |||
400 | hw_dbg(hw, "FW or HW has locked the resource for too long.\n"); | 426 | hw_dbg(hw, "FW or HW has locked the resource for too long.\n"); |
401 | extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; | 427 | extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; |
402 | ew32(EXTCNF_CTRL, extcnf_ctrl); | 428 | ew32(EXTCNF_CTRL, extcnf_ctrl); |
429 | nvm_owner = -1; | ||
430 | mutex_unlock(&nvm_mutex); | ||
403 | return -E1000_ERR_CONFIG; | 431 | return -E1000_ERR_CONFIG; |
404 | } | 432 | } |
405 | 433 | ||
@@ -421,6 +449,9 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw) | |||
421 | extcnf_ctrl = er32(EXTCNF_CTRL); | 449 | extcnf_ctrl = er32(EXTCNF_CTRL); |
422 | extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; | 450 | extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; |
423 | ew32(EXTCNF_CTRL, extcnf_ctrl); | 451 | ew32(EXTCNF_CTRL, extcnf_ctrl); |
452 | |||
453 | nvm_owner = -1; | ||
454 | mutex_unlock(&nvm_mutex); | ||
424 | } | 455 | } |
425 | 456 | ||
426 | /** | 457 | /** |
@@ -1386,6 +1417,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) | |||
1386 | * programming failed. | 1417 | * programming failed. |
1387 | */ | 1418 | */ |
1388 | if (ret_val) { | 1419 | if (ret_val) { |
1420 | /* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */ | ||
1389 | hw_dbg(hw, "Flash commit failed.\n"); | 1421 | hw_dbg(hw, "Flash commit failed.\n"); |
1390 | e1000_release_swflag_ich8lan(hw); | 1422 | e1000_release_swflag_ich8lan(hw); |
1391 | return ret_val; | 1423 | return ret_val; |
@@ -1476,6 +1508,49 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) | |||
1476 | } | 1508 | } |
1477 | 1509 | ||
1478 | /** | 1510 | /** |
1511 | * e1000e_write_protect_nvm_ich8lan - Make the NVM read-only | ||
1512 | * @hw: pointer to the HW structure | ||
1513 | * | ||
1514 | * To prevent malicious write/erase of the NVM, set it to be read-only | ||
1515 | * so that the hardware ignores all write/erase cycles of the NVM via | ||
1516 | * the flash control registers. The shadow-ram copy of the NVM will | ||
1517 | * still be updated, however any updates to this copy will not stick | ||
1518 | * across driver reloads. | ||
1519 | **/ | ||
1520 | void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw) | ||
1521 | { | ||
1522 | union ich8_flash_protected_range pr0; | ||
1523 | union ich8_hws_flash_status hsfsts; | ||
1524 | u32 gfpreg; | ||
1525 | s32 ret_val; | ||
1526 | |||
1527 | ret_val = e1000_acquire_swflag_ich8lan(hw); | ||
1528 | if (ret_val) | ||
1529 | return; | ||
1530 | |||
1531 | gfpreg = er32flash(ICH_FLASH_GFPREG); | ||
1532 | |||
1533 | /* Write-protect GbE Sector of NVM */ | ||
1534 | pr0.regval = er32flash(ICH_FLASH_PR0); | ||
1535 | pr0.range.base = gfpreg & FLASH_GFPREG_BASE_MASK; | ||
1536 | pr0.range.limit = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK); | ||
1537 | pr0.range.wpe = true; | ||
1538 | ew32flash(ICH_FLASH_PR0, pr0.regval); | ||
1539 | |||
1540 | /* | ||
1541 | * Lock down a subset of GbE Flash Control Registers, e.g. | ||
1542 | * PR0 to prevent the write-protection from being lifted. | ||
1543 | * Once FLOCKDN is set, the registers protected by it cannot | ||
1544 | * be written until FLOCKDN is cleared by a hardware reset. | ||
1545 | */ | ||
1546 | hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); | ||
1547 | hsfsts.hsf_status.flockdn = true; | ||
1548 | ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval); | ||
1549 | |||
1550 | e1000_release_swflag_ich8lan(hw); | ||
1551 | } | ||
1552 | |||
1553 | /** | ||
1479 | * e1000_write_flash_data_ich8lan - Writes bytes to the NVM | 1554 | * e1000_write_flash_data_ich8lan - Writes bytes to the NVM |
1480 | * @hw: pointer to the HW structure | 1555 | * @hw: pointer to the HW structure |
1481 | * @offset: The offset (in bytes) of the byte/word to read. | 1556 | * @offset: The offset (in bytes) of the byte/word to read. |
@@ -1822,6 +1897,9 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) | |||
1822 | ew32(CTRL, (ctrl | E1000_CTRL_RST)); | 1897 | ew32(CTRL, (ctrl | E1000_CTRL_RST)); |
1823 | msleep(20); | 1898 | msleep(20); |
1824 | 1899 | ||
1900 | /* release the swflag because it is not reset by hardware reset */ | ||
1901 | e1000_release_swflag_ich8lan(hw); | ||
1902 | |||
1825 | ret_val = e1000e_get_auto_rd_done(hw); | 1903 | ret_val = e1000e_get_auto_rd_done(hw); |
1826 | if (ret_val) { | 1904 | if (ret_val) { |
1827 | /* | 1905 | /* |
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 24d05cb70055..1b72749979c4 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
@@ -47,7 +47,7 @@ | |||
47 | 47 | ||
48 | #include "e1000.h" | 48 | #include "e1000.h" |
49 | 49 | ||
50 | #define DRV_VERSION "0.3.3.3-k2" | 50 | #define DRV_VERSION "0.3.3.3-k6" |
51 | char e1000e_driver_name[] = "e1000e"; | 51 | char e1000e_driver_name[] = "e1000e"; |
52 | const char e1000e_driver_version[] = DRV_VERSION; | 52 | const char e1000e_driver_version[] = DRV_VERSION; |
53 | 53 | ||
@@ -1117,6 +1117,14 @@ static void e1000_clean_rx_ring(struct e1000_adapter *adapter) | |||
1117 | writel(0, adapter->hw.hw_addr + rx_ring->tail); | 1117 | writel(0, adapter->hw.hw_addr + rx_ring->tail); |
1118 | } | 1118 | } |
1119 | 1119 | ||
1120 | static void e1000e_downshift_workaround(struct work_struct *work) | ||
1121 | { | ||
1122 | struct e1000_adapter *adapter = container_of(work, | ||
1123 | struct e1000_adapter, downshift_task); | ||
1124 | |||
1125 | e1000e_gig_downshift_workaround_ich8lan(&adapter->hw); | ||
1126 | } | ||
1127 | |||
1120 | /** | 1128 | /** |
1121 | * e1000_intr_msi - Interrupt Handler | 1129 | * e1000_intr_msi - Interrupt Handler |
1122 | * @irq: interrupt number | 1130 | * @irq: interrupt number |
@@ -1141,7 +1149,7 @@ static irqreturn_t e1000_intr_msi(int irq, void *data) | |||
1141 | */ | 1149 | */ |
1142 | if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && | 1150 | if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && |
1143 | (!(er32(STATUS) & E1000_STATUS_LU))) | 1151 | (!(er32(STATUS) & E1000_STATUS_LU))) |
1144 | e1000e_gig_downshift_workaround_ich8lan(hw); | 1152 | schedule_work(&adapter->downshift_task); |
1145 | 1153 | ||
1146 | /* | 1154 | /* |
1147 | * 80003ES2LAN workaround-- For packet buffer work-around on | 1155 | * 80003ES2LAN workaround-- For packet buffer work-around on |
@@ -1207,7 +1215,7 @@ static irqreturn_t e1000_intr(int irq, void *data) | |||
1207 | */ | 1215 | */ |
1208 | if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && | 1216 | if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && |
1209 | (!(er32(STATUS) & E1000_STATUS_LU))) | 1217 | (!(er32(STATUS) & E1000_STATUS_LU))) |
1210 | e1000e_gig_downshift_workaround_ich8lan(hw); | 1218 | schedule_work(&adapter->downshift_task); |
1211 | 1219 | ||
1212 | /* | 1220 | /* |
1213 | * 80003ES2LAN workaround-- | 1221 | * 80003ES2LAN workaround-- |
@@ -2905,8 +2913,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) | |||
2905 | /* Explicitly disable IRQ since the NIC can be in any state. */ | 2913 | /* Explicitly disable IRQ since the NIC can be in any state. */ |
2906 | e1000_irq_disable(adapter); | 2914 | e1000_irq_disable(adapter); |
2907 | 2915 | ||
2908 | spin_lock_init(&adapter->stats_lock); | ||
2909 | |||
2910 | set_bit(__E1000_DOWN, &adapter->state); | 2916 | set_bit(__E1000_DOWN, &adapter->state); |
2911 | return 0; | 2917 | return 0; |
2912 | } | 2918 | } |
@@ -3221,6 +3227,21 @@ static int e1000_set_mac(struct net_device *netdev, void *p) | |||
3221 | return 0; | 3227 | return 0; |
3222 | } | 3228 | } |
3223 | 3229 | ||
3230 | /** | ||
3231 | * e1000e_update_phy_task - work thread to update phy | ||
3232 | * @work: pointer to our work struct | ||
3233 | * | ||
3234 | * this worker thread exists because we must acquire a | ||
3235 | * semaphore to read the phy, which we could msleep while | ||
3236 | * waiting for it, and we can't msleep in a timer. | ||
3237 | **/ | ||
3238 | static void e1000e_update_phy_task(struct work_struct *work) | ||
3239 | { | ||
3240 | struct e1000_adapter *adapter = container_of(work, | ||
3241 | struct e1000_adapter, update_phy_task); | ||
3242 | e1000_get_phy_info(&adapter->hw); | ||
3243 | } | ||
3244 | |||
3224 | /* | 3245 | /* |
3225 | * Need to wait a few seconds after link up to get diagnostic information from | 3246 | * Need to wait a few seconds after link up to get diagnostic information from |
3226 | * the phy | 3247 | * the phy |
@@ -3228,7 +3249,7 @@ static int e1000_set_mac(struct net_device *netdev, void *p) | |||
3228 | static void e1000_update_phy_info(unsigned long data) | 3249 | static void e1000_update_phy_info(unsigned long data) |
3229 | { | 3250 | { |
3230 | struct e1000_adapter *adapter = (struct e1000_adapter *) data; | 3251 | struct e1000_adapter *adapter = (struct e1000_adapter *) data; |
3231 | e1000_get_phy_info(&adapter->hw); | 3252 | schedule_work(&adapter->update_phy_task); |
3232 | } | 3253 | } |
3233 | 3254 | ||
3234 | /** | 3255 | /** |
@@ -3239,10 +3260,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter) | |||
3239 | { | 3260 | { |
3240 | struct e1000_hw *hw = &adapter->hw; | 3261 | struct e1000_hw *hw = &adapter->hw; |
3241 | struct pci_dev *pdev = adapter->pdev; | 3262 | struct pci_dev *pdev = adapter->pdev; |
3242 | unsigned long irq_flags; | ||
3243 | u16 phy_tmp; | ||
3244 | |||
3245 | #define PHY_IDLE_ERROR_COUNT_MASK 0x00FF | ||
3246 | 3263 | ||
3247 | /* | 3264 | /* |
3248 | * Prevent stats update while adapter is being reset, or if the pci | 3265 | * Prevent stats update while adapter is being reset, or if the pci |
@@ -3253,14 +3270,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter) | |||
3253 | if (pci_channel_offline(pdev)) | 3270 | if (pci_channel_offline(pdev)) |
3254 | return; | 3271 | return; |
3255 | 3272 | ||
3256 | spin_lock_irqsave(&adapter->stats_lock, irq_flags); | ||
3257 | |||
3258 | /* | ||
3259 | * these counters are modified from e1000_adjust_tbi_stats, | ||
3260 | * called from the interrupt context, so they must only | ||
3261 | * be written while holding adapter->stats_lock | ||
3262 | */ | ||
3263 | |||
3264 | adapter->stats.crcerrs += er32(CRCERRS); | 3273 | adapter->stats.crcerrs += er32(CRCERRS); |
3265 | adapter->stats.gprc += er32(GPRC); | 3274 | adapter->stats.gprc += er32(GPRC); |
3266 | adapter->stats.gorc += er32(GORCL); | 3275 | adapter->stats.gorc += er32(GORCL); |
@@ -3332,21 +3341,10 @@ void e1000e_update_stats(struct e1000_adapter *adapter) | |||
3332 | 3341 | ||
3333 | /* Tx Dropped needs to be maintained elsewhere */ | 3342 | /* Tx Dropped needs to be maintained elsewhere */ |
3334 | 3343 | ||
3335 | /* Phy Stats */ | ||
3336 | if (hw->phy.media_type == e1000_media_type_copper) { | ||
3337 | if ((adapter->link_speed == SPEED_1000) && | ||
3338 | (!e1e_rphy(hw, PHY_1000T_STATUS, &phy_tmp))) { | ||
3339 | phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; | ||
3340 | adapter->phy_stats.idle_errors += phy_tmp; | ||
3341 | } | ||
3342 | } | ||
3343 | |||
3344 | /* Management Stats */ | 3344 | /* Management Stats */ |
3345 | adapter->stats.mgptc += er32(MGTPTC); | 3345 | adapter->stats.mgptc += er32(MGTPTC); |
3346 | adapter->stats.mgprc += er32(MGTPRC); | 3346 | adapter->stats.mgprc += er32(MGTPRC); |
3347 | adapter->stats.mgpdc += er32(MGTPDC); | 3347 | adapter->stats.mgpdc += er32(MGTPDC); |
3348 | |||
3349 | spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); | ||
3350 | } | 3348 | } |
3351 | 3349 | ||
3352 | /** | 3350 | /** |
@@ -3358,10 +3356,6 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter) | |||
3358 | struct e1000_hw *hw = &adapter->hw; | 3356 | struct e1000_hw *hw = &adapter->hw; |
3359 | struct e1000_phy_regs *phy = &adapter->phy_regs; | 3357 | struct e1000_phy_regs *phy = &adapter->phy_regs; |
3360 | int ret_val; | 3358 | int ret_val; |
3361 | unsigned long irq_flags; | ||
3362 | |||
3363 | |||
3364 | spin_lock_irqsave(&adapter->stats_lock, irq_flags); | ||
3365 | 3359 | ||
3366 | if ((er32(STATUS) & E1000_STATUS_LU) && | 3360 | if ((er32(STATUS) & E1000_STATUS_LU) && |
3367 | (adapter->hw.phy.media_type == e1000_media_type_copper)) { | 3361 | (adapter->hw.phy.media_type == e1000_media_type_copper)) { |
@@ -3392,8 +3386,6 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter) | |||
3392 | phy->stat1000 = 0; | 3386 | phy->stat1000 = 0; |
3393 | phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF); | 3387 | phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF); |
3394 | } | 3388 | } |
3395 | |||
3396 | spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); | ||
3397 | } | 3389 | } |
3398 | 3390 | ||
3399 | static void e1000_print_link_info(struct e1000_adapter *adapter) | 3391 | static void e1000_print_link_info(struct e1000_adapter *adapter) |
@@ -4822,6 +4814,10 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
4822 | if (err) | 4814 | if (err) |
4823 | goto err_hw_init; | 4815 | goto err_hw_init; |
4824 | 4816 | ||
4817 | if ((adapter->flags & FLAG_IS_ICH) && | ||
4818 | (adapter->flags & FLAG_READ_ONLY_NVM)) | ||
4819 | e1000e_write_protect_nvm_ich8lan(&adapter->hw); | ||
4820 | |||
4825 | hw->mac.ops.get_bus_info(&adapter->hw); | 4821 | hw->mac.ops.get_bus_info(&adapter->hw); |
4826 | 4822 | ||
4827 | adapter->hw.phy.autoneg_wait_to_complete = 0; | 4823 | adapter->hw.phy.autoneg_wait_to_complete = 0; |
@@ -4912,6 +4908,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
4912 | 4908 | ||
4913 | INIT_WORK(&adapter->reset_task, e1000_reset_task); | 4909 | INIT_WORK(&adapter->reset_task, e1000_reset_task); |
4914 | INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task); | 4910 | INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task); |
4911 | INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround); | ||
4912 | INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task); | ||
4915 | 4913 | ||
4916 | /* Initialize link parameters. User can change them with ethtool */ | 4914 | /* Initialize link parameters. User can change them with ethtool */ |
4917 | adapter->hw.mac.autoneg = 1; | 4915 | adapter->hw.mac.autoneg = 1; |
diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index f46db6cda487..77a3d7207a5f 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c | |||
@@ -142,6 +142,15 @@ E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down"); | |||
142 | */ | 142 | */ |
143 | E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); | 143 | E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); |
144 | 144 | ||
145 | /* | ||
146 | * Write Protect NVM | ||
147 | * | ||
148 | * Valid Range: 0, 1 | ||
149 | * | ||
150 | * Default Value: 1 (enabled) | ||
151 | */ | ||
152 | E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]"); | ||
153 | |||
145 | struct e1000_option { | 154 | struct e1000_option { |
146 | enum { enable_option, range_option, list_option } type; | 155 | enum { enable_option, range_option, list_option } type; |
147 | const char *name; | 156 | const char *name; |
@@ -415,4 +424,25 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) | |||
415 | opt.def); | 424 | opt.def); |
416 | } | 425 | } |
417 | } | 426 | } |
427 | { /* Write-protect NVM */ | ||
428 | const struct e1000_option opt = { | ||
429 | .type = enable_option, | ||
430 | .name = "Write-protect NVM", | ||
431 | .err = "defaulting to Enabled", | ||
432 | .def = OPTION_ENABLED | ||
433 | }; | ||
434 | |||
435 | if (adapter->flags & FLAG_IS_ICH) { | ||
436 | if (num_WriteProtectNVM > bd) { | ||
437 | unsigned int write_protect_nvm = WriteProtectNVM[bd]; | ||
438 | e1000_validate_option(&write_protect_nvm, &opt, | ||
439 | adapter); | ||
440 | if (write_protect_nvm) | ||
441 | adapter->flags |= FLAG_READ_ONLY_NVM; | ||
442 | } else { | ||
443 | if (opt.def) | ||
444 | adapter->flags |= FLAG_READ_ONLY_NVM; | ||
445 | } | ||
446 | } | ||
447 | } | ||
418 | } | 448 | } |