aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorLinas Vepstas <linas@austin.ibm.com>2007-05-14 19:37:30 -0400
committerJeff Garzik <jeff@garzik.org>2007-07-08 22:16:38 -0400
commitd796fdb708fc5b10112934cba43e832c36ce4923 (patch)
tree433063c793bd095721bcbb811cf8460ff3ec228f /drivers/net
parentbd5824f138153f407e300728919e814ab7dcfadb (diff)
s2io: add PCI error recovery support
This patch adds PCI error recovery support to the s2io 10-Gigabit ethernet device driver. Third revision, blocks interrupts and the watchdog. Tested, seems to work well. Signed-off-by: Linas Vepstas <linas@austin.ibm.com> Acked-by: Ramkrishna Vepa <Ramkrishna.Vepa@neterion.com> Cc: Raghavendra Koushik <raghavendra.koushik@neterion.com> Cc: Wen Xiong <wenxiong@us.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/s2io.c116
-rw-r--r--drivers/net/s2io.h5
2 files changed, 116 insertions, 5 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 09078ff84cd2..392ad4a42291 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -469,11 +469,18 @@ static struct pci_device_id s2io_tbl[] __devinitdata = {
469 469
470MODULE_DEVICE_TABLE(pci, s2io_tbl); 470MODULE_DEVICE_TABLE(pci, s2io_tbl);
471 471
472static struct pci_error_handlers s2io_err_handler = {
473 .error_detected = s2io_io_error_detected,
474 .slot_reset = s2io_io_slot_reset,
475 .resume = s2io_io_resume,
476};
477
472static struct pci_driver s2io_driver = { 478static struct pci_driver s2io_driver = {
473 .name = "S2IO", 479 .name = "S2IO",
474 .id_table = s2io_tbl, 480 .id_table = s2io_tbl,
475 .probe = s2io_init_nic, 481 .probe = s2io_init_nic,
476 .remove = __devexit_p(s2io_rem_nic), 482 .remove = __devexit_p(s2io_rem_nic),
483 .err_handler = &s2io_err_handler,
477}; 484};
478 485
479/* A simplifier macro used both by init and free shared_mem Fns(). */ 486/* A simplifier macro used both by init and free shared_mem Fns(). */
@@ -2689,6 +2696,9 @@ static void s2io_netpoll(struct net_device *dev)
2689 u64 val64 = 0xFFFFFFFFFFFFFFFFULL; 2696 u64 val64 = 0xFFFFFFFFFFFFFFFFULL;
2690 int i; 2697 int i;
2691 2698
2699 if (pci_channel_offline(nic->pdev))
2700 return;
2701
2692 disable_irq(dev->irq); 2702 disable_irq(dev->irq);
2693 2703
2694 atomic_inc(&nic->isr_cnt); 2704 atomic_inc(&nic->isr_cnt);
@@ -3215,6 +3225,8 @@ static void alarm_intr_handler(struct s2io_nic *nic)
3215 int i; 3225 int i;
3216 if (atomic_read(&nic->card_state) == CARD_DOWN) 3226 if (atomic_read(&nic->card_state) == CARD_DOWN)
3217 return; 3227 return;
3228 if (pci_channel_offline(nic->pdev))
3229 return;
3218 nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0; 3230 nic->mac_control.stats_info->sw_stat.ring_full_cnt = 0;
3219 /* Handling the XPAK counters update */ 3231 /* Handling the XPAK counters update */
3220 if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) { 3232 if(nic->mac_control.stats_info->xpak_stat.xpak_timer_count < 72000) {
@@ -4314,6 +4326,10 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
4314 struct mac_info *mac_control; 4326 struct mac_info *mac_control;
4315 struct config_param *config; 4327 struct config_param *config;
4316 4328
4329 /* Pretend we handled any irq's from a disconnected card */
4330 if (pci_channel_offline(sp->pdev))
4331 return IRQ_NONE;
4332
4317 atomic_inc(&sp->isr_cnt); 4333 atomic_inc(&sp->isr_cnt);
4318 mac_control = &sp->mac_control; 4334 mac_control = &sp->mac_control;
4319 config = &sp->config; 4335 config = &sp->config;
@@ -6569,7 +6585,7 @@ static void s2io_rem_isr(struct s2io_nic * sp)
6569 } while(cnt < 5); 6585 } while(cnt < 5);
6570} 6586}
6571 6587
6572static void s2io_card_down(struct s2io_nic * sp) 6588static void do_s2io_card_down(struct s2io_nic * sp, int do_io)
6573{ 6589{
6574 int cnt = 0; 6590 int cnt = 0;
6575 struct XENA_dev_config __iomem *bar0 = sp->bar0; 6591 struct XENA_dev_config __iomem *bar0 = sp->bar0;
@@ -6584,7 +6600,8 @@ static void s2io_card_down(struct s2io_nic * sp)
6584 atomic_set(&sp->card_state, CARD_DOWN); 6600 atomic_set(&sp->card_state, CARD_DOWN);
6585 6601
6586 /* disable Tx and Rx traffic on the NIC */ 6602 /* disable Tx and Rx traffic on the NIC */
6587 stop_nic(sp); 6603 if (do_io)
6604 stop_nic(sp);
6588 6605
6589 s2io_rem_isr(sp); 6606 s2io_rem_isr(sp);
6590 6607
@@ -6592,7 +6609,7 @@ static void s2io_card_down(struct s2io_nic * sp)
6592 tasklet_kill(&sp->task); 6609 tasklet_kill(&sp->task);
6593 6610
6594 /* Check if the device is Quiescent and then Reset the NIC */ 6611 /* Check if the device is Quiescent and then Reset the NIC */
6595 do { 6612 while(do_io) {
6596 /* As per the HW requirement we need to replenish the 6613 /* As per the HW requirement we need to replenish the
6597 * receive buffer to avoid the ring bump. Since there is 6614 * receive buffer to avoid the ring bump. Since there is
6598 * no intention of processing the Rx frame at this pointwe are 6615 * no intention of processing the Rx frame at this pointwe are
@@ -6617,8 +6634,9 @@ static void s2io_card_down(struct s2io_nic * sp)
6617 (unsigned long long) val64); 6634 (unsigned long long) val64);
6618 break; 6635 break;
6619 } 6636 }
6620 } while (1); 6637 }
6621 s2io_reset(sp); 6638 if (do_io)
6639 s2io_reset(sp);
6622 6640
6623 spin_lock_irqsave(&sp->tx_lock, flags); 6641 spin_lock_irqsave(&sp->tx_lock, flags);
6624 /* Free all Tx buffers */ 6642 /* Free all Tx buffers */
@@ -6633,6 +6651,11 @@ static void s2io_card_down(struct s2io_nic * sp)
6633 clear_bit(0, &(sp->link_state)); 6651 clear_bit(0, &(sp->link_state));
6634} 6652}
6635 6653
6654static void s2io_card_down(struct s2io_nic * sp)
6655{
6656 do_s2io_card_down(sp, 1);
6657}
6658
6636static int s2io_card_up(struct s2io_nic * sp) 6659static int s2io_card_up(struct s2io_nic * sp)
6637{ 6660{
6638 int i, ret = 0; 6661 int i, ret = 0;
@@ -8010,3 +8033,86 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
8010 sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++; 8033 sp->mac_control.stats_info->sw_stat.clubbed_frms_cnt++;
8011 return; 8034 return;
8012} 8035}
8036
8037/**
8038 * s2io_io_error_detected - called when PCI error is detected
8039 * @pdev: Pointer to PCI device
8040 * @state: The current pci conneection state
8041 *
8042 * This function is called after a PCI bus error affecting
8043 * this device has been detected.
8044 */
8045static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
8046 pci_channel_state_t state)
8047{
8048 struct net_device *netdev = pci_get_drvdata(pdev);
8049 struct s2io_nic *sp = netdev->priv;
8050
8051 netif_device_detach(netdev);
8052
8053 if (netif_running(netdev)) {
8054 /* Bring down the card, while avoiding PCI I/O */
8055 do_s2io_card_down(sp, 0);
8056 sp->device_close_flag = TRUE; /* Device is shut down. */
8057 }
8058 pci_disable_device(pdev);
8059
8060 return PCI_ERS_RESULT_NEED_RESET;
8061}
8062
8063/**
8064 * s2io_io_slot_reset - called after the pci bus has been reset.
8065 * @pdev: Pointer to PCI device
8066 *
8067 * Restart the card from scratch, as if from a cold-boot.
8068 * At this point, the card has exprienced a hard reset,
8069 * followed by fixups by BIOS, and has its config space
8070 * set up identically to what it was at cold boot.
8071 */
8072static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev)
8073{
8074 struct net_device *netdev = pci_get_drvdata(pdev);
8075 struct s2io_nic *sp = netdev->priv;
8076
8077 if (pci_enable_device(pdev)) {
8078 printk(KERN_ERR "s2io: "
8079 "Cannot re-enable PCI device after reset.\n");
8080 return PCI_ERS_RESULT_DISCONNECT;
8081 }
8082
8083 pci_set_master(pdev);
8084 s2io_reset(sp);
8085
8086 return PCI_ERS_RESULT_RECOVERED;
8087}
8088
8089/**
8090 * s2io_io_resume - called when traffic can start flowing again.
8091 * @pdev: Pointer to PCI device
8092 *
8093 * This callback is called when the error recovery driver tells
8094 * us that its OK to resume normal operation.
8095 */
8096static void s2io_io_resume(struct pci_dev *pdev)
8097{
8098 struct net_device *netdev = pci_get_drvdata(pdev);
8099 struct s2io_nic *sp = netdev->priv;
8100
8101 if (netif_running(netdev)) {
8102 if (s2io_card_up(sp)) {
8103 printk(KERN_ERR "s2io: "
8104 "Can't bring device back up after reset.\n");
8105 return;
8106 }
8107
8108 if (s2io_set_mac_addr(netdev, netdev->dev_addr) == FAILURE) {
8109 s2io_card_down(sp);
8110 printk(KERN_ERR "s2io: "
8111 "Can't resetore mac addr after reset.\n");
8112 return;
8113 }
8114 }
8115
8116 netif_device_attach(netdev);
8117 netif_wake_queue(netdev);
8118}
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h
index 54baa0b8ec7c..b9b660702abd 100644
--- a/drivers/net/s2io.h
+++ b/drivers/net/s2io.h
@@ -1052,6 +1052,11 @@ static void lro_append_pkt(struct s2io_nic *sp, struct lro *lro,
1052 struct sk_buff *skb, u32 tcp_len); 1052 struct sk_buff *skb, u32 tcp_len);
1053static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring); 1053static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring);
1054 1054
1055static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
1056 pci_channel_state_t state);
1057static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev);
1058static void s2io_io_resume(struct pci_dev *pdev);
1059
1055#define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size 1060#define s2io_tcp_mss(skb) skb_shinfo(skb)->gso_size
1056#define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size 1061#define s2io_udp_mss(skb) skb_shinfo(skb)->gso_size
1057#define s2io_offload_type(skb) skb_shinfo(skb)->gso_type 1062#define s2io_offload_type(skb) skb_shinfo(skb)->gso_type