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_hw.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_hw.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 1048 |
1 files changed, 474 insertions, 574 deletions
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 52a3798d8d94..b1cf46a0c48c 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.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 "netxen_nic.h" | 27 | #include "netxen_nic.h" |
27 | #include "netxen_nic_hw.h" | 28 | #include "netxen_nic_hw.h" |
28 | 29 | ||
@@ -31,6 +32,7 @@ | |||
31 | #define MASK(n) ((1ULL<<(n))-1) | 32 | #define MASK(n) ((1ULL<<(n))-1) |
32 | #define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff)) | 33 | #define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff)) |
33 | #define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff)) | 34 | #define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff)) |
35 | #define OCM_WIN_P3P(addr) (addr & 0xffc0000) | ||
34 | #define MS_WIN(addr) (addr & 0x0ffc0000) | 36 | #define MS_WIN(addr) (addr & 0x0ffc0000) |
35 | 37 | ||
36 | #define GET_MEM_OFFS_2M(addr) (addr & MASK(18)) | 38 | #define GET_MEM_OFFS_2M(addr) (addr & MASK(18)) |
@@ -41,6 +43,11 @@ | |||
41 | #define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000)) | 43 | #define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000)) |
42 | #define CRB_INDIRECT_2M (0x1e0000UL) | 44 | #define CRB_INDIRECT_2M (0x1e0000UL) |
43 | 45 | ||
46 | static void netxen_nic_io_write_128M(struct netxen_adapter *adapter, | ||
47 | void __iomem *addr, u32 data); | ||
48 | static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, | ||
49 | void __iomem *addr); | ||
50 | |||
44 | #ifndef readq | 51 | #ifndef readq |
45 | static inline u64 readq(void __iomem *addr) | 52 | static inline u64 readq(void __iomem *addr) |
46 | { | 53 | { |
@@ -326,7 +333,7 @@ netxen_pcie_sem_lock(struct netxen_adapter *adapter, int sem, u32 id_reg) | |||
326 | if (done == 1) | 333 | if (done == 1) |
327 | break; | 334 | break; |
328 | if (++timeout >= NETXEN_PCIE_SEM_TIMEOUT) | 335 | if (++timeout >= NETXEN_PCIE_SEM_TIMEOUT) |
329 | return -1; | 336 | return -EIO; |
330 | msleep(1); | 337 | msleep(1); |
331 | } | 338 | } |
332 | 339 | ||
@@ -339,8 +346,7 @@ netxen_pcie_sem_lock(struct netxen_adapter *adapter, int sem, u32 id_reg) | |||
339 | void | 346 | void |
340 | netxen_pcie_sem_unlock(struct netxen_adapter *adapter, int sem) | 347 | netxen_pcie_sem_unlock(struct netxen_adapter *adapter, int sem) |
341 | { | 348 | { |
342 | int val; | 349 | NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM_UNLOCK(sem))); |
343 | val = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM_UNLOCK(sem))); | ||
344 | } | 350 | } |
345 | 351 | ||
346 | int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port) | 352 | int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port) |
@@ -534,7 +540,7 @@ void netxen_p2_nic_set_multi(struct net_device *netdev) | |||
534 | struct netxen_adapter *adapter = netdev_priv(netdev); | 540 | struct netxen_adapter *adapter = netdev_priv(netdev); |
535 | struct dev_mc_list *mc_ptr; | 541 | struct dev_mc_list *mc_ptr; |
536 | u8 null_addr[6]; | 542 | u8 null_addr[6]; |
537 | int index = 0; | 543 | int i; |
538 | 544 | ||
539 | memset(null_addr, 0, 6); | 545 | memset(null_addr, 0, 6); |
540 | 546 | ||
@@ -549,7 +555,7 @@ void netxen_p2_nic_set_multi(struct net_device *netdev) | |||
549 | return; | 555 | return; |
550 | } | 556 | } |
551 | 557 | ||
552 | if (netdev->mc_count == 0) { | 558 | if (netdev_mc_empty(netdev)) { |
553 | adapter->set_promisc(adapter, | 559 | adapter->set_promisc(adapter, |
554 | NETXEN_NIU_NON_PROMISC_MODE); | 560 | NETXEN_NIU_NON_PROMISC_MODE); |
555 | netxen_nic_disable_mcast_filter(adapter); | 561 | netxen_nic_disable_mcast_filter(adapter); |
@@ -558,23 +564,20 @@ void netxen_p2_nic_set_multi(struct net_device *netdev) | |||
558 | 564 | ||
559 | adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE); | 565 | adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE); |
560 | if (netdev->flags & IFF_ALLMULTI || | 566 | if (netdev->flags & IFF_ALLMULTI || |
561 | netdev->mc_count > adapter->max_mc_count) { | 567 | netdev_mc_count(netdev) > adapter->max_mc_count) { |
562 | netxen_nic_disable_mcast_filter(adapter); | 568 | netxen_nic_disable_mcast_filter(adapter); |
563 | return; | 569 | return; |
564 | } | 570 | } |
565 | 571 | ||
566 | netxen_nic_enable_mcast_filter(adapter); | 572 | netxen_nic_enable_mcast_filter(adapter); |
567 | 573 | ||
568 | for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next, index++) | 574 | i = 0; |
569 | netxen_nic_set_mcast_addr(adapter, index, mc_ptr->dmi_addr); | 575 | netdev_for_each_mc_addr(mc_ptr, netdev) |
570 | 576 | netxen_nic_set_mcast_addr(adapter, i++, mc_ptr->dmi_addr); | |
571 | if (index != netdev->mc_count) | ||
572 | printk(KERN_WARNING "%s: %s multicast address count mismatch\n", | ||
573 | netxen_nic_driver_name, netdev->name); | ||
574 | 577 | ||
575 | /* Clear out remaining addresses */ | 578 | /* Clear out remaining addresses */ |
576 | for (; index < adapter->max_mc_count; index++) | 579 | while (i < adapter->max_mc_count) |
577 | netxen_nic_set_mcast_addr(adapter, index, null_addr); | 580 | netxen_nic_set_mcast_addr(adapter, i++, null_addr); |
578 | } | 581 | } |
579 | 582 | ||
580 | static int | 583 | static int |
@@ -685,6 +688,9 @@ void netxen_p3_nic_set_multi(struct net_device *netdev) | |||
685 | struct list_head *head; | 688 | struct list_head *head; |
686 | nx_mac_list_t *cur; | 689 | nx_mac_list_t *cur; |
687 | 690 | ||
691 | if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) | ||
692 | return; | ||
693 | |||
688 | list_splice_tail_init(&adapter->mac_list, &del_list); | 694 | list_splice_tail_init(&adapter->mac_list, &del_list); |
689 | 695 | ||
690 | nx_p3_nic_add_mac(adapter, adapter->mac_addr, &del_list); | 696 | nx_p3_nic_add_mac(adapter, adapter->mac_addr, &del_list); |
@@ -696,16 +702,14 @@ void netxen_p3_nic_set_multi(struct net_device *netdev) | |||
696 | } | 702 | } |
697 | 703 | ||
698 | if ((netdev->flags & IFF_ALLMULTI) || | 704 | if ((netdev->flags & IFF_ALLMULTI) || |
699 | (netdev->mc_count > adapter->max_mc_count)) { | 705 | (netdev_mc_count(netdev) > adapter->max_mc_count)) { |
700 | mode = VPORT_MISS_MODE_ACCEPT_MULTI; | 706 | mode = VPORT_MISS_MODE_ACCEPT_MULTI; |
701 | goto send_fw_cmd; | 707 | goto send_fw_cmd; |
702 | } | 708 | } |
703 | 709 | ||
704 | if (netdev->mc_count > 0) { | 710 | if (!netdev_mc_empty(netdev)) { |
705 | for (mc_ptr = netdev->mc_list; mc_ptr; | 711 | netdev_for_each_mc_addr(mc_ptr, netdev) |
706 | mc_ptr = mc_ptr->next) { | ||
707 | nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, &del_list); | 712 | nx_p3_nic_add_mac(adapter, mc_ptr->dmi_addr, &del_list); |
708 | } | ||
709 | } | 713 | } |
710 | 714 | ||
711 | send_fw_cmd: | 715 | send_fw_cmd: |
@@ -769,17 +773,20 @@ int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr) | |||
769 | int netxen_config_intr_coalesce(struct netxen_adapter *adapter) | 773 | int netxen_config_intr_coalesce(struct netxen_adapter *adapter) |
770 | { | 774 | { |
771 | nx_nic_req_t req; | 775 | nx_nic_req_t req; |
772 | u64 word; | 776 | u64 word[6]; |
773 | int rv; | 777 | int rv, i; |
774 | 778 | ||
775 | memset(&req, 0, sizeof(nx_nic_req_t)); | 779 | memset(&req, 0, sizeof(nx_nic_req_t)); |
780 | memset(word, 0, sizeof(word)); | ||
776 | 781 | ||
777 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); | 782 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); |
778 | 783 | ||
779 | word = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16); | 784 | word[0] = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16); |
780 | req.req_hdr = cpu_to_le64(word); | 785 | req.req_hdr = cpu_to_le64(word[0]); |
781 | 786 | ||
782 | memcpy(&req.words[0], &adapter->coal, sizeof(adapter->coal)); | 787 | memcpy(&word[0], &adapter->coal, sizeof(adapter->coal)); |
788 | for (i = 0; i < 6; i++) | ||
789 | req.words[i] = cpu_to_le64(word[i]); | ||
783 | 790 | ||
784 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | 791 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); |
785 | if (rv != 0) { | 792 | if (rv != 0) { |
@@ -1025,7 +1032,7 @@ static int netxen_get_flash_block(struct netxen_adapter *adapter, int base, | |||
1025 | return 0; | 1032 | return 0; |
1026 | } | 1033 | } |
1027 | 1034 | ||
1028 | int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac) | 1035 | int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 *mac) |
1029 | { | 1036 | { |
1030 | __le32 *pmac = (__le32 *) mac; | 1037 | __le32 *pmac = (__le32 *) mac; |
1031 | u32 offset; | 1038 | u32 offset; |
@@ -1050,7 +1057,7 @@ int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac) | |||
1050 | return 0; | 1057 | return 0; |
1051 | } | 1058 | } |
1052 | 1059 | ||
1053 | int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac) | 1060 | int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, u64 *mac) |
1054 | { | 1061 | { |
1055 | uint32_t crbaddr, mac_hi, mac_lo; | 1062 | uint32_t crbaddr, mac_hi, mac_lo; |
1056 | int pci_func = adapter->ahw.pci_func; | 1063 | int pci_func = adapter->ahw.pci_func; |
@@ -1073,89 +1080,71 @@ int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac) | |||
1073 | * Changes the CRB window to the specified window. | 1080 | * Changes the CRB window to the specified window. |
1074 | */ | 1081 | */ |
1075 | static void | 1082 | static void |
1076 | netxen_nic_pci_change_crbwindow_128M(struct netxen_adapter *adapter, u32 wndw) | 1083 | netxen_nic_pci_set_crbwindow_128M(struct netxen_adapter *adapter, |
1084 | u32 window) | ||
1077 | { | 1085 | { |
1078 | void __iomem *offset; | 1086 | void __iomem *offset; |
1079 | u32 tmp; | 1087 | int count = 10; |
1080 | int count = 0; | 1088 | u8 func = adapter->ahw.pci_func; |
1081 | uint8_t func = adapter->ahw.pci_func; | ||
1082 | 1089 | ||
1083 | if (adapter->curr_window == wndw) | 1090 | if (adapter->ahw.crb_win == window) |
1084 | return; | 1091 | return; |
1085 | /* | 1092 | |
1086 | * Move the CRB window. | ||
1087 | * We need to write to the "direct access" region of PCI | ||
1088 | * to avoid a race condition where the window register has | ||
1089 | * not been successfully written across CRB before the target | ||
1090 | * register address is received by PCI. The direct region bypasses | ||
1091 | * the CRB bus. | ||
1092 | */ | ||
1093 | offset = PCI_OFFSET_SECOND_RANGE(adapter, | 1093 | offset = PCI_OFFSET_SECOND_RANGE(adapter, |
1094 | NETXEN_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(func))); | 1094 | NETXEN_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(func))); |
1095 | 1095 | ||
1096 | if (wndw & 0x1) | 1096 | writel(window, offset); |
1097 | wndw = NETXEN_WINDOW_ONE; | 1097 | do { |
1098 | if (window == readl(offset)) | ||
1099 | break; | ||
1098 | 1100 | ||
1099 | writel(wndw, offset); | 1101 | if (printk_ratelimit()) |
1102 | dev_warn(&adapter->pdev->dev, | ||
1103 | "failed to set CRB window to %d\n", | ||
1104 | (window == NETXEN_WINDOW_ONE)); | ||
1105 | udelay(1); | ||
1100 | 1106 | ||
1101 | /* MUST make sure window is set before we forge on... */ | 1107 | } while (--count > 0); |
1102 | while ((tmp = readl(offset)) != wndw) { | ||
1103 | printk(KERN_WARNING "%s: %s WARNING: CRB window value not " | ||
1104 | "registered properly: 0x%08x.\n", | ||
1105 | netxen_nic_driver_name, __func__, tmp); | ||
1106 | mdelay(1); | ||
1107 | if (count >= 10) | ||
1108 | break; | ||
1109 | count++; | ||
1110 | } | ||
1111 | 1108 | ||
1112 | if (wndw == NETXEN_WINDOW_ONE) | 1109 | if (count > 0) |
1113 | adapter->curr_window = 1; | 1110 | adapter->ahw.crb_win = window; |
1114 | else | ||
1115 | adapter->curr_window = 0; | ||
1116 | } | 1111 | } |
1117 | 1112 | ||
1118 | /* | 1113 | /* |
1119 | * Return -1 if off is not valid, | 1114 | * Returns < 0 if off is not valid, |
1120 | * 1 if window access is needed. 'off' is set to offset from | 1115 | * 1 if window access is needed. 'off' is set to offset from |
1121 | * CRB space in 128M pci map | 1116 | * CRB space in 128M pci map |
1122 | * 0 if no window access is needed. 'off' is set to 2M addr | 1117 | * 0 if no window access is needed. 'off' is set to 2M addr |
1123 | * In: 'off' is offset from base in 128M pci map | 1118 | * In: 'off' is offset from base in 128M pci map |
1124 | */ | 1119 | */ |
1125 | static int | 1120 | static int |
1126 | netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, ulong *off) | 1121 | netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, |
1122 | ulong off, void __iomem **addr) | ||
1127 | { | 1123 | { |
1128 | crb_128M_2M_sub_block_map_t *m; | 1124 | crb_128M_2M_sub_block_map_t *m; |
1129 | 1125 | ||
1130 | 1126 | ||
1131 | if (*off >= NETXEN_CRB_MAX) | 1127 | if ((off >= NETXEN_CRB_MAX) || (off < NETXEN_PCI_CRBSPACE)) |
1132 | return -1; | 1128 | return -EINVAL; |
1133 | |||
1134 | if (*off >= NETXEN_PCI_CAMQM && (*off < NETXEN_PCI_CAMQM_2M_END)) { | ||
1135 | *off = (*off - NETXEN_PCI_CAMQM) + NETXEN_PCI_CAMQM_2M_BASE + | ||
1136 | (ulong)adapter->ahw.pci_base0; | ||
1137 | return 0; | ||
1138 | } | ||
1139 | |||
1140 | if (*off < NETXEN_PCI_CRBSPACE) | ||
1141 | return -1; | ||
1142 | 1129 | ||
1143 | *off -= NETXEN_PCI_CRBSPACE; | 1130 | off -= NETXEN_PCI_CRBSPACE; |
1144 | 1131 | ||
1145 | /* | 1132 | /* |
1146 | * Try direct map | 1133 | * Try direct map |
1147 | */ | 1134 | */ |
1148 | m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)]; | 1135 | m = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)]; |
1149 | 1136 | ||
1150 | if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) { | 1137 | if (m->valid && (m->start_128M <= off) && (m->end_128M > off)) { |
1151 | *off = *off + m->start_2M - m->start_128M + | 1138 | *addr = adapter->ahw.pci_base0 + m->start_2M + |
1152 | (ulong)adapter->ahw.pci_base0; | 1139 | (off - m->start_128M); |
1153 | return 0; | 1140 | return 0; |
1154 | } | 1141 | } |
1155 | 1142 | ||
1156 | /* | 1143 | /* |
1157 | * Not in direct map, use crb window | 1144 | * Not in direct map, use crb window |
1158 | */ | 1145 | */ |
1146 | *addr = adapter->ahw.pci_base0 + CRB_INDIRECT_2M + | ||
1147 | (off & MASK(16)); | ||
1159 | return 1; | 1148 | return 1; |
1160 | } | 1149 | } |
1161 | 1150 | ||
@@ -1165,52 +1154,78 @@ netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, ulong *off) | |||
1165 | * side effect: lock crb window | 1154 | * side effect: lock crb window |
1166 | */ | 1155 | */ |
1167 | static void | 1156 | static void |
1168 | netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong *off) | 1157 | netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off) |
1169 | { | 1158 | { |
1170 | u32 win_read; | 1159 | u32 window; |
1160 | void __iomem *addr = adapter->ahw.pci_base0 + CRB_WINDOW_2M; | ||
1171 | 1161 | ||
1172 | adapter->crb_win = CRB_HI(*off); | 1162 | off -= NETXEN_PCI_CRBSPACE; |
1173 | writel(adapter->crb_win, (adapter->ahw.pci_base0 + CRB_WINDOW_2M)); | 1163 | |
1174 | /* | 1164 | window = CRB_HI(off); |
1175 | * Read back value to make sure write has gone through before trying | 1165 | |
1176 | * to use it. | 1166 | if (adapter->ahw.crb_win == window) |
1177 | */ | 1167 | return; |
1178 | win_read = readl(adapter->ahw.pci_base0 + CRB_WINDOW_2M); | 1168 | |
1179 | if (win_read != adapter->crb_win) { | 1169 | writel(window, addr); |
1180 | printk(KERN_ERR "%s: Written crbwin (0x%x) != " | 1170 | if (readl(addr) != window) { |
1181 | "Read crbwin (0x%x), off=0x%lx\n", | 1171 | if (printk_ratelimit()) |
1182 | __func__, adapter->crb_win, win_read, *off); | 1172 | dev_warn(&adapter->pdev->dev, |
1173 | "failed to set CRB window to %d off 0x%lx\n", | ||
1174 | window, off); | ||
1183 | } | 1175 | } |
1184 | *off = (*off & MASK(16)) + CRB_INDIRECT_2M + | 1176 | adapter->ahw.crb_win = window; |
1185 | (ulong)adapter->ahw.pci_base0; | 1177 | } |
1178 | |||
1179 | static void __iomem * | ||
1180 | netxen_nic_map_indirect_address_128M(struct netxen_adapter *adapter, | ||
1181 | ulong win_off, void __iomem **mem_ptr) | ||
1182 | { | ||
1183 | ulong off = win_off; | ||
1184 | void __iomem *addr; | ||
1185 | resource_size_t mem_base; | ||
1186 | |||
1187 | if (ADDR_IN_WINDOW1(win_off)) | ||
1188 | off = NETXEN_CRB_NORMAL(win_off); | ||
1189 | |||
1190 | addr = pci_base_offset(adapter, off); | ||
1191 | if (addr) | ||
1192 | return addr; | ||
1193 | |||
1194 | if (adapter->ahw.pci_len0 == 0) | ||
1195 | off -= NETXEN_PCI_CRBSPACE; | ||
1196 | |||
1197 | mem_base = pci_resource_start(adapter->pdev, 0); | ||
1198 | *mem_ptr = ioremap(mem_base + (off & PAGE_MASK), PAGE_SIZE); | ||
1199 | if (*mem_ptr) | ||
1200 | addr = *mem_ptr + (off & (PAGE_SIZE - 1)); | ||
1201 | |||
1202 | return addr; | ||
1186 | } | 1203 | } |
1187 | 1204 | ||
1188 | static int | 1205 | static int |
1189 | netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data) | 1206 | netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data) |
1190 | { | 1207 | { |
1191 | unsigned long flags; | 1208 | unsigned long flags; |
1192 | void __iomem *addr; | 1209 | void __iomem *addr, *mem_ptr = NULL; |
1193 | |||
1194 | if (ADDR_IN_WINDOW1(off)) | ||
1195 | addr = NETXEN_CRB_NORMALIZE(adapter, off); | ||
1196 | else | ||
1197 | addr = pci_base_offset(adapter, off); | ||
1198 | 1210 | ||
1199 | BUG_ON(!addr); | 1211 | addr = netxen_nic_map_indirect_address_128M(adapter, off, &mem_ptr); |
1212 | if (!addr) | ||
1213 | return -EIO; | ||
1200 | 1214 | ||
1201 | if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ | 1215 | if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ |
1202 | read_lock(&adapter->adapter_lock); | 1216 | netxen_nic_io_write_128M(adapter, addr, data); |
1203 | writel(data, addr); | 1217 | } else { /* Window 0 */ |
1204 | read_unlock(&adapter->adapter_lock); | 1218 | write_lock_irqsave(&adapter->ahw.crb_lock, flags); |
1205 | } else { /* Window 0 */ | 1219 | netxen_nic_pci_set_crbwindow_128M(adapter, 0); |
1206 | write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1207 | addr = pci_base_offset(adapter, off); | ||
1208 | netxen_nic_pci_change_crbwindow_128M(adapter, 0); | ||
1209 | writel(data, addr); | 1220 | writel(data, addr); |
1210 | netxen_nic_pci_change_crbwindow_128M(adapter, 1); | 1221 | netxen_nic_pci_set_crbwindow_128M(adapter, |
1211 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | 1222 | NETXEN_WINDOW_ONE); |
1223 | write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); | ||
1212 | } | 1224 | } |
1213 | 1225 | ||
1226 | if (mem_ptr) | ||
1227 | iounmap(mem_ptr); | ||
1228 | |||
1214 | return 0; | 1229 | return 0; |
1215 | } | 1230 | } |
1216 | 1231 | ||
@@ -1218,28 +1233,27 @@ static u32 | |||
1218 | netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off) | 1233 | netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off) |
1219 | { | 1234 | { |
1220 | unsigned long flags; | 1235 | unsigned long flags; |
1221 | void __iomem *addr; | 1236 | void __iomem *addr, *mem_ptr = NULL; |
1222 | u32 data; | 1237 | u32 data; |
1223 | 1238 | ||
1224 | if (ADDR_IN_WINDOW1(off)) | 1239 | addr = netxen_nic_map_indirect_address_128M(adapter, off, &mem_ptr); |
1225 | addr = NETXEN_CRB_NORMALIZE(adapter, off); | 1240 | if (!addr) |
1226 | else | 1241 | return -EIO; |
1227 | addr = pci_base_offset(adapter, off); | ||
1228 | |||
1229 | BUG_ON(!addr); | ||
1230 | 1242 | ||
1231 | if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ | 1243 | if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ |
1232 | read_lock(&adapter->adapter_lock); | 1244 | data = netxen_nic_io_read_128M(adapter, addr); |
1245 | } else { /* Window 0 */ | ||
1246 | write_lock_irqsave(&adapter->ahw.crb_lock, flags); | ||
1247 | netxen_nic_pci_set_crbwindow_128M(adapter, 0); | ||
1233 | data = readl(addr); | 1248 | data = readl(addr); |
1234 | read_unlock(&adapter->adapter_lock); | 1249 | netxen_nic_pci_set_crbwindow_128M(adapter, |
1235 | } else { /* Window 0 */ | 1250 | NETXEN_WINDOW_ONE); |
1236 | write_lock_irqsave(&adapter->adapter_lock, flags); | 1251 | write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); |
1237 | netxen_nic_pci_change_crbwindow_128M(adapter, 0); | ||
1238 | data = readl(addr); | ||
1239 | netxen_nic_pci_change_crbwindow_128M(adapter, 1); | ||
1240 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | ||
1241 | } | 1252 | } |
1242 | 1253 | ||
1254 | if (mem_ptr) | ||
1255 | iounmap(mem_ptr); | ||
1256 | |||
1243 | return data; | 1257 | return data; |
1244 | } | 1258 | } |
1245 | 1259 | ||
@@ -1248,28 +1262,30 @@ netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data) | |||
1248 | { | 1262 | { |
1249 | unsigned long flags; | 1263 | unsigned long flags; |
1250 | int rv; | 1264 | int rv; |
1265 | void __iomem *addr = NULL; | ||
1251 | 1266 | ||
1252 | rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off); | 1267 | rv = netxen_nic_pci_get_crb_addr_2M(adapter, off, &addr); |
1253 | 1268 | ||
1254 | if (rv == -1) { | 1269 | if (rv == 0) { |
1255 | printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", | 1270 | writel(data, addr); |
1256 | __func__, off); | 1271 | return 0; |
1257 | dump_stack(); | ||
1258 | return -1; | ||
1259 | } | 1272 | } |
1260 | 1273 | ||
1261 | if (rv == 1) { | 1274 | if (rv > 0) { |
1262 | write_lock_irqsave(&adapter->adapter_lock, flags); | 1275 | /* indirect access */ |
1276 | write_lock_irqsave(&adapter->ahw.crb_lock, flags); | ||
1263 | crb_win_lock(adapter); | 1277 | crb_win_lock(adapter); |
1264 | netxen_nic_pci_set_crbwindow_2M(adapter, &off); | 1278 | netxen_nic_pci_set_crbwindow_2M(adapter, off); |
1265 | writel(data, (void __iomem *)off); | 1279 | writel(data, addr); |
1266 | crb_win_unlock(adapter); | 1280 | crb_win_unlock(adapter); |
1267 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | 1281 | write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); |
1268 | } else | 1282 | return 0; |
1269 | writel(data, (void __iomem *)off); | 1283 | } |
1270 | |||
1271 | 1284 | ||
1272 | return 0; | 1285 | dev_err(&adapter->pdev->dev, |
1286 | "%s: invalid offset: 0x%016lx\n", __func__, off); | ||
1287 | dump_stack(); | ||
1288 | return -EIO; | ||
1273 | } | 1289 | } |
1274 | 1290 | ||
1275 | static u32 | 1291 | static u32 |
@@ -1278,102 +1294,37 @@ netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off) | |||
1278 | unsigned long flags; | 1294 | unsigned long flags; |
1279 | int rv; | 1295 | int rv; |
1280 | u32 data; | 1296 | u32 data; |
1297 | void __iomem *addr = NULL; | ||
1281 | 1298 | ||
1282 | rv = netxen_nic_pci_get_crb_addr_2M(adapter, &off); | 1299 | rv = netxen_nic_pci_get_crb_addr_2M(adapter, off, &addr); |
1283 | 1300 | ||
1284 | if (rv == -1) { | 1301 | if (rv == 0) |
1285 | printk(KERN_ERR "%s: invalid offset: 0x%016lx\n", | 1302 | return readl(addr); |
1286 | __func__, off); | ||
1287 | dump_stack(); | ||
1288 | return -1; | ||
1289 | } | ||
1290 | 1303 | ||
1291 | if (rv == 1) { | 1304 | if (rv > 0) { |
1292 | write_lock_irqsave(&adapter->adapter_lock, flags); | 1305 | /* indirect access */ |
1306 | write_lock_irqsave(&adapter->ahw.crb_lock, flags); | ||
1293 | crb_win_lock(adapter); | 1307 | crb_win_lock(adapter); |
1294 | netxen_nic_pci_set_crbwindow_2M(adapter, &off); | 1308 | netxen_nic_pci_set_crbwindow_2M(adapter, off); |
1295 | data = readl((void __iomem *)off); | 1309 | data = readl(addr); |
1296 | crb_win_unlock(adapter); | 1310 | crb_win_unlock(adapter); |
1297 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | 1311 | write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); |
1298 | } else | 1312 | return data; |
1299 | data = readl((void __iomem *)off); | ||
1300 | |||
1301 | return data; | ||
1302 | } | ||
1303 | |||
1304 | static int netxen_pci_set_window_warning_count; | ||
1305 | |||
1306 | static unsigned long | ||
1307 | netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter, | ||
1308 | unsigned long long addr) | ||
1309 | { | ||
1310 | void __iomem *offset; | ||
1311 | int window; | ||
1312 | unsigned long long qdr_max; | ||
1313 | uint8_t func = adapter->ahw.pci_func; | ||
1314 | |||
1315 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
1316 | qdr_max = NETXEN_ADDR_QDR_NET_MAX_P2; | ||
1317 | } else { | ||
1318 | qdr_max = NETXEN_ADDR_QDR_NET_MAX_P3; | ||
1319 | } | 1313 | } |
1320 | 1314 | ||
1321 | if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { | 1315 | dev_err(&adapter->pdev->dev, |
1322 | /* DDR network side */ | 1316 | "%s: invalid offset: 0x%016lx\n", __func__, off); |
1323 | addr -= NETXEN_ADDR_DDR_NET; | 1317 | dump_stack(); |
1324 | window = (addr >> 25) & 0x3ff; | 1318 | return -1; |
1325 | if (adapter->ahw.ddr_mn_window != window) { | ||
1326 | adapter->ahw.ddr_mn_window = window; | ||
1327 | offset = PCI_OFFSET_SECOND_RANGE(adapter, | ||
1328 | NETXEN_PCIX_PH_REG(PCIE_MN_WINDOW_REG(func))); | ||
1329 | writel(window, offset); | ||
1330 | /* MUST make sure window is set before we forge on... */ | ||
1331 | readl(offset); | ||
1332 | } | ||
1333 | addr -= (window * NETXEN_WINDOW_ONE); | ||
1334 | addr += NETXEN_PCI_DDR_NET; | ||
1335 | } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { | ||
1336 | addr -= NETXEN_ADDR_OCM0; | ||
1337 | addr += NETXEN_PCI_OCM0; | ||
1338 | } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { | ||
1339 | addr -= NETXEN_ADDR_OCM1; | ||
1340 | addr += NETXEN_PCI_OCM1; | ||
1341 | } else if (ADDR_IN_RANGE(addr, NETXEN_ADDR_QDR_NET, qdr_max)) { | ||
1342 | /* QDR network side */ | ||
1343 | addr -= NETXEN_ADDR_QDR_NET; | ||
1344 | window = (addr >> 22) & 0x3f; | ||
1345 | if (adapter->ahw.qdr_sn_window != window) { | ||
1346 | adapter->ahw.qdr_sn_window = window; | ||
1347 | offset = PCI_OFFSET_SECOND_RANGE(adapter, | ||
1348 | NETXEN_PCIX_PH_REG(PCIE_SN_WINDOW_REG(func))); | ||
1349 | writel((window << 22), offset); | ||
1350 | /* MUST make sure window is set before we forge on... */ | ||
1351 | readl(offset); | ||
1352 | } | ||
1353 | addr -= (window * 0x400000); | ||
1354 | addr += NETXEN_PCI_QDR_NET; | ||
1355 | } else { | ||
1356 | /* | ||
1357 | * peg gdb frequently accesses memory that doesn't exist, | ||
1358 | * this limits the chit chat so debugging isn't slowed down. | ||
1359 | */ | ||
1360 | if ((netxen_pci_set_window_warning_count++ < 8) | ||
1361 | || (netxen_pci_set_window_warning_count % 64 == 0)) | ||
1362 | printk("%s: Warning:netxen_nic_pci_set_window()" | ||
1363 | " Unknown address range!\n", | ||
1364 | netxen_nic_driver_name); | ||
1365 | addr = -1UL; | ||
1366 | } | ||
1367 | return addr; | ||
1368 | } | 1319 | } |
1369 | 1320 | ||
1370 | /* window 1 registers only */ | 1321 | /* window 1 registers only */ |
1371 | static void netxen_nic_io_write_128M(struct netxen_adapter *adapter, | 1322 | static void netxen_nic_io_write_128M(struct netxen_adapter *adapter, |
1372 | void __iomem *addr, u32 data) | 1323 | void __iomem *addr, u32 data) |
1373 | { | 1324 | { |
1374 | read_lock(&adapter->adapter_lock); | 1325 | read_lock(&adapter->ahw.crb_lock); |
1375 | writel(data, addr); | 1326 | writel(data, addr); |
1376 | read_unlock(&adapter->adapter_lock); | 1327 | read_unlock(&adapter->ahw.crb_lock); |
1377 | } | 1328 | } |
1378 | 1329 | ||
1379 | static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, | 1330 | static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, |
@@ -1381,9 +1332,9 @@ static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, | |||
1381 | { | 1332 | { |
1382 | u32 val; | 1333 | u32 val; |
1383 | 1334 | ||
1384 | read_lock(&adapter->adapter_lock); | 1335 | read_lock(&adapter->ahw.crb_lock); |
1385 | val = readl(addr); | 1336 | val = readl(addr); |
1386 | read_unlock(&adapter->adapter_lock); | 1337 | read_unlock(&adapter->ahw.crb_lock); |
1387 | 1338 | ||
1388 | return val; | 1339 | return val; |
1389 | } | 1340 | } |
@@ -1403,488 +1354,437 @@ static u32 netxen_nic_io_read_2M(struct netxen_adapter *adapter, | |||
1403 | void __iomem * | 1354 | void __iomem * |
1404 | netxen_get_ioaddr(struct netxen_adapter *adapter, u32 offset) | 1355 | netxen_get_ioaddr(struct netxen_adapter *adapter, u32 offset) |
1405 | { | 1356 | { |
1406 | ulong off = offset; | 1357 | void __iomem *addr = NULL; |
1407 | 1358 | ||
1408 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | 1359 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { |
1409 | if (offset < NETXEN_CRB_PCIX_HOST2 && | 1360 | if ((offset < NETXEN_CRB_PCIX_HOST2) && |
1410 | offset > NETXEN_CRB_PCIX_HOST) | 1361 | (offset > NETXEN_CRB_PCIX_HOST)) |
1411 | return PCI_OFFSET_SECOND_RANGE(adapter, offset); | 1362 | addr = PCI_OFFSET_SECOND_RANGE(adapter, offset); |
1412 | return NETXEN_CRB_NORMALIZE(adapter, offset); | 1363 | else |
1364 | addr = NETXEN_CRB_NORMALIZE(adapter, offset); | ||
1365 | } else { | ||
1366 | WARN_ON(netxen_nic_pci_get_crb_addr_2M(adapter, | ||
1367 | offset, &addr)); | ||
1413 | } | 1368 | } |
1414 | 1369 | ||
1415 | BUG_ON(netxen_nic_pci_get_crb_addr_2M(adapter, &off)); | 1370 | return addr; |
1416 | return (void __iomem *)off; | ||
1417 | } | 1371 | } |
1418 | 1372 | ||
1419 | static unsigned long | 1373 | static int |
1420 | netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, | 1374 | netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter, |
1421 | unsigned long long addr) | 1375 | u64 addr, u32 *start) |
1422 | { | 1376 | { |
1423 | int window; | 1377 | if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { |
1424 | u32 win_read; | 1378 | *start = (addr - NETXEN_ADDR_OCM0 + NETXEN_PCI_OCM0); |
1425 | 1379 | return 0; | |
1426 | if (ADDR_IN_RANGE(addr, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { | ||
1427 | /* DDR network side */ | ||
1428 | window = MN_WIN(addr); | ||
1429 | adapter->ahw.ddr_mn_window = window; | ||
1430 | NXWR32(adapter, adapter->ahw.mn_win_crb, window); | ||
1431 | win_read = NXRD32(adapter, adapter->ahw.mn_win_crb); | ||
1432 | if ((win_read << 17) != window) { | ||
1433 | printk(KERN_INFO "Written MNwin (0x%x) != " | ||
1434 | "Read MNwin (0x%x)\n", window, win_read); | ||
1435 | } | ||
1436 | addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_DDR_NET; | ||
1437 | } else if (ADDR_IN_RANGE(addr, | 1380 | } else if (ADDR_IN_RANGE(addr, |
1438 | NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { | 1381 | NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { |
1439 | if ((addr & 0x00ff800) == 0xff800) { | 1382 | *start = (addr - NETXEN_ADDR_OCM1 + NETXEN_PCI_OCM1); |
1440 | printk("%s: QM access not handled.\n", __func__); | 1383 | return 0; |
1441 | addr = -1UL; | 1384 | } |
1442 | } | 1385 | |
1386 | return -EIO; | ||
1387 | } | ||
1443 | 1388 | ||
1389 | static int | ||
1390 | netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, | ||
1391 | u64 addr, u32 *start) | ||
1392 | { | ||
1393 | u32 window; | ||
1394 | struct pci_dev *pdev = adapter->pdev; | ||
1395 | |||
1396 | if ((addr & 0x00ff800) == 0xff800) { | ||
1397 | if (printk_ratelimit()) | ||
1398 | dev_warn(&pdev->dev, "QM access not handled\n"); | ||
1399 | return -EIO; | ||
1400 | } | ||
1401 | |||
1402 | if (NX_IS_REVISION_P3P(adapter->ahw.revision_id)) | ||
1403 | window = OCM_WIN_P3P(addr); | ||
1404 | else | ||
1444 | window = OCM_WIN(addr); | 1405 | window = OCM_WIN(addr); |
1445 | adapter->ahw.ddr_mn_window = window; | ||
1446 | NXWR32(adapter, adapter->ahw.mn_win_crb, window); | ||
1447 | win_read = NXRD32(adapter, adapter->ahw.mn_win_crb); | ||
1448 | if ((win_read >> 7) != window) { | ||
1449 | printk(KERN_INFO "%s: Written OCMwin (0x%x) != " | ||
1450 | "Read OCMwin (0x%x)\n", | ||
1451 | __func__, window, win_read); | ||
1452 | } | ||
1453 | addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_OCM0_2M; | ||
1454 | 1406 | ||
1455 | } else if (ADDR_IN_RANGE(addr, | 1407 | writel(window, adapter->ahw.ocm_win_crb); |
1456 | NETXEN_ADDR_QDR_NET, NETXEN_ADDR_QDR_NET_MAX_P3)) { | 1408 | /* read back to flush */ |
1457 | /* QDR network side */ | 1409 | readl(adapter->ahw.ocm_win_crb); |
1458 | window = MS_WIN(addr); | ||
1459 | adapter->ahw.qdr_sn_window = window; | ||
1460 | NXWR32(adapter, adapter->ahw.ms_win_crb, window); | ||
1461 | win_read = NXRD32(adapter, adapter->ahw.ms_win_crb); | ||
1462 | if (win_read != window) { | ||
1463 | printk(KERN_INFO "%s: Written MSwin (0x%x) != " | ||
1464 | "Read MSwin (0x%x)\n", | ||
1465 | __func__, window, win_read); | ||
1466 | } | ||
1467 | addr = GET_MEM_OFFS_2M(addr) + NETXEN_PCI_QDR_NET; | ||
1468 | 1410 | ||
1469 | } else { | 1411 | adapter->ahw.ocm_win = window; |
1470 | /* | 1412 | *start = NETXEN_PCI_OCM0_2M + GET_MEM_OFFS_2M(addr); |
1471 | * peg gdb frequently accesses memory that doesn't exist, | 1413 | return 0; |
1472 | * this limits the chit chat so debugging isn't slowed down. | ||
1473 | */ | ||
1474 | if ((netxen_pci_set_window_warning_count++ < 8) | ||
1475 | || (netxen_pci_set_window_warning_count%64 == 0)) { | ||
1476 | printk("%s: Warning:%s Unknown address range!\n", | ||
1477 | __func__, netxen_nic_driver_name); | ||
1478 | } | 1414 | } |
1479 | addr = -1UL; | 1415 | |
1416 | static int | ||
1417 | netxen_nic_pci_mem_access_direct(struct netxen_adapter *adapter, u64 off, | ||
1418 | u64 *data, int op) | ||
1419 | { | ||
1420 | void __iomem *addr, *mem_ptr = NULL; | ||
1421 | resource_size_t mem_base; | ||
1422 | int ret = -EIO; | ||
1423 | u32 start; | ||
1424 | |||
1425 | spin_lock(&adapter->ahw.mem_lock); | ||
1426 | |||
1427 | ret = adapter->pci_set_window(adapter, off, &start); | ||
1428 | if (ret != 0) | ||
1429 | goto unlock; | ||
1430 | |||
1431 | addr = pci_base_offset(adapter, start); | ||
1432 | if (addr) | ||
1433 | goto noremap; | ||
1434 | |||
1435 | mem_base = pci_resource_start(adapter->pdev, 0) + (start & PAGE_MASK); | ||
1436 | |||
1437 | mem_ptr = ioremap(mem_base, PAGE_SIZE); | ||
1438 | if (mem_ptr == NULL) { | ||
1439 | ret = -EIO; | ||
1440 | goto unlock; | ||
1480 | } | 1441 | } |
1481 | return addr; | 1442 | |
1443 | addr = mem_ptr + (start & (PAGE_SIZE - 1)); | ||
1444 | |||
1445 | noremap: | ||
1446 | if (op == 0) /* read */ | ||
1447 | *data = readq(addr); | ||
1448 | else /* write */ | ||
1449 | writeq(*data, addr); | ||
1450 | |||
1451 | unlock: | ||
1452 | spin_unlock(&adapter->ahw.mem_lock); | ||
1453 | |||
1454 | if (mem_ptr) | ||
1455 | iounmap(mem_ptr); | ||
1456 | return ret; | ||
1482 | } | 1457 | } |
1483 | 1458 | ||
1484 | #define MAX_CTL_CHECK 1000 | 1459 | #define MAX_CTL_CHECK 1000 |
1485 | 1460 | ||
1486 | static int | 1461 | static int |
1487 | netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, | 1462 | netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, |
1488 | u64 off, void *data, int size) | 1463 | u64 off, u64 data) |
1489 | { | 1464 | { |
1490 | unsigned long flags; | 1465 | int j, ret; |
1491 | int i, j, ret = 0, loop, sz[2], off0; | 1466 | u32 temp, off_lo, off_hi, addr_hi, data_hi, data_lo; |
1492 | uint32_t temp; | ||
1493 | uint64_t off8, tmpw, word[2] = {0, 0}; | ||
1494 | void __iomem *mem_crb; | 1467 | void __iomem *mem_crb; |
1495 | 1468 | ||
1496 | if (size != 8) | 1469 | /* Only 64-bit aligned access */ |
1470 | if (off & 7) | ||
1497 | return -EIO; | 1471 | return -EIO; |
1498 | 1472 | ||
1473 | /* P2 has different SIU and MIU test agent base addr */ | ||
1499 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, | 1474 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, |
1500 | NETXEN_ADDR_QDR_NET_MAX_P2)) { | 1475 | NETXEN_ADDR_QDR_NET_MAX_P2)) { |
1501 | mem_crb = pci_base_offset(adapter, NETXEN_CRB_QDR_NET); | 1476 | mem_crb = pci_base_offset(adapter, |
1477 | NETXEN_CRB_QDR_NET+SIU_TEST_AGT_BASE); | ||
1478 | addr_hi = SIU_TEST_AGT_ADDR_HI; | ||
1479 | data_lo = SIU_TEST_AGT_WRDATA_LO; | ||
1480 | data_hi = SIU_TEST_AGT_WRDATA_HI; | ||
1481 | off_lo = off & SIU_TEST_AGT_ADDR_MASK; | ||
1482 | off_hi = SIU_TEST_AGT_UPPER_ADDR(off); | ||
1502 | goto correct; | 1483 | goto correct; |
1503 | } | 1484 | } |
1504 | 1485 | ||
1505 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { | 1486 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { |
1506 | mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET); | 1487 | mem_crb = pci_base_offset(adapter, |
1488 | NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE); | ||
1489 | addr_hi = MIU_TEST_AGT_ADDR_HI; | ||
1490 | data_lo = MIU_TEST_AGT_WRDATA_LO; | ||
1491 | data_hi = MIU_TEST_AGT_WRDATA_HI; | ||
1492 | off_lo = off & MIU_TEST_AGT_ADDR_MASK; | ||
1493 | off_hi = 0; | ||
1507 | goto correct; | 1494 | goto correct; |
1508 | } | 1495 | } |
1509 | 1496 | ||
1510 | return -EIO; | 1497 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX) || |
1511 | 1498 | ADDR_IN_RANGE(off, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { | |
1512 | correct: | 1499 | if (adapter->ahw.pci_len0 != 0) { |
1513 | off8 = off & 0xfffffff8; | 1500 | return netxen_nic_pci_mem_access_direct(adapter, |
1514 | off0 = off & 0x7; | 1501 | off, &data, 1); |
1515 | sz[0] = (size < (8 - off0)) ? size : (8 - off0); | ||
1516 | sz[1] = size - sz[0]; | ||
1517 | loop = ((off0 + size - 1) >> 3) + 1; | ||
1518 | |||
1519 | if ((size != 8) || (off0 != 0)) { | ||
1520 | for (i = 0; i < loop; i++) { | ||
1521 | if (adapter->pci_mem_read(adapter, | ||
1522 | off8 + (i << 3), &word[i], 8)) | ||
1523 | return -1; | ||
1524 | } | 1502 | } |
1525 | } | 1503 | } |
1526 | 1504 | ||
1527 | switch (size) { | 1505 | return -EIO; |
1528 | case 1: | ||
1529 | tmpw = *((uint8_t *)data); | ||
1530 | break; | ||
1531 | case 2: | ||
1532 | tmpw = *((uint16_t *)data); | ||
1533 | break; | ||
1534 | case 4: | ||
1535 | tmpw = *((uint32_t *)data); | ||
1536 | break; | ||
1537 | case 8: | ||
1538 | default: | ||
1539 | tmpw = *((uint64_t *)data); | ||
1540 | break; | ||
1541 | } | ||
1542 | word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); | ||
1543 | word[0] |= tmpw << (off0 * 8); | ||
1544 | 1506 | ||
1545 | if (loop == 2) { | 1507 | correct: |
1546 | word[1] &= ~(~0ULL << (sz[1] * 8)); | 1508 | spin_lock(&adapter->ahw.mem_lock); |
1547 | word[1] |= tmpw >> (sz[0] * 8); | 1509 | netxen_nic_pci_set_crbwindow_128M(adapter, 0); |
1510 | |||
1511 | writel(off_lo, (mem_crb + MIU_TEST_AGT_ADDR_LO)); | ||
1512 | writel(off_hi, (mem_crb + addr_hi)); | ||
1513 | writel(data & 0xffffffff, (mem_crb + data_lo)); | ||
1514 | writel((data >> 32) & 0xffffffff, (mem_crb + data_hi)); | ||
1515 | writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL)); | ||
1516 | writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE), | ||
1517 | (mem_crb + TEST_AGT_CTRL)); | ||
1518 | |||
1519 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1520 | temp = readl((mem_crb + TEST_AGT_CTRL)); | ||
1521 | if ((temp & TA_CTL_BUSY) == 0) | ||
1522 | break; | ||
1548 | } | 1523 | } |
1549 | 1524 | ||
1550 | write_lock_irqsave(&adapter->adapter_lock, flags); | 1525 | if (j >= MAX_CTL_CHECK) { |
1551 | netxen_nic_pci_change_crbwindow_128M(adapter, 0); | 1526 | if (printk_ratelimit()) |
1552 | 1527 | dev_err(&adapter->pdev->dev, | |
1553 | for (i = 0; i < loop; i++) { | ||
1554 | writel((uint32_t)(off8 + (i << 3)), | ||
1555 | (mem_crb+MIU_TEST_AGT_ADDR_LO)); | ||
1556 | writel(0, | ||
1557 | (mem_crb+MIU_TEST_AGT_ADDR_HI)); | ||
1558 | writel(word[i] & 0xffffffff, | ||
1559 | (mem_crb+MIU_TEST_AGT_WRDATA_LO)); | ||
1560 | writel((word[i] >> 32) & 0xffffffff, | ||
1561 | (mem_crb+MIU_TEST_AGT_WRDATA_HI)); | ||
1562 | writel(MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE, | ||
1563 | (mem_crb+MIU_TEST_AGT_CTRL)); | ||
1564 | writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE|MIU_TA_CTL_WRITE, | ||
1565 | (mem_crb+MIU_TEST_AGT_CTRL)); | ||
1566 | |||
1567 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1568 | temp = readl( | ||
1569 | (mem_crb+MIU_TEST_AGT_CTRL)); | ||
1570 | if ((temp & MIU_TA_CTL_BUSY) == 0) | ||
1571 | break; | ||
1572 | } | ||
1573 | |||
1574 | if (j >= MAX_CTL_CHECK) { | ||
1575 | if (printk_ratelimit()) | ||
1576 | dev_err(&adapter->pdev->dev, | ||
1577 | "failed to write through agent\n"); | 1528 | "failed to write through agent\n"); |
1578 | ret = -1; | 1529 | ret = -EIO; |
1579 | break; | 1530 | } else |
1580 | } | 1531 | ret = 0; |
1581 | } | ||
1582 | 1532 | ||
1583 | netxen_nic_pci_change_crbwindow_128M(adapter, 1); | 1533 | netxen_nic_pci_set_crbwindow_128M(adapter, NETXEN_WINDOW_ONE); |
1584 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | 1534 | spin_unlock(&adapter->ahw.mem_lock); |
1585 | return ret; | 1535 | return ret; |
1586 | } | 1536 | } |
1587 | 1537 | ||
1588 | static int | 1538 | static int |
1589 | netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, | 1539 | netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, |
1590 | u64 off, void *data, int size) | 1540 | u64 off, u64 *data) |
1591 | { | 1541 | { |
1592 | unsigned long flags; | 1542 | int j, ret; |
1593 | int i, j = 0, k, start, end, loop, sz[2], off0[2]; | 1543 | u32 temp, off_lo, off_hi, addr_hi, data_hi, data_lo; |
1594 | uint32_t temp; | 1544 | u64 val; |
1595 | uint64_t off8, val, word[2] = {0, 0}; | ||
1596 | void __iomem *mem_crb; | 1545 | void __iomem *mem_crb; |
1597 | 1546 | ||
1598 | if (size != 8) | 1547 | /* Only 64-bit aligned access */ |
1548 | if (off & 7) | ||
1599 | return -EIO; | 1549 | return -EIO; |
1600 | 1550 | ||
1551 | /* P2 has different SIU and MIU test agent base addr */ | ||
1601 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, | 1552 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, |
1602 | NETXEN_ADDR_QDR_NET_MAX_P2)) { | 1553 | NETXEN_ADDR_QDR_NET_MAX_P2)) { |
1603 | mem_crb = pci_base_offset(adapter, NETXEN_CRB_QDR_NET); | 1554 | mem_crb = pci_base_offset(adapter, |
1555 | NETXEN_CRB_QDR_NET+SIU_TEST_AGT_BASE); | ||
1556 | addr_hi = SIU_TEST_AGT_ADDR_HI; | ||
1557 | data_lo = SIU_TEST_AGT_RDDATA_LO; | ||
1558 | data_hi = SIU_TEST_AGT_RDDATA_HI; | ||
1559 | off_lo = off & SIU_TEST_AGT_ADDR_MASK; | ||
1560 | off_hi = SIU_TEST_AGT_UPPER_ADDR(off); | ||
1604 | goto correct; | 1561 | goto correct; |
1605 | } | 1562 | } |
1606 | 1563 | ||
1607 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { | 1564 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { |
1608 | mem_crb = pci_base_offset(adapter, NETXEN_CRB_DDR_NET); | 1565 | mem_crb = pci_base_offset(adapter, |
1566 | NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE); | ||
1567 | addr_hi = MIU_TEST_AGT_ADDR_HI; | ||
1568 | data_lo = MIU_TEST_AGT_RDDATA_LO; | ||
1569 | data_hi = MIU_TEST_AGT_RDDATA_HI; | ||
1570 | off_lo = off & MIU_TEST_AGT_ADDR_MASK; | ||
1571 | off_hi = 0; | ||
1609 | goto correct; | 1572 | goto correct; |
1610 | } | 1573 | } |
1611 | 1574 | ||
1575 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX) || | ||
1576 | ADDR_IN_RANGE(off, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { | ||
1577 | if (adapter->ahw.pci_len0 != 0) { | ||
1578 | return netxen_nic_pci_mem_access_direct(adapter, | ||
1579 | off, data, 0); | ||
1580 | } | ||
1581 | } | ||
1582 | |||
1612 | return -EIO; | 1583 | return -EIO; |
1613 | 1584 | ||
1614 | correct: | 1585 | correct: |
1615 | off8 = off & 0xfffffff8; | 1586 | spin_lock(&adapter->ahw.mem_lock); |
1616 | off0[0] = off & 0x7; | 1587 | netxen_nic_pci_set_crbwindow_128M(adapter, 0); |
1617 | off0[1] = 0; | ||
1618 | sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]); | ||
1619 | sz[1] = size - sz[0]; | ||
1620 | loop = ((off0[0] + size - 1) >> 3) + 1; | ||
1621 | |||
1622 | write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1623 | netxen_nic_pci_change_crbwindow_128M(adapter, 0); | ||
1624 | |||
1625 | for (i = 0; i < loop; i++) { | ||
1626 | writel((uint32_t)(off8 + (i << 3)), | ||
1627 | (mem_crb+MIU_TEST_AGT_ADDR_LO)); | ||
1628 | writel(0, | ||
1629 | (mem_crb+MIU_TEST_AGT_ADDR_HI)); | ||
1630 | writel(MIU_TA_CTL_ENABLE, | ||
1631 | (mem_crb+MIU_TEST_AGT_CTRL)); | ||
1632 | writel(MIU_TA_CTL_START|MIU_TA_CTL_ENABLE, | ||
1633 | (mem_crb+MIU_TEST_AGT_CTRL)); | ||
1634 | 1588 | ||
1635 | for (j = 0; j < MAX_CTL_CHECK; j++) { | 1589 | writel(off_lo, (mem_crb + MIU_TEST_AGT_ADDR_LO)); |
1636 | temp = readl( | 1590 | writel(off_hi, (mem_crb + addr_hi)); |
1637 | (mem_crb+MIU_TEST_AGT_CTRL)); | 1591 | writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL)); |
1638 | if ((temp & MIU_TA_CTL_BUSY) == 0) | 1592 | writel((TA_CTL_START|TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL)); |
1639 | break; | ||
1640 | } | ||
1641 | 1593 | ||
1642 | if (j >= MAX_CTL_CHECK) { | 1594 | for (j = 0; j < MAX_CTL_CHECK; j++) { |
1643 | if (printk_ratelimit()) | 1595 | temp = readl(mem_crb + TEST_AGT_CTRL); |
1644 | dev_err(&adapter->pdev->dev, | 1596 | if ((temp & TA_CTL_BUSY) == 0) |
1645 | "failed to read through agent\n"); | ||
1646 | break; | 1597 | break; |
1647 | } | ||
1648 | |||
1649 | start = off0[i] >> 2; | ||
1650 | end = (off0[i] + sz[i] - 1) >> 2; | ||
1651 | for (k = start; k <= end; k++) { | ||
1652 | word[i] |= ((uint64_t) readl( | ||
1653 | (mem_crb + | ||
1654 | MIU_TEST_AGT_RDDATA(k))) << (32*k)); | ||
1655 | } | ||
1656 | } | 1598 | } |
1657 | 1599 | ||
1658 | netxen_nic_pci_change_crbwindow_128M(adapter, 1); | 1600 | if (j >= MAX_CTL_CHECK) { |
1659 | write_unlock_irqrestore(&adapter->adapter_lock, flags); | 1601 | if (printk_ratelimit()) |
1660 | 1602 | dev_err(&adapter->pdev->dev, | |
1661 | if (j >= MAX_CTL_CHECK) | 1603 | "failed to read through agent\n"); |
1662 | return -1; | 1604 | ret = -EIO; |
1663 | |||
1664 | if (sz[0] == 8) { | ||
1665 | val = word[0]; | ||
1666 | } else { | 1605 | } else { |
1667 | val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) | | ||
1668 | ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8)); | ||
1669 | } | ||
1670 | 1606 | ||
1671 | switch (size) { | 1607 | temp = readl(mem_crb + data_hi); |
1672 | case 1: | 1608 | val = ((u64)temp << 32); |
1673 | *(uint8_t *)data = val; | 1609 | val |= readl(mem_crb + data_lo); |
1674 | break; | 1610 | *data = val; |
1675 | case 2: | 1611 | ret = 0; |
1676 | *(uint16_t *)data = val; | ||
1677 | break; | ||
1678 | case 4: | ||
1679 | *(uint32_t *)data = val; | ||
1680 | break; | ||
1681 | case 8: | ||
1682 | *(uint64_t *)data = val; | ||
1683 | break; | ||
1684 | } | 1612 | } |
1685 | return 0; | 1613 | |
1614 | netxen_nic_pci_set_crbwindow_128M(adapter, NETXEN_WINDOW_ONE); | ||
1615 | spin_unlock(&adapter->ahw.mem_lock); | ||
1616 | |||
1617 | return ret; | ||
1686 | } | 1618 | } |
1687 | 1619 | ||
1688 | static int | 1620 | static int |
1689 | netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, | 1621 | netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, |
1690 | u64 off, void *data, int size) | 1622 | u64 off, u64 data) |
1691 | { | 1623 | { |
1692 | int i, j, ret = 0, loop, sz[2], off0; | 1624 | int i, j, ret; |
1693 | uint32_t temp; | 1625 | u32 temp, off8; |
1694 | uint64_t off8, tmpw, word[2] = {0, 0}; | 1626 | u64 stride; |
1695 | void __iomem *mem_crb; | 1627 | void __iomem *mem_crb; |
1696 | 1628 | ||
1697 | if (size != 8) | 1629 | /* Only 64-bit aligned access */ |
1630 | if (off & 7) | ||
1698 | return -EIO; | 1631 | return -EIO; |
1699 | 1632 | ||
1633 | /* P3 onward, test agent base for MIU and SIU is same */ | ||
1700 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, | 1634 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, |
1701 | NETXEN_ADDR_QDR_NET_MAX_P3)) { | 1635 | NETXEN_ADDR_QDR_NET_MAX_P3)) { |
1702 | mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_QDR_NET); | 1636 | mem_crb = netxen_get_ioaddr(adapter, |
1637 | NETXEN_CRB_QDR_NET+MIU_TEST_AGT_BASE); | ||
1703 | goto correct; | 1638 | goto correct; |
1704 | } | 1639 | } |
1705 | 1640 | ||
1706 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { | 1641 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { |
1707 | mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_DDR_NET); | 1642 | mem_crb = netxen_get_ioaddr(adapter, |
1643 | NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE); | ||
1708 | goto correct; | 1644 | goto correct; |
1709 | } | 1645 | } |
1710 | 1646 | ||
1647 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) | ||
1648 | return netxen_nic_pci_mem_access_direct(adapter, off, &data, 1); | ||
1649 | |||
1711 | return -EIO; | 1650 | return -EIO; |
1712 | 1651 | ||
1713 | correct: | 1652 | correct: |
1714 | off8 = off & 0xfffffff8; | 1653 | stride = NX_IS_REVISION_P3P(adapter->ahw.revision_id) ? 16 : 8; |
1715 | off0 = off & 0x7; | ||
1716 | sz[0] = (size < (8 - off0)) ? size : (8 - off0); | ||
1717 | sz[1] = size - sz[0]; | ||
1718 | loop = ((off0 + size - 1) >> 3) + 1; | ||
1719 | |||
1720 | if ((size != 8) || (off0 != 0)) { | ||
1721 | for (i = 0; i < loop; i++) { | ||
1722 | if (adapter->pci_mem_read(adapter, | ||
1723 | off8 + (i << 3), &word[i], 8)) | ||
1724 | return -1; | ||
1725 | } | ||
1726 | } | ||
1727 | 1654 | ||
1728 | switch (size) { | 1655 | off8 = off & ~(stride-1); |
1729 | case 1: | ||
1730 | tmpw = *((uint8_t *)data); | ||
1731 | break; | ||
1732 | case 2: | ||
1733 | tmpw = *((uint16_t *)data); | ||
1734 | break; | ||
1735 | case 4: | ||
1736 | tmpw = *((uint32_t *)data); | ||
1737 | break; | ||
1738 | case 8: | ||
1739 | default: | ||
1740 | tmpw = *((uint64_t *)data); | ||
1741 | break; | ||
1742 | } | ||
1743 | 1656 | ||
1744 | word[0] &= ~((~(~0ULL << (sz[0] * 8))) << (off0 * 8)); | 1657 | spin_lock(&adapter->ahw.mem_lock); |
1745 | word[0] |= tmpw << (off0 * 8); | ||
1746 | 1658 | ||
1747 | if (loop == 2) { | 1659 | writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO)); |
1748 | word[1] &= ~(~0ULL << (sz[1] * 8)); | 1660 | writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI)); |
1749 | word[1] |= tmpw >> (sz[0] * 8); | ||
1750 | } | ||
1751 | |||
1752 | /* | ||
1753 | * don't lock here - write_wx gets the lock if each time | ||
1754 | * write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1755 | * netxen_nic_pci_change_crbwindow_128M(adapter, 0); | ||
1756 | */ | ||
1757 | 1661 | ||
1758 | for (i = 0; i < loop; i++) { | 1662 | i = 0; |
1759 | writel(off8 + (i << 3), mem_crb+MIU_TEST_AGT_ADDR_LO); | 1663 | if (stride == 16) { |
1760 | writel(0, mem_crb+MIU_TEST_AGT_ADDR_HI); | 1664 | writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL)); |
1761 | writel(word[i] & 0xffffffff, mem_crb+MIU_TEST_AGT_WRDATA_LO); | 1665 | writel((TA_CTL_START | TA_CTL_ENABLE), |
1762 | writel((word[i] >> 32) & 0xffffffff, | 1666 | (mem_crb + TEST_AGT_CTRL)); |
1763 | mem_crb+MIU_TEST_AGT_WRDATA_HI); | ||
1764 | writel((MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE), | ||
1765 | mem_crb+MIU_TEST_AGT_CTRL); | ||
1766 | writel(MIU_TA_CTL_START | MIU_TA_CTL_ENABLE | MIU_TA_CTL_WRITE, | ||
1767 | mem_crb+MIU_TEST_AGT_CTRL); | ||
1768 | 1667 | ||
1769 | for (j = 0; j < MAX_CTL_CHECK; j++) { | 1668 | for (j = 0; j < MAX_CTL_CHECK; j++) { |
1770 | temp = readl(mem_crb + MIU_TEST_AGT_CTRL); | 1669 | temp = readl(mem_crb + TEST_AGT_CTRL); |
1771 | if ((temp & MIU_TA_CTL_BUSY) == 0) | 1670 | if ((temp & TA_CTL_BUSY) == 0) |
1772 | break; | 1671 | break; |
1773 | } | 1672 | } |
1774 | 1673 | ||
1775 | if (j >= MAX_CTL_CHECK) { | 1674 | if (j >= MAX_CTL_CHECK) { |
1776 | if (printk_ratelimit()) | 1675 | ret = -EIO; |
1777 | dev_err(&adapter->pdev->dev, | 1676 | goto done; |
1778 | "failed to write through agent\n"); | ||
1779 | ret = -1; | ||
1780 | break; | ||
1781 | } | 1677 | } |
1678 | |||
1679 | i = (off & 0xf) ? 0 : 2; | ||
1680 | writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i)), | ||
1681 | mem_crb + MIU_TEST_AGT_WRDATA(i)); | ||
1682 | writel(readl(mem_crb + MIU_TEST_AGT_RDDATA(i+1)), | ||
1683 | mem_crb + MIU_TEST_AGT_WRDATA(i+1)); | ||
1684 | i = (off & 0xf) ? 2 : 0; | ||
1782 | } | 1685 | } |
1783 | 1686 | ||
1784 | /* | 1687 | writel(data & 0xffffffff, |
1785 | * netxen_nic_pci_change_crbwindow_128M(adapter, 1); | 1688 | mem_crb + MIU_TEST_AGT_WRDATA(i)); |
1786 | * write_unlock_irqrestore(&adapter->adapter_lock, flags); | 1689 | writel((data >> 32) & 0xffffffff, |
1787 | */ | 1690 | mem_crb + MIU_TEST_AGT_WRDATA(i+1)); |
1691 | |||
1692 | writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL)); | ||
1693 | writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE), | ||
1694 | (mem_crb + TEST_AGT_CTRL)); | ||
1695 | |||
1696 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1697 | temp = readl(mem_crb + TEST_AGT_CTRL); | ||
1698 | if ((temp & TA_CTL_BUSY) == 0) | ||
1699 | break; | ||
1700 | } | ||
1701 | |||
1702 | if (j >= MAX_CTL_CHECK) { | ||
1703 | if (printk_ratelimit()) | ||
1704 | dev_err(&adapter->pdev->dev, | ||
1705 | "failed to write through agent\n"); | ||
1706 | ret = -EIO; | ||
1707 | } else | ||
1708 | ret = 0; | ||
1709 | |||
1710 | done: | ||
1711 | spin_unlock(&adapter->ahw.mem_lock); | ||
1712 | |||
1788 | return ret; | 1713 | return ret; |
1789 | } | 1714 | } |
1790 | 1715 | ||
1791 | static int | 1716 | static int |
1792 | netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, | 1717 | netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, |
1793 | u64 off, void *data, int size) | 1718 | u64 off, u64 *data) |
1794 | { | 1719 | { |
1795 | int i, j = 0, k, start, end, loop, sz[2], off0[2]; | 1720 | int j, ret; |
1796 | uint32_t temp; | 1721 | u32 temp, off8; |
1797 | uint64_t off8, val, word[2] = {0, 0}; | 1722 | u64 val, stride; |
1798 | void __iomem *mem_crb; | 1723 | void __iomem *mem_crb; |
1799 | 1724 | ||
1800 | if (size != 8) | 1725 | /* Only 64-bit aligned access */ |
1726 | if (off & 7) | ||
1801 | return -EIO; | 1727 | return -EIO; |
1802 | 1728 | ||
1729 | /* P3 onward, test agent base for MIU and SIU is same */ | ||
1803 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, | 1730 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, |
1804 | NETXEN_ADDR_QDR_NET_MAX_P3)) { | 1731 | NETXEN_ADDR_QDR_NET_MAX_P3)) { |
1805 | mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_QDR_NET); | 1732 | mem_crb = netxen_get_ioaddr(adapter, |
1733 | NETXEN_CRB_QDR_NET+MIU_TEST_AGT_BASE); | ||
1806 | goto correct; | 1734 | goto correct; |
1807 | } | 1735 | } |
1808 | 1736 | ||
1809 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { | 1737 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { |
1810 | mem_crb = netxen_get_ioaddr(adapter, NETXEN_CRB_DDR_NET); | 1738 | mem_crb = netxen_get_ioaddr(adapter, |
1739 | NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE); | ||
1811 | goto correct; | 1740 | goto correct; |
1812 | } | 1741 | } |
1813 | 1742 | ||
1743 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { | ||
1744 | return netxen_nic_pci_mem_access_direct(adapter, | ||
1745 | off, data, 0); | ||
1746 | } | ||
1747 | |||
1814 | return -EIO; | 1748 | return -EIO; |
1815 | 1749 | ||
1816 | correct: | 1750 | correct: |
1817 | off8 = off & 0xfffffff8; | 1751 | stride = NX_IS_REVISION_P3P(adapter->ahw.revision_id) ? 16 : 8; |
1818 | off0[0] = off & 0x7; | ||
1819 | off0[1] = 0; | ||
1820 | sz[0] = (size < (8 - off0[0])) ? size : (8 - off0[0]); | ||
1821 | sz[1] = size - sz[0]; | ||
1822 | loop = ((off0[0] + size - 1) >> 3) + 1; | ||
1823 | 1752 | ||
1824 | /* | 1753 | off8 = off & ~(stride-1); |
1825 | * don't lock here - write_wx gets the lock if each time | ||
1826 | * write_lock_irqsave(&adapter->adapter_lock, flags); | ||
1827 | * netxen_nic_pci_change_crbwindow_128M(adapter, 0); | ||
1828 | */ | ||
1829 | 1754 | ||
1830 | for (i = 0; i < loop; i++) { | 1755 | spin_lock(&adapter->ahw.mem_lock); |
1831 | writel(off8 + (i << 3), mem_crb + MIU_TEST_AGT_ADDR_LO); | ||
1832 | writel(0, mem_crb + MIU_TEST_AGT_ADDR_HI); | ||
1833 | writel(MIU_TA_CTL_ENABLE, mem_crb + MIU_TEST_AGT_CTRL); | ||
1834 | writel(MIU_TA_CTL_START | MIU_TA_CTL_ENABLE, | ||
1835 | mem_crb + MIU_TEST_AGT_CTRL); | ||
1836 | 1756 | ||
1837 | for (j = 0; j < MAX_CTL_CHECK; j++) { | 1757 | writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO)); |
1838 | temp = readl(mem_crb + MIU_TEST_AGT_CTRL); | 1758 | writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI)); |
1839 | if ((temp & MIU_TA_CTL_BUSY) == 0) | 1759 | writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL)); |
1840 | break; | 1760 | writel((TA_CTL_START | TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL)); |
1841 | } | ||
1842 | 1761 | ||
1843 | if (j >= MAX_CTL_CHECK) { | 1762 | for (j = 0; j < MAX_CTL_CHECK; j++) { |
1844 | if (printk_ratelimit()) | 1763 | temp = readl(mem_crb + TEST_AGT_CTRL); |
1845 | dev_err(&adapter->pdev->dev, | 1764 | if ((temp & TA_CTL_BUSY) == 0) |
1846 | "failed to read through agent\n"); | ||
1847 | break; | 1765 | break; |
1848 | } | ||
1849 | |||
1850 | start = off0[i] >> 2; | ||
1851 | end = (off0[i] + sz[i] - 1) >> 2; | ||
1852 | for (k = start; k <= end; k++) { | ||
1853 | temp = readl(mem_crb + MIU_TEST_AGT_RDDATA(k)); | ||
1854 | word[i] |= ((uint64_t)temp << (32 * k)); | ||
1855 | } | ||
1856 | } | 1766 | } |
1857 | 1767 | ||
1858 | /* | 1768 | if (j >= MAX_CTL_CHECK) { |
1859 | * netxen_nic_pci_change_crbwindow_128M(adapter, 1); | 1769 | if (printk_ratelimit()) |
1860 | * write_unlock_irqrestore(&adapter->adapter_lock, flags); | 1770 | dev_err(&adapter->pdev->dev, |
1861 | */ | 1771 | "failed to read through agent\n"); |
1862 | 1772 | ret = -EIO; | |
1863 | if (j >= MAX_CTL_CHECK) | ||
1864 | return -1; | ||
1865 | |||
1866 | if (sz[0] == 8) { | ||
1867 | val = word[0]; | ||
1868 | } else { | 1773 | } else { |
1869 | val = ((word[0] >> (off0[0] * 8)) & (~(~0ULL << (sz[0] * 8)))) | | 1774 | off8 = MIU_TEST_AGT_RDDATA_LO; |
1870 | ((word[1] & (~(~0ULL << (sz[1] * 8)))) << (sz[0] * 8)); | 1775 | if ((stride == 16) && (off & 0xf)) |
1871 | } | 1776 | off8 = MIU_TEST_AGT_RDDATA_UPPER_LO; |
1872 | 1777 | ||
1873 | switch (size) { | 1778 | temp = readl(mem_crb + off8 + 4); |
1874 | case 1: | 1779 | val = (u64)temp << 32; |
1875 | *(uint8_t *)data = val; | 1780 | val |= readl(mem_crb + off8); |
1876 | break; | 1781 | *data = val; |
1877 | case 2: | 1782 | ret = 0; |
1878 | *(uint16_t *)data = val; | ||
1879 | break; | ||
1880 | case 4: | ||
1881 | *(uint32_t *)data = val; | ||
1882 | break; | ||
1883 | case 8: | ||
1884 | *(uint64_t *)data = val; | ||
1885 | break; | ||
1886 | } | 1783 | } |
1887 | return 0; | 1784 | |
1785 | spin_unlock(&adapter->ahw.mem_lock); | ||
1786 | |||
1787 | return ret; | ||
1888 | } | 1788 | } |
1889 | 1789 | ||
1890 | void | 1790 | void |
@@ -2037,10 +1937,10 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) | |||
2037 | return; | 1937 | return; |
2038 | } | 1938 | } |
2039 | 1939 | ||
2040 | if (adapter->phy_read | 1940 | if (adapter->phy_read && |
2041 | && adapter->phy_read(adapter, | 1941 | adapter->phy_read(adapter, |
2042 | NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, | 1942 | NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, |
2043 | &status) == 0) { | 1943 | &status) == 0) { |
2044 | if (netxen_get_phy_link(status)) { | 1944 | if (netxen_get_phy_link(status)) { |
2045 | switch (netxen_get_phy_speed(status)) { | 1945 | switch (netxen_get_phy_speed(status)) { |
2046 | case 0: | 1946 | case 0: |
@@ -2067,10 +1967,10 @@ void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) | |||
2067 | adapter->link_duplex = -1; | 1967 | adapter->link_duplex = -1; |
2068 | break; | 1968 | break; |
2069 | } | 1969 | } |
2070 | if (adapter->phy_read | 1970 | if (adapter->phy_read && |
2071 | && adapter->phy_read(adapter, | 1971 | adapter->phy_read(adapter, |
2072 | NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG, | 1972 | NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG, |
2073 | &autoneg) != 0) | 1973 | &autoneg) != 0) |
2074 | adapter->link_autoneg = autoneg; | 1974 | adapter->link_autoneg = autoneg; |
2075 | } else | 1975 | } else |
2076 | goto link_down; | 1976 | goto link_down; |