diff options
author | Auke Kok <auke-jan.h.kok@intel.com> | 2007-03-06 11:57:21 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-04-26 02:22:41 -0400 |
commit | e0aac5a289b1dacbc94bd9ae8c449bcdf9ab508c (patch) | |
tree | 53fdb8fe23d6413f20a1b3555d93d12f1742d9ce /drivers/net/e1000 | |
parent | de46c33745f5e2ad594c72f2cf5f490861b16ce1 (diff) |
e1000: FIX: be ready for incoming irq at pci_request_irq
DEBUG_SHIRQ code exposed that e1000 was not ready for incoming interrupts
after having called pci_request_irq. This obviously requires us to finish
our software setup which assigns the irq handler before we request the
irq.
Signed-off-by: Auke Kok <auke-jan.h.kok@intel.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/e1000')
-rw-r--r-- | drivers/net/e1000/e1000_main.c | 66 |
1 files changed, 45 insertions, 21 deletions
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index b28a915bd980..f777d37d8e66 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -522,14 +522,15 @@ e1000_release_manageability(struct e1000_adapter *adapter) | |||
522 | } | 522 | } |
523 | } | 523 | } |
524 | 524 | ||
525 | int | 525 | /** |
526 | e1000_up(struct e1000_adapter *adapter) | 526 | * e1000_configure - configure the hardware for RX and TX |
527 | * @adapter = private board structure | ||
528 | **/ | ||
529 | static void e1000_configure(struct e1000_adapter *adapter) | ||
527 | { | 530 | { |
528 | struct net_device *netdev = adapter->netdev; | 531 | struct net_device *netdev = adapter->netdev; |
529 | int i; | 532 | int i; |
530 | 533 | ||
531 | /* hardware has been reset, we need to reload some things */ | ||
532 | |||
533 | e1000_set_multi(netdev); | 534 | e1000_set_multi(netdev); |
534 | 535 | ||
535 | e1000_restore_vlan(adapter); | 536 | e1000_restore_vlan(adapter); |
@@ -548,14 +549,20 @@ e1000_up(struct e1000_adapter *adapter) | |||
548 | } | 549 | } |
549 | 550 | ||
550 | adapter->tx_queue_len = netdev->tx_queue_len; | 551 | adapter->tx_queue_len = netdev->tx_queue_len; |
552 | } | ||
553 | |||
554 | int e1000_up(struct e1000_adapter *adapter) | ||
555 | { | ||
556 | /* hardware has been reset, we need to reload some things */ | ||
557 | e1000_configure(adapter); | ||
558 | |||
559 | clear_bit(__E1000_DOWN, &adapter->flags); | ||
551 | 560 | ||
552 | #ifdef CONFIG_E1000_NAPI | 561 | #ifdef CONFIG_E1000_NAPI |
553 | netif_poll_enable(netdev); | 562 | netif_poll_enable(adapter->netdev); |
554 | #endif | 563 | #endif |
555 | e1000_irq_enable(adapter); | 564 | e1000_irq_enable(adapter); |
556 | 565 | ||
557 | clear_bit(__E1000_DOWN, &adapter->flags); | ||
558 | |||
559 | /* fire a link change interrupt to start the watchdog */ | 566 | /* fire a link change interrupt to start the watchdog */ |
560 | E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_LSC); | 567 | E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_LSC); |
561 | return 0; | 568 | return 0; |
@@ -640,15 +647,15 @@ e1000_down(struct e1000_adapter *adapter) | |||
640 | * reschedule our watchdog timer */ | 647 | * reschedule our watchdog timer */ |
641 | set_bit(__E1000_DOWN, &adapter->flags); | 648 | set_bit(__E1000_DOWN, &adapter->flags); |
642 | 649 | ||
650 | #ifdef CONFIG_E1000_NAPI | ||
651 | netif_poll_disable(netdev); | ||
652 | #endif | ||
643 | e1000_irq_disable(adapter); | 653 | e1000_irq_disable(adapter); |
644 | 654 | ||
645 | del_timer_sync(&adapter->tx_fifo_stall_timer); | 655 | del_timer_sync(&adapter->tx_fifo_stall_timer); |
646 | del_timer_sync(&adapter->watchdog_timer); | 656 | del_timer_sync(&adapter->watchdog_timer); |
647 | del_timer_sync(&adapter->phy_info_timer); | 657 | del_timer_sync(&adapter->phy_info_timer); |
648 | 658 | ||
649 | #ifdef CONFIG_E1000_NAPI | ||
650 | netif_poll_disable(netdev); | ||
651 | #endif | ||
652 | netdev->tx_queue_len = adapter->tx_queue_len; | 659 | netdev->tx_queue_len = adapter->tx_queue_len; |
653 | adapter->link_speed = 0; | 660 | adapter->link_speed = 0; |
654 | adapter->link_duplex = 0; | 661 | adapter->link_duplex = 0; |
@@ -1410,21 +1417,17 @@ e1000_open(struct net_device *netdev) | |||
1410 | return -EBUSY; | 1417 | return -EBUSY; |
1411 | 1418 | ||
1412 | /* allocate transmit descriptors */ | 1419 | /* allocate transmit descriptors */ |
1413 | if ((err = e1000_setup_all_tx_resources(adapter))) | 1420 | err = e1000_setup_all_tx_resources(adapter); |
1421 | if (err) | ||
1414 | goto err_setup_tx; | 1422 | goto err_setup_tx; |
1415 | 1423 | ||
1416 | /* allocate receive descriptors */ | 1424 | /* allocate receive descriptors */ |
1417 | if ((err = e1000_setup_all_rx_resources(adapter))) | 1425 | err = e1000_setup_all_rx_resources(adapter); |
1418 | goto err_setup_rx; | ||
1419 | |||
1420 | err = e1000_request_irq(adapter); | ||
1421 | if (err) | 1426 | if (err) |
1422 | goto err_req_irq; | 1427 | goto err_setup_rx; |
1423 | 1428 | ||
1424 | e1000_power_up_phy(adapter); | 1429 | e1000_power_up_phy(adapter); |
1425 | 1430 | ||
1426 | if ((err = e1000_up(adapter))) | ||
1427 | goto err_up; | ||
1428 | adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; | 1431 | adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; |
1429 | if ((adapter->hw.mng_cookie.status & | 1432 | if ((adapter->hw.mng_cookie.status & |
1430 | E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { | 1433 | E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { |
@@ -1437,12 +1440,33 @@ e1000_open(struct net_device *netdev) | |||
1437 | e1000_check_mng_mode(&adapter->hw)) | 1440 | e1000_check_mng_mode(&adapter->hw)) |
1438 | e1000_get_hw_control(adapter); | 1441 | e1000_get_hw_control(adapter); |
1439 | 1442 | ||
1443 | /* before we allocate an interrupt, we must be ready to handle it. | ||
1444 | * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt | ||
1445 | * as soon as we call pci_request_irq, so we have to setup our | ||
1446 | * clean_rx handler before we do so. */ | ||
1447 | e1000_configure(adapter); | ||
1448 | |||
1449 | err = e1000_request_irq(adapter); | ||
1450 | if (err) | ||
1451 | goto err_req_irq; | ||
1452 | |||
1453 | /* From here on the code is the same as e1000_up() */ | ||
1454 | clear_bit(__E1000_DOWN, &adapter->flags); | ||
1455 | |||
1456 | #ifdef CONFIG_E1000_NAPI | ||
1457 | netif_poll_enable(netdev); | ||
1458 | #endif | ||
1459 | |||
1460 | e1000_irq_enable(adapter); | ||
1461 | |||
1462 | /* fire a link status change interrupt to start the watchdog */ | ||
1463 | E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_LSC); | ||
1464 | |||
1440 | return E1000_SUCCESS; | 1465 | return E1000_SUCCESS; |
1441 | 1466 | ||
1442 | err_up: | ||
1443 | e1000_power_down_phy(adapter); | ||
1444 | e1000_free_irq(adapter); | ||
1445 | err_req_irq: | 1467 | err_req_irq: |
1468 | e1000_release_hw_control(adapter); | ||
1469 | e1000_power_down_phy(adapter); | ||
1446 | e1000_free_all_rx_resources(adapter); | 1470 | e1000_free_all_rx_resources(adapter); |
1447 | err_setup_rx: | 1471 | err_setup_rx: |
1448 | e1000_free_all_tx_resources(adapter); | 1472 | e1000_free_all_tx_resources(adapter); |