diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-04-27 13:14:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-04-27 13:14:53 -0400 |
commit | c58b8e4a25a1ba347a0e5d21984c97bd296f1691 (patch) | |
tree | 89f4727038fe7c108c3fa77494c9304f3d11d793 /drivers | |
parent | afc2e82c0851317931a9bfdb98271253371825c6 (diff) | |
parent | f50393fe869ba457cd75569c74c0f9bd2e7f7a0f (diff) |
Merge branch 'e1000-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6
* 'e1000-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/netdev-2.6:
e1000: FIX: Stop raw interrupts disabled nag from RT
e1000: FIX: firmware handover bits
e1000: FIX: be ready for incoming irq at pci_request_irq
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 104 |
1 files changed, 58 insertions, 46 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 48e2ade704d3..9267f16b1b32 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -409,25 +409,21 @@ e1000_release_hw_control(struct e1000_adapter *adapter) | |||
409 | { | 409 | { |
410 | uint32_t ctrl_ext; | 410 | uint32_t ctrl_ext; |
411 | uint32_t swsm; | 411 | uint32_t swsm; |
412 | uint32_t extcnf; | ||
413 | 412 | ||
414 | /* Let firmware taken over control of h/w */ | 413 | /* Let firmware taken over control of h/w */ |
415 | switch (adapter->hw.mac_type) { | 414 | switch (adapter->hw.mac_type) { |
416 | case e1000_82571: | ||
417 | case e1000_82572: | ||
418 | case e1000_80003es2lan: | ||
419 | ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); | ||
420 | E1000_WRITE_REG(&adapter->hw, CTRL_EXT, | ||
421 | ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); | ||
422 | break; | ||
423 | case e1000_82573: | 415 | case e1000_82573: |
424 | swsm = E1000_READ_REG(&adapter->hw, SWSM); | 416 | swsm = E1000_READ_REG(&adapter->hw, SWSM); |
425 | E1000_WRITE_REG(&adapter->hw, SWSM, | 417 | E1000_WRITE_REG(&adapter->hw, SWSM, |
426 | swsm & ~E1000_SWSM_DRV_LOAD); | 418 | swsm & ~E1000_SWSM_DRV_LOAD); |
419 | break; | ||
420 | case e1000_82571: | ||
421 | case e1000_82572: | ||
422 | case e1000_80003es2lan: | ||
427 | case e1000_ich8lan: | 423 | case e1000_ich8lan: |
428 | extcnf = E1000_READ_REG(&adapter->hw, CTRL_EXT); | 424 | ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); |
429 | E1000_WRITE_REG(&adapter->hw, CTRL_EXT, | 425 | E1000_WRITE_REG(&adapter->hw, CTRL_EXT, |
430 | extcnf & ~E1000_CTRL_EXT_DRV_LOAD); | 426 | ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); |
431 | break; | 427 | break; |
432 | default: | 428 | default: |
433 | break; | 429 | break; |
@@ -450,26 +446,21 @@ e1000_get_hw_control(struct e1000_adapter *adapter) | |||
450 | { | 446 | { |
451 | uint32_t ctrl_ext; | 447 | uint32_t ctrl_ext; |
452 | uint32_t swsm; | 448 | uint32_t swsm; |
453 | uint32_t extcnf; | ||
454 | 449 | ||
455 | /* Let firmware know the driver has taken over */ | 450 | /* Let firmware know the driver has taken over */ |
456 | switch (adapter->hw.mac_type) { | 451 | switch (adapter->hw.mac_type) { |
457 | case e1000_82571: | ||
458 | case e1000_82572: | ||
459 | case e1000_80003es2lan: | ||
460 | ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); | ||
461 | E1000_WRITE_REG(&adapter->hw, CTRL_EXT, | ||
462 | ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); | ||
463 | break; | ||
464 | case e1000_82573: | 452 | case e1000_82573: |
465 | swsm = E1000_READ_REG(&adapter->hw, SWSM); | 453 | swsm = E1000_READ_REG(&adapter->hw, SWSM); |
466 | E1000_WRITE_REG(&adapter->hw, SWSM, | 454 | E1000_WRITE_REG(&adapter->hw, SWSM, |
467 | swsm | E1000_SWSM_DRV_LOAD); | 455 | swsm | E1000_SWSM_DRV_LOAD); |
468 | break; | 456 | break; |
457 | case e1000_82571: | ||
458 | case e1000_82572: | ||
459 | case e1000_80003es2lan: | ||
469 | case e1000_ich8lan: | 460 | case e1000_ich8lan: |
470 | extcnf = E1000_READ_REG(&adapter->hw, EXTCNF_CTRL); | 461 | ctrl_ext = E1000_READ_REG(&adapter->hw, CTRL_EXT); |
471 | E1000_WRITE_REG(&adapter->hw, EXTCNF_CTRL, | 462 | E1000_WRITE_REG(&adapter->hw, CTRL_EXT, |
472 | extcnf | E1000_EXTCNF_CTRL_SWFLAG); | 463 | ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); |
473 | break; | 464 | break; |
474 | default: | 465 | default: |
475 | break; | 466 | break; |
@@ -522,14 +513,15 @@ e1000_release_manageability(struct e1000_adapter *adapter) | |||
522 | } | 513 | } |
523 | } | 514 | } |
524 | 515 | ||
525 | int | 516 | /** |
526 | e1000_up(struct e1000_adapter *adapter) | 517 | * e1000_configure - configure the hardware for RX and TX |
518 | * @adapter = private board structure | ||
519 | **/ | ||
520 | static void e1000_configure(struct e1000_adapter *adapter) | ||
527 | { | 521 | { |
528 | struct net_device *netdev = adapter->netdev; | 522 | struct net_device *netdev = adapter->netdev; |
529 | int i; | 523 | int i; |
530 | 524 | ||
531 | /* hardware has been reset, we need to reload some things */ | ||
532 | |||
533 | e1000_set_multi(netdev); | 525 | e1000_set_multi(netdev); |
534 | 526 | ||
535 | e1000_restore_vlan(adapter); | 527 | e1000_restore_vlan(adapter); |
@@ -548,14 +540,20 @@ e1000_up(struct e1000_adapter *adapter) | |||
548 | } | 540 | } |
549 | 541 | ||
550 | adapter->tx_queue_len = netdev->tx_queue_len; | 542 | adapter->tx_queue_len = netdev->tx_queue_len; |
543 | } | ||
544 | |||
545 | int e1000_up(struct e1000_adapter *adapter) | ||
546 | { | ||
547 | /* hardware has been reset, we need to reload some things */ | ||
548 | e1000_configure(adapter); | ||
549 | |||
550 | clear_bit(__E1000_DOWN, &adapter->flags); | ||
551 | 551 | ||
552 | #ifdef CONFIG_E1000_NAPI | 552 | #ifdef CONFIG_E1000_NAPI |
553 | netif_poll_enable(netdev); | 553 | netif_poll_enable(adapter->netdev); |
554 | #endif | 554 | #endif |
555 | e1000_irq_enable(adapter); | 555 | e1000_irq_enable(adapter); |
556 | 556 | ||
557 | clear_bit(__E1000_DOWN, &adapter->flags); | ||
558 | |||
559 | /* fire a link change interrupt to start the watchdog */ | 557 | /* fire a link change interrupt to start the watchdog */ |
560 | E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_LSC); | 558 | E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_LSC); |
561 | return 0; | 559 | return 0; |
@@ -640,15 +638,15 @@ e1000_down(struct e1000_adapter *adapter) | |||
640 | * reschedule our watchdog timer */ | 638 | * reschedule our watchdog timer */ |
641 | set_bit(__E1000_DOWN, &adapter->flags); | 639 | set_bit(__E1000_DOWN, &adapter->flags); |
642 | 640 | ||
641 | #ifdef CONFIG_E1000_NAPI | ||
642 | netif_poll_disable(netdev); | ||
643 | #endif | ||
643 | e1000_irq_disable(adapter); | 644 | e1000_irq_disable(adapter); |
644 | 645 | ||
645 | del_timer_sync(&adapter->tx_fifo_stall_timer); | 646 | del_timer_sync(&adapter->tx_fifo_stall_timer); |
646 | del_timer_sync(&adapter->watchdog_timer); | 647 | del_timer_sync(&adapter->watchdog_timer); |
647 | del_timer_sync(&adapter->phy_info_timer); | 648 | del_timer_sync(&adapter->phy_info_timer); |
648 | 649 | ||
649 | #ifdef CONFIG_E1000_NAPI | ||
650 | netif_poll_disable(netdev); | ||
651 | #endif | ||
652 | netdev->tx_queue_len = adapter->tx_queue_len; | 650 | netdev->tx_queue_len = adapter->tx_queue_len; |
653 | adapter->link_speed = 0; | 651 | adapter->link_speed = 0; |
654 | adapter->link_duplex = 0; | 652 | adapter->link_duplex = 0; |
@@ -1410,21 +1408,17 @@ e1000_open(struct net_device *netdev) | |||
1410 | return -EBUSY; | 1408 | return -EBUSY; |
1411 | 1409 | ||
1412 | /* allocate transmit descriptors */ | 1410 | /* allocate transmit descriptors */ |
1413 | if ((err = e1000_setup_all_tx_resources(adapter))) | 1411 | err = e1000_setup_all_tx_resources(adapter); |
1412 | if (err) | ||
1414 | goto err_setup_tx; | 1413 | goto err_setup_tx; |
1415 | 1414 | ||
1416 | /* allocate receive descriptors */ | 1415 | /* allocate receive descriptors */ |
1417 | if ((err = e1000_setup_all_rx_resources(adapter))) | 1416 | err = e1000_setup_all_rx_resources(adapter); |
1418 | goto err_setup_rx; | ||
1419 | |||
1420 | err = e1000_request_irq(adapter); | ||
1421 | if (err) | 1417 | if (err) |
1422 | goto err_req_irq; | 1418 | goto err_setup_rx; |
1423 | 1419 | ||
1424 | e1000_power_up_phy(adapter); | 1420 | e1000_power_up_phy(adapter); |
1425 | 1421 | ||
1426 | if ((err = e1000_up(adapter))) | ||
1427 | goto err_up; | ||
1428 | adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; | 1422 | adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; |
1429 | if ((adapter->hw.mng_cookie.status & | 1423 | if ((adapter->hw.mng_cookie.status & |
1430 | E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { | 1424 | E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { |
@@ -1437,12 +1431,33 @@ e1000_open(struct net_device *netdev) | |||
1437 | e1000_check_mng_mode(&adapter->hw)) | 1431 | e1000_check_mng_mode(&adapter->hw)) |
1438 | e1000_get_hw_control(adapter); | 1432 | e1000_get_hw_control(adapter); |
1439 | 1433 | ||
1434 | /* before we allocate an interrupt, we must be ready to handle it. | ||
1435 | * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt | ||
1436 | * as soon as we call pci_request_irq, so we have to setup our | ||
1437 | * clean_rx handler before we do so. */ | ||
1438 | e1000_configure(adapter); | ||
1439 | |||
1440 | err = e1000_request_irq(adapter); | ||
1441 | if (err) | ||
1442 | goto err_req_irq; | ||
1443 | |||
1444 | /* From here on the code is the same as e1000_up() */ | ||
1445 | clear_bit(__E1000_DOWN, &adapter->flags); | ||
1446 | |||
1447 | #ifdef CONFIG_E1000_NAPI | ||
1448 | netif_poll_enable(netdev); | ||
1449 | #endif | ||
1450 | |||
1451 | e1000_irq_enable(adapter); | ||
1452 | |||
1453 | /* fire a link status change interrupt to start the watchdog */ | ||
1454 | E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_LSC); | ||
1455 | |||
1440 | return E1000_SUCCESS; | 1456 | return E1000_SUCCESS; |
1441 | 1457 | ||
1442 | err_up: | ||
1443 | e1000_power_down_phy(adapter); | ||
1444 | e1000_free_irq(adapter); | ||
1445 | err_req_irq: | 1458 | err_req_irq: |
1459 | e1000_release_hw_control(adapter); | ||
1460 | e1000_power_down_phy(adapter); | ||
1446 | e1000_free_all_rx_resources(adapter); | 1461 | e1000_free_all_rx_resources(adapter); |
1447 | err_setup_rx: | 1462 | err_setup_rx: |
1448 | e1000_free_all_tx_resources(adapter); | 1463 | e1000_free_all_tx_resources(adapter); |
@@ -3361,12 +3376,9 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
3361 | (adapter->hw.mac_type == e1000_82573)) | 3376 | (adapter->hw.mac_type == e1000_82573)) |
3362 | e1000_transfer_dhcp_info(adapter, skb); | 3377 | e1000_transfer_dhcp_info(adapter, skb); |
3363 | 3378 | ||
3364 | local_irq_save(flags); | 3379 | if (!spin_trylock_irqsave(&tx_ring->tx_lock, flags)) |
3365 | if (!spin_trylock(&tx_ring->tx_lock)) { | ||
3366 | /* Collision - tell upper layer to requeue */ | 3380 | /* Collision - tell upper layer to requeue */ |
3367 | local_irq_restore(flags); | ||
3368 | return NETDEV_TX_LOCKED; | 3381 | return NETDEV_TX_LOCKED; |
3369 | } | ||
3370 | 3382 | ||
3371 | /* need: count + 2 desc gap to keep tail from touching | 3383 | /* need: count + 2 desc gap to keep tail from touching |
3372 | * head, otherwise try next time */ | 3384 | * head, otherwise try next time */ |