34
34
#include <linux/ipv6.h>
35
35
#include <linux/inetdevice.h>
36
36
#include <linux/sysfs.h>
37
+ #include <linux/aer.h>
37
38
38
39
MODULE_DESCRIPTION ("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver" );
39
40
MODULE_LICENSE ("GPL" );
@@ -1306,6 +1307,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1306
1307
goto err_out_disable_pdev ;
1307
1308
1308
1309
pci_set_master (pdev );
1310
+ pci_enable_pcie_error_reporting (pdev );
1309
1311
1310
1312
netdev = alloc_etherdev (sizeof (struct qlcnic_adapter ));
1311
1313
if (!netdev ) {
@@ -1437,6 +1439,7 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
1437
1439
1438
1440
qlcnic_release_firmware (adapter );
1439
1441
1442
+ pci_disable_pcie_error_reporting (pdev );
1440
1443
pci_release_regions (pdev );
1441
1444
pci_disable_device (pdev );
1442
1445
pci_set_drvdata (pdev , NULL );
@@ -2521,6 +2524,9 @@ static void
2521
2524
qlcnic_schedule_work (struct qlcnic_adapter * adapter ,
2522
2525
work_func_t func , int delay )
2523
2526
{
2527
+ if (test_bit (__QLCNIC_AER , & adapter -> state ))
2528
+ return ;
2529
+
2524
2530
INIT_DELAYED_WORK (& adapter -> fw_work , func );
2525
2531
schedule_delayed_work (& adapter -> fw_work , round_jiffies_relative (delay ));
2526
2532
}
@@ -2631,6 +2637,128 @@ qlcnic_fw_poll_work(struct work_struct *work)
2631
2637
qlcnic_schedule_work (adapter , qlcnic_fw_poll_work , FW_POLL_DELAY );
2632
2638
}
2633
2639
2640
+ static int qlcnic_is_first_func (struct pci_dev * pdev )
2641
+ {
2642
+ struct pci_dev * oth_pdev ;
2643
+ int val = pdev -> devfn ;
2644
+
2645
+ while (val -- > 0 ) {
2646
+ oth_pdev = pci_get_domain_bus_and_slot (pci_domain_nr
2647
+ (pdev -> bus ), pdev -> bus -> number ,
2648
+ PCI_DEVFN (PCI_SLOT (pdev -> devfn ), val ));
2649
+
2650
+ if (oth_pdev && (oth_pdev -> current_state != PCI_D3cold ))
2651
+ return 0 ;
2652
+ }
2653
+ return 1 ;
2654
+ }
2655
+
2656
+ static int qlcnic_attach_func (struct pci_dev * pdev )
2657
+ {
2658
+ int err , first_func ;
2659
+ struct qlcnic_adapter * adapter = pci_get_drvdata (pdev );
2660
+ struct net_device * netdev = adapter -> netdev ;
2661
+
2662
+ pdev -> error_state = pci_channel_io_normal ;
2663
+
2664
+ err = pci_enable_device (pdev );
2665
+ if (err )
2666
+ return err ;
2667
+
2668
+ pci_set_power_state (pdev , PCI_D0 );
2669
+ pci_set_master (pdev );
2670
+ pci_restore_state (pdev );
2671
+
2672
+ first_func = qlcnic_is_first_func (pdev );
2673
+
2674
+ if (qlcnic_api_lock (adapter ))
2675
+ return - EINVAL ;
2676
+
2677
+ if (first_func ) {
2678
+ adapter -> need_fw_reset = 1 ;
2679
+ set_bit (__QLCNIC_START_FW , & adapter -> state );
2680
+ QLCWR32 (adapter , QLCNIC_CRB_DEV_STATE , QLCNIC_DEV_INITIALIZING );
2681
+ QLCDB (adapter , DRV , "Restarting fw\n" );
2682
+ }
2683
+ qlcnic_api_unlock (adapter );
2684
+
2685
+ err = adapter -> nic_ops -> start_firmware (adapter );
2686
+ if (err )
2687
+ return err ;
2688
+
2689
+ qlcnic_clr_drv_state (adapter );
2690
+ qlcnic_setup_intr (adapter );
2691
+
2692
+ if (netif_running (netdev )) {
2693
+ err = qlcnic_attach (adapter );
2694
+ if (err ) {
2695
+ qlcnic_clr_all_drv_state (adapter );
2696
+ clear_bit (__QLCNIC_AER , & adapter -> state );
2697
+ netif_device_attach (netdev );
2698
+ return err ;
2699
+ }
2700
+
2701
+ err = qlcnic_up (adapter , netdev );
2702
+ if (err )
2703
+ goto done ;
2704
+
2705
+ qlcnic_config_indev_addr (netdev , NETDEV_UP );
2706
+ }
2707
+ done :
2708
+ netif_device_attach (netdev );
2709
+ return err ;
2710
+ }
2711
+
2712
+ static pci_ers_result_t qlcnic_io_error_detected (struct pci_dev * pdev ,
2713
+ pci_channel_state_t state )
2714
+ {
2715
+ struct qlcnic_adapter * adapter = pci_get_drvdata (pdev );
2716
+ struct net_device * netdev = adapter -> netdev ;
2717
+
2718
+ if (state == pci_channel_io_perm_failure )
2719
+ return PCI_ERS_RESULT_DISCONNECT ;
2720
+
2721
+ if (state == pci_channel_io_normal )
2722
+ return PCI_ERS_RESULT_RECOVERED ;
2723
+
2724
+ set_bit (__QLCNIC_AER , & adapter -> state );
2725
+ netif_device_detach (netdev );
2726
+
2727
+ cancel_delayed_work_sync (& adapter -> fw_work );
2728
+
2729
+ if (netif_running (netdev ))
2730
+ qlcnic_down (adapter , netdev );
2731
+
2732
+ qlcnic_detach (adapter );
2733
+ qlcnic_teardown_intr (adapter );
2734
+
2735
+ clear_bit (__QLCNIC_RESETTING , & adapter -> state );
2736
+
2737
+ pci_save_state (pdev );
2738
+ pci_disable_device (pdev );
2739
+
2740
+ return PCI_ERS_RESULT_NEED_RESET ;
2741
+ }
2742
+
2743
+ static pci_ers_result_t qlcnic_io_slot_reset (struct pci_dev * pdev )
2744
+ {
2745
+ return qlcnic_attach_func (pdev ) ? PCI_ERS_RESULT_DISCONNECT :
2746
+ PCI_ERS_RESULT_RECOVERED ;
2747
+ }
2748
+
2749
+ static void qlcnic_io_resume (struct pci_dev * pdev )
2750
+ {
2751
+ struct qlcnic_adapter * adapter = pci_get_drvdata (pdev );
2752
+
2753
+ pci_cleanup_aer_uncorrect_error_status (pdev );
2754
+
2755
+ if (QLCRD32 (adapter , QLCNIC_CRB_DEV_STATE ) == QLCNIC_DEV_READY &&
2756
+ test_and_clear_bit (__QLCNIC_AER , & adapter -> state ))
2757
+ qlcnic_schedule_work (adapter , qlcnic_fw_poll_work ,
2758
+ FW_POLL_DELAY );
2759
+ }
2760
+
2761
+
2634
2762
static int
2635
2763
qlcnicvf_start_firmware (struct qlcnic_adapter * adapter )
2636
2764
{
@@ -3436,6 +3564,11 @@ static void
3436
3564
qlcnic_config_indev_addr (struct net_device * dev , unsigned long event )
3437
3565
{ }
3438
3566
#endif
3567
+ static struct pci_error_handlers qlcnic_err_handler = {
3568
+ .error_detected = qlcnic_io_error_detected ,
3569
+ .slot_reset = qlcnic_io_slot_reset ,
3570
+ .resume = qlcnic_io_resume ,
3571
+ };
3439
3572
3440
3573
static struct pci_driver qlcnic_driver = {
3441
3574
.name = qlcnic_driver_name ,
@@ -3446,7 +3579,9 @@ static struct pci_driver qlcnic_driver = {
3446
3579
.suspend = qlcnic_suspend ,
3447
3580
.resume = qlcnic_resume ,
3448
3581
#endif
3449
- .shutdown = qlcnic_shutdown
3582
+ .shutdown = qlcnic_shutdown ,
3583
+ .err_handler = & qlcnic_err_handler
3584
+
3450
3585
};
3451
3586
3452
3587
static int __init qlcnic_init_module (void )
0 commit comments