diff options
Diffstat (limited to 'drivers/net/netxen/netxen_nic_hw.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_hw.c | 1976 |
1 files changed, 1976 insertions, 0 deletions
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c new file mode 100644 index 00000000000..3f89e57cae5 --- /dev/null +++ b/drivers/net/netxen/netxen_nic_hw.c | |||
@@ -0,0 +1,1976 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2003 - 2009 NetXen, Inc. | ||
3 | * Copyright (C) 2009 - QLogic Corporation. | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but | ||
12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, | ||
19 | * MA 02111-1307, USA. | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution | ||
22 | * in the file called "COPYING". | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <linux/slab.h> | ||
27 | #include "netxen_nic.h" | ||
28 | #include "netxen_nic_hw.h" | ||
29 | |||
30 | #include <net/ip.h> | ||
31 | |||
32 | #define MASK(n) ((1ULL<<(n))-1) | ||
33 | #define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | ((addr >> 25) & 0x3ff)) | ||
34 | #define OCM_WIN(addr) (((addr & 0x1ff0000) >> 1) | ((addr >> 25) & 0x3ff)) | ||
35 | #define MS_WIN(addr) (addr & 0x0ffc0000) | ||
36 | |||
37 | #define GET_MEM_OFFS_2M(addr) (addr & MASK(18)) | ||
38 | |||
39 | #define CRB_BLK(off) ((off >> 20) & 0x3f) | ||
40 | #define CRB_SUBBLK(off) ((off >> 16) & 0xf) | ||
41 | #define CRB_WINDOW_2M (0x130060) | ||
42 | #define CRB_HI(off) ((crb_hub_agt[CRB_BLK(off)] << 20) | ((off) & 0xf0000)) | ||
43 | #define CRB_INDIRECT_2M (0x1e0000UL) | ||
44 | |||
45 | static void netxen_nic_io_write_128M(struct netxen_adapter *adapter, | ||
46 | void __iomem *addr, u32 data); | ||
47 | static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, | ||
48 | void __iomem *addr); | ||
49 | |||
50 | #ifndef readq | ||
51 | static inline u64 readq(void __iomem *addr) | ||
52 | { | ||
53 | return readl(addr) | (((u64) readl(addr + 4)) << 32LL); | ||
54 | } | ||
55 | #endif | ||
56 | |||
57 | #ifndef writeq | ||
58 | static inline void writeq(u64 val, void __iomem *addr) | ||
59 | { | ||
60 | writel(((u32) (val)), (addr)); | ||
61 | writel(((u32) (val >> 32)), (addr + 4)); | ||
62 | } | ||
63 | #endif | ||
64 | |||
65 | #define PCI_OFFSET_FIRST_RANGE(adapter, off) \ | ||
66 | ((adapter)->ahw.pci_base0 + (off)) | ||
67 | #define PCI_OFFSET_SECOND_RANGE(adapter, off) \ | ||
68 | ((adapter)->ahw.pci_base1 + (off) - SECOND_PAGE_GROUP_START) | ||
69 | #define PCI_OFFSET_THIRD_RANGE(adapter, off) \ | ||
70 | ((adapter)->ahw.pci_base2 + (off) - THIRD_PAGE_GROUP_START) | ||
71 | |||
72 | static void __iomem *pci_base_offset(struct netxen_adapter *adapter, | ||
73 | unsigned long off) | ||
74 | { | ||
75 | if (ADDR_IN_RANGE(off, FIRST_PAGE_GROUP_START, FIRST_PAGE_GROUP_END)) | ||
76 | return PCI_OFFSET_FIRST_RANGE(adapter, off); | ||
77 | |||
78 | if (ADDR_IN_RANGE(off, SECOND_PAGE_GROUP_START, SECOND_PAGE_GROUP_END)) | ||
79 | return PCI_OFFSET_SECOND_RANGE(adapter, off); | ||
80 | |||
81 | if (ADDR_IN_RANGE(off, THIRD_PAGE_GROUP_START, THIRD_PAGE_GROUP_END)) | ||
82 | return PCI_OFFSET_THIRD_RANGE(adapter, off); | ||
83 | |||
84 | return NULL; | ||
85 | } | ||
86 | |||
87 | static crb_128M_2M_block_map_t | ||
88 | crb_128M_2M_map[64] __cacheline_aligned_in_smp = { | ||
89 | {{{0, 0, 0, 0} } }, /* 0: PCI */ | ||
90 | {{{1, 0x0100000, 0x0102000, 0x120000}, /* 1: PCIE */ | ||
91 | {1, 0x0110000, 0x0120000, 0x130000}, | ||
92 | {1, 0x0120000, 0x0122000, 0x124000}, | ||
93 | {1, 0x0130000, 0x0132000, 0x126000}, | ||
94 | {1, 0x0140000, 0x0142000, 0x128000}, | ||
95 | {1, 0x0150000, 0x0152000, 0x12a000}, | ||
96 | {1, 0x0160000, 0x0170000, 0x110000}, | ||
97 | {1, 0x0170000, 0x0172000, 0x12e000}, | ||
98 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
99 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
100 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
101 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
102 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
103 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
104 | {1, 0x01e0000, 0x01e0800, 0x122000}, | ||
105 | {0, 0x0000000, 0x0000000, 0x000000} } }, | ||
106 | {{{1, 0x0200000, 0x0210000, 0x180000} } },/* 2: MN */ | ||
107 | {{{0, 0, 0, 0} } }, /* 3: */ | ||
108 | {{{1, 0x0400000, 0x0401000, 0x169000} } },/* 4: P2NR1 */ | ||
109 | {{{1, 0x0500000, 0x0510000, 0x140000} } },/* 5: SRE */ | ||
110 | {{{1, 0x0600000, 0x0610000, 0x1c0000} } },/* 6: NIU */ | ||
111 | {{{1, 0x0700000, 0x0704000, 0x1b8000} } },/* 7: QM */ | ||
112 | {{{1, 0x0800000, 0x0802000, 0x170000}, /* 8: SQM0 */ | ||
113 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
114 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
115 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
116 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
117 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
118 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
119 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
120 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
121 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
122 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
123 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
124 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
125 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
126 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
127 | {1, 0x08f0000, 0x08f2000, 0x172000} } }, | ||
128 | {{{1, 0x0900000, 0x0902000, 0x174000}, /* 9: SQM1*/ | ||
129 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
130 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
131 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
132 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
133 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
134 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
135 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
136 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
137 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
138 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
139 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
140 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
141 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
142 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
143 | {1, 0x09f0000, 0x09f2000, 0x176000} } }, | ||
144 | {{{0, 0x0a00000, 0x0a02000, 0x178000}, /* 10: SQM2*/ | ||
145 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
146 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
147 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
148 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
149 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
150 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
151 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
152 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
153 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
154 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
155 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
156 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
157 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
158 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
159 | {1, 0x0af0000, 0x0af2000, 0x17a000} } }, | ||
160 | {{{0, 0x0b00000, 0x0b02000, 0x17c000}, /* 11: SQM3*/ | ||
161 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
162 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
163 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
164 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
165 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
166 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
167 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
168 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
169 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
170 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
171 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
172 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
173 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
174 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
175 | {1, 0x0bf0000, 0x0bf2000, 0x17e000} } }, | ||
176 | {{{1, 0x0c00000, 0x0c04000, 0x1d4000} } },/* 12: I2Q */ | ||
177 | {{{1, 0x0d00000, 0x0d04000, 0x1a4000} } },/* 13: TMR */ | ||
178 | {{{1, 0x0e00000, 0x0e04000, 0x1a0000} } },/* 14: ROMUSB */ | ||
179 | {{{1, 0x0f00000, 0x0f01000, 0x164000} } },/* 15: PEG4 */ | ||
180 | {{{0, 0x1000000, 0x1004000, 0x1a8000} } },/* 16: XDMA */ | ||
181 | {{{1, 0x1100000, 0x1101000, 0x160000} } },/* 17: PEG0 */ | ||
182 | {{{1, 0x1200000, 0x1201000, 0x161000} } },/* 18: PEG1 */ | ||
183 | {{{1, 0x1300000, 0x1301000, 0x162000} } },/* 19: PEG2 */ | ||
184 | {{{1, 0x1400000, 0x1401000, 0x163000} } },/* 20: PEG3 */ | ||
185 | {{{1, 0x1500000, 0x1501000, 0x165000} } },/* 21: P2ND */ | ||
186 | {{{1, 0x1600000, 0x1601000, 0x166000} } },/* 22: P2NI */ | ||
187 | {{{0, 0, 0, 0} } }, /* 23: */ | ||
188 | {{{0, 0, 0, 0} } }, /* 24: */ | ||
189 | {{{0, 0, 0, 0} } }, /* 25: */ | ||
190 | {{{0, 0, 0, 0} } }, /* 26: */ | ||
191 | {{{0, 0, 0, 0} } }, /* 27: */ | ||
192 | {{{0, 0, 0, 0} } }, /* 28: */ | ||
193 | {{{1, 0x1d00000, 0x1d10000, 0x190000} } },/* 29: MS */ | ||
194 | {{{1, 0x1e00000, 0x1e01000, 0x16a000} } },/* 30: P2NR2 */ | ||
195 | {{{1, 0x1f00000, 0x1f10000, 0x150000} } },/* 31: EPG */ | ||
196 | {{{0} } }, /* 32: PCI */ | ||
197 | {{{1, 0x2100000, 0x2102000, 0x120000}, /* 33: PCIE */ | ||
198 | {1, 0x2110000, 0x2120000, 0x130000}, | ||
199 | {1, 0x2120000, 0x2122000, 0x124000}, | ||
200 | {1, 0x2130000, 0x2132000, 0x126000}, | ||
201 | {1, 0x2140000, 0x2142000, 0x128000}, | ||
202 | {1, 0x2150000, 0x2152000, 0x12a000}, | ||
203 | {1, 0x2160000, 0x2170000, 0x110000}, | ||
204 | {1, 0x2170000, 0x2172000, 0x12e000}, | ||
205 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
206 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
207 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
208 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
209 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
210 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
211 | {0, 0x0000000, 0x0000000, 0x000000}, | ||
212 | {0, 0x0000000, 0x0000000, 0x000000} } }, | ||
213 | {{{1, 0x2200000, 0x2204000, 0x1b0000} } },/* 34: CAM */ | ||
214 | {{{0} } }, /* 35: */ | ||
215 | {{{0} } }, /* 36: */ | ||
216 | {{{0} } }, /* 37: */ | ||
217 | {{{0} } }, /* 38: */ | ||
218 | {{{0} } }, /* 39: */ | ||
219 | {{{1, 0x2800000, 0x2804000, 0x1a4000} } },/* 40: TMR */ | ||
220 | {{{1, 0x2900000, 0x2901000, 0x16b000} } },/* 41: P2NR3 */ | ||
221 | {{{1, 0x2a00000, 0x2a00400, 0x1ac400} } },/* 42: RPMX1 */ | ||
222 | {{{1, 0x2b00000, 0x2b00400, 0x1ac800} } },/* 43: RPMX2 */ | ||
223 | {{{1, 0x2c00000, 0x2c00400, 0x1acc00} } },/* 44: RPMX3 */ | ||
224 | {{{1, 0x2d00000, 0x2d00400, 0x1ad000} } },/* 45: RPMX4 */ | ||
225 | {{{1, 0x2e00000, 0x2e00400, 0x1ad400} } },/* 46: RPMX5 */ | ||
226 | {{{1, 0x2f00000, 0x2f00400, 0x1ad800} } },/* 47: RPMX6 */ | ||
227 | {{{1, 0x3000000, 0x3000400, 0x1adc00} } },/* 48: RPMX7 */ | ||
228 | {{{0, 0x3100000, 0x3104000, 0x1a8000} } },/* 49: XDMA */ | ||
229 | {{{1, 0x3200000, 0x3204000, 0x1d4000} } },/* 50: I2Q */ | ||
230 | {{{1, 0x3300000, 0x3304000, 0x1a0000} } },/* 51: ROMUSB */ | ||
231 | {{{0} } }, /* 52: */ | ||
232 | {{{1, 0x3500000, 0x3500400, 0x1ac000} } },/* 53: RPMX0 */ | ||
233 | {{{1, 0x3600000, 0x3600400, 0x1ae000} } },/* 54: RPMX8 */ | ||
234 | {{{1, 0x3700000, 0x3700400, 0x1ae400} } },/* 55: RPMX9 */ | ||
235 | {{{1, 0x3800000, 0x3804000, 0x1d0000} } },/* 56: OCM0 */ | ||
236 | {{{1, 0x3900000, 0x3904000, 0x1b4000} } },/* 57: CRYPTO */ | ||
237 | {{{1, 0x3a00000, 0x3a04000, 0x1d8000} } },/* 58: SMB */ | ||
238 | {{{0} } }, /* 59: I2C0 */ | ||
239 | {{{0} } }, /* 60: I2C1 */ | ||
240 | {{{1, 0x3d00000, 0x3d04000, 0x1d8000} } },/* 61: LPC */ | ||
241 | {{{1, 0x3e00000, 0x3e01000, 0x167000} } },/* 62: P2NC */ | ||
242 | {{{1, 0x3f00000, 0x3f01000, 0x168000} } } /* 63: P2NR0 */ | ||
243 | }; | ||
244 | |||
245 | /* | ||
246 | * top 12 bits of crb internal address (hub, agent) | ||
247 | */ | ||
248 | static unsigned crb_hub_agt[64] = | ||
249 | { | ||
250 | 0, | ||
251 | NETXEN_HW_CRB_HUB_AGT_ADR_PS, | ||
252 | NETXEN_HW_CRB_HUB_AGT_ADR_MN, | ||
253 | NETXEN_HW_CRB_HUB_AGT_ADR_MS, | ||
254 | 0, | ||
255 | NETXEN_HW_CRB_HUB_AGT_ADR_SRE, | ||
256 | NETXEN_HW_CRB_HUB_AGT_ADR_NIU, | ||
257 | NETXEN_HW_CRB_HUB_AGT_ADR_QMN, | ||
258 | NETXEN_HW_CRB_HUB_AGT_ADR_SQN0, | ||
259 | NETXEN_HW_CRB_HUB_AGT_ADR_SQN1, | ||
260 | NETXEN_HW_CRB_HUB_AGT_ADR_SQN2, | ||
261 | NETXEN_HW_CRB_HUB_AGT_ADR_SQN3, | ||
262 | NETXEN_HW_CRB_HUB_AGT_ADR_I2Q, | ||
263 | NETXEN_HW_CRB_HUB_AGT_ADR_TIMR, | ||
264 | NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB, | ||
265 | NETXEN_HW_CRB_HUB_AGT_ADR_PGN4, | ||
266 | NETXEN_HW_CRB_HUB_AGT_ADR_XDMA, | ||
267 | NETXEN_HW_CRB_HUB_AGT_ADR_PGN0, | ||
268 | NETXEN_HW_CRB_HUB_AGT_ADR_PGN1, | ||
269 | NETXEN_HW_CRB_HUB_AGT_ADR_PGN2, | ||
270 | NETXEN_HW_CRB_HUB_AGT_ADR_PGN3, | ||
271 | NETXEN_HW_CRB_HUB_AGT_ADR_PGND, | ||
272 | NETXEN_HW_CRB_HUB_AGT_ADR_PGNI, | ||
273 | NETXEN_HW_CRB_HUB_AGT_ADR_PGS0, | ||
274 | NETXEN_HW_CRB_HUB_AGT_ADR_PGS1, | ||
275 | NETXEN_HW_CRB_HUB_AGT_ADR_PGS2, | ||
276 | NETXEN_HW_CRB_HUB_AGT_ADR_PGS3, | ||
277 | 0, | ||
278 | NETXEN_HW_CRB_HUB_AGT_ADR_PGSI, | ||
279 | NETXEN_HW_CRB_HUB_AGT_ADR_SN, | ||
280 | 0, | ||
281 | NETXEN_HW_CRB_HUB_AGT_ADR_EG, | ||
282 | 0, | ||
283 | NETXEN_HW_CRB_HUB_AGT_ADR_PS, | ||
284 | NETXEN_HW_CRB_HUB_AGT_ADR_CAM, | ||
285 | 0, | ||
286 | 0, | ||
287 | 0, | ||
288 | 0, | ||
289 | 0, | ||
290 | NETXEN_HW_CRB_HUB_AGT_ADR_TIMR, | ||
291 | 0, | ||
292 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX1, | ||
293 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX2, | ||
294 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX3, | ||
295 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX4, | ||
296 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX5, | ||
297 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX6, | ||
298 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX7, | ||
299 | NETXEN_HW_CRB_HUB_AGT_ADR_XDMA, | ||
300 | NETXEN_HW_CRB_HUB_AGT_ADR_I2Q, | ||
301 | NETXEN_HW_CRB_HUB_AGT_ADR_ROMUSB, | ||
302 | 0, | ||
303 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX0, | ||
304 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX8, | ||
305 | NETXEN_HW_CRB_HUB_AGT_ADR_RPMX9, | ||
306 | NETXEN_HW_CRB_HUB_AGT_ADR_OCM0, | ||
307 | 0, | ||
308 | NETXEN_HW_CRB_HUB_AGT_ADR_SMB, | ||
309 | NETXEN_HW_CRB_HUB_AGT_ADR_I2C0, | ||
310 | NETXEN_HW_CRB_HUB_AGT_ADR_I2C1, | ||
311 | 0, | ||
312 | NETXEN_HW_CRB_HUB_AGT_ADR_PGNC, | ||
313 | 0, | ||
314 | }; | ||
315 | |||
316 | /* PCI Windowing for DDR regions. */ | ||
317 | |||
318 | #define NETXEN_WINDOW_ONE 0x2000000 /*CRB Window: bit 25 of CRB address */ | ||
319 | |||
320 | #define NETXEN_PCIE_SEM_TIMEOUT 10000 | ||
321 | |||
322 | static int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu); | ||
323 | |||
324 | int | ||
325 | netxen_pcie_sem_lock(struct netxen_adapter *adapter, int sem, u32 id_reg) | ||
326 | { | ||
327 | int done = 0, timeout = 0; | ||
328 | |||
329 | while (!done) { | ||
330 | done = NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM_LOCK(sem))); | ||
331 | if (done == 1) | ||
332 | break; | ||
333 | if (++timeout >= NETXEN_PCIE_SEM_TIMEOUT) | ||
334 | return -EIO; | ||
335 | msleep(1); | ||
336 | } | ||
337 | |||
338 | if (id_reg) | ||
339 | NXWR32(adapter, id_reg, adapter->portnum); | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | void | ||
345 | netxen_pcie_sem_unlock(struct netxen_adapter *adapter, int sem) | ||
346 | { | ||
347 | NXRD32(adapter, NETXEN_PCIE_REG(PCIE_SEM_UNLOCK(sem))); | ||
348 | } | ||
349 | |||
350 | static int netxen_niu_xg_init_port(struct netxen_adapter *adapter, int port) | ||
351 | { | ||
352 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
353 | NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_1+(0x10000*port), 0x1447); | ||
354 | NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0+(0x10000*port), 0x5); | ||
355 | } | ||
356 | |||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | /* Disable an XG interface */ | ||
361 | static int netxen_niu_disable_xg_port(struct netxen_adapter *adapter) | ||
362 | { | ||
363 | __u32 mac_cfg; | ||
364 | u32 port = adapter->physical_port; | ||
365 | |||
366 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
367 | return 0; | ||
368 | |||
369 | if (port > NETXEN_NIU_MAX_XG_PORTS) | ||
370 | return -EINVAL; | ||
371 | |||
372 | mac_cfg = 0; | ||
373 | if (NXWR32(adapter, | ||
374 | NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg)) | ||
375 | return -EIO; | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | #define NETXEN_UNICAST_ADDR(port, index) \ | ||
380 | (NETXEN_UNICAST_ADDR_BASE+(port*32)+(index*8)) | ||
381 | #define NETXEN_MCAST_ADDR(port, index) \ | ||
382 | (NETXEN_MULTICAST_ADDR_BASE+(port*0x80)+(index*8)) | ||
383 | #define MAC_HI(addr) \ | ||
384 | ((addr[2] << 16) | (addr[1] << 8) | (addr[0])) | ||
385 | #define MAC_LO(addr) \ | ||
386 | ((addr[5] << 16) | (addr[4] << 8) | (addr[3])) | ||
387 | |||
388 | static int netxen_p2_nic_set_promisc(struct netxen_adapter *adapter, u32 mode) | ||
389 | { | ||
390 | u32 mac_cfg; | ||
391 | u32 cnt = 0; | ||
392 | __u32 reg = 0x0200; | ||
393 | u32 port = adapter->physical_port; | ||
394 | u16 board_type = adapter->ahw.board_type; | ||
395 | |||
396 | if (port > NETXEN_NIU_MAX_XG_PORTS) | ||
397 | return -EINVAL; | ||
398 | |||
399 | mac_cfg = NXRD32(adapter, NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port)); | ||
400 | mac_cfg &= ~0x4; | ||
401 | NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg); | ||
402 | |||
403 | if ((board_type == NETXEN_BRDTYPE_P2_SB31_10G_IMEZ) || | ||
404 | (board_type == NETXEN_BRDTYPE_P2_SB31_10G_HMEZ)) | ||
405 | reg = (0x20 << port); | ||
406 | |||
407 | NXWR32(adapter, NETXEN_NIU_FRAME_COUNT_SELECT, reg); | ||
408 | |||
409 | mdelay(10); | ||
410 | |||
411 | while (NXRD32(adapter, NETXEN_NIU_FRAME_COUNT) && ++cnt < 20) | ||
412 | mdelay(10); | ||
413 | |||
414 | if (cnt < 20) { | ||
415 | |||
416 | reg = NXRD32(adapter, | ||
417 | NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port)); | ||
418 | |||
419 | if (mode == NETXEN_NIU_PROMISC_MODE) | ||
420 | reg = (reg | 0x2000UL); | ||
421 | else | ||
422 | reg = (reg & ~0x2000UL); | ||
423 | |||
424 | if (mode == NETXEN_NIU_ALLMULTI_MODE) | ||
425 | reg = (reg | 0x1000UL); | ||
426 | else | ||
427 | reg = (reg & ~0x1000UL); | ||
428 | |||
429 | NXWR32(adapter, | ||
430 | NETXEN_NIU_XGE_CONFIG_1 + (0x10000 * port), reg); | ||
431 | } | ||
432 | |||
433 | mac_cfg |= 0x4; | ||
434 | NXWR32(adapter, NETXEN_NIU_XGE_CONFIG_0 + (0x10000 * port), mac_cfg); | ||
435 | |||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | static int netxen_p2_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr) | ||
440 | { | ||
441 | u32 mac_hi, mac_lo; | ||
442 | u32 reg_hi, reg_lo; | ||
443 | |||
444 | u8 phy = adapter->physical_port; | ||
445 | |||
446 | if (phy >= NETXEN_NIU_MAX_XG_PORTS) | ||
447 | return -EINVAL; | ||
448 | |||
449 | mac_lo = ((u32)addr[0] << 16) | ((u32)addr[1] << 24); | ||
450 | mac_hi = addr[2] | ((u32)addr[3] << 8) | | ||
451 | ((u32)addr[4] << 16) | ((u32)addr[5] << 24); | ||
452 | |||
453 | reg_lo = NETXEN_NIU_XGE_STATION_ADDR_0_1 + (0x10000 * phy); | ||
454 | reg_hi = NETXEN_NIU_XGE_STATION_ADDR_0_HI + (0x10000 * phy); | ||
455 | |||
456 | /* write twice to flush */ | ||
457 | if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi)) | ||
458 | return -EIO; | ||
459 | if (NXWR32(adapter, reg_lo, mac_lo) || NXWR32(adapter, reg_hi, mac_hi)) | ||
460 | return -EIO; | ||
461 | |||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static int | ||
466 | netxen_nic_enable_mcast_filter(struct netxen_adapter *adapter) | ||
467 | { | ||
468 | u32 val = 0; | ||
469 | u16 port = adapter->physical_port; | ||
470 | u8 *addr = adapter->mac_addr; | ||
471 | |||
472 | if (adapter->mc_enabled) | ||
473 | return 0; | ||
474 | |||
475 | val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG); | ||
476 | val |= (1UL << (28+port)); | ||
477 | NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val); | ||
478 | |||
479 | /* add broadcast addr to filter */ | ||
480 | val = 0xffffff; | ||
481 | NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val); | ||
482 | NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val); | ||
483 | |||
484 | /* add station addr to filter */ | ||
485 | val = MAC_HI(addr); | ||
486 | NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), val); | ||
487 | val = MAC_LO(addr); | ||
488 | NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, val); | ||
489 | |||
490 | adapter->mc_enabled = 1; | ||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static int | ||
495 | netxen_nic_disable_mcast_filter(struct netxen_adapter *adapter) | ||
496 | { | ||
497 | u32 val = 0; | ||
498 | u16 port = adapter->physical_port; | ||
499 | u8 *addr = adapter->mac_addr; | ||
500 | |||
501 | if (!adapter->mc_enabled) | ||
502 | return 0; | ||
503 | |||
504 | val = NXRD32(adapter, NETXEN_MAC_ADDR_CNTL_REG); | ||
505 | val &= ~(1UL << (28+port)); | ||
506 | NXWR32(adapter, NETXEN_MAC_ADDR_CNTL_REG, val); | ||
507 | |||
508 | val = MAC_HI(addr); | ||
509 | NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0), val); | ||
510 | val = MAC_LO(addr); | ||
511 | NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 0)+4, val); | ||
512 | |||
513 | NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1), 0); | ||
514 | NXWR32(adapter, NETXEN_UNICAST_ADDR(port, 1)+4, 0); | ||
515 | |||
516 | adapter->mc_enabled = 0; | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | static int | ||
521 | netxen_nic_set_mcast_addr(struct netxen_adapter *adapter, | ||
522 | int index, u8 *addr) | ||
523 | { | ||
524 | u32 hi = 0, lo = 0; | ||
525 | u16 port = adapter->physical_port; | ||
526 | |||
527 | lo = MAC_LO(addr); | ||
528 | hi = MAC_HI(addr); | ||
529 | |||
530 | NXWR32(adapter, NETXEN_MCAST_ADDR(port, index), hi); | ||
531 | NXWR32(adapter, NETXEN_MCAST_ADDR(port, index)+4, lo); | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | static void netxen_p2_nic_set_multi(struct net_device *netdev) | ||
537 | { | ||
538 | struct netxen_adapter *adapter = netdev_priv(netdev); | ||
539 | struct netdev_hw_addr *ha; | ||
540 | u8 null_addr[6]; | ||
541 | int i; | ||
542 | |||
543 | memset(null_addr, 0, 6); | ||
544 | |||
545 | if (netdev->flags & IFF_PROMISC) { | ||
546 | |||
547 | adapter->set_promisc(adapter, | ||
548 | NETXEN_NIU_PROMISC_MODE); | ||
549 | |||
550 | /* Full promiscuous mode */ | ||
551 | netxen_nic_disable_mcast_filter(adapter); | ||
552 | |||
553 | return; | ||
554 | } | ||
555 | |||
556 | if (netdev_mc_empty(netdev)) { | ||
557 | adapter->set_promisc(adapter, | ||
558 | NETXEN_NIU_NON_PROMISC_MODE); | ||
559 | netxen_nic_disable_mcast_filter(adapter); | ||
560 | return; | ||
561 | } | ||
562 | |||
563 | adapter->set_promisc(adapter, NETXEN_NIU_ALLMULTI_MODE); | ||
564 | if (netdev->flags & IFF_ALLMULTI || | ||
565 | netdev_mc_count(netdev) > adapter->max_mc_count) { | ||
566 | netxen_nic_disable_mcast_filter(adapter); | ||
567 | return; | ||
568 | } | ||
569 | |||
570 | netxen_nic_enable_mcast_filter(adapter); | ||
571 | |||
572 | i = 0; | ||
573 | netdev_for_each_mc_addr(ha, netdev) | ||
574 | netxen_nic_set_mcast_addr(adapter, i++, ha->addr); | ||
575 | |||
576 | /* Clear out remaining addresses */ | ||
577 | while (i < adapter->max_mc_count) | ||
578 | netxen_nic_set_mcast_addr(adapter, i++, null_addr); | ||
579 | } | ||
580 | |||
581 | static int | ||
582 | netxen_send_cmd_descs(struct netxen_adapter *adapter, | ||
583 | struct cmd_desc_type0 *cmd_desc_arr, int nr_desc) | ||
584 | { | ||
585 | u32 i, producer, consumer; | ||
586 | struct netxen_cmd_buffer *pbuf; | ||
587 | struct cmd_desc_type0 *cmd_desc; | ||
588 | struct nx_host_tx_ring *tx_ring; | ||
589 | |||
590 | i = 0; | ||
591 | |||
592 | if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) | ||
593 | return -EIO; | ||
594 | |||
595 | tx_ring = adapter->tx_ring; | ||
596 | __netif_tx_lock_bh(tx_ring->txq); | ||
597 | |||
598 | producer = tx_ring->producer; | ||
599 | consumer = tx_ring->sw_consumer; | ||
600 | |||
601 | if (nr_desc >= netxen_tx_avail(tx_ring)) { | ||
602 | netif_tx_stop_queue(tx_ring->txq); | ||
603 | smp_mb(); | ||
604 | if (netxen_tx_avail(tx_ring) > nr_desc) { | ||
605 | if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) | ||
606 | netif_tx_wake_queue(tx_ring->txq); | ||
607 | } else { | ||
608 | __netif_tx_unlock_bh(tx_ring->txq); | ||
609 | return -EBUSY; | ||
610 | } | ||
611 | } | ||
612 | |||
613 | do { | ||
614 | cmd_desc = &cmd_desc_arr[i]; | ||
615 | |||
616 | pbuf = &tx_ring->cmd_buf_arr[producer]; | ||
617 | pbuf->skb = NULL; | ||
618 | pbuf->frag_count = 0; | ||
619 | |||
620 | memcpy(&tx_ring->desc_head[producer], | ||
621 | &cmd_desc_arr[i], sizeof(struct cmd_desc_type0)); | ||
622 | |||
623 | producer = get_next_index(producer, tx_ring->num_desc); | ||
624 | i++; | ||
625 | |||
626 | } while (i != nr_desc); | ||
627 | |||
628 | tx_ring->producer = producer; | ||
629 | |||
630 | netxen_nic_update_cmd_producer(adapter, tx_ring); | ||
631 | |||
632 | __netif_tx_unlock_bh(tx_ring->txq); | ||
633 | |||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | static int | ||
638 | nx_p3_sre_macaddr_change(struct netxen_adapter *adapter, u8 *addr, unsigned op) | ||
639 | { | ||
640 | nx_nic_req_t req; | ||
641 | nx_mac_req_t *mac_req; | ||
642 | u64 word; | ||
643 | |||
644 | memset(&req, 0, sizeof(nx_nic_req_t)); | ||
645 | req.qhdr = cpu_to_le64(NX_NIC_REQUEST << 23); | ||
646 | |||
647 | word = NX_MAC_EVENT | ((u64)adapter->portnum << 16); | ||
648 | req.req_hdr = cpu_to_le64(word); | ||
649 | |||
650 | mac_req = (nx_mac_req_t *)&req.words[0]; | ||
651 | mac_req->op = op; | ||
652 | memcpy(mac_req->mac_addr, addr, 6); | ||
653 | |||
654 | return netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | ||
655 | } | ||
656 | |||
657 | static int nx_p3_nic_add_mac(struct netxen_adapter *adapter, | ||
658 | const u8 *addr, struct list_head *del_list) | ||
659 | { | ||
660 | struct list_head *head; | ||
661 | nx_mac_list_t *cur; | ||
662 | |||
663 | /* look up if already exists */ | ||
664 | list_for_each(head, del_list) { | ||
665 | cur = list_entry(head, nx_mac_list_t, list); | ||
666 | |||
667 | if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) { | ||
668 | list_move_tail(head, &adapter->mac_list); | ||
669 | return 0; | ||
670 | } | ||
671 | } | ||
672 | |||
673 | cur = kzalloc(sizeof(nx_mac_list_t), GFP_ATOMIC); | ||
674 | if (cur == NULL) { | ||
675 | printk(KERN_ERR "%s: failed to add mac address filter\n", | ||
676 | adapter->netdev->name); | ||
677 | return -ENOMEM; | ||
678 | } | ||
679 | memcpy(cur->mac_addr, addr, ETH_ALEN); | ||
680 | list_add_tail(&cur->list, &adapter->mac_list); | ||
681 | return nx_p3_sre_macaddr_change(adapter, | ||
682 | cur->mac_addr, NETXEN_MAC_ADD); | ||
683 | } | ||
684 | |||
685 | static void netxen_p3_nic_set_multi(struct net_device *netdev) | ||
686 | { | ||
687 | struct netxen_adapter *adapter = netdev_priv(netdev); | ||
688 | struct netdev_hw_addr *ha; | ||
689 | static const u8 bcast_addr[ETH_ALEN] = { | ||
690 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
691 | }; | ||
692 | u32 mode = VPORT_MISS_MODE_DROP; | ||
693 | LIST_HEAD(del_list); | ||
694 | struct list_head *head; | ||
695 | nx_mac_list_t *cur; | ||
696 | |||
697 | if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) | ||
698 | return; | ||
699 | |||
700 | list_splice_tail_init(&adapter->mac_list, &del_list); | ||
701 | |||
702 | nx_p3_nic_add_mac(adapter, adapter->mac_addr, &del_list); | ||
703 | nx_p3_nic_add_mac(adapter, bcast_addr, &del_list); | ||
704 | |||
705 | if (netdev->flags & IFF_PROMISC) { | ||
706 | mode = VPORT_MISS_MODE_ACCEPT_ALL; | ||
707 | goto send_fw_cmd; | ||
708 | } | ||
709 | |||
710 | if ((netdev->flags & IFF_ALLMULTI) || | ||
711 | (netdev_mc_count(netdev) > adapter->max_mc_count)) { | ||
712 | mode = VPORT_MISS_MODE_ACCEPT_MULTI; | ||
713 | goto send_fw_cmd; | ||
714 | } | ||
715 | |||
716 | if (!netdev_mc_empty(netdev)) { | ||
717 | netdev_for_each_mc_addr(ha, netdev) | ||
718 | nx_p3_nic_add_mac(adapter, ha->addr, &del_list); | ||
719 | } | ||
720 | |||
721 | send_fw_cmd: | ||
722 | adapter->set_promisc(adapter, mode); | ||
723 | head = &del_list; | ||
724 | while (!list_empty(head)) { | ||
725 | cur = list_entry(head->next, nx_mac_list_t, list); | ||
726 | |||
727 | nx_p3_sre_macaddr_change(adapter, | ||
728 | cur->mac_addr, NETXEN_MAC_DEL); | ||
729 | list_del(&cur->list); | ||
730 | kfree(cur); | ||
731 | } | ||
732 | } | ||
733 | |||
734 | static int netxen_p3_nic_set_promisc(struct netxen_adapter *adapter, u32 mode) | ||
735 | { | ||
736 | nx_nic_req_t req; | ||
737 | u64 word; | ||
738 | |||
739 | memset(&req, 0, sizeof(nx_nic_req_t)); | ||
740 | |||
741 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); | ||
742 | |||
743 | word = NX_NIC_H2C_OPCODE_PROXY_SET_VPORT_MISS_MODE | | ||
744 | ((u64)adapter->portnum << 16); | ||
745 | req.req_hdr = cpu_to_le64(word); | ||
746 | |||
747 | req.words[0] = cpu_to_le64(mode); | ||
748 | |||
749 | return netxen_send_cmd_descs(adapter, | ||
750 | (struct cmd_desc_type0 *)&req, 1); | ||
751 | } | ||
752 | |||
753 | void netxen_p3_free_mac_list(struct netxen_adapter *adapter) | ||
754 | { | ||
755 | nx_mac_list_t *cur; | ||
756 | struct list_head *head = &adapter->mac_list; | ||
757 | |||
758 | while (!list_empty(head)) { | ||
759 | cur = list_entry(head->next, nx_mac_list_t, list); | ||
760 | nx_p3_sre_macaddr_change(adapter, | ||
761 | cur->mac_addr, NETXEN_MAC_DEL); | ||
762 | list_del(&cur->list); | ||
763 | kfree(cur); | ||
764 | } | ||
765 | } | ||
766 | |||
767 | static int netxen_p3_nic_set_mac_addr(struct netxen_adapter *adapter, u8 *addr) | ||
768 | { | ||
769 | /* assuming caller has already copied new addr to netdev */ | ||
770 | netxen_p3_nic_set_multi(adapter->netdev); | ||
771 | return 0; | ||
772 | } | ||
773 | |||
774 | #define NETXEN_CONFIG_INTR_COALESCE 3 | ||
775 | |||
776 | /* | ||
777 | * Send the interrupt coalescing parameter set by ethtool to the card. | ||
778 | */ | ||
779 | int netxen_config_intr_coalesce(struct netxen_adapter *adapter) | ||
780 | { | ||
781 | nx_nic_req_t req; | ||
782 | u64 word[6]; | ||
783 | int rv, i; | ||
784 | |||
785 | memset(&req, 0, sizeof(nx_nic_req_t)); | ||
786 | memset(word, 0, sizeof(word)); | ||
787 | |||
788 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); | ||
789 | |||
790 | word[0] = NETXEN_CONFIG_INTR_COALESCE | ((u64)adapter->portnum << 16); | ||
791 | req.req_hdr = cpu_to_le64(word[0]); | ||
792 | |||
793 | memcpy(&word[0], &adapter->coal, sizeof(adapter->coal)); | ||
794 | for (i = 0; i < 6; i++) | ||
795 | req.words[i] = cpu_to_le64(word[i]); | ||
796 | |||
797 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | ||
798 | if (rv != 0) { | ||
799 | printk(KERN_ERR "ERROR. Could not send " | ||
800 | "interrupt coalescing parameters\n"); | ||
801 | } | ||
802 | |||
803 | return rv; | ||
804 | } | ||
805 | |||
806 | int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable) | ||
807 | { | ||
808 | nx_nic_req_t req; | ||
809 | u64 word; | ||
810 | int rv = 0; | ||
811 | |||
812 | if (!test_bit(__NX_FW_ATTACHED, &adapter->state)) | ||
813 | return 0; | ||
814 | |||
815 | memset(&req, 0, sizeof(nx_nic_req_t)); | ||
816 | |||
817 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); | ||
818 | |||
819 | word = NX_NIC_H2C_OPCODE_CONFIG_HW_LRO | ((u64)adapter->portnum << 16); | ||
820 | req.req_hdr = cpu_to_le64(word); | ||
821 | |||
822 | req.words[0] = cpu_to_le64(enable); | ||
823 | |||
824 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | ||
825 | if (rv != 0) { | ||
826 | printk(KERN_ERR "ERROR. Could not send " | ||
827 | "configure hw lro request\n"); | ||
828 | } | ||
829 | |||
830 | return rv; | ||
831 | } | ||
832 | |||
833 | int netxen_config_bridged_mode(struct netxen_adapter *adapter, int enable) | ||
834 | { | ||
835 | nx_nic_req_t req; | ||
836 | u64 word; | ||
837 | int rv = 0; | ||
838 | |||
839 | if (!!(adapter->flags & NETXEN_NIC_BRIDGE_ENABLED) == enable) | ||
840 | return rv; | ||
841 | |||
842 | memset(&req, 0, sizeof(nx_nic_req_t)); | ||
843 | |||
844 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); | ||
845 | |||
846 | word = NX_NIC_H2C_OPCODE_CONFIG_BRIDGING | | ||
847 | ((u64)adapter->portnum << 16); | ||
848 | req.req_hdr = cpu_to_le64(word); | ||
849 | |||
850 | req.words[0] = cpu_to_le64(enable); | ||
851 | |||
852 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | ||
853 | if (rv != 0) { | ||
854 | printk(KERN_ERR "ERROR. Could not send " | ||
855 | "configure bridge mode request\n"); | ||
856 | } | ||
857 | |||
858 | adapter->flags ^= NETXEN_NIC_BRIDGE_ENABLED; | ||
859 | |||
860 | return rv; | ||
861 | } | ||
862 | |||
863 | |||
864 | #define RSS_HASHTYPE_IP_TCP 0x3 | ||
865 | |||
866 | int netxen_config_rss(struct netxen_adapter *adapter, int enable) | ||
867 | { | ||
868 | nx_nic_req_t req; | ||
869 | u64 word; | ||
870 | int i, rv; | ||
871 | |||
872 | static const u64 key[] = { | ||
873 | 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL, | ||
874 | 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL, | ||
875 | 0x255b0ec26d5a56daULL | ||
876 | }; | ||
877 | |||
878 | |||
879 | memset(&req, 0, sizeof(nx_nic_req_t)); | ||
880 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); | ||
881 | |||
882 | word = NX_NIC_H2C_OPCODE_CONFIG_RSS | ((u64)adapter->portnum << 16); | ||
883 | req.req_hdr = cpu_to_le64(word); | ||
884 | |||
885 | /* | ||
886 | * RSS request: | ||
887 | * bits 3-0: hash_method | ||
888 | * 5-4: hash_type_ipv4 | ||
889 | * 7-6: hash_type_ipv6 | ||
890 | * 8: enable | ||
891 | * 9: use indirection table | ||
892 | * 47-10: reserved | ||
893 | * 63-48: indirection table mask | ||
894 | */ | ||
895 | word = ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) | | ||
896 | ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) | | ||
897 | ((u64)(enable & 0x1) << 8) | | ||
898 | ((0x7ULL) << 48); | ||
899 | req.words[0] = cpu_to_le64(word); | ||
900 | for (i = 0; i < ARRAY_SIZE(key); i++) | ||
901 | req.words[i+1] = cpu_to_le64(key[i]); | ||
902 | |||
903 | |||
904 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | ||
905 | if (rv != 0) { | ||
906 | printk(KERN_ERR "%s: could not configure RSS\n", | ||
907 | adapter->netdev->name); | ||
908 | } | ||
909 | |||
910 | return rv; | ||
911 | } | ||
912 | |||
913 | int netxen_config_ipaddr(struct netxen_adapter *adapter, u32 ip, int cmd) | ||
914 | { | ||
915 | nx_nic_req_t req; | ||
916 | u64 word; | ||
917 | int rv; | ||
918 | |||
919 | memset(&req, 0, sizeof(nx_nic_req_t)); | ||
920 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); | ||
921 | |||
922 | word = NX_NIC_H2C_OPCODE_CONFIG_IPADDR | ((u64)adapter->portnum << 16); | ||
923 | req.req_hdr = cpu_to_le64(word); | ||
924 | |||
925 | req.words[0] = cpu_to_le64(cmd); | ||
926 | req.words[1] = cpu_to_le64(ip); | ||
927 | |||
928 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | ||
929 | if (rv != 0) { | ||
930 | printk(KERN_ERR "%s: could not notify %s IP 0x%x reuqest\n", | ||
931 | adapter->netdev->name, | ||
932 | (cmd == NX_IP_UP) ? "Add" : "Remove", ip); | ||
933 | } | ||
934 | return rv; | ||
935 | } | ||
936 | |||
937 | int netxen_linkevent_request(struct netxen_adapter *adapter, int enable) | ||
938 | { | ||
939 | nx_nic_req_t req; | ||
940 | u64 word; | ||
941 | int rv; | ||
942 | |||
943 | memset(&req, 0, sizeof(nx_nic_req_t)); | ||
944 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); | ||
945 | |||
946 | word = NX_NIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16); | ||
947 | req.req_hdr = cpu_to_le64(word); | ||
948 | req.words[0] = cpu_to_le64(enable | (enable << 8)); | ||
949 | |||
950 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | ||
951 | if (rv != 0) { | ||
952 | printk(KERN_ERR "%s: could not configure link notification\n", | ||
953 | adapter->netdev->name); | ||
954 | } | ||
955 | |||
956 | return rv; | ||
957 | } | ||
958 | |||
959 | int netxen_send_lro_cleanup(struct netxen_adapter *adapter) | ||
960 | { | ||
961 | nx_nic_req_t req; | ||
962 | u64 word; | ||
963 | int rv; | ||
964 | |||
965 | if (!test_bit(__NX_FW_ATTACHED, &adapter->state)) | ||
966 | return 0; | ||
967 | |||
968 | memset(&req, 0, sizeof(nx_nic_req_t)); | ||
969 | req.qhdr = cpu_to_le64(NX_HOST_REQUEST << 23); | ||
970 | |||
971 | word = NX_NIC_H2C_OPCODE_LRO_REQUEST | | ||
972 | ((u64)adapter->portnum << 16) | | ||
973 | ((u64)NX_NIC_LRO_REQUEST_CLEANUP << 56) ; | ||
974 | |||
975 | req.req_hdr = cpu_to_le64(word); | ||
976 | |||
977 | rv = netxen_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | ||
978 | if (rv != 0) { | ||
979 | printk(KERN_ERR "%s: could not cleanup lro flows\n", | ||
980 | adapter->netdev->name); | ||
981 | } | ||
982 | return rv; | ||
983 | } | ||
984 | |||
985 | /* | ||
986 | * netxen_nic_change_mtu - Change the Maximum Transfer Unit | ||
987 | * @returns 0 on success, negative on failure | ||
988 | */ | ||
989 | |||
990 | #define MTU_FUDGE_FACTOR 100 | ||
991 | |||
992 | int netxen_nic_change_mtu(struct net_device *netdev, int mtu) | ||
993 | { | ||
994 | struct netxen_adapter *adapter = netdev_priv(netdev); | ||
995 | int max_mtu; | ||
996 | int rc = 0; | ||
997 | |||
998 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
999 | max_mtu = P3_MAX_MTU; | ||
1000 | else | ||
1001 | max_mtu = P2_MAX_MTU; | ||
1002 | |||
1003 | if (mtu > max_mtu) { | ||
1004 | printk(KERN_ERR "%s: mtu > %d bytes unsupported\n", | ||
1005 | netdev->name, max_mtu); | ||
1006 | return -EINVAL; | ||
1007 | } | ||
1008 | |||
1009 | if (adapter->set_mtu) | ||
1010 | rc = adapter->set_mtu(adapter, mtu); | ||
1011 | |||
1012 | if (!rc) | ||
1013 | netdev->mtu = mtu; | ||
1014 | |||
1015 | return rc; | ||
1016 | } | ||
1017 | |||
1018 | static int netxen_get_flash_block(struct netxen_adapter *adapter, int base, | ||
1019 | int size, __le32 * buf) | ||
1020 | { | ||
1021 | int i, v, addr; | ||
1022 | __le32 *ptr32; | ||
1023 | |||
1024 | addr = base; | ||
1025 | ptr32 = buf; | ||
1026 | for (i = 0; i < size / sizeof(u32); i++) { | ||
1027 | if (netxen_rom_fast_read(adapter, addr, &v) == -1) | ||
1028 | return -1; | ||
1029 | *ptr32 = cpu_to_le32(v); | ||
1030 | ptr32++; | ||
1031 | addr += sizeof(u32); | ||
1032 | } | ||
1033 | if ((char *)buf + size > (char *)ptr32) { | ||
1034 | __le32 local; | ||
1035 | if (netxen_rom_fast_read(adapter, addr, &v) == -1) | ||
1036 | return -1; | ||
1037 | local = cpu_to_le32(v); | ||
1038 | memcpy(ptr32, &local, (char *)buf + size - (char *)ptr32); | ||
1039 | } | ||
1040 | |||
1041 | return 0; | ||
1042 | } | ||
1043 | |||
1044 | int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, u64 *mac) | ||
1045 | { | ||
1046 | __le32 *pmac = (__le32 *) mac; | ||
1047 | u32 offset; | ||
1048 | |||
1049 | offset = NX_FW_MAC_ADDR_OFFSET + (adapter->portnum * sizeof(u64)); | ||
1050 | |||
1051 | if (netxen_get_flash_block(adapter, offset, sizeof(u64), pmac) == -1) | ||
1052 | return -1; | ||
1053 | |||
1054 | if (*mac == cpu_to_le64(~0ULL)) { | ||
1055 | |||
1056 | offset = NX_OLD_MAC_ADDR_OFFSET + | ||
1057 | (adapter->portnum * sizeof(u64)); | ||
1058 | |||
1059 | if (netxen_get_flash_block(adapter, | ||
1060 | offset, sizeof(u64), pmac) == -1) | ||
1061 | return -1; | ||
1062 | |||
1063 | if (*mac == cpu_to_le64(~0ULL)) | ||
1064 | return -1; | ||
1065 | } | ||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, u64 *mac) | ||
1070 | { | ||
1071 | uint32_t crbaddr, mac_hi, mac_lo; | ||
1072 | int pci_func = adapter->ahw.pci_func; | ||
1073 | |||
1074 | crbaddr = CRB_MAC_BLOCK_START + | ||
1075 | (4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1)); | ||
1076 | |||
1077 | mac_lo = NXRD32(adapter, crbaddr); | ||
1078 | mac_hi = NXRD32(adapter, crbaddr+4); | ||
1079 | |||
1080 | if (pci_func & 1) | ||
1081 | *mac = le64_to_cpu((mac_lo >> 16) | ((u64)mac_hi << 16)); | ||
1082 | else | ||
1083 | *mac = le64_to_cpu((u64)mac_lo | ((u64)mac_hi << 32)); | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | /* | ||
1089 | * Changes the CRB window to the specified window. | ||
1090 | */ | ||
1091 | static void | ||
1092 | netxen_nic_pci_set_crbwindow_128M(struct netxen_adapter *adapter, | ||
1093 | u32 window) | ||
1094 | { | ||
1095 | void __iomem *offset; | ||
1096 | int count = 10; | ||
1097 | u8 func = adapter->ahw.pci_func; | ||
1098 | |||
1099 | if (adapter->ahw.crb_win == window) | ||
1100 | return; | ||
1101 | |||
1102 | offset = PCI_OFFSET_SECOND_RANGE(adapter, | ||
1103 | NETXEN_PCIX_PH_REG(PCIE_CRB_WINDOW_REG(func))); | ||
1104 | |||
1105 | writel(window, offset); | ||
1106 | do { | ||
1107 | if (window == readl(offset)) | ||
1108 | break; | ||
1109 | |||
1110 | if (printk_ratelimit()) | ||
1111 | dev_warn(&adapter->pdev->dev, | ||
1112 | "failed to set CRB window to %d\n", | ||
1113 | (window == NETXEN_WINDOW_ONE)); | ||
1114 | udelay(1); | ||
1115 | |||
1116 | } while (--count > 0); | ||
1117 | |||
1118 | if (count > 0) | ||
1119 | adapter->ahw.crb_win = window; | ||
1120 | } | ||
1121 | |||
1122 | /* | ||
1123 | * Returns < 0 if off is not valid, | ||
1124 | * 1 if window access is needed. 'off' is set to offset from | ||
1125 | * CRB space in 128M pci map | ||
1126 | * 0 if no window access is needed. 'off' is set to 2M addr | ||
1127 | * In: 'off' is offset from base in 128M pci map | ||
1128 | */ | ||
1129 | static int | ||
1130 | netxen_nic_pci_get_crb_addr_2M(struct netxen_adapter *adapter, | ||
1131 | ulong off, void __iomem **addr) | ||
1132 | { | ||
1133 | crb_128M_2M_sub_block_map_t *m; | ||
1134 | |||
1135 | |||
1136 | if ((off >= NETXEN_CRB_MAX) || (off < NETXEN_PCI_CRBSPACE)) | ||
1137 | return -EINVAL; | ||
1138 | |||
1139 | off -= NETXEN_PCI_CRBSPACE; | ||
1140 | |||
1141 | /* | ||
1142 | * Try direct map | ||
1143 | */ | ||
1144 | m = &crb_128M_2M_map[CRB_BLK(off)].sub_block[CRB_SUBBLK(off)]; | ||
1145 | |||
1146 | if (m->valid && (m->start_128M <= off) && (m->end_128M > off)) { | ||
1147 | *addr = adapter->ahw.pci_base0 + m->start_2M + | ||
1148 | (off - m->start_128M); | ||
1149 | return 0; | ||
1150 | } | ||
1151 | |||
1152 | /* | ||
1153 | * Not in direct map, use crb window | ||
1154 | */ | ||
1155 | *addr = adapter->ahw.pci_base0 + CRB_INDIRECT_2M + | ||
1156 | (off & MASK(16)); | ||
1157 | return 1; | ||
1158 | } | ||
1159 | |||
1160 | /* | ||
1161 | * In: 'off' is offset from CRB space in 128M pci map | ||
1162 | * Out: 'off' is 2M pci map addr | ||
1163 | * side effect: lock crb window | ||
1164 | */ | ||
1165 | static void | ||
1166 | netxen_nic_pci_set_crbwindow_2M(struct netxen_adapter *adapter, ulong off) | ||
1167 | { | ||
1168 | u32 window; | ||
1169 | void __iomem *addr = adapter->ahw.pci_base0 + CRB_WINDOW_2M; | ||
1170 | |||
1171 | off -= NETXEN_PCI_CRBSPACE; | ||
1172 | |||
1173 | window = CRB_HI(off); | ||
1174 | |||
1175 | writel(window, addr); | ||
1176 | if (readl(addr) != window) { | ||
1177 | if (printk_ratelimit()) | ||
1178 | dev_warn(&adapter->pdev->dev, | ||
1179 | "failed to set CRB window to %d off 0x%lx\n", | ||
1180 | window, off); | ||
1181 | } | ||
1182 | } | ||
1183 | |||
1184 | static void __iomem * | ||
1185 | netxen_nic_map_indirect_address_128M(struct netxen_adapter *adapter, | ||
1186 | ulong win_off, void __iomem **mem_ptr) | ||
1187 | { | ||
1188 | ulong off = win_off; | ||
1189 | void __iomem *addr; | ||
1190 | resource_size_t mem_base; | ||
1191 | |||
1192 | if (ADDR_IN_WINDOW1(win_off)) | ||
1193 | off = NETXEN_CRB_NORMAL(win_off); | ||
1194 | |||
1195 | addr = pci_base_offset(adapter, off); | ||
1196 | if (addr) | ||
1197 | return addr; | ||
1198 | |||
1199 | if (adapter->ahw.pci_len0 == 0) | ||
1200 | off -= NETXEN_PCI_CRBSPACE; | ||
1201 | |||
1202 | mem_base = pci_resource_start(adapter->pdev, 0); | ||
1203 | *mem_ptr = ioremap(mem_base + (off & PAGE_MASK), PAGE_SIZE); | ||
1204 | if (*mem_ptr) | ||
1205 | addr = *mem_ptr + (off & (PAGE_SIZE - 1)); | ||
1206 | |||
1207 | return addr; | ||
1208 | } | ||
1209 | |||
1210 | static int | ||
1211 | netxen_nic_hw_write_wx_128M(struct netxen_adapter *adapter, ulong off, u32 data) | ||
1212 | { | ||
1213 | unsigned long flags; | ||
1214 | void __iomem *addr, *mem_ptr = NULL; | ||
1215 | |||
1216 | addr = netxen_nic_map_indirect_address_128M(adapter, off, &mem_ptr); | ||
1217 | if (!addr) | ||
1218 | return -EIO; | ||
1219 | |||
1220 | if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ | ||
1221 | netxen_nic_io_write_128M(adapter, addr, data); | ||
1222 | } else { /* Window 0 */ | ||
1223 | write_lock_irqsave(&adapter->ahw.crb_lock, flags); | ||
1224 | netxen_nic_pci_set_crbwindow_128M(adapter, 0); | ||
1225 | writel(data, addr); | ||
1226 | netxen_nic_pci_set_crbwindow_128M(adapter, | ||
1227 | NETXEN_WINDOW_ONE); | ||
1228 | write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); | ||
1229 | } | ||
1230 | |||
1231 | if (mem_ptr) | ||
1232 | iounmap(mem_ptr); | ||
1233 | |||
1234 | return 0; | ||
1235 | } | ||
1236 | |||
1237 | static u32 | ||
1238 | netxen_nic_hw_read_wx_128M(struct netxen_adapter *adapter, ulong off) | ||
1239 | { | ||
1240 | unsigned long flags; | ||
1241 | void __iomem *addr, *mem_ptr = NULL; | ||
1242 | u32 data; | ||
1243 | |||
1244 | addr = netxen_nic_map_indirect_address_128M(adapter, off, &mem_ptr); | ||
1245 | if (!addr) | ||
1246 | return -EIO; | ||
1247 | |||
1248 | if (ADDR_IN_WINDOW1(off)) { /* Window 1 */ | ||
1249 | data = netxen_nic_io_read_128M(adapter, addr); | ||
1250 | } else { /* Window 0 */ | ||
1251 | write_lock_irqsave(&adapter->ahw.crb_lock, flags); | ||
1252 | netxen_nic_pci_set_crbwindow_128M(adapter, 0); | ||
1253 | data = readl(addr); | ||
1254 | netxen_nic_pci_set_crbwindow_128M(adapter, | ||
1255 | NETXEN_WINDOW_ONE); | ||
1256 | write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); | ||
1257 | } | ||
1258 | |||
1259 | if (mem_ptr) | ||
1260 | iounmap(mem_ptr); | ||
1261 | |||
1262 | return data; | ||
1263 | } | ||
1264 | |||
1265 | static int | ||
1266 | netxen_nic_hw_write_wx_2M(struct netxen_adapter *adapter, ulong off, u32 data) | ||
1267 | { | ||
1268 | unsigned long flags; | ||
1269 | int rv; | ||
1270 | void __iomem *addr = NULL; | ||
1271 | |||
1272 | rv = netxen_nic_pci_get_crb_addr_2M(adapter, off, &addr); | ||
1273 | |||
1274 | if (rv == 0) { | ||
1275 | writel(data, addr); | ||
1276 | return 0; | ||
1277 | } | ||
1278 | |||
1279 | if (rv > 0) { | ||
1280 | /* indirect access */ | ||
1281 | write_lock_irqsave(&adapter->ahw.crb_lock, flags); | ||
1282 | crb_win_lock(adapter); | ||
1283 | netxen_nic_pci_set_crbwindow_2M(adapter, off); | ||
1284 | writel(data, addr); | ||
1285 | crb_win_unlock(adapter); | ||
1286 | write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); | ||
1287 | return 0; | ||
1288 | } | ||
1289 | |||
1290 | dev_err(&adapter->pdev->dev, | ||
1291 | "%s: invalid offset: 0x%016lx\n", __func__, off); | ||
1292 | dump_stack(); | ||
1293 | return -EIO; | ||
1294 | } | ||
1295 | |||
1296 | static u32 | ||
1297 | netxen_nic_hw_read_wx_2M(struct netxen_adapter *adapter, ulong off) | ||
1298 | { | ||
1299 | unsigned long flags; | ||
1300 | int rv; | ||
1301 | u32 data; | ||
1302 | void __iomem *addr = NULL; | ||
1303 | |||
1304 | rv = netxen_nic_pci_get_crb_addr_2M(adapter, off, &addr); | ||
1305 | |||
1306 | if (rv == 0) | ||
1307 | return readl(addr); | ||
1308 | |||
1309 | if (rv > 0) { | ||
1310 | /* indirect access */ | ||
1311 | write_lock_irqsave(&adapter->ahw.crb_lock, flags); | ||
1312 | crb_win_lock(adapter); | ||
1313 | netxen_nic_pci_set_crbwindow_2M(adapter, off); | ||
1314 | data = readl(addr); | ||
1315 | crb_win_unlock(adapter); | ||
1316 | write_unlock_irqrestore(&adapter->ahw.crb_lock, flags); | ||
1317 | return data; | ||
1318 | } | ||
1319 | |||
1320 | dev_err(&adapter->pdev->dev, | ||
1321 | "%s: invalid offset: 0x%016lx\n", __func__, off); | ||
1322 | dump_stack(); | ||
1323 | return -1; | ||
1324 | } | ||
1325 | |||
1326 | /* window 1 registers only */ | ||
1327 | static void netxen_nic_io_write_128M(struct netxen_adapter *adapter, | ||
1328 | void __iomem *addr, u32 data) | ||
1329 | { | ||
1330 | read_lock(&adapter->ahw.crb_lock); | ||
1331 | writel(data, addr); | ||
1332 | read_unlock(&adapter->ahw.crb_lock); | ||
1333 | } | ||
1334 | |||
1335 | static u32 netxen_nic_io_read_128M(struct netxen_adapter *adapter, | ||
1336 | void __iomem *addr) | ||
1337 | { | ||
1338 | u32 val; | ||
1339 | |||
1340 | read_lock(&adapter->ahw.crb_lock); | ||
1341 | val = readl(addr); | ||
1342 | read_unlock(&adapter->ahw.crb_lock); | ||
1343 | |||
1344 | return val; | ||
1345 | } | ||
1346 | |||
1347 | static void netxen_nic_io_write_2M(struct netxen_adapter *adapter, | ||
1348 | void __iomem *addr, u32 data) | ||
1349 | { | ||
1350 | writel(data, addr); | ||
1351 | } | ||
1352 | |||
1353 | static u32 netxen_nic_io_read_2M(struct netxen_adapter *adapter, | ||
1354 | void __iomem *addr) | ||
1355 | { | ||
1356 | return readl(addr); | ||
1357 | } | ||
1358 | |||
1359 | void __iomem * | ||
1360 | netxen_get_ioaddr(struct netxen_adapter *adapter, u32 offset) | ||
1361 | { | ||
1362 | void __iomem *addr = NULL; | ||
1363 | |||
1364 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
1365 | if ((offset < NETXEN_CRB_PCIX_HOST2) && | ||
1366 | (offset > NETXEN_CRB_PCIX_HOST)) | ||
1367 | addr = PCI_OFFSET_SECOND_RANGE(adapter, offset); | ||
1368 | else | ||
1369 | addr = NETXEN_CRB_NORMALIZE(adapter, offset); | ||
1370 | } else { | ||
1371 | WARN_ON(netxen_nic_pci_get_crb_addr_2M(adapter, | ||
1372 | offset, &addr)); | ||
1373 | } | ||
1374 | |||
1375 | return addr; | ||
1376 | } | ||
1377 | |||
1378 | static int | ||
1379 | netxen_nic_pci_set_window_128M(struct netxen_adapter *adapter, | ||
1380 | u64 addr, u32 *start) | ||
1381 | { | ||
1382 | if (ADDR_IN_RANGE(addr, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { | ||
1383 | *start = (addr - NETXEN_ADDR_OCM0 + NETXEN_PCI_OCM0); | ||
1384 | return 0; | ||
1385 | } else if (ADDR_IN_RANGE(addr, | ||
1386 | NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { | ||
1387 | *start = (addr - NETXEN_ADDR_OCM1 + NETXEN_PCI_OCM1); | ||
1388 | return 0; | ||
1389 | } | ||
1390 | |||
1391 | return -EIO; | ||
1392 | } | ||
1393 | |||
1394 | static int | ||
1395 | netxen_nic_pci_set_window_2M(struct netxen_adapter *adapter, | ||
1396 | u64 addr, u32 *start) | ||
1397 | { | ||
1398 | u32 window; | ||
1399 | |||
1400 | window = OCM_WIN(addr); | ||
1401 | |||
1402 | writel(window, adapter->ahw.ocm_win_crb); | ||
1403 | /* read back to flush */ | ||
1404 | readl(adapter->ahw.ocm_win_crb); | ||
1405 | |||
1406 | adapter->ahw.ocm_win = window; | ||
1407 | *start = NETXEN_PCI_OCM0_2M + GET_MEM_OFFS_2M(addr); | ||
1408 | return 0; | ||
1409 | } | ||
1410 | |||
1411 | static int | ||
1412 | netxen_nic_pci_mem_access_direct(struct netxen_adapter *adapter, u64 off, | ||
1413 | u64 *data, int op) | ||
1414 | { | ||
1415 | void __iomem *addr, *mem_ptr = NULL; | ||
1416 | resource_size_t mem_base; | ||
1417 | int ret; | ||
1418 | u32 start; | ||
1419 | |||
1420 | spin_lock(&adapter->ahw.mem_lock); | ||
1421 | |||
1422 | ret = adapter->pci_set_window(adapter, off, &start); | ||
1423 | if (ret != 0) | ||
1424 | goto unlock; | ||
1425 | |||
1426 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { | ||
1427 | addr = adapter->ahw.pci_base0 + start; | ||
1428 | } else { | ||
1429 | addr = pci_base_offset(adapter, start); | ||
1430 | if (addr) | ||
1431 | goto noremap; | ||
1432 | |||
1433 | mem_base = pci_resource_start(adapter->pdev, 0) + | ||
1434 | (start & PAGE_MASK); | ||
1435 | mem_ptr = ioremap(mem_base, PAGE_SIZE); | ||
1436 | if (mem_ptr == NULL) { | ||
1437 | ret = -EIO; | ||
1438 | goto unlock; | ||
1439 | } | ||
1440 | |||
1441 | addr = mem_ptr + (start & (PAGE_SIZE-1)); | ||
1442 | } | ||
1443 | noremap: | ||
1444 | if (op == 0) /* read */ | ||
1445 | *data = readq(addr); | ||
1446 | else /* write */ | ||
1447 | writeq(*data, addr); | ||
1448 | |||
1449 | unlock: | ||
1450 | spin_unlock(&adapter->ahw.mem_lock); | ||
1451 | |||
1452 | if (mem_ptr) | ||
1453 | iounmap(mem_ptr); | ||
1454 | return ret; | ||
1455 | } | ||
1456 | |||
1457 | void | ||
1458 | netxen_pci_camqm_read_2M(struct netxen_adapter *adapter, u64 off, u64 *data) | ||
1459 | { | ||
1460 | void __iomem *addr = adapter->ahw.pci_base0 + | ||
1461 | NETXEN_PCI_CAMQM_2M_BASE + (off - NETXEN_PCI_CAMQM); | ||
1462 | |||
1463 | spin_lock(&adapter->ahw.mem_lock); | ||
1464 | *data = readq(addr); | ||
1465 | spin_unlock(&adapter->ahw.mem_lock); | ||
1466 | } | ||
1467 | |||
1468 | void | ||
1469 | netxen_pci_camqm_write_2M(struct netxen_adapter *adapter, u64 off, u64 data) | ||
1470 | { | ||
1471 | void __iomem *addr = adapter->ahw.pci_base0 + | ||
1472 | NETXEN_PCI_CAMQM_2M_BASE + (off - NETXEN_PCI_CAMQM); | ||
1473 | |||
1474 | spin_lock(&adapter->ahw.mem_lock); | ||
1475 | writeq(data, addr); | ||
1476 | spin_unlock(&adapter->ahw.mem_lock); | ||
1477 | } | ||
1478 | |||
1479 | #define MAX_CTL_CHECK 1000 | ||
1480 | |||
1481 | static int | ||
1482 | netxen_nic_pci_mem_write_128M(struct netxen_adapter *adapter, | ||
1483 | u64 off, u64 data) | ||
1484 | { | ||
1485 | int j, ret; | ||
1486 | u32 temp, off_lo, off_hi, addr_hi, data_hi, data_lo; | ||
1487 | void __iomem *mem_crb; | ||
1488 | |||
1489 | /* Only 64-bit aligned access */ | ||
1490 | if (off & 7) | ||
1491 | return -EIO; | ||
1492 | |||
1493 | /* P2 has different SIU and MIU test agent base addr */ | ||
1494 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, | ||
1495 | NETXEN_ADDR_QDR_NET_MAX_P2)) { | ||
1496 | mem_crb = pci_base_offset(adapter, | ||
1497 | NETXEN_CRB_QDR_NET+SIU_TEST_AGT_BASE); | ||
1498 | addr_hi = SIU_TEST_AGT_ADDR_HI; | ||
1499 | data_lo = SIU_TEST_AGT_WRDATA_LO; | ||
1500 | data_hi = SIU_TEST_AGT_WRDATA_HI; | ||
1501 | off_lo = off & SIU_TEST_AGT_ADDR_MASK; | ||
1502 | off_hi = SIU_TEST_AGT_UPPER_ADDR(off); | ||
1503 | goto correct; | ||
1504 | } | ||
1505 | |||
1506 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { | ||
1507 | mem_crb = pci_base_offset(adapter, | ||
1508 | NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE); | ||
1509 | addr_hi = MIU_TEST_AGT_ADDR_HI; | ||
1510 | data_lo = MIU_TEST_AGT_WRDATA_LO; | ||
1511 | data_hi = MIU_TEST_AGT_WRDATA_HI; | ||
1512 | off_lo = off & MIU_TEST_AGT_ADDR_MASK; | ||
1513 | off_hi = 0; | ||
1514 | goto correct; | ||
1515 | } | ||
1516 | |||
1517 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX) || | ||
1518 | ADDR_IN_RANGE(off, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { | ||
1519 | if (adapter->ahw.pci_len0 != 0) { | ||
1520 | return netxen_nic_pci_mem_access_direct(adapter, | ||
1521 | off, &data, 1); | ||
1522 | } | ||
1523 | } | ||
1524 | |||
1525 | return -EIO; | ||
1526 | |||
1527 | correct: | ||
1528 | spin_lock(&adapter->ahw.mem_lock); | ||
1529 | netxen_nic_pci_set_crbwindow_128M(adapter, 0); | ||
1530 | |||
1531 | writel(off_lo, (mem_crb + MIU_TEST_AGT_ADDR_LO)); | ||
1532 | writel(off_hi, (mem_crb + addr_hi)); | ||
1533 | writel(data & 0xffffffff, (mem_crb + data_lo)); | ||
1534 | writel((data >> 32) & 0xffffffff, (mem_crb + data_hi)); | ||
1535 | writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL)); | ||
1536 | writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE), | ||
1537 | (mem_crb + TEST_AGT_CTRL)); | ||
1538 | |||
1539 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1540 | temp = readl((mem_crb + TEST_AGT_CTRL)); | ||
1541 | if ((temp & TA_CTL_BUSY) == 0) | ||
1542 | break; | ||
1543 | } | ||
1544 | |||
1545 | if (j >= MAX_CTL_CHECK) { | ||
1546 | if (printk_ratelimit()) | ||
1547 | dev_err(&adapter->pdev->dev, | ||
1548 | "failed to write through agent\n"); | ||
1549 | ret = -EIO; | ||
1550 | } else | ||
1551 | ret = 0; | ||
1552 | |||
1553 | netxen_nic_pci_set_crbwindow_128M(adapter, NETXEN_WINDOW_ONE); | ||
1554 | spin_unlock(&adapter->ahw.mem_lock); | ||
1555 | return ret; | ||
1556 | } | ||
1557 | |||
1558 | static int | ||
1559 | netxen_nic_pci_mem_read_128M(struct netxen_adapter *adapter, | ||
1560 | u64 off, u64 *data) | ||
1561 | { | ||
1562 | int j, ret; | ||
1563 | u32 temp, off_lo, off_hi, addr_hi, data_hi, data_lo; | ||
1564 | u64 val; | ||
1565 | void __iomem *mem_crb; | ||
1566 | |||
1567 | /* Only 64-bit aligned access */ | ||
1568 | if (off & 7) | ||
1569 | return -EIO; | ||
1570 | |||
1571 | /* P2 has different SIU and MIU test agent base addr */ | ||
1572 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, | ||
1573 | NETXEN_ADDR_QDR_NET_MAX_P2)) { | ||
1574 | mem_crb = pci_base_offset(adapter, | ||
1575 | NETXEN_CRB_QDR_NET+SIU_TEST_AGT_BASE); | ||
1576 | addr_hi = SIU_TEST_AGT_ADDR_HI; | ||
1577 | data_lo = SIU_TEST_AGT_RDDATA_LO; | ||
1578 | data_hi = SIU_TEST_AGT_RDDATA_HI; | ||
1579 | off_lo = off & SIU_TEST_AGT_ADDR_MASK; | ||
1580 | off_hi = SIU_TEST_AGT_UPPER_ADDR(off); | ||
1581 | goto correct; | ||
1582 | } | ||
1583 | |||
1584 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { | ||
1585 | mem_crb = pci_base_offset(adapter, | ||
1586 | NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE); | ||
1587 | addr_hi = MIU_TEST_AGT_ADDR_HI; | ||
1588 | data_lo = MIU_TEST_AGT_RDDATA_LO; | ||
1589 | data_hi = MIU_TEST_AGT_RDDATA_HI; | ||
1590 | off_lo = off & MIU_TEST_AGT_ADDR_MASK; | ||
1591 | off_hi = 0; | ||
1592 | goto correct; | ||
1593 | } | ||
1594 | |||
1595 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX) || | ||
1596 | ADDR_IN_RANGE(off, NETXEN_ADDR_OCM1, NETXEN_ADDR_OCM1_MAX)) { | ||
1597 | if (adapter->ahw.pci_len0 != 0) { | ||
1598 | return netxen_nic_pci_mem_access_direct(adapter, | ||
1599 | off, data, 0); | ||
1600 | } | ||
1601 | } | ||
1602 | |||
1603 | return -EIO; | ||
1604 | |||
1605 | correct: | ||
1606 | spin_lock(&adapter->ahw.mem_lock); | ||
1607 | netxen_nic_pci_set_crbwindow_128M(adapter, 0); | ||
1608 | |||
1609 | writel(off_lo, (mem_crb + MIU_TEST_AGT_ADDR_LO)); | ||
1610 | writel(off_hi, (mem_crb + addr_hi)); | ||
1611 | writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL)); | ||
1612 | writel((TA_CTL_START|TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL)); | ||
1613 | |||
1614 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1615 | temp = readl(mem_crb + TEST_AGT_CTRL); | ||
1616 | if ((temp & TA_CTL_BUSY) == 0) | ||
1617 | break; | ||
1618 | } | ||
1619 | |||
1620 | if (j >= MAX_CTL_CHECK) { | ||
1621 | if (printk_ratelimit()) | ||
1622 | dev_err(&adapter->pdev->dev, | ||
1623 | "failed to read through agent\n"); | ||
1624 | ret = -EIO; | ||
1625 | } else { | ||
1626 | |||
1627 | temp = readl(mem_crb + data_hi); | ||
1628 | val = ((u64)temp << 32); | ||
1629 | val |= readl(mem_crb + data_lo); | ||
1630 | *data = val; | ||
1631 | ret = 0; | ||
1632 | } | ||
1633 | |||
1634 | netxen_nic_pci_set_crbwindow_128M(adapter, NETXEN_WINDOW_ONE); | ||
1635 | spin_unlock(&adapter->ahw.mem_lock); | ||
1636 | |||
1637 | return ret; | ||
1638 | } | ||
1639 | |||
1640 | static int | ||
1641 | netxen_nic_pci_mem_write_2M(struct netxen_adapter *adapter, | ||
1642 | u64 off, u64 data) | ||
1643 | { | ||
1644 | int j, ret; | ||
1645 | u32 temp, off8; | ||
1646 | void __iomem *mem_crb; | ||
1647 | |||
1648 | /* Only 64-bit aligned access */ | ||
1649 | if (off & 7) | ||
1650 | return -EIO; | ||
1651 | |||
1652 | /* P3 onward, test agent base for MIU and SIU is same */ | ||
1653 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, | ||
1654 | NETXEN_ADDR_QDR_NET_MAX_P3)) { | ||
1655 | mem_crb = netxen_get_ioaddr(adapter, | ||
1656 | NETXEN_CRB_QDR_NET+MIU_TEST_AGT_BASE); | ||
1657 | goto correct; | ||
1658 | } | ||
1659 | |||
1660 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { | ||
1661 | mem_crb = netxen_get_ioaddr(adapter, | ||
1662 | NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE); | ||
1663 | goto correct; | ||
1664 | } | ||
1665 | |||
1666 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) | ||
1667 | return netxen_nic_pci_mem_access_direct(adapter, off, &data, 1); | ||
1668 | |||
1669 | return -EIO; | ||
1670 | |||
1671 | correct: | ||
1672 | off8 = off & 0xfffffff8; | ||
1673 | |||
1674 | spin_lock(&adapter->ahw.mem_lock); | ||
1675 | |||
1676 | writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO)); | ||
1677 | writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI)); | ||
1678 | |||
1679 | writel(data & 0xffffffff, | ||
1680 | mem_crb + MIU_TEST_AGT_WRDATA_LO); | ||
1681 | writel((data >> 32) & 0xffffffff, | ||
1682 | mem_crb + MIU_TEST_AGT_WRDATA_HI); | ||
1683 | |||
1684 | writel((TA_CTL_ENABLE | TA_CTL_WRITE), (mem_crb + TEST_AGT_CTRL)); | ||
1685 | writel((TA_CTL_START | TA_CTL_ENABLE | TA_CTL_WRITE), | ||
1686 | (mem_crb + TEST_AGT_CTRL)); | ||
1687 | |||
1688 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1689 | temp = readl(mem_crb + TEST_AGT_CTRL); | ||
1690 | if ((temp & TA_CTL_BUSY) == 0) | ||
1691 | break; | ||
1692 | } | ||
1693 | |||
1694 | if (j >= MAX_CTL_CHECK) { | ||
1695 | if (printk_ratelimit()) | ||
1696 | dev_err(&adapter->pdev->dev, | ||
1697 | "failed to write through agent\n"); | ||
1698 | ret = -EIO; | ||
1699 | } else | ||
1700 | ret = 0; | ||
1701 | |||
1702 | spin_unlock(&adapter->ahw.mem_lock); | ||
1703 | |||
1704 | return ret; | ||
1705 | } | ||
1706 | |||
1707 | static int | ||
1708 | netxen_nic_pci_mem_read_2M(struct netxen_adapter *adapter, | ||
1709 | u64 off, u64 *data) | ||
1710 | { | ||
1711 | int j, ret; | ||
1712 | u32 temp, off8; | ||
1713 | u64 val; | ||
1714 | void __iomem *mem_crb; | ||
1715 | |||
1716 | /* Only 64-bit aligned access */ | ||
1717 | if (off & 7) | ||
1718 | return -EIO; | ||
1719 | |||
1720 | /* P3 onward, test agent base for MIU and SIU is same */ | ||
1721 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_QDR_NET, | ||
1722 | NETXEN_ADDR_QDR_NET_MAX_P3)) { | ||
1723 | mem_crb = netxen_get_ioaddr(adapter, | ||
1724 | NETXEN_CRB_QDR_NET+MIU_TEST_AGT_BASE); | ||
1725 | goto correct; | ||
1726 | } | ||
1727 | |||
1728 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_DDR_NET, NETXEN_ADDR_DDR_NET_MAX)) { | ||
1729 | mem_crb = netxen_get_ioaddr(adapter, | ||
1730 | NETXEN_CRB_DDR_NET+MIU_TEST_AGT_BASE); | ||
1731 | goto correct; | ||
1732 | } | ||
1733 | |||
1734 | if (ADDR_IN_RANGE(off, NETXEN_ADDR_OCM0, NETXEN_ADDR_OCM0_MAX)) { | ||
1735 | return netxen_nic_pci_mem_access_direct(adapter, | ||
1736 | off, data, 0); | ||
1737 | } | ||
1738 | |||
1739 | return -EIO; | ||
1740 | |||
1741 | correct: | ||
1742 | off8 = off & 0xfffffff8; | ||
1743 | |||
1744 | spin_lock(&adapter->ahw.mem_lock); | ||
1745 | |||
1746 | writel(off8, (mem_crb + MIU_TEST_AGT_ADDR_LO)); | ||
1747 | writel(0, (mem_crb + MIU_TEST_AGT_ADDR_HI)); | ||
1748 | writel(TA_CTL_ENABLE, (mem_crb + TEST_AGT_CTRL)); | ||
1749 | writel((TA_CTL_START | TA_CTL_ENABLE), (mem_crb + TEST_AGT_CTRL)); | ||
1750 | |||
1751 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
1752 | temp = readl(mem_crb + TEST_AGT_CTRL); | ||
1753 | if ((temp & TA_CTL_BUSY) == 0) | ||
1754 | break; | ||
1755 | } | ||
1756 | |||
1757 | if (j >= MAX_CTL_CHECK) { | ||
1758 | if (printk_ratelimit()) | ||
1759 | dev_err(&adapter->pdev->dev, | ||
1760 | "failed to read through agent\n"); | ||
1761 | ret = -EIO; | ||
1762 | } else { | ||
1763 | val = (u64)(readl(mem_crb + MIU_TEST_AGT_RDDATA_HI)) << 32; | ||
1764 | val |= readl(mem_crb + MIU_TEST_AGT_RDDATA_LO); | ||
1765 | *data = val; | ||
1766 | ret = 0; | ||
1767 | } | ||
1768 | |||
1769 | spin_unlock(&adapter->ahw.mem_lock); | ||
1770 | |||
1771 | return ret; | ||
1772 | } | ||
1773 | |||
1774 | void | ||
1775 | netxen_setup_hwops(struct netxen_adapter *adapter) | ||
1776 | { | ||
1777 | adapter->init_port = netxen_niu_xg_init_port; | ||
1778 | adapter->stop_port = netxen_niu_disable_xg_port; | ||
1779 | |||
1780 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
1781 | adapter->crb_read = netxen_nic_hw_read_wx_128M, | ||
1782 | adapter->crb_write = netxen_nic_hw_write_wx_128M, | ||
1783 | adapter->pci_set_window = netxen_nic_pci_set_window_128M, | ||
1784 | adapter->pci_mem_read = netxen_nic_pci_mem_read_128M, | ||
1785 | adapter->pci_mem_write = netxen_nic_pci_mem_write_128M, | ||
1786 | adapter->io_read = netxen_nic_io_read_128M, | ||
1787 | adapter->io_write = netxen_nic_io_write_128M, | ||
1788 | |||
1789 | adapter->macaddr_set = netxen_p2_nic_set_mac_addr; | ||
1790 | adapter->set_multi = netxen_p2_nic_set_multi; | ||
1791 | adapter->set_mtu = netxen_nic_set_mtu_xgb; | ||
1792 | adapter->set_promisc = netxen_p2_nic_set_promisc; | ||
1793 | |||
1794 | } else { | ||
1795 | adapter->crb_read = netxen_nic_hw_read_wx_2M, | ||
1796 | adapter->crb_write = netxen_nic_hw_write_wx_2M, | ||
1797 | adapter->pci_set_window = netxen_nic_pci_set_window_2M, | ||
1798 | adapter->pci_mem_read = netxen_nic_pci_mem_read_2M, | ||
1799 | adapter->pci_mem_write = netxen_nic_pci_mem_write_2M, | ||
1800 | adapter->io_read = netxen_nic_io_read_2M, | ||
1801 | adapter->io_write = netxen_nic_io_write_2M, | ||
1802 | |||
1803 | adapter->set_mtu = nx_fw_cmd_set_mtu; | ||
1804 | adapter->set_promisc = netxen_p3_nic_set_promisc; | ||
1805 | adapter->macaddr_set = netxen_p3_nic_set_mac_addr; | ||
1806 | adapter->set_multi = netxen_p3_nic_set_multi; | ||
1807 | |||
1808 | adapter->phy_read = nx_fw_cmd_query_phy; | ||
1809 | adapter->phy_write = nx_fw_cmd_set_phy; | ||
1810 | } | ||
1811 | } | ||
1812 | |||
1813 | int netxen_nic_get_board_info(struct netxen_adapter *adapter) | ||
1814 | { | ||
1815 | int offset, board_type, magic; | ||
1816 | struct pci_dev *pdev = adapter->pdev; | ||
1817 | |||
1818 | offset = NX_FW_MAGIC_OFFSET; | ||
1819 | if (netxen_rom_fast_read(adapter, offset, &magic)) | ||
1820 | return -EIO; | ||
1821 | |||
1822 | if (magic != NETXEN_BDINFO_MAGIC) { | ||
1823 | dev_err(&pdev->dev, "invalid board config, magic=%08x\n", | ||
1824 | magic); | ||
1825 | return -EIO; | ||
1826 | } | ||
1827 | |||
1828 | offset = NX_BRDTYPE_OFFSET; | ||
1829 | if (netxen_rom_fast_read(adapter, offset, &board_type)) | ||
1830 | return -EIO; | ||
1831 | |||
1832 | if (board_type == NETXEN_BRDTYPE_P3_4_GB_MM) { | ||
1833 | u32 gpio = NXRD32(adapter, NETXEN_ROMUSB_GLB_PAD_GPIO_I); | ||
1834 | if ((gpio & 0x8000) == 0) | ||
1835 | board_type = NETXEN_BRDTYPE_P3_10G_TP; | ||
1836 | } | ||
1837 | |||
1838 | adapter->ahw.board_type = board_type; | ||
1839 | |||
1840 | switch (board_type) { | ||
1841 | case NETXEN_BRDTYPE_P2_SB35_4G: | ||
1842 | adapter->ahw.port_type = NETXEN_NIC_GBE; | ||
1843 | break; | ||
1844 | case NETXEN_BRDTYPE_P2_SB31_10G: | ||
1845 | case NETXEN_BRDTYPE_P2_SB31_10G_IMEZ: | ||
1846 | case NETXEN_BRDTYPE_P2_SB31_10G_HMEZ: | ||
1847 | case NETXEN_BRDTYPE_P2_SB31_10G_CX4: | ||
1848 | case NETXEN_BRDTYPE_P3_HMEZ: | ||
1849 | case NETXEN_BRDTYPE_P3_XG_LOM: | ||
1850 | case NETXEN_BRDTYPE_P3_10G_CX4: | ||
1851 | case NETXEN_BRDTYPE_P3_10G_CX4_LP: | ||
1852 | case NETXEN_BRDTYPE_P3_IMEZ: | ||
1853 | case NETXEN_BRDTYPE_P3_10G_SFP_PLUS: | ||
1854 | case NETXEN_BRDTYPE_P3_10G_SFP_CT: | ||
1855 | case NETXEN_BRDTYPE_P3_10G_SFP_QT: | ||
1856 | case NETXEN_BRDTYPE_P3_10G_XFP: | ||
1857 | case NETXEN_BRDTYPE_P3_10000_BASE_T: | ||
1858 | adapter->ahw.port_type = NETXEN_NIC_XGBE; | ||
1859 | break; | ||
1860 | case NETXEN_BRDTYPE_P1_BD: | ||
1861 | case NETXEN_BRDTYPE_P1_SB: | ||
1862 | case NETXEN_BRDTYPE_P1_SMAX: | ||
1863 | case NETXEN_BRDTYPE_P1_SOCK: | ||
1864 | case NETXEN_BRDTYPE_P3_REF_QG: | ||
1865 | case NETXEN_BRDTYPE_P3_4_GB: | ||
1866 | case NETXEN_BRDTYPE_P3_4_GB_MM: | ||
1867 | adapter->ahw.port_type = NETXEN_NIC_GBE; | ||
1868 | break; | ||
1869 | case NETXEN_BRDTYPE_P3_10G_TP: | ||
1870 | adapter->ahw.port_type = (adapter->portnum < 2) ? | ||
1871 | NETXEN_NIC_XGBE : NETXEN_NIC_GBE; | ||
1872 | break; | ||
1873 | default: | ||
1874 | dev_err(&pdev->dev, "unknown board type %x\n", board_type); | ||
1875 | adapter->ahw.port_type = NETXEN_NIC_XGBE; | ||
1876 | break; | ||
1877 | } | ||
1878 | |||
1879 | return 0; | ||
1880 | } | ||
1881 | |||
1882 | /* NIU access sections */ | ||
1883 | static int netxen_nic_set_mtu_xgb(struct netxen_adapter *adapter, int new_mtu) | ||
1884 | { | ||
1885 | new_mtu += MTU_FUDGE_FACTOR; | ||
1886 | if (adapter->physical_port == 0) | ||
1887 | NXWR32(adapter, NETXEN_NIU_XGE_MAX_FRAME_SIZE, new_mtu); | ||
1888 | else | ||
1889 | NXWR32(adapter, NETXEN_NIU_XG1_MAX_FRAME_SIZE, new_mtu); | ||
1890 | return 0; | ||
1891 | } | ||
1892 | |||
1893 | void netxen_nic_set_link_parameters(struct netxen_adapter *adapter) | ||
1894 | { | ||
1895 | __u32 status; | ||
1896 | __u32 autoneg; | ||
1897 | __u32 port_mode; | ||
1898 | |||
1899 | if (!netif_carrier_ok(adapter->netdev)) { | ||
1900 | adapter->link_speed = 0; | ||
1901 | adapter->link_duplex = -1; | ||
1902 | adapter->link_autoneg = AUTONEG_ENABLE; | ||
1903 | return; | ||
1904 | } | ||
1905 | |||
1906 | if (adapter->ahw.port_type == NETXEN_NIC_GBE) { | ||
1907 | port_mode = NXRD32(adapter, NETXEN_PORT_MODE_ADDR); | ||
1908 | if (port_mode == NETXEN_PORT_MODE_802_3_AP) { | ||
1909 | adapter->link_speed = SPEED_1000; | ||
1910 | adapter->link_duplex = DUPLEX_FULL; | ||
1911 | adapter->link_autoneg = AUTONEG_DISABLE; | ||
1912 | return; | ||
1913 | } | ||
1914 | |||
1915 | if (adapter->phy_read && | ||
1916 | adapter->phy_read(adapter, | ||
1917 | NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS, | ||
1918 | &status) == 0) { | ||
1919 | if (netxen_get_phy_link(status)) { | ||
1920 | switch (netxen_get_phy_speed(status)) { | ||
1921 | case 0: | ||
1922 | adapter->link_speed = SPEED_10; | ||
1923 | break; | ||
1924 | case 1: | ||
1925 | adapter->link_speed = SPEED_100; | ||
1926 | break; | ||
1927 | case 2: | ||
1928 | adapter->link_speed = SPEED_1000; | ||
1929 | break; | ||
1930 | default: | ||
1931 | adapter->link_speed = 0; | ||
1932 | break; | ||
1933 | } | ||
1934 | switch (netxen_get_phy_duplex(status)) { | ||
1935 | case 0: | ||
1936 | adapter->link_duplex = DUPLEX_HALF; | ||
1937 | break; | ||
1938 | case 1: | ||
1939 | adapter->link_duplex = DUPLEX_FULL; | ||
1940 | break; | ||
1941 | default: | ||
1942 | adapter->link_duplex = -1; | ||
1943 | break; | ||
1944 | } | ||
1945 | if (adapter->phy_read && | ||
1946 | adapter->phy_read(adapter, | ||
1947 | NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG, | ||
1948 | &autoneg) != 0) | ||
1949 | adapter->link_autoneg = autoneg; | ||
1950 | } else | ||
1951 | goto link_down; | ||
1952 | } else { | ||
1953 | link_down: | ||
1954 | adapter->link_speed = 0; | ||
1955 | adapter->link_duplex = -1; | ||
1956 | } | ||
1957 | } | ||
1958 | } | ||
1959 | |||
1960 | int | ||
1961 | netxen_nic_wol_supported(struct netxen_adapter *adapter) | ||
1962 | { | ||
1963 | u32 wol_cfg; | ||
1964 | |||
1965 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
1966 | return 0; | ||
1967 | |||
1968 | wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG_NV); | ||
1969 | if (wol_cfg & (1UL << adapter->portnum)) { | ||
1970 | wol_cfg = NXRD32(adapter, NETXEN_WOL_CONFIG); | ||
1971 | if (wol_cfg & (1 << adapter->portnum)) | ||
1972 | return 1; | ||
1973 | } | ||
1974 | |||
1975 | return 0; | ||
1976 | } | ||