diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/netxen/netxen_nic_main.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/netxen/netxen_nic_main.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 603 |
1 files changed, 470 insertions, 133 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 3bf78dbfbf0f..ce838f7c8b0f 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -19,10 +19,11 @@ | |||
19 | * MA 02111-1307, USA. | 19 | * MA 02111-1307, USA. |
20 | * | 20 | * |
21 | * The full GNU General Public License is included in this distribution | 21 | * The full GNU General Public License is included in this distribution |
22 | * in the file called LICENSE. | 22 | * in the file called "COPYING". |
23 | * | 23 | * |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/slab.h> | ||
26 | #include <linux/vmalloc.h> | 27 | #include <linux/vmalloc.h> |
27 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
28 | #include "netxen_nic_hw.h" | 29 | #include "netxen_nic_hw.h" |
@@ -34,13 +35,19 @@ | |||
34 | #include <net/ip.h> | 35 | #include <net/ip.h> |
35 | #include <linux/ipv6.h> | 36 | #include <linux/ipv6.h> |
36 | #include <linux/inetdevice.h> | 37 | #include <linux/inetdevice.h> |
38 | #include <linux/sysfs.h> | ||
39 | #include <linux/aer.h> | ||
37 | 40 | ||
38 | MODULE_DESCRIPTION("NetXen Multi port (1/10) Gigabit Network Driver"); | 41 | MODULE_DESCRIPTION("QLogic/NetXen (1/10) GbE Converged Ethernet Driver"); |
39 | MODULE_LICENSE("GPL"); | 42 | MODULE_LICENSE("GPL"); |
40 | MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); | 43 | MODULE_VERSION(NETXEN_NIC_LINUX_VERSIONID); |
44 | MODULE_FIRMWARE(NX_P2_MN_ROMIMAGE_NAME); | ||
45 | MODULE_FIRMWARE(NX_P3_CT_ROMIMAGE_NAME); | ||
46 | MODULE_FIRMWARE(NX_P3_MN_ROMIMAGE_NAME); | ||
47 | MODULE_FIRMWARE(NX_UNIFIED_ROMIMAGE_NAME); | ||
41 | 48 | ||
42 | char netxen_nic_driver_name[] = "netxen_nic"; | 49 | char netxen_nic_driver_name[] = "netxen_nic"; |
43 | static char netxen_nic_driver_string[] = "NetXen Network Driver version " | 50 | static char netxen_nic_driver_string[] = "QLogic/NetXen Network Driver v" |
44 | NETXEN_NIC_LINUX_VERSIONID; | 51 | NETXEN_NIC_LINUX_VERSIONID; |
45 | 52 | ||
46 | static int port_mode = NETXEN_PORT_MODE_AUTO_NEG; | 53 | static int port_mode = NETXEN_PORT_MODE_AUTO_NEG; |
@@ -52,7 +59,10 @@ static int use_msi = 1; | |||
52 | 59 | ||
53 | static int use_msi_x = 1; | 60 | static int use_msi_x = 1; |
54 | 61 | ||
55 | /* Local functions to NetXen NIC driver */ | 62 | static int auto_fw_reset = AUTO_FW_RESET_ENABLED; |
63 | module_param(auto_fw_reset, int, 0644); | ||
64 | MODULE_PARM_DESC(auto_fw_reset,"Auto firmware reset (0=disabled, 1=enabled"); | ||
65 | |||
56 | static int __devinit netxen_nic_probe(struct pci_dev *pdev, | 66 | static int __devinit netxen_nic_probe(struct pci_dev *pdev, |
57 | const struct pci_device_id *ent); | 67 | const struct pci_device_id *ent); |
58 | static void __devexit netxen_nic_remove(struct pci_dev *pdev); | 68 | static void __devexit netxen_nic_remove(struct pci_dev *pdev); |
@@ -73,7 +83,10 @@ static void netxen_nic_poll_controller(struct net_device *netdev); | |||
73 | 83 | ||
74 | static void netxen_create_sysfs_entries(struct netxen_adapter *adapter); | 84 | static void netxen_create_sysfs_entries(struct netxen_adapter *adapter); |
75 | static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter); | 85 | static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter); |
86 | static void netxen_create_diag_entries(struct netxen_adapter *adapter); | ||
87 | static void netxen_remove_diag_entries(struct netxen_adapter *adapter); | ||
76 | 88 | ||
89 | static int nx_dev_request_aer(struct netxen_adapter *adapter); | ||
77 | static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter); | 90 | static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter); |
78 | static int netxen_can_start_firmware(struct netxen_adapter *adapter); | 91 | static int netxen_can_start_firmware(struct netxen_adapter *adapter); |
79 | 92 | ||
@@ -88,7 +101,7 @@ static void netxen_config_indev_addr(struct net_device *dev, unsigned long); | |||
88 | {PCI_DEVICE(PCI_VENDOR_ID_NETXEN, (device)), \ | 101 | {PCI_DEVICE(PCI_VENDOR_ID_NETXEN, (device)), \ |
89 | .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0} | 102 | .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0} |
90 | 103 | ||
91 | static struct pci_device_id netxen_pci_tbl[] __devinitdata = { | 104 | static DEFINE_PCI_DEVICE_TABLE(netxen_pci_tbl) = { |
92 | ENTRY(PCI_DEVICE_ID_NX2031_10GXSR), | 105 | ENTRY(PCI_DEVICE_ID_NX2031_10GXSR), |
93 | ENTRY(PCI_DEVICE_ID_NX2031_10GCX4), | 106 | ENTRY(PCI_DEVICE_ID_NX2031_10GCX4), |
94 | ENTRY(PCI_DEVICE_ID_NX2031_4GCU), | 107 | ENTRY(PCI_DEVICE_ID_NX2031_4GCU), |
@@ -330,7 +343,7 @@ netxen_check_hw_init(struct netxen_adapter *adapter, int first_boot) | |||
330 | if (!(first_boot & 0x4)) { | 343 | if (!(first_boot & 0x4)) { |
331 | first_boot |= 0x4; | 344 | first_boot |= 0x4; |
332 | NXWR32(adapter, NETXEN_PCIE_REG(0x4), first_boot); | 345 | NXWR32(adapter, NETXEN_PCIE_REG(0x4), first_boot); |
333 | first_boot = NXRD32(adapter, NETXEN_PCIE_REG(0x4)); | 346 | NXRD32(adapter, NETXEN_PCIE_REG(0x4)); |
334 | } | 347 | } |
335 | 348 | ||
336 | /* This is the first boot after power up */ | 349 | /* This is the first boot after power up */ |
@@ -420,7 +433,7 @@ netxen_read_mac_addr(struct netxen_adapter *adapter) | |||
420 | { | 433 | { |
421 | int i; | 434 | int i; |
422 | unsigned char *p; | 435 | unsigned char *p; |
423 | __le64 mac_addr; | 436 | u64 mac_addr; |
424 | struct net_device *netdev = adapter->netdev; | 437 | struct net_device *netdev = adapter->netdev; |
425 | struct pci_dev *pdev = adapter->pdev; | 438 | struct pci_dev *pdev = adapter->pdev; |
426 | 439 | ||
@@ -592,16 +605,14 @@ netxen_cleanup_pci_map(struct netxen_adapter *adapter) | |||
592 | static int | 605 | static int |
593 | netxen_setup_pci_map(struct netxen_adapter *adapter) | 606 | netxen_setup_pci_map(struct netxen_adapter *adapter) |
594 | { | 607 | { |
595 | void __iomem *mem_ptr0 = NULL; | ||
596 | void __iomem *mem_ptr1 = NULL; | ||
597 | void __iomem *mem_ptr2 = NULL; | ||
598 | void __iomem *db_ptr = NULL; | 608 | void __iomem *db_ptr = NULL; |
599 | 609 | ||
600 | resource_size_t mem_base, db_base; | 610 | resource_size_t mem_base, db_base; |
601 | unsigned long mem_len, db_len = 0, pci_len0 = 0; | 611 | unsigned long mem_len, db_len = 0; |
602 | 612 | ||
603 | struct pci_dev *pdev = adapter->pdev; | 613 | struct pci_dev *pdev = adapter->pdev; |
604 | int pci_func = adapter->ahw.pci_func; | 614 | int pci_func = adapter->ahw.pci_func; |
615 | struct netxen_hardware_context *ahw = &adapter->ahw; | ||
605 | 616 | ||
606 | int err = 0; | 617 | int err = 0; |
607 | 618 | ||
@@ -609,47 +620,49 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) | |||
609 | * Set the CRB window to invalid. If any register in window 0 is | 620 | * Set the CRB window to invalid. If any register in window 0 is |
610 | * accessed it should set the window to 0 and then reset it to 1. | 621 | * accessed it should set the window to 0 and then reset it to 1. |
611 | */ | 622 | */ |
612 | adapter->curr_window = 255; | 623 | adapter->ahw.crb_win = -1; |
613 | adapter->ahw.qdr_sn_window = -1; | 624 | adapter->ahw.ocm_win = -1; |
614 | adapter->ahw.ddr_mn_window = -1; | ||
615 | 625 | ||
616 | /* remap phys address */ | 626 | /* remap phys address */ |
617 | mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ | 627 | mem_base = pci_resource_start(pdev, 0); /* 0 is for BAR 0 */ |
618 | mem_len = pci_resource_len(pdev, 0); | 628 | mem_len = pci_resource_len(pdev, 0); |
619 | pci_len0 = 0; | ||
620 | 629 | ||
621 | /* 128 Meg of memory */ | 630 | /* 128 Meg of memory */ |
622 | if (mem_len == NETXEN_PCI_128MB_SIZE) { | 631 | if (mem_len == NETXEN_PCI_128MB_SIZE) { |
623 | mem_ptr0 = ioremap(mem_base, FIRST_PAGE_GROUP_SIZE); | 632 | |
624 | mem_ptr1 = ioremap(mem_base + SECOND_PAGE_GROUP_START, | 633 | ahw->pci_base0 = ioremap(mem_base, FIRST_PAGE_GROUP_SIZE); |
634 | ahw->pci_base1 = ioremap(mem_base + SECOND_PAGE_GROUP_START, | ||
625 | SECOND_PAGE_GROUP_SIZE); | 635 | SECOND_PAGE_GROUP_SIZE); |
626 | mem_ptr2 = ioremap(mem_base + THIRD_PAGE_GROUP_START, | 636 | ahw->pci_base2 = ioremap(mem_base + THIRD_PAGE_GROUP_START, |
627 | THIRD_PAGE_GROUP_SIZE); | 637 | THIRD_PAGE_GROUP_SIZE); |
638 | if (ahw->pci_base0 == NULL || ahw->pci_base1 == NULL || | ||
639 | ahw->pci_base2 == NULL) { | ||
640 | dev_err(&pdev->dev, "failed to map PCI bar 0\n"); | ||
641 | err = -EIO; | ||
642 | goto err_out; | ||
643 | } | ||
644 | |||
645 | ahw->pci_len0 = FIRST_PAGE_GROUP_SIZE; | ||
646 | |||
628 | } else if (mem_len == NETXEN_PCI_32MB_SIZE) { | 647 | } else if (mem_len == NETXEN_PCI_32MB_SIZE) { |
629 | mem_ptr1 = ioremap(mem_base, SECOND_PAGE_GROUP_SIZE); | 648 | |
630 | mem_ptr2 = ioremap(mem_base + THIRD_PAGE_GROUP_START - | 649 | ahw->pci_base1 = ioremap(mem_base, SECOND_PAGE_GROUP_SIZE); |
650 | ahw->pci_base2 = ioremap(mem_base + THIRD_PAGE_GROUP_START - | ||
631 | SECOND_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE); | 651 | SECOND_PAGE_GROUP_START, THIRD_PAGE_GROUP_SIZE); |
652 | if (ahw->pci_base1 == NULL || ahw->pci_base2 == NULL) { | ||
653 | dev_err(&pdev->dev, "failed to map PCI bar 0\n"); | ||
654 | err = -EIO; | ||
655 | goto err_out; | ||
656 | } | ||
657 | |||
632 | } else if (mem_len == NETXEN_PCI_2MB_SIZE) { | 658 | } else if (mem_len == NETXEN_PCI_2MB_SIZE) { |
633 | 659 | ||
634 | mem_ptr0 = pci_ioremap_bar(pdev, 0); | 660 | ahw->pci_base0 = pci_ioremap_bar(pdev, 0); |
635 | if (mem_ptr0 == NULL) { | 661 | if (ahw->pci_base0 == NULL) { |
636 | dev_err(&pdev->dev, "failed to map PCI bar 0\n"); | 662 | dev_err(&pdev->dev, "failed to map PCI bar 0\n"); |
637 | return -EIO; | 663 | return -EIO; |
638 | } | 664 | } |
639 | pci_len0 = mem_len; | 665 | ahw->pci_len0 = mem_len; |
640 | |||
641 | adapter->ahw.ddr_mn_window = 0; | ||
642 | adapter->ahw.qdr_sn_window = 0; | ||
643 | |||
644 | adapter->ahw.mn_win_crb = NETXEN_PCI_CRBSPACE + | ||
645 | 0x100000 + PCIX_MN_WINDOW + (pci_func * 0x20); | ||
646 | adapter->ahw.ms_win_crb = NETXEN_PCI_CRBSPACE + | ||
647 | 0x100000 + PCIX_SN_WINDOW; | ||
648 | if (pci_func < 4) | ||
649 | adapter->ahw.ms_win_crb += (pci_func * 0x20); | ||
650 | else | ||
651 | adapter->ahw.ms_win_crb += | ||
652 | 0xA0 + ((pci_func - 4) * 0x10); | ||
653 | } else { | 666 | } else { |
654 | return -EIO; | 667 | return -EIO; |
655 | } | 668 | } |
@@ -658,10 +671,14 @@ netxen_setup_pci_map(struct netxen_adapter *adapter) | |||
658 | 671 | ||
659 | dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20)); | 672 | dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20)); |
660 | 673 | ||
661 | adapter->ahw.pci_base0 = mem_ptr0; | 674 | if (NX_IS_REVISION_P3P(adapter->ahw.revision_id)) { |
662 | adapter->ahw.pci_len0 = pci_len0; | 675 | adapter->ahw.ocm_win_crb = netxen_get_ioaddr(adapter, |
663 | adapter->ahw.pci_base1 = mem_ptr1; | 676 | NETXEN_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(pci_func))); |
664 | adapter->ahw.pci_base2 = mem_ptr2; | 677 | |
678 | } else if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { | ||
679 | adapter->ahw.ocm_win_crb = netxen_get_ioaddr(adapter, | ||
680 | NETXEN_PCIX_PS_REG(PCIE_MN_WINDOW_REG(pci_func))); | ||
681 | } | ||
665 | 682 | ||
666 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | 683 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) |
667 | goto skip_doorbell; | 684 | goto skip_doorbell; |
@@ -727,7 +744,8 @@ netxen_check_options(struct netxen_adapter *adapter) | |||
727 | if (adapter->portnum == 0) { | 744 | if (adapter->portnum == 0) { |
728 | get_brd_name_by_type(adapter->ahw.board_type, brd_name); | 745 | get_brd_name_by_type(adapter->ahw.board_type, brd_name); |
729 | 746 | ||
730 | printk(KERN_INFO "NetXen %s Board S/N %s Chip rev 0x%x\n", | 747 | pr_info("%s: %s Board S/N %s Chip rev 0x%x\n", |
748 | module_name(THIS_MODULE), | ||
731 | brd_name, serial_num, adapter->ahw.revision_id); | 749 | brd_name, serial_num, adapter->ahw.revision_id); |
732 | } | 750 | } |
733 | 751 | ||
@@ -815,11 +833,11 @@ netxen_start_firmware(struct netxen_adapter *adapter) | |||
815 | if (err < 0) | 833 | if (err < 0) |
816 | goto err_out; | 834 | goto err_out; |
817 | if (err == 0) | 835 | if (err == 0) |
818 | goto ready; | 836 | goto wait_init; |
819 | 837 | ||
820 | if (first_boot != 0x55555555) { | 838 | if (first_boot != 0x55555555) { |
821 | NXWR32(adapter, CRB_CMDPEG_STATE, 0); | 839 | NXWR32(adapter, CRB_CMDPEG_STATE, 0); |
822 | netxen_pinit_from_rom(adapter, 0); | 840 | netxen_pinit_from_rom(adapter); |
823 | msleep(1); | 841 | msleep(1); |
824 | } | 842 | } |
825 | 843 | ||
@@ -858,9 +876,6 @@ netxen_start_firmware(struct netxen_adapter *adapter) | |||
858 | | (_NETXEN_NIC_LINUX_SUBVERSION); | 876 | | (_NETXEN_NIC_LINUX_SUBVERSION); |
859 | NXWR32(adapter, CRB_DRIVER_VERSION, val); | 877 | NXWR32(adapter, CRB_DRIVER_VERSION, val); |
860 | 878 | ||
861 | ready: | ||
862 | NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_READY); | ||
863 | |||
864 | wait_init: | 879 | wait_init: |
865 | /* Handshake with the card before we register the devices. */ | 880 | /* Handshake with the card before we register the devices. */ |
866 | err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); | 881 | err = netxen_phantom_init(adapter, NETXEN_NIC_PEG_TUNE); |
@@ -869,6 +884,8 @@ wait_init: | |||
869 | goto err_out; | 884 | goto err_out; |
870 | } | 885 | } |
871 | 886 | ||
887 | NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_READY); | ||
888 | |||
872 | nx_update_dma_mask(adapter); | 889 | nx_update_dma_mask(adapter); |
873 | 890 | ||
874 | netxen_check_options(adapter); | 891 | netxen_check_options(adapter); |
@@ -943,8 +960,9 @@ netxen_nic_init_coalesce_defaults(struct netxen_adapter *adapter) | |||
943 | NETXEN_DEFAULT_INTR_COALESCE_TX_PACKETS; | 960 | NETXEN_DEFAULT_INTR_COALESCE_TX_PACKETS; |
944 | } | 961 | } |
945 | 962 | ||
963 | /* with rtnl_lock */ | ||
946 | static int | 964 | static int |
947 | netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) | 965 | __netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) |
948 | { | 966 | { |
949 | int err; | 967 | int err; |
950 | 968 | ||
@@ -985,14 +1003,32 @@ netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) | |||
985 | return 0; | 1003 | return 0; |
986 | } | 1004 | } |
987 | 1005 | ||
1006 | /* Usage: During resume and firmware recovery module.*/ | ||
1007 | |||
1008 | static inline int | ||
1009 | netxen_nic_up(struct netxen_adapter *adapter, struct net_device *netdev) | ||
1010 | { | ||
1011 | int err = 0; | ||
1012 | |||
1013 | rtnl_lock(); | ||
1014 | if (netif_running(netdev)) | ||
1015 | err = __netxen_nic_up(adapter, netdev); | ||
1016 | rtnl_unlock(); | ||
1017 | |||
1018 | return err; | ||
1019 | } | ||
1020 | |||
1021 | /* with rtnl_lock */ | ||
988 | static void | 1022 | static void |
989 | netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) | 1023 | __netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) |
990 | { | 1024 | { |
991 | if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) | 1025 | if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) |
992 | return; | 1026 | return; |
993 | 1027 | ||
994 | clear_bit(__NX_DEV_UP, &adapter->state); | 1028 | if (!test_and_clear_bit(__NX_DEV_UP, &adapter->state)) |
1029 | return; | ||
995 | 1030 | ||
1031 | smp_mb(); | ||
996 | spin_lock(&adapter->tx_clean_lock); | 1032 | spin_lock(&adapter->tx_clean_lock); |
997 | netif_carrier_off(netdev); | 1033 | netif_carrier_off(netdev); |
998 | netif_tx_disable(netdev); | 1034 | netif_tx_disable(netdev); |
@@ -1011,6 +1047,17 @@ netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) | |||
1011 | spin_unlock(&adapter->tx_clean_lock); | 1047 | spin_unlock(&adapter->tx_clean_lock); |
1012 | } | 1048 | } |
1013 | 1049 | ||
1050 | /* Usage: During suspend and firmware recovery module */ | ||
1051 | |||
1052 | static inline void | ||
1053 | netxen_nic_down(struct netxen_adapter *adapter, struct net_device *netdev) | ||
1054 | { | ||
1055 | rtnl_lock(); | ||
1056 | if (netif_running(netdev)) | ||
1057 | __netxen_nic_down(adapter, netdev); | ||
1058 | rtnl_unlock(); | ||
1059 | |||
1060 | } | ||
1014 | 1061 | ||
1015 | static int | 1062 | static int |
1016 | netxen_nic_attach(struct netxen_adapter *adapter) | 1063 | netxen_nic_attach(struct netxen_adapter *adapter) |
@@ -1119,14 +1166,14 @@ netxen_nic_reset_context(struct netxen_adapter *adapter) | |||
1119 | netif_device_detach(netdev); | 1166 | netif_device_detach(netdev); |
1120 | 1167 | ||
1121 | if (netif_running(netdev)) | 1168 | if (netif_running(netdev)) |
1122 | netxen_nic_down(adapter, netdev); | 1169 | __netxen_nic_down(adapter, netdev); |
1123 | 1170 | ||
1124 | netxen_nic_detach(adapter); | 1171 | netxen_nic_detach(adapter); |
1125 | 1172 | ||
1126 | if (netif_running(netdev)) { | 1173 | if (netif_running(netdev)) { |
1127 | err = netxen_nic_attach(adapter); | 1174 | err = netxen_nic_attach(adapter); |
1128 | if (!err) | 1175 | if (!err) |
1129 | err = netxen_nic_up(adapter, netdev); | 1176 | err = __netxen_nic_up(adapter, netdev); |
1130 | 1177 | ||
1131 | if (err) | 1178 | if (err) |
1132 | goto done; | 1179 | goto done; |
@@ -1209,16 +1256,10 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1209 | int pci_func_id = PCI_FUNC(pdev->devfn); | 1256 | int pci_func_id = PCI_FUNC(pdev->devfn); |
1210 | uint8_t revision_id; | 1257 | uint8_t revision_id; |
1211 | 1258 | ||
1212 | if (pdev->class != 0x020000) { | 1259 | if (pdev->revision >= NX_P3_A0 && pdev->revision <= NX_P3_B1) { |
1213 | printk(KERN_DEBUG "NetXen function %d, class %x will not " | 1260 | pr_warning("%s: chip revisions between 0x%x-0x%x " |
1214 | "be enabled.\n",pci_func_id, pdev->class); | ||
1215 | return -ENODEV; | ||
1216 | } | ||
1217 | |||
1218 | if (pdev->revision >= NX_P3_A0 && pdev->revision < NX_P3_B1) { | ||
1219 | printk(KERN_WARNING "NetXen chip revisions between 0x%x-0x%x" | ||
1220 | "will not be enabled.\n", | 1261 | "will not be enabled.\n", |
1221 | NX_P3_A0, NX_P3_B1); | 1262 | module_name(THIS_MODULE), NX_P3_A0, NX_P3_B1); |
1222 | return -ENODEV; | 1263 | return -ENODEV; |
1223 | } | 1264 | } |
1224 | 1265 | ||
@@ -1233,6 +1274,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1233 | if ((err = pci_request_regions(pdev, netxen_nic_driver_name))) | 1274 | if ((err = pci_request_regions(pdev, netxen_nic_driver_name))) |
1234 | goto err_out_disable_pdev; | 1275 | goto err_out_disable_pdev; |
1235 | 1276 | ||
1277 | if (NX_IS_REVISION_P3(pdev->revision)) | ||
1278 | pci_enable_pcie_error_reporting(pdev); | ||
1279 | |||
1236 | pci_set_master(pdev); | 1280 | pci_set_master(pdev); |
1237 | 1281 | ||
1238 | netdev = alloc_etherdev(sizeof(struct netxen_adapter)); | 1282 | netdev = alloc_etherdev(sizeof(struct netxen_adapter)); |
@@ -1252,7 +1296,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1252 | revision_id = pdev->revision; | 1296 | revision_id = pdev->revision; |
1253 | adapter->ahw.revision_id = revision_id; | 1297 | adapter->ahw.revision_id = revision_id; |
1254 | 1298 | ||
1255 | rwlock_init(&adapter->adapter_lock); | 1299 | rwlock_init(&adapter->ahw.crb_lock); |
1300 | spin_lock_init(&adapter->ahw.mem_lock); | ||
1301 | |||
1256 | spin_lock_init(&adapter->tx_clean_lock); | 1302 | spin_lock_init(&adapter->tx_clean_lock); |
1257 | INIT_LIST_HEAD(&adapter->mac_list); | 1303 | INIT_LIST_HEAD(&adapter->mac_list); |
1258 | 1304 | ||
@@ -1282,7 +1328,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1282 | 1328 | ||
1283 | err = netxen_start_firmware(adapter); | 1329 | err = netxen_start_firmware(adapter); |
1284 | if (err) | 1330 | if (err) |
1285 | goto err_out_iounmap; | 1331 | goto err_out_decr_ref; |
1286 | 1332 | ||
1287 | /* | 1333 | /* |
1288 | * See if the firmware gave us a virtual-physical port mapping. | 1334 | * See if the firmware gave us a virtual-physical port mapping. |
@@ -1317,6 +1363,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1317 | break; | 1363 | break; |
1318 | } | 1364 | } |
1319 | 1365 | ||
1366 | netxen_create_diag_entries(adapter); | ||
1367 | |||
1320 | return 0; | 1368 | return 0; |
1321 | 1369 | ||
1322 | err_out_disable_msi: | 1370 | err_out_disable_msi: |
@@ -1324,6 +1372,7 @@ err_out_disable_msi: | |||
1324 | 1372 | ||
1325 | netxen_free_dummy_dma(adapter); | 1373 | netxen_free_dummy_dma(adapter); |
1326 | 1374 | ||
1375 | err_out_decr_ref: | ||
1327 | nx_decr_dev_ref_cnt(adapter); | 1376 | nx_decr_dev_ref_cnt(adapter); |
1328 | 1377 | ||
1329 | err_out_iounmap: | 1378 | err_out_iounmap: |
@@ -1369,21 +1418,25 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) | |||
1369 | 1418 | ||
1370 | netxen_teardown_intr(adapter); | 1419 | netxen_teardown_intr(adapter); |
1371 | 1420 | ||
1421 | netxen_remove_diag_entries(adapter); | ||
1422 | |||
1372 | netxen_cleanup_pci_map(adapter); | 1423 | netxen_cleanup_pci_map(adapter); |
1373 | 1424 | ||
1374 | netxen_release_firmware(adapter); | 1425 | netxen_release_firmware(adapter); |
1375 | 1426 | ||
1427 | if (NX_IS_REVISION_P3(pdev->revision)) | ||
1428 | pci_disable_pcie_error_reporting(pdev); | ||
1429 | |||
1376 | pci_release_regions(pdev); | 1430 | pci_release_regions(pdev); |
1377 | pci_disable_device(pdev); | 1431 | pci_disable_device(pdev); |
1378 | pci_set_drvdata(pdev, NULL); | 1432 | pci_set_drvdata(pdev, NULL); |
1379 | 1433 | ||
1380 | free_netdev(netdev); | 1434 | free_netdev(netdev); |
1381 | } | 1435 | } |
1382 | static int __netxen_nic_shutdown(struct pci_dev *pdev) | 1436 | |
1437 | static void netxen_nic_detach_func(struct netxen_adapter *adapter) | ||
1383 | { | 1438 | { |
1384 | struct netxen_adapter *adapter = pci_get_drvdata(pdev); | ||
1385 | struct net_device *netdev = adapter->netdev; | 1439 | struct net_device *netdev = adapter->netdev; |
1386 | int retval; | ||
1387 | 1440 | ||
1388 | netif_device_detach(netdev); | 1441 | netif_device_detach(netdev); |
1389 | 1442 | ||
@@ -1402,54 +1455,24 @@ static int __netxen_nic_shutdown(struct pci_dev *pdev) | |||
1402 | nx_decr_dev_ref_cnt(adapter); | 1455 | nx_decr_dev_ref_cnt(adapter); |
1403 | 1456 | ||
1404 | clear_bit(__NX_RESETTING, &adapter->state); | 1457 | clear_bit(__NX_RESETTING, &adapter->state); |
1405 | |||
1406 | retval = pci_save_state(pdev); | ||
1407 | if (retval) | ||
1408 | return retval; | ||
1409 | |||
1410 | if (netxen_nic_wol_supported(adapter)) { | ||
1411 | pci_enable_wake(pdev, PCI_D3cold, 1); | ||
1412 | pci_enable_wake(pdev, PCI_D3hot, 1); | ||
1413 | } | ||
1414 | |||
1415 | pci_disable_device(pdev); | ||
1416 | |||
1417 | return 0; | ||
1418 | } | ||
1419 | static void netxen_nic_shutdown(struct pci_dev *pdev) | ||
1420 | { | ||
1421 | if (__netxen_nic_shutdown(pdev)) | ||
1422 | return; | ||
1423 | } | ||
1424 | #ifdef CONFIG_PM | ||
1425 | static int | ||
1426 | netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) | ||
1427 | { | ||
1428 | int retval; | ||
1429 | |||
1430 | retval = __netxen_nic_shutdown(pdev); | ||
1431 | if (retval) | ||
1432 | return retval; | ||
1433 | |||
1434 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
1435 | return 0; | ||
1436 | } | 1458 | } |
1437 | 1459 | ||
1438 | static int | 1460 | static int netxen_nic_attach_func(struct pci_dev *pdev) |
1439 | netxen_nic_resume(struct pci_dev *pdev) | ||
1440 | { | 1461 | { |
1441 | struct netxen_adapter *adapter = pci_get_drvdata(pdev); | 1462 | struct netxen_adapter *adapter = pci_get_drvdata(pdev); |
1442 | struct net_device *netdev = adapter->netdev; | 1463 | struct net_device *netdev = adapter->netdev; |
1443 | int err; | 1464 | int err; |
1444 | 1465 | ||
1445 | pci_set_power_state(pdev, PCI_D0); | ||
1446 | pci_restore_state(pdev); | ||
1447 | |||
1448 | err = pci_enable_device(pdev); | 1466 | err = pci_enable_device(pdev); |
1449 | if (err) | 1467 | if (err) |
1450 | return err; | 1468 | return err; |
1451 | 1469 | ||
1452 | adapter->curr_window = 255; | 1470 | pci_set_power_state(pdev, PCI_D0); |
1471 | pci_set_master(pdev); | ||
1472 | pci_restore_state(pdev); | ||
1473 | |||
1474 | adapter->ahw.crb_win = -1; | ||
1475 | adapter->ahw.ocm_win = -1; | ||
1453 | 1476 | ||
1454 | err = netxen_start_firmware(adapter); | 1477 | err = netxen_start_firmware(adapter); |
1455 | if (err) { | 1478 | if (err) { |
@@ -1466,11 +1489,10 @@ netxen_nic_resume(struct pci_dev *pdev) | |||
1466 | if (err) | 1489 | if (err) |
1467 | goto err_out_detach; | 1490 | goto err_out_detach; |
1468 | 1491 | ||
1469 | netif_device_attach(netdev); | ||
1470 | |||
1471 | netxen_config_indev_addr(netdev, NETDEV_UP); | 1492 | netxen_config_indev_addr(netdev, NETDEV_UP); |
1472 | } | 1493 | } |
1473 | 1494 | ||
1495 | netif_device_attach(netdev); | ||
1474 | netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY); | 1496 | netxen_schedule_work(adapter, netxen_fw_poll_work, FW_POLL_DELAY); |
1475 | return 0; | 1497 | return 0; |
1476 | 1498 | ||
@@ -1480,6 +1502,85 @@ err_out: | |||
1480 | nx_decr_dev_ref_cnt(adapter); | 1502 | nx_decr_dev_ref_cnt(adapter); |
1481 | return err; | 1503 | return err; |
1482 | } | 1504 | } |
1505 | |||
1506 | static pci_ers_result_t netxen_io_error_detected(struct pci_dev *pdev, | ||
1507 | pci_channel_state_t state) | ||
1508 | { | ||
1509 | struct netxen_adapter *adapter = pci_get_drvdata(pdev); | ||
1510 | |||
1511 | if (state == pci_channel_io_perm_failure) | ||
1512 | return PCI_ERS_RESULT_DISCONNECT; | ||
1513 | |||
1514 | if (nx_dev_request_aer(adapter)) | ||
1515 | return PCI_ERS_RESULT_RECOVERED; | ||
1516 | |||
1517 | netxen_nic_detach_func(adapter); | ||
1518 | |||
1519 | pci_disable_device(pdev); | ||
1520 | |||
1521 | return PCI_ERS_RESULT_NEED_RESET; | ||
1522 | } | ||
1523 | |||
1524 | static pci_ers_result_t netxen_io_slot_reset(struct pci_dev *pdev) | ||
1525 | { | ||
1526 | int err = 0; | ||
1527 | |||
1528 | err = netxen_nic_attach_func(pdev); | ||
1529 | |||
1530 | return err ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED; | ||
1531 | } | ||
1532 | |||
1533 | static void netxen_io_resume(struct pci_dev *pdev) | ||
1534 | { | ||
1535 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
1536 | } | ||
1537 | |||
1538 | static void netxen_nic_shutdown(struct pci_dev *pdev) | ||
1539 | { | ||
1540 | struct netxen_adapter *adapter = pci_get_drvdata(pdev); | ||
1541 | |||
1542 | netxen_nic_detach_func(adapter); | ||
1543 | |||
1544 | if (pci_save_state(pdev)) | ||
1545 | return; | ||
1546 | |||
1547 | if (netxen_nic_wol_supported(adapter)) { | ||
1548 | pci_enable_wake(pdev, PCI_D3cold, 1); | ||
1549 | pci_enable_wake(pdev, PCI_D3hot, 1); | ||
1550 | } | ||
1551 | |||
1552 | pci_disable_device(pdev); | ||
1553 | } | ||
1554 | |||
1555 | #ifdef CONFIG_PM | ||
1556 | static int | ||
1557 | netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state) | ||
1558 | { | ||
1559 | struct netxen_adapter *adapter = pci_get_drvdata(pdev); | ||
1560 | int retval; | ||
1561 | |||
1562 | netxen_nic_detach_func(adapter); | ||
1563 | |||
1564 | retval = pci_save_state(pdev); | ||
1565 | if (retval) | ||
1566 | return retval; | ||
1567 | |||
1568 | if (netxen_nic_wol_supported(adapter)) { | ||
1569 | pci_enable_wake(pdev, PCI_D3cold, 1); | ||
1570 | pci_enable_wake(pdev, PCI_D3hot, 1); | ||
1571 | } | ||
1572 | |||
1573 | pci_disable_device(pdev); | ||
1574 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
1575 | |||
1576 | return 0; | ||
1577 | } | ||
1578 | |||
1579 | static int | ||
1580 | netxen_nic_resume(struct pci_dev *pdev) | ||
1581 | { | ||
1582 | return netxen_nic_attach_func(pdev); | ||
1583 | } | ||
1483 | #endif | 1584 | #endif |
1484 | 1585 | ||
1485 | static int netxen_nic_open(struct net_device *netdev) | 1586 | static int netxen_nic_open(struct net_device *netdev) |
@@ -1494,7 +1595,7 @@ static int netxen_nic_open(struct net_device *netdev) | |||
1494 | if (err) | 1595 | if (err) |
1495 | return err; | 1596 | return err; |
1496 | 1597 | ||
1497 | err = netxen_nic_up(adapter, netdev); | 1598 | err = __netxen_nic_up(adapter, netdev); |
1498 | if (err) | 1599 | if (err) |
1499 | goto err_out; | 1600 | goto err_out; |
1500 | 1601 | ||
@@ -1514,7 +1615,7 @@ static int netxen_nic_close(struct net_device *netdev) | |||
1514 | { | 1615 | { |
1515 | struct netxen_adapter *adapter = netdev_priv(netdev); | 1616 | struct netxen_adapter *adapter = netdev_priv(netdev); |
1516 | 1617 | ||
1517 | netxen_nic_down(adapter, netdev); | 1618 | __netxen_nic_down(adapter, netdev); |
1518 | return 0; | 1619 | return 0; |
1519 | } | 1620 | } |
1520 | 1621 | ||
@@ -1861,12 +1962,8 @@ static void netxen_nic_handle_phy_intr(struct netxen_adapter *adapter) | |||
1861 | linkup = (val == XG_LINK_UP_P3); | 1962 | linkup = (val == XG_LINK_UP_P3); |
1862 | } else { | 1963 | } else { |
1863 | val = NXRD32(adapter, CRB_XG_STATE); | 1964 | val = NXRD32(adapter, CRB_XG_STATE); |
1864 | if (adapter->ahw.port_type == NETXEN_NIC_GBE) | 1965 | val = (val >> port*8) & 0xff; |
1865 | linkup = (val >> port) & 1; | 1966 | linkup = (val == XG_LINK_UP); |
1866 | else { | ||
1867 | val = (val >> port*8) & 0xff; | ||
1868 | linkup = (val == XG_LINK_UP); | ||
1869 | } | ||
1870 | } | 1967 | } |
1871 | 1968 | ||
1872 | netxen_advert_link_change(adapter, linkup); | 1969 | netxen_advert_link_change(adapter, linkup); |
@@ -1908,7 +2005,7 @@ static void netxen_tx_timeout_task(struct work_struct *work) | |||
1908 | netif_wake_queue(adapter->netdev); | 2005 | netif_wake_queue(adapter->netdev); |
1909 | 2006 | ||
1910 | clear_bit(__NX_RESETTING, &adapter->state); | 2007 | clear_bit(__NX_RESETTING, &adapter->state); |
1911 | 2008 | return; | |
1912 | } else { | 2009 | } else { |
1913 | clear_bit(__NX_RESETTING, &adapter->state); | 2010 | clear_bit(__NX_RESETTING, &adapter->state); |
1914 | if (!netxen_nic_reset_context(adapter)) { | 2011 | if (!netxen_nic_reset_context(adapter)) { |
@@ -1927,7 +2024,7 @@ request_reset: | |||
1927 | struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) | 2024 | struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) |
1928 | { | 2025 | { |
1929 | struct netxen_adapter *adapter = netdev_priv(netdev); | 2026 | struct netxen_adapter *adapter = netdev_priv(netdev); |
1930 | struct net_device_stats *stats = &adapter->net_stats; | 2027 | struct net_device_stats *stats = &netdev->stats; |
1931 | 2028 | ||
1932 | memset(stats, 0, sizeof(*stats)); | 2029 | memset(stats, 0, sizeof(*stats)); |
1933 | 2030 | ||
@@ -2020,7 +2117,7 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget) | |||
2020 | 2117 | ||
2021 | if ((work_done < budget) && tx_complete) { | 2118 | if ((work_done < budget) && tx_complete) { |
2022 | napi_complete(&sds_ring->napi); | 2119 | napi_complete(&sds_ring->napi); |
2023 | if (netif_running(adapter->netdev)) | 2120 | if (test_bit(__NX_DEV_UP, &adapter->state)) |
2024 | netxen_nic_enable_int(sds_ring); | 2121 | netxen_nic_enable_int(sds_ring); |
2025 | } | 2122 | } |
2026 | 2123 | ||
@@ -2071,20 +2168,49 @@ nx_decr_dev_ref_cnt(struct netxen_adapter *adapter) | |||
2071 | return count; | 2168 | return count; |
2072 | } | 2169 | } |
2073 | 2170 | ||
2074 | static void | 2171 | static int |
2172 | nx_dev_request_aer(struct netxen_adapter *adapter) | ||
2173 | { | ||
2174 | u32 state; | ||
2175 | int ret = -EINVAL; | ||
2176 | |||
2177 | if (netxen_api_lock(adapter)) | ||
2178 | return ret; | ||
2179 | |||
2180 | state = NXRD32(adapter, NX_CRB_DEV_STATE); | ||
2181 | |||
2182 | if (state == NX_DEV_NEED_AER) | ||
2183 | ret = 0; | ||
2184 | else if (state == NX_DEV_READY) { | ||
2185 | NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_AER); | ||
2186 | ret = 0; | ||
2187 | } | ||
2188 | |||
2189 | netxen_api_unlock(adapter); | ||
2190 | return ret; | ||
2191 | } | ||
2192 | |||
2193 | static int | ||
2075 | nx_dev_request_reset(struct netxen_adapter *adapter) | 2194 | nx_dev_request_reset(struct netxen_adapter *adapter) |
2076 | { | 2195 | { |
2077 | u32 state; | 2196 | u32 state; |
2197 | int ret = -EINVAL; | ||
2078 | 2198 | ||
2079 | if (netxen_api_lock(adapter)) | 2199 | if (netxen_api_lock(adapter)) |
2080 | return; | 2200 | return ret; |
2081 | 2201 | ||
2082 | state = NXRD32(adapter, NX_CRB_DEV_STATE); | 2202 | state = NXRD32(adapter, NX_CRB_DEV_STATE); |
2083 | 2203 | ||
2084 | if (state != NX_DEV_INITALIZING) | 2204 | if (state == NX_DEV_NEED_RESET) |
2205 | ret = 0; | ||
2206 | else if (state != NX_DEV_INITALIZING && state != NX_DEV_NEED_AER) { | ||
2085 | NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET); | 2207 | NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET); |
2208 | ret = 0; | ||
2209 | } | ||
2086 | 2210 | ||
2087 | netxen_api_unlock(adapter); | 2211 | netxen_api_unlock(adapter); |
2212 | |||
2213 | return ret; | ||
2088 | } | 2214 | } |
2089 | 2215 | ||
2090 | static int | 2216 | static int |
@@ -2184,14 +2310,13 @@ netxen_fwinit_work(struct work_struct *work) | |||
2184 | netxen_fwinit_work, 2 * FW_POLL_DELAY); | 2310 | netxen_fwinit_work, 2 * FW_POLL_DELAY); |
2185 | return; | 2311 | return; |
2186 | } | 2312 | } |
2187 | break; | ||
2188 | 2313 | ||
2189 | case NX_DEV_FAILED: | 2314 | case NX_DEV_FAILED: |
2190 | default: | 2315 | default: |
2316 | nx_incr_dev_ref_cnt(adapter); | ||
2191 | break; | 2317 | break; |
2192 | } | 2318 | } |
2193 | 2319 | ||
2194 | nx_incr_dev_ref_cnt(adapter); | ||
2195 | clear_bit(__NX_RESETTING, &adapter->state); | 2320 | clear_bit(__NX_RESETTING, &adapter->state); |
2196 | } | 2321 | } |
2197 | 2322 | ||
@@ -2206,25 +2331,31 @@ netxen_detach_work(struct work_struct *work) | |||
2206 | 2331 | ||
2207 | netif_device_detach(netdev); | 2332 | netif_device_detach(netdev); |
2208 | 2333 | ||
2209 | if (netif_running(netdev)) | 2334 | netxen_nic_down(adapter, netdev); |
2210 | netxen_nic_down(adapter, netdev); | ||
2211 | 2335 | ||
2336 | rtnl_lock(); | ||
2212 | netxen_nic_detach(adapter); | 2337 | netxen_nic_detach(adapter); |
2338 | rtnl_unlock(); | ||
2213 | 2339 | ||
2214 | status = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1); | 2340 | status = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1); |
2215 | 2341 | ||
2216 | ref_cnt = nx_decr_dev_ref_cnt(adapter); | ||
2217 | |||
2218 | if (status & NX_RCODE_FATAL_ERROR) | 2342 | if (status & NX_RCODE_FATAL_ERROR) |
2219 | return; | 2343 | goto err_ret; |
2220 | 2344 | ||
2221 | if (adapter->temp == NX_TEMP_PANIC) | 2345 | if (adapter->temp == NX_TEMP_PANIC) |
2222 | return; | 2346 | goto err_ret; |
2347 | |||
2348 | ref_cnt = nx_decr_dev_ref_cnt(adapter); | ||
2223 | 2349 | ||
2224 | delay = (ref_cnt == 0) ? 0 : (2 * FW_POLL_DELAY); | 2350 | delay = (ref_cnt == 0) ? 0 : (2 * FW_POLL_DELAY); |
2225 | 2351 | ||
2226 | adapter->fw_wait_cnt = 0; | 2352 | adapter->fw_wait_cnt = 0; |
2227 | netxen_schedule_work(adapter, netxen_fwinit_work, delay); | 2353 | netxen_schedule_work(adapter, netxen_fwinit_work, delay); |
2354 | |||
2355 | return; | ||
2356 | |||
2357 | err_ret: | ||
2358 | clear_bit(__NX_RESETTING, &adapter->state); | ||
2228 | } | 2359 | } |
2229 | 2360 | ||
2230 | static int | 2361 | static int |
@@ -2233,17 +2364,29 @@ netxen_check_health(struct netxen_adapter *adapter) | |||
2233 | u32 state, heartbit; | 2364 | u32 state, heartbit; |
2234 | struct net_device *netdev = adapter->netdev; | 2365 | struct net_device *netdev = adapter->netdev; |
2235 | 2366 | ||
2367 | state = NXRD32(adapter, NX_CRB_DEV_STATE); | ||
2368 | if (state == NX_DEV_NEED_AER) | ||
2369 | return 0; | ||
2370 | |||
2236 | if (netxen_nic_check_temp(adapter)) | 2371 | if (netxen_nic_check_temp(adapter)) |
2237 | goto detach; | 2372 | goto detach; |
2238 | 2373 | ||
2239 | if (adapter->need_fw_reset) { | 2374 | if (adapter->need_fw_reset) { |
2240 | nx_dev_request_reset(adapter); | 2375 | if (nx_dev_request_reset(adapter)) |
2376 | return 0; | ||
2241 | goto detach; | 2377 | goto detach; |
2242 | } | 2378 | } |
2243 | 2379 | ||
2244 | state = NXRD32(adapter, NX_CRB_DEV_STATE); | 2380 | /* NX_DEV_NEED_RESET, this state can be marked in two cases |
2245 | if (state == NX_DEV_NEED_RESET) | 2381 | * 1. Tx timeout 2. Fw hang |
2246 | goto detach; | 2382 | * Send request to destroy context in case of tx timeout only |
2383 | * and doesn't required in case of Fw hang | ||
2384 | */ | ||
2385 | if (state == NX_DEV_NEED_RESET) { | ||
2386 | adapter->need_fw_reset = 1; | ||
2387 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
2388 | goto detach; | ||
2389 | } | ||
2247 | 2390 | ||
2248 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | 2391 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) |
2249 | return 0; | 2392 | return 0; |
@@ -2252,18 +2395,24 @@ netxen_check_health(struct netxen_adapter *adapter) | |||
2252 | if (heartbit != adapter->heartbit) { | 2395 | if (heartbit != adapter->heartbit) { |
2253 | adapter->heartbit = heartbit; | 2396 | adapter->heartbit = heartbit; |
2254 | adapter->fw_fail_cnt = 0; | 2397 | adapter->fw_fail_cnt = 0; |
2398 | if (adapter->need_fw_reset) | ||
2399 | goto detach; | ||
2255 | return 0; | 2400 | return 0; |
2256 | } | 2401 | } |
2257 | 2402 | ||
2258 | if (++adapter->fw_fail_cnt < FW_FAIL_THRESH) | 2403 | if (++adapter->fw_fail_cnt < FW_FAIL_THRESH) |
2259 | return 0; | 2404 | return 0; |
2260 | 2405 | ||
2406 | if (nx_dev_request_reset(adapter)) | ||
2407 | return 0; | ||
2408 | |||
2261 | clear_bit(__NX_FW_ATTACHED, &adapter->state); | 2409 | clear_bit(__NX_FW_ATTACHED, &adapter->state); |
2262 | 2410 | ||
2263 | dev_info(&netdev->dev, "firmware hang detected\n"); | 2411 | dev_info(&netdev->dev, "firmware hang detected\n"); |
2264 | 2412 | ||
2265 | detach: | 2413 | detach: |
2266 | if (!test_and_set_bit(__NX_RESETTING, &adapter->state)) | 2414 | if ((auto_fw_reset == AUTO_FW_RESET_ENABLED) && |
2415 | !test_and_set_bit(__NX_RESETTING, &adapter->state)) | ||
2267 | netxen_schedule_work(adapter, netxen_detach_work, 0); | 2416 | netxen_schedule_work(adapter, netxen_detach_work, 0); |
2268 | return 1; | 2417 | return 1; |
2269 | } | 2418 | } |
@@ -2341,6 +2490,161 @@ static struct device_attribute dev_attr_bridged_mode = { | |||
2341 | .store = netxen_store_bridged_mode, | 2490 | .store = netxen_store_bridged_mode, |
2342 | }; | 2491 | }; |
2343 | 2492 | ||
2493 | static ssize_t | ||
2494 | netxen_store_diag_mode(struct device *dev, | ||
2495 | struct device_attribute *attr, const char *buf, size_t len) | ||
2496 | { | ||
2497 | struct netxen_adapter *adapter = dev_get_drvdata(dev); | ||
2498 | unsigned long new; | ||
2499 | |||
2500 | if (strict_strtoul(buf, 2, &new)) | ||
2501 | return -EINVAL; | ||
2502 | |||
2503 | if (!!new != !!(adapter->flags & NETXEN_NIC_DIAG_ENABLED)) | ||
2504 | adapter->flags ^= NETXEN_NIC_DIAG_ENABLED; | ||
2505 | |||
2506 | return len; | ||
2507 | } | ||
2508 | |||
2509 | static ssize_t | ||
2510 | netxen_show_diag_mode(struct device *dev, | ||
2511 | struct device_attribute *attr, char *buf) | ||
2512 | { | ||
2513 | struct netxen_adapter *adapter = dev_get_drvdata(dev); | ||
2514 | |||
2515 | return sprintf(buf, "%d\n", | ||
2516 | !!(adapter->flags & NETXEN_NIC_DIAG_ENABLED)); | ||
2517 | } | ||
2518 | |||
2519 | static struct device_attribute dev_attr_diag_mode = { | ||
2520 | .attr = {.name = "diag_mode", .mode = (S_IRUGO | S_IWUSR)}, | ||
2521 | .show = netxen_show_diag_mode, | ||
2522 | .store = netxen_store_diag_mode, | ||
2523 | }; | ||
2524 | |||
2525 | static int | ||
2526 | netxen_sysfs_validate_crb(struct netxen_adapter *adapter, | ||
2527 | loff_t offset, size_t size) | ||
2528 | { | ||
2529 | if (!(adapter->flags & NETXEN_NIC_DIAG_ENABLED)) | ||
2530 | return -EIO; | ||
2531 | |||
2532 | if ((size != 4) || (offset & 0x3)) | ||
2533 | return -EINVAL; | ||
2534 | |||
2535 | if (offset < NETXEN_PCI_CRBSPACE) | ||
2536 | return -EINVAL; | ||
2537 | |||
2538 | return 0; | ||
2539 | } | ||
2540 | |||
2541 | static ssize_t | ||
2542 | netxen_sysfs_read_crb(struct kobject *kobj, struct bin_attribute *attr, | ||
2543 | char *buf, loff_t offset, size_t size) | ||
2544 | { | ||
2545 | struct device *dev = container_of(kobj, struct device, kobj); | ||
2546 | struct netxen_adapter *adapter = dev_get_drvdata(dev); | ||
2547 | u32 data; | ||
2548 | int ret; | ||
2549 | |||
2550 | ret = netxen_sysfs_validate_crb(adapter, offset, size); | ||
2551 | if (ret != 0) | ||
2552 | return ret; | ||
2553 | |||
2554 | data = NXRD32(adapter, offset); | ||
2555 | memcpy(buf, &data, size); | ||
2556 | return size; | ||
2557 | } | ||
2558 | |||
2559 | static ssize_t | ||
2560 | netxen_sysfs_write_crb(struct kobject *kobj, struct bin_attribute *attr, | ||
2561 | char *buf, loff_t offset, size_t size) | ||
2562 | { | ||
2563 | struct device *dev = container_of(kobj, struct device, kobj); | ||
2564 | struct netxen_adapter *adapter = dev_get_drvdata(dev); | ||
2565 | u32 data; | ||
2566 | int ret; | ||
2567 | |||
2568 | ret = netxen_sysfs_validate_crb(adapter, offset, size); | ||
2569 | if (ret != 0) | ||
2570 | return ret; | ||
2571 | |||
2572 | memcpy(&data, buf, size); | ||
2573 | NXWR32(adapter, offset, data); | ||
2574 | return size; | ||
2575 | } | ||
2576 | |||
2577 | static int | ||
2578 | netxen_sysfs_validate_mem(struct netxen_adapter *adapter, | ||
2579 | loff_t offset, size_t size) | ||
2580 | { | ||
2581 | if (!(adapter->flags & NETXEN_NIC_DIAG_ENABLED)) | ||
2582 | return -EIO; | ||
2583 | |||
2584 | if ((size != 8) || (offset & 0x7)) | ||
2585 | return -EIO; | ||
2586 | |||
2587 | return 0; | ||
2588 | } | ||
2589 | |||
2590 | static ssize_t | ||
2591 | netxen_sysfs_read_mem(struct kobject *kobj, struct bin_attribute *attr, | ||
2592 | char *buf, loff_t offset, size_t size) | ||
2593 | { | ||
2594 | struct device *dev = container_of(kobj, struct device, kobj); | ||
2595 | struct netxen_adapter *adapter = dev_get_drvdata(dev); | ||
2596 | u64 data; | ||
2597 | int ret; | ||
2598 | |||
2599 | ret = netxen_sysfs_validate_mem(adapter, offset, size); | ||
2600 | if (ret != 0) | ||
2601 | return ret; | ||
2602 | |||
2603 | if (adapter->pci_mem_read(adapter, offset, &data)) | ||
2604 | return -EIO; | ||
2605 | |||
2606 | memcpy(buf, &data, size); | ||
2607 | |||
2608 | return size; | ||
2609 | } | ||
2610 | |||
2611 | static ssize_t netxen_sysfs_write_mem(struct kobject *kobj, | ||
2612 | struct bin_attribute *attr, char *buf, | ||
2613 | loff_t offset, size_t size) | ||
2614 | { | ||
2615 | struct device *dev = container_of(kobj, struct device, kobj); | ||
2616 | struct netxen_adapter *adapter = dev_get_drvdata(dev); | ||
2617 | u64 data; | ||
2618 | int ret; | ||
2619 | |||
2620 | ret = netxen_sysfs_validate_mem(adapter, offset, size); | ||
2621 | if (ret != 0) | ||
2622 | return ret; | ||
2623 | |||
2624 | memcpy(&data, buf, size); | ||
2625 | |||
2626 | if (adapter->pci_mem_write(adapter, offset, data)) | ||
2627 | return -EIO; | ||
2628 | |||
2629 | return size; | ||
2630 | } | ||
2631 | |||
2632 | |||
2633 | static struct bin_attribute bin_attr_crb = { | ||
2634 | .attr = {.name = "crb", .mode = (S_IRUGO | S_IWUSR)}, | ||
2635 | .size = 0, | ||
2636 | .read = netxen_sysfs_read_crb, | ||
2637 | .write = netxen_sysfs_write_crb, | ||
2638 | }; | ||
2639 | |||
2640 | static struct bin_attribute bin_attr_mem = { | ||
2641 | .attr = {.name = "mem", .mode = (S_IRUGO | S_IWUSR)}, | ||
2642 | .size = 0, | ||
2643 | .read = netxen_sysfs_read_mem, | ||
2644 | .write = netxen_sysfs_write_mem, | ||
2645 | }; | ||
2646 | |||
2647 | |||
2344 | static void | 2648 | static void |
2345 | netxen_create_sysfs_entries(struct netxen_adapter *adapter) | 2649 | netxen_create_sysfs_entries(struct netxen_adapter *adapter) |
2346 | { | 2650 | { |
@@ -2366,6 +2670,33 @@ netxen_remove_sysfs_entries(struct netxen_adapter *adapter) | |||
2366 | device_remove_file(dev, &dev_attr_bridged_mode); | 2670 | device_remove_file(dev, &dev_attr_bridged_mode); |
2367 | } | 2671 | } |
2368 | 2672 | ||
2673 | static void | ||
2674 | netxen_create_diag_entries(struct netxen_adapter *adapter) | ||
2675 | { | ||
2676 | struct pci_dev *pdev = adapter->pdev; | ||
2677 | struct device *dev; | ||
2678 | |||
2679 | dev = &pdev->dev; | ||
2680 | if (device_create_file(dev, &dev_attr_diag_mode)) | ||
2681 | dev_info(dev, "failed to create diag_mode sysfs entry\n"); | ||
2682 | if (device_create_bin_file(dev, &bin_attr_crb)) | ||
2683 | dev_info(dev, "failed to create crb sysfs entry\n"); | ||
2684 | if (device_create_bin_file(dev, &bin_attr_mem)) | ||
2685 | dev_info(dev, "failed to create mem sysfs entry\n"); | ||
2686 | } | ||
2687 | |||
2688 | |||
2689 | static void | ||
2690 | netxen_remove_diag_entries(struct netxen_adapter *adapter) | ||
2691 | { | ||
2692 | struct pci_dev *pdev = adapter->pdev; | ||
2693 | struct device *dev = &pdev->dev; | ||
2694 | |||
2695 | device_remove_file(dev, &dev_attr_diag_mode); | ||
2696 | device_remove_bin_file(dev, &bin_attr_crb); | ||
2697 | device_remove_bin_file(dev, &bin_attr_mem); | ||
2698 | } | ||
2699 | |||
2369 | #ifdef CONFIG_INET | 2700 | #ifdef CONFIG_INET |
2370 | 2701 | ||
2371 | #define is_netxen_netdev(dev) (dev->netdev_ops == &netxen_netdev_ops) | 2702 | #define is_netxen_netdev(dev) (dev->netdev_ops == &netxen_netdev_ops) |
@@ -2504,6 +2835,12 @@ netxen_config_indev_addr(struct net_device *dev, unsigned long event) | |||
2504 | { } | 2835 | { } |
2505 | #endif | 2836 | #endif |
2506 | 2837 | ||
2838 | static struct pci_error_handlers netxen_err_handler = { | ||
2839 | .error_detected = netxen_io_error_detected, | ||
2840 | .slot_reset = netxen_io_slot_reset, | ||
2841 | .resume = netxen_io_resume, | ||
2842 | }; | ||
2843 | |||
2507 | static struct pci_driver netxen_driver = { | 2844 | static struct pci_driver netxen_driver = { |
2508 | .name = netxen_nic_driver_name, | 2845 | .name = netxen_nic_driver_name, |
2509 | .id_table = netxen_pci_tbl, | 2846 | .id_table = netxen_pci_tbl, |
@@ -2513,7 +2850,8 @@ static struct pci_driver netxen_driver = { | |||
2513 | .suspend = netxen_nic_suspend, | 2850 | .suspend = netxen_nic_suspend, |
2514 | .resume = netxen_nic_resume, | 2851 | .resume = netxen_nic_resume, |
2515 | #endif | 2852 | #endif |
2516 | .shutdown = netxen_nic_shutdown | 2853 | .shutdown = netxen_nic_shutdown, |
2854 | .err_handler = &netxen_err_handler | ||
2517 | }; | 2855 | }; |
2518 | 2856 | ||
2519 | static int __init netxen_init_module(void) | 2857 | static int __init netxen_init_module(void) |
@@ -2524,7 +2862,6 @@ static int __init netxen_init_module(void) | |||
2524 | register_netdevice_notifier(&netxen_netdev_cb); | 2862 | register_netdevice_notifier(&netxen_netdev_cb); |
2525 | register_inetaddr_notifier(&netxen_inetaddr_cb); | 2863 | register_inetaddr_notifier(&netxen_inetaddr_cb); |
2526 | #endif | 2864 | #endif |
2527 | |||
2528 | return pci_register_driver(&netxen_driver); | 2865 | return pci_register_driver(&netxen_driver); |
2529 | } | 2866 | } |
2530 | 2867 | ||