diff options
author | Divy Le Ray <divy@chelsio.com> | 2008-05-06 22:26:01 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-05-13 01:31:37 -0400 |
commit | 204e2f98c2d13f869b8541f3c57c7314f75cab11 (patch) | |
tree | a415a3e80acfe19298d0238747aed6b665971558 /drivers/net/cxgb3 | |
parent | 48c4b6dbb7e246957e13302668acf7c77e4f8b3a (diff) |
cxgb3 - fix EEH
Reset the chip when the PCI link goes down.
Preserve the napi structure when a sge qset's resources are freed.
Replay only HW initialization when the chip comes out of reset.
Signed-off-by: Divy Le ray <divy@chelsio.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/net/cxgb3')
-rw-r--r-- | drivers/net/cxgb3/common.h | 1 | ||||
-rw-r--r-- | drivers/net/cxgb3/cxgb3_main.c | 10 | ||||
-rw-r--r-- | drivers/net/cxgb3/regs.h | 8 | ||||
-rw-r--r-- | drivers/net/cxgb3/sge.c | 29 | ||||
-rw-r--r-- | drivers/net/cxgb3/t3_hw.c | 28 |
5 files changed, 70 insertions, 6 deletions
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index 91ee7277b813..579bee42a5cb 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h | |||
@@ -698,6 +698,7 @@ void mac_prep(struct cmac *mac, struct adapter *adapter, int index); | |||
698 | void early_hw_init(struct adapter *adapter, const struct adapter_info *ai); | 698 | void early_hw_init(struct adapter *adapter, const struct adapter_info *ai); |
699 | int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, | 699 | int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, |
700 | int reset); | 700 | int reset); |
701 | int t3_replay_prep_adapter(struct adapter *adapter); | ||
701 | void t3_led_ready(struct adapter *adapter); | 702 | void t3_led_ready(struct adapter *adapter); |
702 | void t3_fatal_err(struct adapter *adapter); | 703 | void t3_fatal_err(struct adapter *adapter); |
703 | void t3_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on); | 704 | void t3_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on); |
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index d67fc10a6b36..3a3127216791 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
@@ -2430,9 +2430,6 @@ static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev, | |||
2430 | test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) | 2430 | test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) |
2431 | offload_close(&adapter->tdev); | 2431 | offload_close(&adapter->tdev); |
2432 | 2432 | ||
2433 | /* Free sge resources */ | ||
2434 | t3_free_sge_resources(adapter); | ||
2435 | |||
2436 | adapter->flags &= ~FULL_INIT_DONE; | 2433 | adapter->flags &= ~FULL_INIT_DONE; |
2437 | 2434 | ||
2438 | pci_disable_device(pdev); | 2435 | pci_disable_device(pdev); |
@@ -2457,8 +2454,12 @@ static pci_ers_result_t t3_io_slot_reset(struct pci_dev *pdev) | |||
2457 | goto err; | 2454 | goto err; |
2458 | } | 2455 | } |
2459 | pci_set_master(pdev); | 2456 | pci_set_master(pdev); |
2457 | pci_restore_state(pdev); | ||
2458 | |||
2459 | /* Free sge resources */ | ||
2460 | t3_free_sge_resources(adapter); | ||
2460 | 2461 | ||
2461 | if (t3_prep_adapter(adapter, adapter->params.info, 1)) | 2462 | if (t3_replay_prep_adapter(adapter)) |
2462 | goto err; | 2463 | goto err; |
2463 | 2464 | ||
2464 | return PCI_ERS_RESULT_RECOVERED; | 2465 | return PCI_ERS_RESULT_RECOVERED; |
@@ -2610,6 +2611,7 @@ static int __devinit init_one(struct pci_dev *pdev, | |||
2610 | } | 2611 | } |
2611 | 2612 | ||
2612 | pci_set_master(pdev); | 2613 | pci_set_master(pdev); |
2614 | pci_save_state(pdev); | ||
2613 | 2615 | ||
2614 | mmio_start = pci_resource_start(pdev, 0); | 2616 | mmio_start = pci_resource_start(pdev, 0); |
2615 | mmio_len = pci_resource_len(pdev, 0); | 2617 | mmio_len = pci_resource_len(pdev, 0); |
diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index 02dbbb300929..567178879345 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h | |||
@@ -444,6 +444,14 @@ | |||
444 | 444 | ||
445 | #define A_PCIE_CFG 0x88 | 445 | #define A_PCIE_CFG 0x88 |
446 | 446 | ||
447 | #define S_ENABLELINKDWNDRST 21 | ||
448 | #define V_ENABLELINKDWNDRST(x) ((x) << S_ENABLELINKDWNDRST) | ||
449 | #define F_ENABLELINKDWNDRST V_ENABLELINKDWNDRST(1U) | ||
450 | |||
451 | #define S_ENABLELINKDOWNRST 20 | ||
452 | #define V_ENABLELINKDOWNRST(x) ((x) << S_ENABLELINKDOWNRST) | ||
453 | #define F_ENABLELINKDOWNRST V_ENABLELINKDOWNRST(1U) | ||
454 | |||
447 | #define S_PCIE_CLIDECEN 16 | 455 | #define S_PCIE_CLIDECEN 16 |
448 | #define V_PCIE_CLIDECEN(x) ((x) << S_PCIE_CLIDECEN) | 456 | #define V_PCIE_CLIDECEN(x) ((x) << S_PCIE_CLIDECEN) |
449 | #define F_PCIE_CLIDECEN V_PCIE_CLIDECEN(1U) | 457 | #define F_PCIE_CLIDECEN V_PCIE_CLIDECEN(1U) |
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 98a6bbd11d4c..796eb305cdc3 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c | |||
@@ -539,6 +539,31 @@ static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size, | |||
539 | } | 539 | } |
540 | 540 | ||
541 | /** | 541 | /** |
542 | * t3_reset_qset - reset a sge qset | ||
543 | * @q: the queue set | ||
544 | * | ||
545 | * Reset the qset structure. | ||
546 | * the NAPI structure is preserved in the event of | ||
547 | * the qset's reincarnation, for example during EEH recovery. | ||
548 | */ | ||
549 | static void t3_reset_qset(struct sge_qset *q) | ||
550 | { | ||
551 | if (q->adap && | ||
552 | !(q->adap->flags & NAPI_INIT)) { | ||
553 | memset(q, 0, sizeof(*q)); | ||
554 | return; | ||
555 | } | ||
556 | |||
557 | q->adap = NULL; | ||
558 | memset(&q->rspq, 0, sizeof(q->rspq)); | ||
559 | memset(q->fl, 0, sizeof(struct sge_fl) * SGE_RXQ_PER_SET); | ||
560 | memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET); | ||
561 | q->txq_stopped = 0; | ||
562 | memset(&q->tx_reclaim_timer, 0, sizeof(q->tx_reclaim_timer)); | ||
563 | } | ||
564 | |||
565 | |||
566 | /** | ||
542 | * free_qset - free the resources of an SGE queue set | 567 | * free_qset - free the resources of an SGE queue set |
543 | * @adapter: the adapter owning the queue set | 568 | * @adapter: the adapter owning the queue set |
544 | * @q: the queue set | 569 | * @q: the queue set |
@@ -594,7 +619,7 @@ static void t3_free_qset(struct adapter *adapter, struct sge_qset *q) | |||
594 | q->rspq.desc, q->rspq.phys_addr); | 619 | q->rspq.desc, q->rspq.phys_addr); |
595 | } | 620 | } |
596 | 621 | ||
597 | memset(q, 0, sizeof(*q)); | 622 | t3_reset_qset(q); |
598 | } | 623 | } |
599 | 624 | ||
600 | /** | 625 | /** |
@@ -1365,7 +1390,7 @@ static void restart_ctrlq(unsigned long data) | |||
1365 | */ | 1390 | */ |
1366 | int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb) | 1391 | int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb) |
1367 | { | 1392 | { |
1368 | int ret; | 1393 | int ret; |
1369 | local_bh_disable(); | 1394 | local_bh_disable(); |
1370 | ret = ctrl_xmit(adap, &adap->sge.qs[0].txq[TXQ_CTRL], skb); | 1395 | ret = ctrl_xmit(adap, &adap->sge.qs[0].txq[TXQ_CTRL], skb); |
1371 | local_bh_enable(); | 1396 | local_bh_enable(); |
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index a99496a431c4..d405a932c73a 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c | |||
@@ -3264,6 +3264,7 @@ static void config_pcie(struct adapter *adap) | |||
3264 | 3264 | ||
3265 | t3_write_reg(adap, A_PCIE_PEX_ERR, 0xffffffff); | 3265 | t3_write_reg(adap, A_PCIE_PEX_ERR, 0xffffffff); |
3266 | t3_set_reg_field(adap, A_PCIE_CFG, 0, | 3266 | t3_set_reg_field(adap, A_PCIE_CFG, 0, |
3267 | F_ENABLELINKDWNDRST | F_ENABLELINKDOWNRST | | ||
3267 | F_PCIE_DMASTOPEN | F_PCIE_CLIDECEN); | 3268 | F_PCIE_DMASTOPEN | F_PCIE_CLIDECEN); |
3268 | } | 3269 | } |
3269 | 3270 | ||
@@ -3655,3 +3656,30 @@ void t3_led_ready(struct adapter *adapter) | |||
3655 | t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, | 3656 | t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, |
3656 | F_GPIO0_OUT_VAL); | 3657 | F_GPIO0_OUT_VAL); |
3657 | } | 3658 | } |
3659 | |||
3660 | int t3_replay_prep_adapter(struct adapter *adapter) | ||
3661 | { | ||
3662 | const struct adapter_info *ai = adapter->params.info; | ||
3663 | unsigned int i, j = 0; | ||
3664 | int ret; | ||
3665 | |||
3666 | early_hw_init(adapter, ai); | ||
3667 | ret = init_parity(adapter); | ||
3668 | if (ret) | ||
3669 | return ret; | ||
3670 | |||
3671 | for_each_port(adapter, i) { | ||
3672 | struct port_info *p = adap2pinfo(adapter, i); | ||
3673 | while (!adapter->params.vpd.port_type[j]) | ||
3674 | ++j; | ||
3675 | |||
3676 | p->port_type->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, | ||
3677 | ai->mdio_ops); | ||
3678 | |||
3679 | p->phy.ops->power_down(&p->phy, 1); | ||
3680 | ++j; | ||
3681 | } | ||
3682 | |||
3683 | return 0; | ||
3684 | } | ||
3685 | |||