aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAuke Kok <auke-jan.h.kok@intel.com>2007-03-06 11:57:21 -0500
committerJeff Garzik <jeff@garzik.org>2007-04-26 02:22:41 -0400
commite0aac5a289b1dacbc94bd9ae8c449bcdf9ab508c (patch)
tree53fdb8fe23d6413f20a1b3555d93d12f1742d9ce /drivers
parentde46c33745f5e2ad594c72f2cf5f490861b16ce1 (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')
-rw-r--r--drivers/net/e1000/e1000_main.c66
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
525int 525/**
526e1000_up(struct e1000_adapter *adapter) 526 * e1000_configure - configure the hardware for RX and TX
527 * @adapter = private board structure
528 **/
529static 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
554int 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
1442err_up:
1443 e1000_power_down_phy(adapter);
1444 e1000_free_irq(adapter);
1445err_req_irq: 1467err_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);
1447err_setup_rx: 1471err_setup_rx:
1448 e1000_free_all_tx_resources(adapter); 1472 e1000_free_all_tx_resources(adapter);