diff options
Diffstat (limited to 'drivers/net/netxen/netxen_nic_init.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 1945 |
1 files changed, 1945 insertions, 0 deletions
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c new file mode 100644 index 00000000000..e8993a76a08 --- /dev/null +++ b/drivers/net/netxen/netxen_nic_init.c | |||
@@ -0,0 +1,1945 @@ | |||
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/netdevice.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/slab.h> | ||
29 | #include "netxen_nic.h" | ||
30 | #include "netxen_nic_hw.h" | ||
31 | |||
32 | struct crb_addr_pair { | ||
33 | u32 addr; | ||
34 | u32 data; | ||
35 | }; | ||
36 | |||
37 | #define NETXEN_MAX_CRB_XFORM 60 | ||
38 | static unsigned int crb_addr_xform[NETXEN_MAX_CRB_XFORM]; | ||
39 | #define NETXEN_ADDR_ERROR (0xffffffff) | ||
40 | |||
41 | #define crb_addr_transform(name) \ | ||
42 | crb_addr_xform[NETXEN_HW_PX_MAP_CRB_##name] = \ | ||
43 | NETXEN_HW_CRB_HUB_AGT_ADR_##name << 20 | ||
44 | |||
45 | #define NETXEN_NIC_XDMA_RESET 0x8000ff | ||
46 | |||
47 | static void | ||
48 | netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, | ||
49 | struct nx_host_rds_ring *rds_ring); | ||
50 | static int netxen_p3_has_mn(struct netxen_adapter *adapter); | ||
51 | |||
52 | static void crb_addr_transform_setup(void) | ||
53 | { | ||
54 | crb_addr_transform(XDMA); | ||
55 | crb_addr_transform(TIMR); | ||
56 | crb_addr_transform(SRE); | ||
57 | crb_addr_transform(SQN3); | ||
58 | crb_addr_transform(SQN2); | ||
59 | crb_addr_transform(SQN1); | ||
60 | crb_addr_transform(SQN0); | ||
61 | crb_addr_transform(SQS3); | ||
62 | crb_addr_transform(SQS2); | ||
63 | crb_addr_transform(SQS1); | ||
64 | crb_addr_transform(SQS0); | ||
65 | crb_addr_transform(RPMX7); | ||
66 | crb_addr_transform(RPMX6); | ||
67 | crb_addr_transform(RPMX5); | ||
68 | crb_addr_transform(RPMX4); | ||
69 | crb_addr_transform(RPMX3); | ||
70 | crb_addr_transform(RPMX2); | ||
71 | crb_addr_transform(RPMX1); | ||
72 | crb_addr_transform(RPMX0); | ||
73 | crb_addr_transform(ROMUSB); | ||
74 | crb_addr_transform(SN); | ||
75 | crb_addr_transform(QMN); | ||
76 | crb_addr_transform(QMS); | ||
77 | crb_addr_transform(PGNI); | ||
78 | crb_addr_transform(PGND); | ||
79 | crb_addr_transform(PGN3); | ||
80 | crb_addr_transform(PGN2); | ||
81 | crb_addr_transform(PGN1); | ||
82 | crb_addr_transform(PGN0); | ||
83 | crb_addr_transform(PGSI); | ||
84 | crb_addr_transform(PGSD); | ||
85 | crb_addr_transform(PGS3); | ||
86 | crb_addr_transform(PGS2); | ||
87 | crb_addr_transform(PGS1); | ||
88 | crb_addr_transform(PGS0); | ||
89 | crb_addr_transform(PS); | ||
90 | crb_addr_transform(PH); | ||
91 | crb_addr_transform(NIU); | ||
92 | crb_addr_transform(I2Q); | ||
93 | crb_addr_transform(EG); | ||
94 | crb_addr_transform(MN); | ||
95 | crb_addr_transform(MS); | ||
96 | crb_addr_transform(CAS2); | ||
97 | crb_addr_transform(CAS1); | ||
98 | crb_addr_transform(CAS0); | ||
99 | crb_addr_transform(CAM); | ||
100 | crb_addr_transform(C2C1); | ||
101 | crb_addr_transform(C2C0); | ||
102 | crb_addr_transform(SMB); | ||
103 | crb_addr_transform(OCM0); | ||
104 | crb_addr_transform(I2C0); | ||
105 | } | ||
106 | |||
107 | void netxen_release_rx_buffers(struct netxen_adapter *adapter) | ||
108 | { | ||
109 | struct netxen_recv_context *recv_ctx; | ||
110 | struct nx_host_rds_ring *rds_ring; | ||
111 | struct netxen_rx_buffer *rx_buf; | ||
112 | int i, ring; | ||
113 | |||
114 | recv_ctx = &adapter->recv_ctx; | ||
115 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | ||
116 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
117 | for (i = 0; i < rds_ring->num_desc; ++i) { | ||
118 | rx_buf = &(rds_ring->rx_buf_arr[i]); | ||
119 | if (rx_buf->state == NETXEN_BUFFER_FREE) | ||
120 | continue; | ||
121 | pci_unmap_single(adapter->pdev, | ||
122 | rx_buf->dma, | ||
123 | rds_ring->dma_size, | ||
124 | PCI_DMA_FROMDEVICE); | ||
125 | if (rx_buf->skb != NULL) | ||
126 | dev_kfree_skb_any(rx_buf->skb); | ||
127 | } | ||
128 | } | ||
129 | } | ||
130 | |||
131 | void netxen_release_tx_buffers(struct netxen_adapter *adapter) | ||
132 | { | ||
133 | struct netxen_cmd_buffer *cmd_buf; | ||
134 | struct netxen_skb_frag *buffrag; | ||
135 | int i, j; | ||
136 | struct nx_host_tx_ring *tx_ring = adapter->tx_ring; | ||
137 | |||
138 | cmd_buf = tx_ring->cmd_buf_arr; | ||
139 | for (i = 0; i < tx_ring->num_desc; i++) { | ||
140 | buffrag = cmd_buf->frag_array; | ||
141 | if (buffrag->dma) { | ||
142 | pci_unmap_single(adapter->pdev, buffrag->dma, | ||
143 | buffrag->length, PCI_DMA_TODEVICE); | ||
144 | buffrag->dma = 0ULL; | ||
145 | } | ||
146 | for (j = 0; j < cmd_buf->frag_count; j++) { | ||
147 | buffrag++; | ||
148 | if (buffrag->dma) { | ||
149 | pci_unmap_page(adapter->pdev, buffrag->dma, | ||
150 | buffrag->length, | ||
151 | PCI_DMA_TODEVICE); | ||
152 | buffrag->dma = 0ULL; | ||
153 | } | ||
154 | } | ||
155 | if (cmd_buf->skb) { | ||
156 | dev_kfree_skb_any(cmd_buf->skb); | ||
157 | cmd_buf->skb = NULL; | ||
158 | } | ||
159 | cmd_buf++; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | void netxen_free_sw_resources(struct netxen_adapter *adapter) | ||
164 | { | ||
165 | struct netxen_recv_context *recv_ctx; | ||
166 | struct nx_host_rds_ring *rds_ring; | ||
167 | struct nx_host_tx_ring *tx_ring; | ||
168 | int ring; | ||
169 | |||
170 | recv_ctx = &adapter->recv_ctx; | ||
171 | |||
172 | if (recv_ctx->rds_rings == NULL) | ||
173 | goto skip_rds; | ||
174 | |||
175 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | ||
176 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
177 | vfree(rds_ring->rx_buf_arr); | ||
178 | rds_ring->rx_buf_arr = NULL; | ||
179 | } | ||
180 | kfree(recv_ctx->rds_rings); | ||
181 | |||
182 | skip_rds: | ||
183 | if (adapter->tx_ring == NULL) | ||
184 | return; | ||
185 | |||
186 | tx_ring = adapter->tx_ring; | ||
187 | vfree(tx_ring->cmd_buf_arr); | ||
188 | kfree(tx_ring); | ||
189 | adapter->tx_ring = NULL; | ||
190 | } | ||
191 | |||
192 | int netxen_alloc_sw_resources(struct netxen_adapter *adapter) | ||
193 | { | ||
194 | struct netxen_recv_context *recv_ctx; | ||
195 | struct nx_host_rds_ring *rds_ring; | ||
196 | struct nx_host_sds_ring *sds_ring; | ||
197 | struct nx_host_tx_ring *tx_ring; | ||
198 | struct netxen_rx_buffer *rx_buf; | ||
199 | int ring, i, size; | ||
200 | |||
201 | struct netxen_cmd_buffer *cmd_buf_arr; | ||
202 | struct net_device *netdev = adapter->netdev; | ||
203 | struct pci_dev *pdev = adapter->pdev; | ||
204 | |||
205 | size = sizeof(struct nx_host_tx_ring); | ||
206 | tx_ring = kzalloc(size, GFP_KERNEL); | ||
207 | if (tx_ring == NULL) { | ||
208 | dev_err(&pdev->dev, "%s: failed to allocate tx ring struct\n", | ||
209 | netdev->name); | ||
210 | return -ENOMEM; | ||
211 | } | ||
212 | adapter->tx_ring = tx_ring; | ||
213 | |||
214 | tx_ring->num_desc = adapter->num_txd; | ||
215 | tx_ring->txq = netdev_get_tx_queue(netdev, 0); | ||
216 | |||
217 | cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring)); | ||
218 | if (cmd_buf_arr == NULL) { | ||
219 | dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n", | ||
220 | netdev->name); | ||
221 | goto err_out; | ||
222 | } | ||
223 | tx_ring->cmd_buf_arr = cmd_buf_arr; | ||
224 | |||
225 | recv_ctx = &adapter->recv_ctx; | ||
226 | |||
227 | size = adapter->max_rds_rings * sizeof (struct nx_host_rds_ring); | ||
228 | rds_ring = kzalloc(size, GFP_KERNEL); | ||
229 | if (rds_ring == NULL) { | ||
230 | dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n", | ||
231 | netdev->name); | ||
232 | goto err_out; | ||
233 | } | ||
234 | recv_ctx->rds_rings = rds_ring; | ||
235 | |||
236 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | ||
237 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
238 | switch (ring) { | ||
239 | case RCV_RING_NORMAL: | ||
240 | rds_ring->num_desc = adapter->num_rxd; | ||
241 | if (adapter->ahw.cut_through) { | ||
242 | rds_ring->dma_size = | ||
243 | NX_CT_DEFAULT_RX_BUF_LEN; | ||
244 | rds_ring->skb_size = | ||
245 | NX_CT_DEFAULT_RX_BUF_LEN; | ||
246 | } else { | ||
247 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
248 | rds_ring->dma_size = | ||
249 | NX_P3_RX_BUF_MAX_LEN; | ||
250 | else | ||
251 | rds_ring->dma_size = | ||
252 | NX_P2_RX_BUF_MAX_LEN; | ||
253 | rds_ring->skb_size = | ||
254 | rds_ring->dma_size + NET_IP_ALIGN; | ||
255 | } | ||
256 | break; | ||
257 | |||
258 | case RCV_RING_JUMBO: | ||
259 | rds_ring->num_desc = adapter->num_jumbo_rxd; | ||
260 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
261 | rds_ring->dma_size = | ||
262 | NX_P3_RX_JUMBO_BUF_MAX_LEN; | ||
263 | else | ||
264 | rds_ring->dma_size = | ||
265 | NX_P2_RX_JUMBO_BUF_MAX_LEN; | ||
266 | |||
267 | if (adapter->capabilities & NX_CAP0_HW_LRO) | ||
268 | rds_ring->dma_size += NX_LRO_BUFFER_EXTRA; | ||
269 | |||
270 | rds_ring->skb_size = | ||
271 | rds_ring->dma_size + NET_IP_ALIGN; | ||
272 | break; | ||
273 | |||
274 | case RCV_RING_LRO: | ||
275 | rds_ring->num_desc = adapter->num_lro_rxd; | ||
276 | rds_ring->dma_size = NX_RX_LRO_BUFFER_LENGTH; | ||
277 | rds_ring->skb_size = rds_ring->dma_size + NET_IP_ALIGN; | ||
278 | break; | ||
279 | |||
280 | } | ||
281 | rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring)); | ||
282 | if (rds_ring->rx_buf_arr == NULL) { | ||
283 | printk(KERN_ERR "%s: Failed to allocate " | ||
284 | "rx buffer ring %d\n", | ||
285 | netdev->name, ring); | ||
286 | /* free whatever was already allocated */ | ||
287 | goto err_out; | ||
288 | } | ||
289 | INIT_LIST_HEAD(&rds_ring->free_list); | ||
290 | /* | ||
291 | * Now go through all of them, set reference handles | ||
292 | * and put them in the queues. | ||
293 | */ | ||
294 | rx_buf = rds_ring->rx_buf_arr; | ||
295 | for (i = 0; i < rds_ring->num_desc; i++) { | ||
296 | list_add_tail(&rx_buf->list, | ||
297 | &rds_ring->free_list); | ||
298 | rx_buf->ref_handle = i; | ||
299 | rx_buf->state = NETXEN_BUFFER_FREE; | ||
300 | rx_buf++; | ||
301 | } | ||
302 | spin_lock_init(&rds_ring->lock); | ||
303 | } | ||
304 | |||
305 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
306 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
307 | sds_ring->irq = adapter->msix_entries[ring].vector; | ||
308 | sds_ring->adapter = adapter; | ||
309 | sds_ring->num_desc = adapter->num_rxd; | ||
310 | |||
311 | for (i = 0; i < NUM_RCV_DESC_RINGS; i++) | ||
312 | INIT_LIST_HEAD(&sds_ring->free_list[i]); | ||
313 | } | ||
314 | |||
315 | return 0; | ||
316 | |||
317 | err_out: | ||
318 | netxen_free_sw_resources(adapter); | ||
319 | return -ENOMEM; | ||
320 | } | ||
321 | |||
322 | /* | ||
323 | * netxen_decode_crb_addr(0 - utility to translate from internal Phantom CRB | ||
324 | * address to external PCI CRB address. | ||
325 | */ | ||
326 | static u32 netxen_decode_crb_addr(u32 addr) | ||
327 | { | ||
328 | int i; | ||
329 | u32 base_addr, offset, pci_base; | ||
330 | |||
331 | crb_addr_transform_setup(); | ||
332 | |||
333 | pci_base = NETXEN_ADDR_ERROR; | ||
334 | base_addr = addr & 0xfff00000; | ||
335 | offset = addr & 0x000fffff; | ||
336 | |||
337 | for (i = 0; i < NETXEN_MAX_CRB_XFORM; i++) { | ||
338 | if (crb_addr_xform[i] == base_addr) { | ||
339 | pci_base = i << 20; | ||
340 | break; | ||
341 | } | ||
342 | } | ||
343 | if (pci_base == NETXEN_ADDR_ERROR) | ||
344 | return pci_base; | ||
345 | else | ||
346 | return pci_base + offset; | ||
347 | } | ||
348 | |||
349 | #define NETXEN_MAX_ROM_WAIT_USEC 100 | ||
350 | |||
351 | static int netxen_wait_rom_done(struct netxen_adapter *adapter) | ||
352 | { | ||
353 | long timeout = 0; | ||
354 | long done = 0; | ||
355 | |||
356 | cond_resched(); | ||
357 | |||
358 | while (done == 0) { | ||
359 | done = NXRD32(adapter, NETXEN_ROMUSB_GLB_STATUS); | ||
360 | done &= 2; | ||
361 | if (++timeout >= NETXEN_MAX_ROM_WAIT_USEC) { | ||
362 | dev_err(&adapter->pdev->dev, | ||
363 | "Timeout reached waiting for rom done"); | ||
364 | return -EIO; | ||
365 | } | ||
366 | udelay(1); | ||
367 | } | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static int do_rom_fast_read(struct netxen_adapter *adapter, | ||
372 | int addr, int *valp) | ||
373 | { | ||
374 | NXWR32(adapter, NETXEN_ROMUSB_ROM_ADDRESS, addr); | ||
375 | NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); | ||
376 | NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 3); | ||
377 | NXWR32(adapter, NETXEN_ROMUSB_ROM_INSTR_OPCODE, 0xb); | ||
378 | if (netxen_wait_rom_done(adapter)) { | ||
379 | printk("Error waiting for rom done\n"); | ||
380 | return -EIO; | ||
381 | } | ||
382 | /* reset abyte_cnt and dummy_byte_cnt */ | ||
383 | NXWR32(adapter, NETXEN_ROMUSB_ROM_ABYTE_CNT, 0); | ||
384 | udelay(10); | ||
385 | NXWR32(adapter, NETXEN_ROMUSB_ROM_DUMMY_BYTE_CNT, 0); | ||
386 | |||
387 | *valp = NXRD32(adapter, NETXEN_ROMUSB_ROM_RDATA); | ||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | static int do_rom_fast_read_words(struct netxen_adapter *adapter, int addr, | ||
392 | u8 *bytes, size_t size) | ||
393 | { | ||
394 | int addridx; | ||
395 | int ret = 0; | ||
396 | |||
397 | for (addridx = addr; addridx < (addr + size); addridx += 4) { | ||
398 | int v; | ||
399 | ret = do_rom_fast_read(adapter, addridx, &v); | ||
400 | if (ret != 0) | ||
401 | break; | ||
402 | *(__le32 *)bytes = cpu_to_le32(v); | ||
403 | bytes += 4; | ||
404 | } | ||
405 | |||
406 | return ret; | ||
407 | } | ||
408 | |||
409 | int | ||
410 | netxen_rom_fast_read_words(struct netxen_adapter *adapter, int addr, | ||
411 | u8 *bytes, size_t size) | ||
412 | { | ||
413 | int ret; | ||
414 | |||
415 | ret = netxen_rom_lock(adapter); | ||
416 | if (ret < 0) | ||
417 | return ret; | ||
418 | |||
419 | ret = do_rom_fast_read_words(adapter, addr, bytes, size); | ||
420 | |||
421 | netxen_rom_unlock(adapter); | ||
422 | return ret; | ||
423 | } | ||
424 | |||
425 | int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp) | ||
426 | { | ||
427 | int ret; | ||
428 | |||
429 | if (netxen_rom_lock(adapter) != 0) | ||
430 | return -EIO; | ||
431 | |||
432 | ret = do_rom_fast_read(adapter, addr, valp); | ||
433 | netxen_rom_unlock(adapter); | ||
434 | return ret; | ||
435 | } | ||
436 | |||
437 | #define NETXEN_BOARDTYPE 0x4008 | ||
438 | #define NETXEN_BOARDNUM 0x400c | ||
439 | #define NETXEN_CHIPNUM 0x4010 | ||
440 | |||
441 | int netxen_pinit_from_rom(struct netxen_adapter *adapter) | ||
442 | { | ||
443 | int addr, val; | ||
444 | int i, n, init_delay = 0; | ||
445 | struct crb_addr_pair *buf; | ||
446 | unsigned offset; | ||
447 | u32 off; | ||
448 | |||
449 | /* resetall */ | ||
450 | netxen_rom_lock(adapter); | ||
451 | NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0xffffffff); | ||
452 | netxen_rom_unlock(adapter); | ||
453 | |||
454 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { | ||
455 | if (netxen_rom_fast_read(adapter, 0, &n) != 0 || | ||
456 | (n != 0xcafecafe) || | ||
457 | netxen_rom_fast_read(adapter, 4, &n) != 0) { | ||
458 | printk(KERN_ERR "%s: ERROR Reading crb_init area: " | ||
459 | "n: %08x\n", netxen_nic_driver_name, n); | ||
460 | return -EIO; | ||
461 | } | ||
462 | offset = n & 0xffffU; | ||
463 | n = (n >> 16) & 0xffffU; | ||
464 | } else { | ||
465 | if (netxen_rom_fast_read(adapter, 0, &n) != 0 || | ||
466 | !(n & 0x80000000)) { | ||
467 | printk(KERN_ERR "%s: ERROR Reading crb_init area: " | ||
468 | "n: %08x\n", netxen_nic_driver_name, n); | ||
469 | return -EIO; | ||
470 | } | ||
471 | offset = 1; | ||
472 | n &= ~0x80000000; | ||
473 | } | ||
474 | |||
475 | if (n >= 1024) { | ||
476 | printk(KERN_ERR "%s:n=0x%x Error! NetXen card flash not" | ||
477 | " initialized.\n", __func__, n); | ||
478 | return -EIO; | ||
479 | } | ||
480 | |||
481 | buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL); | ||
482 | if (buf == NULL) { | ||
483 | printk("%s: netxen_pinit_from_rom: Unable to calloc memory.\n", | ||
484 | netxen_nic_driver_name); | ||
485 | return -ENOMEM; | ||
486 | } | ||
487 | |||
488 | for (i = 0; i < n; i++) { | ||
489 | if (netxen_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 || | ||
490 | netxen_rom_fast_read(adapter, 8*i + 4*offset + 4, &addr) != 0) { | ||
491 | kfree(buf); | ||
492 | return -EIO; | ||
493 | } | ||
494 | |||
495 | buf[i].addr = addr; | ||
496 | buf[i].data = val; | ||
497 | |||
498 | } | ||
499 | |||
500 | for (i = 0; i < n; i++) { | ||
501 | |||
502 | off = netxen_decode_crb_addr(buf[i].addr); | ||
503 | if (off == NETXEN_ADDR_ERROR) { | ||
504 | printk(KERN_ERR"CRB init value out of range %x\n", | ||
505 | buf[i].addr); | ||
506 | continue; | ||
507 | } | ||
508 | off += NETXEN_PCI_CRBSPACE; | ||
509 | |||
510 | if (off & 1) | ||
511 | continue; | ||
512 | |||
513 | /* skipping cold reboot MAGIC */ | ||
514 | if (off == NETXEN_CAM_RAM(0x1fc)) | ||
515 | continue; | ||
516 | |||
517 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { | ||
518 | if (off == (NETXEN_CRB_I2C0 + 0x1c)) | ||
519 | continue; | ||
520 | /* do not reset PCI */ | ||
521 | if (off == (ROMUSB_GLB + 0xbc)) | ||
522 | continue; | ||
523 | if (off == (ROMUSB_GLB + 0xa8)) | ||
524 | continue; | ||
525 | if (off == (ROMUSB_GLB + 0xc8)) /* core clock */ | ||
526 | continue; | ||
527 | if (off == (ROMUSB_GLB + 0x24)) /* MN clock */ | ||
528 | continue; | ||
529 | if (off == (ROMUSB_GLB + 0x1c)) /* MS clock */ | ||
530 | continue; | ||
531 | if ((off & 0x0ff00000) == NETXEN_CRB_DDR_NET) | ||
532 | continue; | ||
533 | if (off == (NETXEN_CRB_PEG_NET_1 + 0x18) && | ||
534 | !NX_IS_REVISION_P3P(adapter->ahw.revision_id)) | ||
535 | buf[i].data = 0x1020; | ||
536 | /* skip the function enable register */ | ||
537 | if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION)) | ||
538 | continue; | ||
539 | if (off == NETXEN_PCIE_REG(PCIE_SETUP_FUNCTION2)) | ||
540 | continue; | ||
541 | if ((off & 0x0ff00000) == NETXEN_CRB_SMB) | ||
542 | continue; | ||
543 | } | ||
544 | |||
545 | init_delay = 1; | ||
546 | /* After writing this register, HW needs time for CRB */ | ||
547 | /* to quiet down (else crb_window returns 0xffffffff) */ | ||
548 | if (off == NETXEN_ROMUSB_GLB_SW_RESET) { | ||
549 | init_delay = 1000; | ||
550 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
551 | /* hold xdma in reset also */ | ||
552 | buf[i].data = NETXEN_NIC_XDMA_RESET; | ||
553 | buf[i].data = 0x8000ff; | ||
554 | } | ||
555 | } | ||
556 | |||
557 | NXWR32(adapter, off, buf[i].data); | ||
558 | |||
559 | msleep(init_delay); | ||
560 | } | ||
561 | kfree(buf); | ||
562 | |||
563 | /* disable_peg_cache_all */ | ||
564 | |||
565 | /* unreset_net_cache */ | ||
566 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
567 | val = NXRD32(adapter, NETXEN_ROMUSB_GLB_SW_RESET); | ||
568 | NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, (val & 0xffffff0f)); | ||
569 | } | ||
570 | |||
571 | /* p2dn replyCount */ | ||
572 | NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0xec, 0x1e); | ||
573 | /* disable_peg_cache 0 */ | ||
574 | NXWR32(adapter, NETXEN_CRB_PEG_NET_D + 0x4c, 8); | ||
575 | /* disable_peg_cache 1 */ | ||
576 | NXWR32(adapter, NETXEN_CRB_PEG_NET_I + 0x4c, 8); | ||
577 | |||
578 | /* peg_clr_all */ | ||
579 | |||
580 | /* peg_clr 0 */ | ||
581 | NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0x8, 0); | ||
582 | NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0xc, 0); | ||
583 | /* peg_clr 1 */ | ||
584 | NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0x8, 0); | ||
585 | NXWR32(adapter, NETXEN_CRB_PEG_NET_1 + 0xc, 0); | ||
586 | /* peg_clr 2 */ | ||
587 | NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0x8, 0); | ||
588 | NXWR32(adapter, NETXEN_CRB_PEG_NET_2 + 0xc, 0); | ||
589 | /* peg_clr 3 */ | ||
590 | NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0x8, 0); | ||
591 | NXWR32(adapter, NETXEN_CRB_PEG_NET_3 + 0xc, 0); | ||
592 | return 0; | ||
593 | } | ||
594 | |||
595 | static struct uni_table_desc *nx_get_table_desc(const u8 *unirom, int section) | ||
596 | { | ||
597 | uint32_t i; | ||
598 | struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0]; | ||
599 | __le32 entries = cpu_to_le32(directory->num_entries); | ||
600 | |||
601 | for (i = 0; i < entries; i++) { | ||
602 | |||
603 | __le32 offs = cpu_to_le32(directory->findex) + | ||
604 | (i * cpu_to_le32(directory->entry_size)); | ||
605 | __le32 tab_type = cpu_to_le32(*((u32 *)&unirom[offs] + 8)); | ||
606 | |||
607 | if (tab_type == section) | ||
608 | return (struct uni_table_desc *) &unirom[offs]; | ||
609 | } | ||
610 | |||
611 | return NULL; | ||
612 | } | ||
613 | |||
614 | #define QLCNIC_FILEHEADER_SIZE (14 * 4) | ||
615 | |||
616 | static int | ||
617 | netxen_nic_validate_header(struct netxen_adapter *adapter) | ||
618 | { | ||
619 | const u8 *unirom = adapter->fw->data; | ||
620 | struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0]; | ||
621 | u32 fw_file_size = adapter->fw->size; | ||
622 | u32 tab_size; | ||
623 | __le32 entries; | ||
624 | __le32 entry_size; | ||
625 | |||
626 | if (fw_file_size < QLCNIC_FILEHEADER_SIZE) | ||
627 | return -EINVAL; | ||
628 | |||
629 | entries = cpu_to_le32(directory->num_entries); | ||
630 | entry_size = cpu_to_le32(directory->entry_size); | ||
631 | tab_size = cpu_to_le32(directory->findex) + (entries * entry_size); | ||
632 | |||
633 | if (fw_file_size < tab_size) | ||
634 | return -EINVAL; | ||
635 | |||
636 | return 0; | ||
637 | } | ||
638 | |||
639 | static int | ||
640 | netxen_nic_validate_bootld(struct netxen_adapter *adapter) | ||
641 | { | ||
642 | struct uni_table_desc *tab_desc; | ||
643 | struct uni_data_desc *descr; | ||
644 | const u8 *unirom = adapter->fw->data; | ||
645 | __le32 idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + | ||
646 | NX_UNI_BOOTLD_IDX_OFF)); | ||
647 | u32 offs; | ||
648 | u32 tab_size; | ||
649 | u32 data_size; | ||
650 | |||
651 | tab_desc = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_BOOTLD); | ||
652 | |||
653 | if (!tab_desc) | ||
654 | return -EINVAL; | ||
655 | |||
656 | tab_size = cpu_to_le32(tab_desc->findex) + | ||
657 | (cpu_to_le32(tab_desc->entry_size) * (idx + 1)); | ||
658 | |||
659 | if (adapter->fw->size < tab_size) | ||
660 | return -EINVAL; | ||
661 | |||
662 | offs = cpu_to_le32(tab_desc->findex) + | ||
663 | (cpu_to_le32(tab_desc->entry_size) * (idx)); | ||
664 | descr = (struct uni_data_desc *)&unirom[offs]; | ||
665 | |||
666 | data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size); | ||
667 | |||
668 | if (adapter->fw->size < data_size) | ||
669 | return -EINVAL; | ||
670 | |||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | static int | ||
675 | netxen_nic_validate_fw(struct netxen_adapter *adapter) | ||
676 | { | ||
677 | struct uni_table_desc *tab_desc; | ||
678 | struct uni_data_desc *descr; | ||
679 | const u8 *unirom = adapter->fw->data; | ||
680 | __le32 idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + | ||
681 | NX_UNI_FIRMWARE_IDX_OFF)); | ||
682 | u32 offs; | ||
683 | u32 tab_size; | ||
684 | u32 data_size; | ||
685 | |||
686 | tab_desc = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_FW); | ||
687 | |||
688 | if (!tab_desc) | ||
689 | return -EINVAL; | ||
690 | |||
691 | tab_size = cpu_to_le32(tab_desc->findex) + | ||
692 | (cpu_to_le32(tab_desc->entry_size) * (idx + 1)); | ||
693 | |||
694 | if (adapter->fw->size < tab_size) | ||
695 | return -EINVAL; | ||
696 | |||
697 | offs = cpu_to_le32(tab_desc->findex) + | ||
698 | (cpu_to_le32(tab_desc->entry_size) * (idx)); | ||
699 | descr = (struct uni_data_desc *)&unirom[offs]; | ||
700 | data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size); | ||
701 | |||
702 | if (adapter->fw->size < data_size) | ||
703 | return -EINVAL; | ||
704 | |||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | |||
709 | static int | ||
710 | netxen_nic_validate_product_offs(struct netxen_adapter *adapter) | ||
711 | { | ||
712 | struct uni_table_desc *ptab_descr; | ||
713 | const u8 *unirom = adapter->fw->data; | ||
714 | int mn_present = (NX_IS_REVISION_P2(adapter->ahw.revision_id)) ? | ||
715 | 1 : netxen_p3_has_mn(adapter); | ||
716 | __le32 entries; | ||
717 | __le32 entry_size; | ||
718 | u32 tab_size; | ||
719 | u32 i; | ||
720 | |||
721 | ptab_descr = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_PRODUCT_TBL); | ||
722 | if (ptab_descr == NULL) | ||
723 | return -EINVAL; | ||
724 | |||
725 | entries = cpu_to_le32(ptab_descr->num_entries); | ||
726 | entry_size = cpu_to_le32(ptab_descr->entry_size); | ||
727 | tab_size = cpu_to_le32(ptab_descr->findex) + (entries * entry_size); | ||
728 | |||
729 | if (adapter->fw->size < tab_size) | ||
730 | return -EINVAL; | ||
731 | |||
732 | nomn: | ||
733 | for (i = 0; i < entries; i++) { | ||
734 | |||
735 | __le32 flags, file_chiprev, offs; | ||
736 | u8 chiprev = adapter->ahw.revision_id; | ||
737 | uint32_t flagbit; | ||
738 | |||
739 | offs = cpu_to_le32(ptab_descr->findex) + | ||
740 | (i * cpu_to_le32(ptab_descr->entry_size)); | ||
741 | flags = cpu_to_le32(*((int *)&unirom[offs] + NX_UNI_FLAGS_OFF)); | ||
742 | file_chiprev = cpu_to_le32(*((int *)&unirom[offs] + | ||
743 | NX_UNI_CHIP_REV_OFF)); | ||
744 | |||
745 | flagbit = mn_present ? 1 : 2; | ||
746 | |||
747 | if ((chiprev == file_chiprev) && | ||
748 | ((1ULL << flagbit) & flags)) { | ||
749 | adapter->file_prd_off = offs; | ||
750 | return 0; | ||
751 | } | ||
752 | } | ||
753 | |||
754 | if (mn_present && NX_IS_REVISION_P3(adapter->ahw.revision_id)) { | ||
755 | mn_present = 0; | ||
756 | goto nomn; | ||
757 | } | ||
758 | |||
759 | return -EINVAL; | ||
760 | } | ||
761 | |||
762 | static int | ||
763 | netxen_nic_validate_unified_romimage(struct netxen_adapter *adapter) | ||
764 | { | ||
765 | if (netxen_nic_validate_header(adapter)) { | ||
766 | dev_err(&adapter->pdev->dev, | ||
767 | "unified image: header validation failed\n"); | ||
768 | return -EINVAL; | ||
769 | } | ||
770 | |||
771 | if (netxen_nic_validate_product_offs(adapter)) { | ||
772 | dev_err(&adapter->pdev->dev, | ||
773 | "unified image: product validation failed\n"); | ||
774 | return -EINVAL; | ||
775 | } | ||
776 | |||
777 | if (netxen_nic_validate_bootld(adapter)) { | ||
778 | dev_err(&adapter->pdev->dev, | ||
779 | "unified image: bootld validation failed\n"); | ||
780 | return -EINVAL; | ||
781 | } | ||
782 | |||
783 | if (netxen_nic_validate_fw(adapter)) { | ||
784 | dev_err(&adapter->pdev->dev, | ||
785 | "unified image: firmware validation failed\n"); | ||
786 | return -EINVAL; | ||
787 | } | ||
788 | |||
789 | return 0; | ||
790 | } | ||
791 | |||
792 | static struct uni_data_desc *nx_get_data_desc(struct netxen_adapter *adapter, | ||
793 | u32 section, u32 idx_offset) | ||
794 | { | ||
795 | const u8 *unirom = adapter->fw->data; | ||
796 | int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + | ||
797 | idx_offset)); | ||
798 | struct uni_table_desc *tab_desc; | ||
799 | __le32 offs; | ||
800 | |||
801 | tab_desc = nx_get_table_desc(unirom, section); | ||
802 | |||
803 | if (tab_desc == NULL) | ||
804 | return NULL; | ||
805 | |||
806 | offs = cpu_to_le32(tab_desc->findex) + | ||
807 | (cpu_to_le32(tab_desc->entry_size) * idx); | ||
808 | |||
809 | return (struct uni_data_desc *)&unirom[offs]; | ||
810 | } | ||
811 | |||
812 | static u8 * | ||
813 | nx_get_bootld_offs(struct netxen_adapter *adapter) | ||
814 | { | ||
815 | u32 offs = NETXEN_BOOTLD_START; | ||
816 | |||
817 | if (adapter->fw_type == NX_UNIFIED_ROMIMAGE) | ||
818 | offs = cpu_to_le32((nx_get_data_desc(adapter, | ||
819 | NX_UNI_DIR_SECT_BOOTLD, | ||
820 | NX_UNI_BOOTLD_IDX_OFF))->findex); | ||
821 | |||
822 | return (u8 *)&adapter->fw->data[offs]; | ||
823 | } | ||
824 | |||
825 | static u8 * | ||
826 | nx_get_fw_offs(struct netxen_adapter *adapter) | ||
827 | { | ||
828 | u32 offs = NETXEN_IMAGE_START; | ||
829 | |||
830 | if (adapter->fw_type == NX_UNIFIED_ROMIMAGE) | ||
831 | offs = cpu_to_le32((nx_get_data_desc(adapter, | ||
832 | NX_UNI_DIR_SECT_FW, | ||
833 | NX_UNI_FIRMWARE_IDX_OFF))->findex); | ||
834 | |||
835 | return (u8 *)&adapter->fw->data[offs]; | ||
836 | } | ||
837 | |||
838 | static __le32 | ||
839 | nx_get_fw_size(struct netxen_adapter *adapter) | ||
840 | { | ||
841 | if (adapter->fw_type == NX_UNIFIED_ROMIMAGE) | ||
842 | return cpu_to_le32((nx_get_data_desc(adapter, | ||
843 | NX_UNI_DIR_SECT_FW, | ||
844 | NX_UNI_FIRMWARE_IDX_OFF))->size); | ||
845 | else | ||
846 | return cpu_to_le32( | ||
847 | *(u32 *)&adapter->fw->data[NX_FW_SIZE_OFFSET]); | ||
848 | } | ||
849 | |||
850 | static __le32 | ||
851 | nx_get_fw_version(struct netxen_adapter *adapter) | ||
852 | { | ||
853 | struct uni_data_desc *fw_data_desc; | ||
854 | const struct firmware *fw = adapter->fw; | ||
855 | __le32 major, minor, sub; | ||
856 | const u8 *ver_str; | ||
857 | int i, ret = 0; | ||
858 | |||
859 | if (adapter->fw_type == NX_UNIFIED_ROMIMAGE) { | ||
860 | |||
861 | fw_data_desc = nx_get_data_desc(adapter, | ||
862 | NX_UNI_DIR_SECT_FW, NX_UNI_FIRMWARE_IDX_OFF); | ||
863 | ver_str = fw->data + cpu_to_le32(fw_data_desc->findex) + | ||
864 | cpu_to_le32(fw_data_desc->size) - 17; | ||
865 | |||
866 | for (i = 0; i < 12; i++) { | ||
867 | if (!strncmp(&ver_str[i], "REV=", 4)) { | ||
868 | ret = sscanf(&ver_str[i+4], "%u.%u.%u ", | ||
869 | &major, &minor, &sub); | ||
870 | break; | ||
871 | } | ||
872 | } | ||
873 | |||
874 | if (ret != 3) | ||
875 | return 0; | ||
876 | |||
877 | return major + (minor << 8) + (sub << 16); | ||
878 | |||
879 | } else | ||
880 | return cpu_to_le32(*(u32 *)&fw->data[NX_FW_VERSION_OFFSET]); | ||
881 | } | ||
882 | |||
883 | static __le32 | ||
884 | nx_get_bios_version(struct netxen_adapter *adapter) | ||
885 | { | ||
886 | const struct firmware *fw = adapter->fw; | ||
887 | __le32 bios_ver, prd_off = adapter->file_prd_off; | ||
888 | |||
889 | if (adapter->fw_type == NX_UNIFIED_ROMIMAGE) { | ||
890 | bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off]) | ||
891 | + NX_UNI_BIOS_VERSION_OFF)); | ||
892 | return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + | ||
893 | (bios_ver >> 24); | ||
894 | } else | ||
895 | return cpu_to_le32(*(u32 *)&fw->data[NX_BIOS_VERSION_OFFSET]); | ||
896 | |||
897 | } | ||
898 | |||
899 | int | ||
900 | netxen_need_fw_reset(struct netxen_adapter *adapter) | ||
901 | { | ||
902 | u32 count, old_count; | ||
903 | u32 val, version, major, minor, build; | ||
904 | int i, timeout; | ||
905 | u8 fw_type; | ||
906 | |||
907 | /* NX2031 firmware doesn't support heartbit */ | ||
908 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
909 | return 1; | ||
910 | |||
911 | if (adapter->need_fw_reset) | ||
912 | return 1; | ||
913 | |||
914 | /* last attempt had failed */ | ||
915 | if (NXRD32(adapter, CRB_CMDPEG_STATE) == PHAN_INITIALIZE_FAILED) | ||
916 | return 1; | ||
917 | |||
918 | old_count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER); | ||
919 | |||
920 | for (i = 0; i < 10; i++) { | ||
921 | |||
922 | timeout = msleep_interruptible(200); | ||
923 | if (timeout) { | ||
924 | NXWR32(adapter, CRB_CMDPEG_STATE, | ||
925 | PHAN_INITIALIZE_FAILED); | ||
926 | return -EINTR; | ||
927 | } | ||
928 | |||
929 | count = NXRD32(adapter, NETXEN_PEG_ALIVE_COUNTER); | ||
930 | if (count != old_count) | ||
931 | break; | ||
932 | } | ||
933 | |||
934 | /* firmware is dead */ | ||
935 | if (count == old_count) | ||
936 | return 1; | ||
937 | |||
938 | /* check if we have got newer or different file firmware */ | ||
939 | if (adapter->fw) { | ||
940 | |||
941 | val = nx_get_fw_version(adapter); | ||
942 | |||
943 | version = NETXEN_DECODE_VERSION(val); | ||
944 | |||
945 | major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); | ||
946 | minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); | ||
947 | build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); | ||
948 | |||
949 | if (version > NETXEN_VERSION_CODE(major, minor, build)) | ||
950 | return 1; | ||
951 | |||
952 | if (version == NETXEN_VERSION_CODE(major, minor, build) && | ||
953 | adapter->fw_type != NX_UNIFIED_ROMIMAGE) { | ||
954 | |||
955 | val = NXRD32(adapter, NETXEN_MIU_MN_CONTROL); | ||
956 | fw_type = (val & 0x4) ? | ||
957 | NX_P3_CT_ROMIMAGE : NX_P3_MN_ROMIMAGE; | ||
958 | |||
959 | if (adapter->fw_type != fw_type) | ||
960 | return 1; | ||
961 | } | ||
962 | } | ||
963 | |||
964 | return 0; | ||
965 | } | ||
966 | |||
967 | #define NETXEN_MIN_P3_FW_SUPP NETXEN_VERSION_CODE(4, 0, 505) | ||
968 | |||
969 | int | ||
970 | netxen_check_flash_fw_compatibility(struct netxen_adapter *adapter) | ||
971 | { | ||
972 | u32 flash_fw_ver, min_fw_ver; | ||
973 | |||
974 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
975 | return 0; | ||
976 | |||
977 | if (netxen_rom_fast_read(adapter, | ||
978 | NX_FW_VERSION_OFFSET, (int *)&flash_fw_ver)) { | ||
979 | dev_err(&adapter->pdev->dev, "Unable to read flash fw" | ||
980 | "version\n"); | ||
981 | return -EIO; | ||
982 | } | ||
983 | |||
984 | flash_fw_ver = NETXEN_DECODE_VERSION(flash_fw_ver); | ||
985 | min_fw_ver = NETXEN_MIN_P3_FW_SUPP; | ||
986 | if (flash_fw_ver >= min_fw_ver) | ||
987 | return 0; | ||
988 | |||
989 | dev_info(&adapter->pdev->dev, "Flash fw[%d.%d.%d] is < min fw supported" | ||
990 | "[4.0.505]. Please update firmware on flash\n", | ||
991 | _major(flash_fw_ver), _minor(flash_fw_ver), | ||
992 | _build(flash_fw_ver)); | ||
993 | return -EINVAL; | ||
994 | } | ||
995 | |||
996 | static char *fw_name[] = { | ||
997 | NX_P2_MN_ROMIMAGE_NAME, | ||
998 | NX_P3_CT_ROMIMAGE_NAME, | ||
999 | NX_P3_MN_ROMIMAGE_NAME, | ||
1000 | NX_UNIFIED_ROMIMAGE_NAME, | ||
1001 | NX_FLASH_ROMIMAGE_NAME, | ||
1002 | }; | ||
1003 | |||
1004 | int | ||
1005 | netxen_load_firmware(struct netxen_adapter *adapter) | ||
1006 | { | ||
1007 | u64 *ptr64; | ||
1008 | u32 i, flashaddr, size; | ||
1009 | const struct firmware *fw = adapter->fw; | ||
1010 | struct pci_dev *pdev = adapter->pdev; | ||
1011 | |||
1012 | dev_info(&pdev->dev, "loading firmware from %s\n", | ||
1013 | fw_name[adapter->fw_type]); | ||
1014 | |||
1015 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
1016 | NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 1); | ||
1017 | |||
1018 | if (fw) { | ||
1019 | __le64 data; | ||
1020 | |||
1021 | size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8; | ||
1022 | |||
1023 | ptr64 = (u64 *)nx_get_bootld_offs(adapter); | ||
1024 | flashaddr = NETXEN_BOOTLD_START; | ||
1025 | |||
1026 | for (i = 0; i < size; i++) { | ||
1027 | data = cpu_to_le64(ptr64[i]); | ||
1028 | |||
1029 | if (adapter->pci_mem_write(adapter, flashaddr, data)) | ||
1030 | return -EIO; | ||
1031 | |||
1032 | flashaddr += 8; | ||
1033 | } | ||
1034 | |||
1035 | size = (__force u32)nx_get_fw_size(adapter) / 8; | ||
1036 | |||
1037 | ptr64 = (u64 *)nx_get_fw_offs(adapter); | ||
1038 | flashaddr = NETXEN_IMAGE_START; | ||
1039 | |||
1040 | for (i = 0; i < size; i++) { | ||
1041 | data = cpu_to_le64(ptr64[i]); | ||
1042 | |||
1043 | if (adapter->pci_mem_write(adapter, | ||
1044 | flashaddr, data)) | ||
1045 | return -EIO; | ||
1046 | |||
1047 | flashaddr += 8; | ||
1048 | } | ||
1049 | |||
1050 | size = (__force u32)nx_get_fw_size(adapter) % 8; | ||
1051 | if (size) { | ||
1052 | data = cpu_to_le64(ptr64[i]); | ||
1053 | |||
1054 | if (adapter->pci_mem_write(adapter, | ||
1055 | flashaddr, data)) | ||
1056 | return -EIO; | ||
1057 | } | ||
1058 | |||
1059 | } else { | ||
1060 | u64 data; | ||
1061 | u32 hi, lo; | ||
1062 | |||
1063 | size = (NETXEN_IMAGE_START - NETXEN_BOOTLD_START) / 8; | ||
1064 | flashaddr = NETXEN_BOOTLD_START; | ||
1065 | |||
1066 | for (i = 0; i < size; i++) { | ||
1067 | if (netxen_rom_fast_read(adapter, | ||
1068 | flashaddr, (int *)&lo) != 0) | ||
1069 | return -EIO; | ||
1070 | if (netxen_rom_fast_read(adapter, | ||
1071 | flashaddr + 4, (int *)&hi) != 0) | ||
1072 | return -EIO; | ||
1073 | |||
1074 | /* hi, lo are already in host endian byteorder */ | ||
1075 | data = (((u64)hi << 32) | lo); | ||
1076 | |||
1077 | if (adapter->pci_mem_write(adapter, | ||
1078 | flashaddr, data)) | ||
1079 | return -EIO; | ||
1080 | |||
1081 | flashaddr += 8; | ||
1082 | } | ||
1083 | } | ||
1084 | msleep(1); | ||
1085 | |||
1086 | if (NX_IS_REVISION_P3P(adapter->ahw.revision_id)) { | ||
1087 | NXWR32(adapter, NETXEN_CRB_PEG_NET_0 + 0x18, 0x1020); | ||
1088 | NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0x80001e); | ||
1089 | } else if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
1090 | NXWR32(adapter, NETXEN_ROMUSB_GLB_SW_RESET, 0x80001d); | ||
1091 | else { | ||
1092 | NXWR32(adapter, NETXEN_ROMUSB_GLB_CHIP_CLK_CTRL, 0x3fff); | ||
1093 | NXWR32(adapter, NETXEN_ROMUSB_GLB_CAS_RST, 0); | ||
1094 | } | ||
1095 | |||
1096 | return 0; | ||
1097 | } | ||
1098 | |||
1099 | static int | ||
1100 | netxen_validate_firmware(struct netxen_adapter *adapter) | ||
1101 | { | ||
1102 | __le32 val; | ||
1103 | __le32 flash_fw_ver; | ||
1104 | u32 file_fw_ver, min_ver, bios; | ||
1105 | struct pci_dev *pdev = adapter->pdev; | ||
1106 | const struct firmware *fw = adapter->fw; | ||
1107 | u8 fw_type = adapter->fw_type; | ||
1108 | u32 crbinit_fix_fw; | ||
1109 | |||
1110 | if (fw_type == NX_UNIFIED_ROMIMAGE) { | ||
1111 | if (netxen_nic_validate_unified_romimage(adapter)) | ||
1112 | return -EINVAL; | ||
1113 | } else { | ||
1114 | val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]); | ||
1115 | if ((__force u32)val != NETXEN_BDINFO_MAGIC) | ||
1116 | return -EINVAL; | ||
1117 | |||
1118 | if (fw->size < NX_FW_MIN_SIZE) | ||
1119 | return -EINVAL; | ||
1120 | } | ||
1121 | |||
1122 | val = nx_get_fw_version(adapter); | ||
1123 | |||
1124 | if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) | ||
1125 | min_ver = NETXEN_MIN_P3_FW_SUPP; | ||
1126 | else | ||
1127 | min_ver = NETXEN_VERSION_CODE(3, 4, 216); | ||
1128 | |||
1129 | file_fw_ver = NETXEN_DECODE_VERSION(val); | ||
1130 | |||
1131 | if ((_major(file_fw_ver) > _NETXEN_NIC_LINUX_MAJOR) || | ||
1132 | (file_fw_ver < min_ver)) { | ||
1133 | dev_err(&pdev->dev, | ||
1134 | "%s: firmware version %d.%d.%d unsupported\n", | ||
1135 | fw_name[fw_type], _major(file_fw_ver), _minor(file_fw_ver), | ||
1136 | _build(file_fw_ver)); | ||
1137 | return -EINVAL; | ||
1138 | } | ||
1139 | |||
1140 | val = nx_get_bios_version(adapter); | ||
1141 | netxen_rom_fast_read(adapter, NX_BIOS_VERSION_OFFSET, (int *)&bios); | ||
1142 | if ((__force u32)val != bios) { | ||
1143 | dev_err(&pdev->dev, "%s: firmware bios is incompatible\n", | ||
1144 | fw_name[fw_type]); | ||
1145 | return -EINVAL; | ||
1146 | } | ||
1147 | |||
1148 | if (netxen_rom_fast_read(adapter, | ||
1149 | NX_FW_VERSION_OFFSET, (int *)&flash_fw_ver)) { | ||
1150 | dev_err(&pdev->dev, "Unable to read flash fw version\n"); | ||
1151 | return -EIO; | ||
1152 | } | ||
1153 | flash_fw_ver = NETXEN_DECODE_VERSION(flash_fw_ver); | ||
1154 | |||
1155 | /* New fw from file is not allowed, if fw on flash is < 4.0.554 */ | ||
1156 | crbinit_fix_fw = NETXEN_VERSION_CODE(4, 0, 554); | ||
1157 | if (file_fw_ver >= crbinit_fix_fw && flash_fw_ver < crbinit_fix_fw && | ||
1158 | NX_IS_REVISION_P3(adapter->ahw.revision_id)) { | ||
1159 | dev_err(&pdev->dev, "Incompatibility detected between driver " | ||
1160 | "and firmware version on flash. This configuration " | ||
1161 | "is not recommended. Please update the firmware on " | ||
1162 | "flash immediately\n"); | ||
1163 | return -EINVAL; | ||
1164 | } | ||
1165 | |||
1166 | /* check if flashed firmware is newer only for no-mn and P2 case*/ | ||
1167 | if (!netxen_p3_has_mn(adapter) || | ||
1168 | NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
1169 | if (flash_fw_ver > file_fw_ver) { | ||
1170 | dev_info(&pdev->dev, "%s: firmware is older than flash\n", | ||
1171 | fw_name[fw_type]); | ||
1172 | return -EINVAL; | ||
1173 | } | ||
1174 | } | ||
1175 | |||
1176 | NXWR32(adapter, NETXEN_CAM_RAM(0x1fc), NETXEN_BDINFO_MAGIC); | ||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | static void | ||
1181 | nx_get_next_fwtype(struct netxen_adapter *adapter) | ||
1182 | { | ||
1183 | u8 fw_type; | ||
1184 | |||
1185 | switch (adapter->fw_type) { | ||
1186 | case NX_UNKNOWN_ROMIMAGE: | ||
1187 | fw_type = NX_UNIFIED_ROMIMAGE; | ||
1188 | break; | ||
1189 | |||
1190 | case NX_UNIFIED_ROMIMAGE: | ||
1191 | if (NX_IS_REVISION_P3P(adapter->ahw.revision_id)) | ||
1192 | fw_type = NX_FLASH_ROMIMAGE; | ||
1193 | else if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
1194 | fw_type = NX_P2_MN_ROMIMAGE; | ||
1195 | else if (netxen_p3_has_mn(adapter)) | ||
1196 | fw_type = NX_P3_MN_ROMIMAGE; | ||
1197 | else | ||
1198 | fw_type = NX_P3_CT_ROMIMAGE; | ||
1199 | break; | ||
1200 | |||
1201 | case NX_P3_MN_ROMIMAGE: | ||
1202 | fw_type = NX_P3_CT_ROMIMAGE; | ||
1203 | break; | ||
1204 | |||
1205 | case NX_P2_MN_ROMIMAGE: | ||
1206 | case NX_P3_CT_ROMIMAGE: | ||
1207 | default: | ||
1208 | fw_type = NX_FLASH_ROMIMAGE; | ||
1209 | break; | ||
1210 | } | ||
1211 | |||
1212 | adapter->fw_type = fw_type; | ||
1213 | } | ||
1214 | |||
1215 | static int | ||
1216 | netxen_p3_has_mn(struct netxen_adapter *adapter) | ||
1217 | { | ||
1218 | u32 capability, flashed_ver; | ||
1219 | capability = 0; | ||
1220 | |||
1221 | /* NX2031 always had MN */ | ||
1222 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
1223 | return 1; | ||
1224 | |||
1225 | netxen_rom_fast_read(adapter, | ||
1226 | NX_FW_VERSION_OFFSET, (int *)&flashed_ver); | ||
1227 | flashed_ver = NETXEN_DECODE_VERSION(flashed_ver); | ||
1228 | |||
1229 | if (flashed_ver >= NETXEN_VERSION_CODE(4, 0, 220)) { | ||
1230 | |||
1231 | capability = NXRD32(adapter, NX_PEG_TUNE_CAPABILITY); | ||
1232 | if (capability & NX_PEG_TUNE_MN_PRESENT) | ||
1233 | return 1; | ||
1234 | } | ||
1235 | return 0; | ||
1236 | } | ||
1237 | |||
1238 | void netxen_request_firmware(struct netxen_adapter *adapter) | ||
1239 | { | ||
1240 | struct pci_dev *pdev = adapter->pdev; | ||
1241 | int rc = 0; | ||
1242 | |||
1243 | adapter->fw_type = NX_UNKNOWN_ROMIMAGE; | ||
1244 | |||
1245 | next: | ||
1246 | nx_get_next_fwtype(adapter); | ||
1247 | |||
1248 | if (adapter->fw_type == NX_FLASH_ROMIMAGE) { | ||
1249 | adapter->fw = NULL; | ||
1250 | } else { | ||
1251 | rc = request_firmware(&adapter->fw, | ||
1252 | fw_name[adapter->fw_type], &pdev->dev); | ||
1253 | if (rc != 0) | ||
1254 | goto next; | ||
1255 | |||
1256 | rc = netxen_validate_firmware(adapter); | ||
1257 | if (rc != 0) { | ||
1258 | release_firmware(adapter->fw); | ||
1259 | msleep(1); | ||
1260 | goto next; | ||
1261 | } | ||
1262 | } | ||
1263 | } | ||
1264 | |||
1265 | |||
1266 | void | ||
1267 | netxen_release_firmware(struct netxen_adapter *adapter) | ||
1268 | { | ||
1269 | if (adapter->fw) | ||
1270 | release_firmware(adapter->fw); | ||
1271 | adapter->fw = NULL; | ||
1272 | } | ||
1273 | |||
1274 | int netxen_init_dummy_dma(struct netxen_adapter *adapter) | ||
1275 | { | ||
1276 | u64 addr; | ||
1277 | u32 hi, lo; | ||
1278 | |||
1279 | if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
1280 | return 0; | ||
1281 | |||
1282 | adapter->dummy_dma.addr = pci_alloc_consistent(adapter->pdev, | ||
1283 | NETXEN_HOST_DUMMY_DMA_SIZE, | ||
1284 | &adapter->dummy_dma.phys_addr); | ||
1285 | if (adapter->dummy_dma.addr == NULL) { | ||
1286 | dev_err(&adapter->pdev->dev, | ||
1287 | "ERROR: Could not allocate dummy DMA memory\n"); | ||
1288 | return -ENOMEM; | ||
1289 | } | ||
1290 | |||
1291 | addr = (uint64_t) adapter->dummy_dma.phys_addr; | ||
1292 | hi = (addr >> 32) & 0xffffffff; | ||
1293 | lo = addr & 0xffffffff; | ||
1294 | |||
1295 | NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, hi); | ||
1296 | NXWR32(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, lo); | ||
1297 | |||
1298 | return 0; | ||
1299 | } | ||
1300 | |||
1301 | /* | ||
1302 | * NetXen DMA watchdog control: | ||
1303 | * | ||
1304 | * Bit 0 : enabled => R/O: 1 watchdog active, 0 inactive | ||
1305 | * Bit 1 : disable_request => 1 req disable dma watchdog | ||
1306 | * Bit 2 : enable_request => 1 req enable dma watchdog | ||
1307 | * Bit 3-31 : unused | ||
1308 | */ | ||
1309 | void netxen_free_dummy_dma(struct netxen_adapter *adapter) | ||
1310 | { | ||
1311 | int i = 100; | ||
1312 | u32 ctrl; | ||
1313 | |||
1314 | if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
1315 | return; | ||
1316 | |||
1317 | if (!adapter->dummy_dma.addr) | ||
1318 | return; | ||
1319 | |||
1320 | ctrl = NXRD32(adapter, NETXEN_DMA_WATCHDOG_CTRL); | ||
1321 | if ((ctrl & 0x1) != 0) { | ||
1322 | NXWR32(adapter, NETXEN_DMA_WATCHDOG_CTRL, (ctrl | 0x2)); | ||
1323 | |||
1324 | while ((ctrl & 0x1) != 0) { | ||
1325 | |||
1326 | msleep(50); | ||
1327 | |||
1328 | ctrl = NXRD32(adapter, NETXEN_DMA_WATCHDOG_CTRL); | ||
1329 | |||
1330 | if (--i == 0) | ||
1331 | break; | ||
1332 | } | ||
1333 | } | ||
1334 | |||
1335 | if (i) { | ||
1336 | pci_free_consistent(adapter->pdev, | ||
1337 | NETXEN_HOST_DUMMY_DMA_SIZE, | ||
1338 | adapter->dummy_dma.addr, | ||
1339 | adapter->dummy_dma.phys_addr); | ||
1340 | adapter->dummy_dma.addr = NULL; | ||
1341 | } else | ||
1342 | dev_err(&adapter->pdev->dev, "dma_watchdog_shutdown failed\n"); | ||
1343 | } | ||
1344 | |||
1345 | int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val) | ||
1346 | { | ||
1347 | u32 val = 0; | ||
1348 | int retries = 60; | ||
1349 | |||
1350 | if (pegtune_val) | ||
1351 | return 0; | ||
1352 | |||
1353 | do { | ||
1354 | val = NXRD32(adapter, CRB_CMDPEG_STATE); | ||
1355 | |||
1356 | switch (val) { | ||
1357 | case PHAN_INITIALIZE_COMPLETE: | ||
1358 | case PHAN_INITIALIZE_ACK: | ||
1359 | return 0; | ||
1360 | case PHAN_INITIALIZE_FAILED: | ||
1361 | goto out_err; | ||
1362 | default: | ||
1363 | break; | ||
1364 | } | ||
1365 | |||
1366 | msleep(500); | ||
1367 | |||
1368 | } while (--retries); | ||
1369 | |||
1370 | NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED); | ||
1371 | |||
1372 | out_err: | ||
1373 | dev_warn(&adapter->pdev->dev, "firmware init failed\n"); | ||
1374 | return -EIO; | ||
1375 | } | ||
1376 | |||
1377 | static int | ||
1378 | netxen_receive_peg_ready(struct netxen_adapter *adapter) | ||
1379 | { | ||
1380 | u32 val = 0; | ||
1381 | int retries = 2000; | ||
1382 | |||
1383 | do { | ||
1384 | val = NXRD32(adapter, CRB_RCVPEG_STATE); | ||
1385 | |||
1386 | if (val == PHAN_PEG_RCV_INITIALIZED) | ||
1387 | return 0; | ||
1388 | |||
1389 | msleep(10); | ||
1390 | |||
1391 | } while (--retries); | ||
1392 | |||
1393 | if (!retries) { | ||
1394 | printk(KERN_ERR "Receive Peg initialization not " | ||
1395 | "complete, state: 0x%x.\n", val); | ||
1396 | return -EIO; | ||
1397 | } | ||
1398 | |||
1399 | return 0; | ||
1400 | } | ||
1401 | |||
1402 | int netxen_init_firmware(struct netxen_adapter *adapter) | ||
1403 | { | ||
1404 | int err; | ||
1405 | |||
1406 | err = netxen_receive_peg_ready(adapter); | ||
1407 | if (err) | ||
1408 | return err; | ||
1409 | |||
1410 | NXWR32(adapter, CRB_NIC_CAPABILITIES_HOST, INTR_SCHEME_PERPORT); | ||
1411 | NXWR32(adapter, CRB_MPORT_MODE, MPORT_MULTI_FUNCTION_MODE); | ||
1412 | NXWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); | ||
1413 | |||
1414 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
1415 | NXWR32(adapter, CRB_NIC_MSI_MODE_HOST, MSI_MODE_MULTIFUNC); | ||
1416 | |||
1417 | return err; | ||
1418 | } | ||
1419 | |||
1420 | static void | ||
1421 | netxen_handle_linkevent(struct netxen_adapter *adapter, nx_fw_msg_t *msg) | ||
1422 | { | ||
1423 | u32 cable_OUI; | ||
1424 | u16 cable_len; | ||
1425 | u16 link_speed; | ||
1426 | u8 link_status, module, duplex, autoneg; | ||
1427 | struct net_device *netdev = adapter->netdev; | ||
1428 | |||
1429 | adapter->has_link_events = 1; | ||
1430 | |||
1431 | cable_OUI = msg->body[1] & 0xffffffff; | ||
1432 | cable_len = (msg->body[1] >> 32) & 0xffff; | ||
1433 | link_speed = (msg->body[1] >> 48) & 0xffff; | ||
1434 | |||
1435 | link_status = msg->body[2] & 0xff; | ||
1436 | duplex = (msg->body[2] >> 16) & 0xff; | ||
1437 | autoneg = (msg->body[2] >> 24) & 0xff; | ||
1438 | |||
1439 | module = (msg->body[2] >> 8) & 0xff; | ||
1440 | if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLE) { | ||
1441 | printk(KERN_INFO "%s: unsupported cable: OUI 0x%x, length %d\n", | ||
1442 | netdev->name, cable_OUI, cable_len); | ||
1443 | } else if (module == LINKEVENT_MODULE_TWINAX_UNSUPPORTED_CABLELEN) { | ||
1444 | printk(KERN_INFO "%s: unsupported cable length %d\n", | ||
1445 | netdev->name, cable_len); | ||
1446 | } | ||
1447 | |||
1448 | netxen_advert_link_change(adapter, link_status); | ||
1449 | |||
1450 | /* update link parameters */ | ||
1451 | if (duplex == LINKEVENT_FULL_DUPLEX) | ||
1452 | adapter->link_duplex = DUPLEX_FULL; | ||
1453 | else | ||
1454 | adapter->link_duplex = DUPLEX_HALF; | ||
1455 | adapter->module_type = module; | ||
1456 | adapter->link_autoneg = autoneg; | ||
1457 | adapter->link_speed = link_speed; | ||
1458 | } | ||
1459 | |||
1460 | static void | ||
1461 | netxen_handle_fw_message(int desc_cnt, int index, | ||
1462 | struct nx_host_sds_ring *sds_ring) | ||
1463 | { | ||
1464 | nx_fw_msg_t msg; | ||
1465 | struct status_desc *desc; | ||
1466 | int i = 0, opcode; | ||
1467 | |||
1468 | while (desc_cnt > 0 && i < 8) { | ||
1469 | desc = &sds_ring->desc_head[index]; | ||
1470 | msg.words[i++] = le64_to_cpu(desc->status_desc_data[0]); | ||
1471 | msg.words[i++] = le64_to_cpu(desc->status_desc_data[1]); | ||
1472 | |||
1473 | index = get_next_index(index, sds_ring->num_desc); | ||
1474 | desc_cnt--; | ||
1475 | } | ||
1476 | |||
1477 | opcode = netxen_get_nic_msg_opcode(msg.body[0]); | ||
1478 | switch (opcode) { | ||
1479 | case NX_NIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE: | ||
1480 | netxen_handle_linkevent(sds_ring->adapter, &msg); | ||
1481 | break; | ||
1482 | default: | ||
1483 | break; | ||
1484 | } | ||
1485 | } | ||
1486 | |||
1487 | static int | ||
1488 | netxen_alloc_rx_skb(struct netxen_adapter *adapter, | ||
1489 | struct nx_host_rds_ring *rds_ring, | ||
1490 | struct netxen_rx_buffer *buffer) | ||
1491 | { | ||
1492 | struct sk_buff *skb; | ||
1493 | dma_addr_t dma; | ||
1494 | struct pci_dev *pdev = adapter->pdev; | ||
1495 | |||
1496 | buffer->skb = dev_alloc_skb(rds_ring->skb_size); | ||
1497 | if (!buffer->skb) | ||
1498 | return 1; | ||
1499 | |||
1500 | skb = buffer->skb; | ||
1501 | |||
1502 | if (!adapter->ahw.cut_through) | ||
1503 | skb_reserve(skb, 2); | ||
1504 | |||
1505 | dma = pci_map_single(pdev, skb->data, | ||
1506 | rds_ring->dma_size, PCI_DMA_FROMDEVICE); | ||
1507 | |||
1508 | if (pci_dma_mapping_error(pdev, dma)) { | ||
1509 | dev_kfree_skb_any(skb); | ||
1510 | buffer->skb = NULL; | ||
1511 | return 1; | ||
1512 | } | ||
1513 | |||
1514 | buffer->skb = skb; | ||
1515 | buffer->dma = dma; | ||
1516 | buffer->state = NETXEN_BUFFER_BUSY; | ||
1517 | |||
1518 | return 0; | ||
1519 | } | ||
1520 | |||
1521 | static struct sk_buff *netxen_process_rxbuf(struct netxen_adapter *adapter, | ||
1522 | struct nx_host_rds_ring *rds_ring, u16 index, u16 cksum) | ||
1523 | { | ||
1524 | struct netxen_rx_buffer *buffer; | ||
1525 | struct sk_buff *skb; | ||
1526 | |||
1527 | buffer = &rds_ring->rx_buf_arr[index]; | ||
1528 | |||
1529 | pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size, | ||
1530 | PCI_DMA_FROMDEVICE); | ||
1531 | |||
1532 | skb = buffer->skb; | ||
1533 | if (!skb) | ||
1534 | goto no_skb; | ||
1535 | |||
1536 | if (likely((adapter->netdev->features & NETIF_F_RXCSUM) | ||
1537 | && cksum == STATUS_CKSUM_OK)) { | ||
1538 | adapter->stats.csummed++; | ||
1539 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1540 | } else | ||
1541 | skb->ip_summed = CHECKSUM_NONE; | ||
1542 | |||
1543 | skb->dev = adapter->netdev; | ||
1544 | |||
1545 | buffer->skb = NULL; | ||
1546 | no_skb: | ||
1547 | buffer->state = NETXEN_BUFFER_FREE; | ||
1548 | return skb; | ||
1549 | } | ||
1550 | |||
1551 | static struct netxen_rx_buffer * | ||
1552 | netxen_process_rcv(struct netxen_adapter *adapter, | ||
1553 | struct nx_host_sds_ring *sds_ring, | ||
1554 | int ring, u64 sts_data0) | ||
1555 | { | ||
1556 | struct net_device *netdev = adapter->netdev; | ||
1557 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; | ||
1558 | struct netxen_rx_buffer *buffer; | ||
1559 | struct sk_buff *skb; | ||
1560 | struct nx_host_rds_ring *rds_ring; | ||
1561 | int index, length, cksum, pkt_offset; | ||
1562 | |||
1563 | if (unlikely(ring >= adapter->max_rds_rings)) | ||
1564 | return NULL; | ||
1565 | |||
1566 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
1567 | |||
1568 | index = netxen_get_sts_refhandle(sts_data0); | ||
1569 | if (unlikely(index >= rds_ring->num_desc)) | ||
1570 | return NULL; | ||
1571 | |||
1572 | buffer = &rds_ring->rx_buf_arr[index]; | ||
1573 | |||
1574 | length = netxen_get_sts_totallength(sts_data0); | ||
1575 | cksum = netxen_get_sts_status(sts_data0); | ||
1576 | pkt_offset = netxen_get_sts_pkt_offset(sts_data0); | ||
1577 | |||
1578 | skb = netxen_process_rxbuf(adapter, rds_ring, index, cksum); | ||
1579 | if (!skb) | ||
1580 | return buffer; | ||
1581 | |||
1582 | if (length > rds_ring->skb_size) | ||
1583 | skb_put(skb, rds_ring->skb_size); | ||
1584 | else | ||
1585 | skb_put(skb, length); | ||
1586 | |||
1587 | |||
1588 | if (pkt_offset) | ||
1589 | skb_pull(skb, pkt_offset); | ||
1590 | |||
1591 | skb->protocol = eth_type_trans(skb, netdev); | ||
1592 | |||
1593 | napi_gro_receive(&sds_ring->napi, skb); | ||
1594 | |||
1595 | adapter->stats.rx_pkts++; | ||
1596 | adapter->stats.rxbytes += length; | ||
1597 | |||
1598 | return buffer; | ||
1599 | } | ||
1600 | |||
1601 | #define TCP_HDR_SIZE 20 | ||
1602 | #define TCP_TS_OPTION_SIZE 12 | ||
1603 | #define TCP_TS_HDR_SIZE (TCP_HDR_SIZE + TCP_TS_OPTION_SIZE) | ||
1604 | |||
1605 | static struct netxen_rx_buffer * | ||
1606 | netxen_process_lro(struct netxen_adapter *adapter, | ||
1607 | struct nx_host_sds_ring *sds_ring, | ||
1608 | int ring, u64 sts_data0, u64 sts_data1) | ||
1609 | { | ||
1610 | struct net_device *netdev = adapter->netdev; | ||
1611 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; | ||
1612 | struct netxen_rx_buffer *buffer; | ||
1613 | struct sk_buff *skb; | ||
1614 | struct nx_host_rds_ring *rds_ring; | ||
1615 | struct iphdr *iph; | ||
1616 | struct tcphdr *th; | ||
1617 | bool push, timestamp; | ||
1618 | int l2_hdr_offset, l4_hdr_offset; | ||
1619 | int index; | ||
1620 | u16 lro_length, length, data_offset; | ||
1621 | u32 seq_number; | ||
1622 | |||
1623 | if (unlikely(ring > adapter->max_rds_rings)) | ||
1624 | return NULL; | ||
1625 | |||
1626 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
1627 | |||
1628 | index = netxen_get_lro_sts_refhandle(sts_data0); | ||
1629 | if (unlikely(index > rds_ring->num_desc)) | ||
1630 | return NULL; | ||
1631 | |||
1632 | buffer = &rds_ring->rx_buf_arr[index]; | ||
1633 | |||
1634 | timestamp = netxen_get_lro_sts_timestamp(sts_data0); | ||
1635 | lro_length = netxen_get_lro_sts_length(sts_data0); | ||
1636 | l2_hdr_offset = netxen_get_lro_sts_l2_hdr_offset(sts_data0); | ||
1637 | l4_hdr_offset = netxen_get_lro_sts_l4_hdr_offset(sts_data0); | ||
1638 | push = netxen_get_lro_sts_push_flag(sts_data0); | ||
1639 | seq_number = netxen_get_lro_sts_seq_number(sts_data1); | ||
1640 | |||
1641 | skb = netxen_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK); | ||
1642 | if (!skb) | ||
1643 | return buffer; | ||
1644 | |||
1645 | if (timestamp) | ||
1646 | data_offset = l4_hdr_offset + TCP_TS_HDR_SIZE; | ||
1647 | else | ||
1648 | data_offset = l4_hdr_offset + TCP_HDR_SIZE; | ||
1649 | |||
1650 | skb_put(skb, lro_length + data_offset); | ||
1651 | |||
1652 | skb_pull(skb, l2_hdr_offset); | ||
1653 | skb->protocol = eth_type_trans(skb, netdev); | ||
1654 | |||
1655 | iph = (struct iphdr *)skb->data; | ||
1656 | th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); | ||
1657 | |||
1658 | length = (iph->ihl << 2) + (th->doff << 2) + lro_length; | ||
1659 | iph->tot_len = htons(length); | ||
1660 | iph->check = 0; | ||
1661 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); | ||
1662 | th->psh = push; | ||
1663 | th->seq = htonl(seq_number); | ||
1664 | |||
1665 | length = skb->len; | ||
1666 | |||
1667 | netif_receive_skb(skb); | ||
1668 | |||
1669 | adapter->stats.lro_pkts++; | ||
1670 | adapter->stats.rxbytes += length; | ||
1671 | |||
1672 | return buffer; | ||
1673 | } | ||
1674 | |||
1675 | #define netxen_merge_rx_buffers(list, head) \ | ||
1676 | do { list_splice_tail_init(list, head); } while (0); | ||
1677 | |||
1678 | int | ||
1679 | netxen_process_rcv_ring(struct nx_host_sds_ring *sds_ring, int max) | ||
1680 | { | ||
1681 | struct netxen_adapter *adapter = sds_ring->adapter; | ||
1682 | |||
1683 | struct list_head *cur; | ||
1684 | |||
1685 | struct status_desc *desc; | ||
1686 | struct netxen_rx_buffer *rxbuf; | ||
1687 | |||
1688 | u32 consumer = sds_ring->consumer; | ||
1689 | |||
1690 | int count = 0; | ||
1691 | u64 sts_data0, sts_data1; | ||
1692 | int opcode, ring = 0, desc_cnt; | ||
1693 | |||
1694 | while (count < max) { | ||
1695 | desc = &sds_ring->desc_head[consumer]; | ||
1696 | sts_data0 = le64_to_cpu(desc->status_desc_data[0]); | ||
1697 | |||
1698 | if (!(sts_data0 & STATUS_OWNER_HOST)) | ||
1699 | break; | ||
1700 | |||
1701 | desc_cnt = netxen_get_sts_desc_cnt(sts_data0); | ||
1702 | |||
1703 | opcode = netxen_get_sts_opcode(sts_data0); | ||
1704 | |||
1705 | switch (opcode) { | ||
1706 | case NETXEN_NIC_RXPKT_DESC: | ||
1707 | case NETXEN_OLD_RXPKT_DESC: | ||
1708 | case NETXEN_NIC_SYN_OFFLOAD: | ||
1709 | ring = netxen_get_sts_type(sts_data0); | ||
1710 | rxbuf = netxen_process_rcv(adapter, sds_ring, | ||
1711 | ring, sts_data0); | ||
1712 | break; | ||
1713 | case NETXEN_NIC_LRO_DESC: | ||
1714 | ring = netxen_get_lro_sts_type(sts_data0); | ||
1715 | sts_data1 = le64_to_cpu(desc->status_desc_data[1]); | ||
1716 | rxbuf = netxen_process_lro(adapter, sds_ring, | ||
1717 | ring, sts_data0, sts_data1); | ||
1718 | break; | ||
1719 | case NETXEN_NIC_RESPONSE_DESC: | ||
1720 | netxen_handle_fw_message(desc_cnt, consumer, sds_ring); | ||
1721 | default: | ||
1722 | goto skip; | ||
1723 | } | ||
1724 | |||
1725 | WARN_ON(desc_cnt > 1); | ||
1726 | |||
1727 | if (rxbuf) | ||
1728 | list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); | ||
1729 | |||
1730 | skip: | ||
1731 | for (; desc_cnt > 0; desc_cnt--) { | ||
1732 | desc = &sds_ring->desc_head[consumer]; | ||
1733 | desc->status_desc_data[0] = | ||
1734 | cpu_to_le64(STATUS_OWNER_PHANTOM); | ||
1735 | consumer = get_next_index(consumer, sds_ring->num_desc); | ||
1736 | } | ||
1737 | count++; | ||
1738 | } | ||
1739 | |||
1740 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | ||
1741 | struct nx_host_rds_ring *rds_ring = | ||
1742 | &adapter->recv_ctx.rds_rings[ring]; | ||
1743 | |||
1744 | if (!list_empty(&sds_ring->free_list[ring])) { | ||
1745 | list_for_each(cur, &sds_ring->free_list[ring]) { | ||
1746 | rxbuf = list_entry(cur, | ||
1747 | struct netxen_rx_buffer, list); | ||
1748 | netxen_alloc_rx_skb(adapter, rds_ring, rxbuf); | ||
1749 | } | ||
1750 | spin_lock(&rds_ring->lock); | ||
1751 | netxen_merge_rx_buffers(&sds_ring->free_list[ring], | ||
1752 | &rds_ring->free_list); | ||
1753 | spin_unlock(&rds_ring->lock); | ||
1754 | } | ||
1755 | |||
1756 | netxen_post_rx_buffers_nodb(adapter, rds_ring); | ||
1757 | } | ||
1758 | |||
1759 | if (count) { | ||
1760 | sds_ring->consumer = consumer; | ||
1761 | NXWRIO(adapter, sds_ring->crb_sts_consumer, consumer); | ||
1762 | } | ||
1763 | |||
1764 | return count; | ||
1765 | } | ||
1766 | |||
1767 | /* Process Command status ring */ | ||
1768 | int netxen_process_cmd_ring(struct netxen_adapter *adapter) | ||
1769 | { | ||
1770 | u32 sw_consumer, hw_consumer; | ||
1771 | int count = 0, i; | ||
1772 | struct netxen_cmd_buffer *buffer; | ||
1773 | struct pci_dev *pdev = adapter->pdev; | ||
1774 | struct net_device *netdev = adapter->netdev; | ||
1775 | struct netxen_skb_frag *frag; | ||
1776 | int done = 0; | ||
1777 | struct nx_host_tx_ring *tx_ring = adapter->tx_ring; | ||
1778 | |||
1779 | if (!spin_trylock(&adapter->tx_clean_lock)) | ||
1780 | return 1; | ||
1781 | |||
1782 | sw_consumer = tx_ring->sw_consumer; | ||
1783 | hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); | ||
1784 | |||
1785 | while (sw_consumer != hw_consumer) { | ||
1786 | buffer = &tx_ring->cmd_buf_arr[sw_consumer]; | ||
1787 | if (buffer->skb) { | ||
1788 | frag = &buffer->frag_array[0]; | ||
1789 | pci_unmap_single(pdev, frag->dma, frag->length, | ||
1790 | PCI_DMA_TODEVICE); | ||
1791 | frag->dma = 0ULL; | ||
1792 | for (i = 1; i < buffer->frag_count; i++) { | ||
1793 | frag++; /* Get the next frag */ | ||
1794 | pci_unmap_page(pdev, frag->dma, frag->length, | ||
1795 | PCI_DMA_TODEVICE); | ||
1796 | frag->dma = 0ULL; | ||
1797 | } | ||
1798 | |||
1799 | adapter->stats.xmitfinished++; | ||
1800 | dev_kfree_skb_any(buffer->skb); | ||
1801 | buffer->skb = NULL; | ||
1802 | } | ||
1803 | |||
1804 | sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc); | ||
1805 | if (++count >= MAX_STATUS_HANDLE) | ||
1806 | break; | ||
1807 | } | ||
1808 | |||
1809 | if (count && netif_running(netdev)) { | ||
1810 | tx_ring->sw_consumer = sw_consumer; | ||
1811 | |||
1812 | smp_mb(); | ||
1813 | |||
1814 | if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) | ||
1815 | if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) | ||
1816 | netif_wake_queue(netdev); | ||
1817 | adapter->tx_timeo_cnt = 0; | ||
1818 | } | ||
1819 | /* | ||
1820 | * If everything is freed up to consumer then check if the ring is full | ||
1821 | * If the ring is full then check if more needs to be freed and | ||
1822 | * schedule the call back again. | ||
1823 | * | ||
1824 | * This happens when there are 2 CPUs. One could be freeing and the | ||
1825 | * other filling it. If the ring is full when we get out of here and | ||
1826 | * the card has already interrupted the host then the host can miss the | ||
1827 | * interrupt. | ||
1828 | * | ||
1829 | * There is still a possible race condition and the host could miss an | ||
1830 | * interrupt. The card has to take care of this. | ||
1831 | */ | ||
1832 | hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); | ||
1833 | done = (sw_consumer == hw_consumer); | ||
1834 | spin_unlock(&adapter->tx_clean_lock); | ||
1835 | |||
1836 | return done; | ||
1837 | } | ||
1838 | |||
1839 | void | ||
1840 | netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ringid, | ||
1841 | struct nx_host_rds_ring *rds_ring) | ||
1842 | { | ||
1843 | struct rcv_desc *pdesc; | ||
1844 | struct netxen_rx_buffer *buffer; | ||
1845 | int producer, count = 0; | ||
1846 | netxen_ctx_msg msg = 0; | ||
1847 | struct list_head *head; | ||
1848 | |||
1849 | producer = rds_ring->producer; | ||
1850 | |||
1851 | head = &rds_ring->free_list; | ||
1852 | while (!list_empty(head)) { | ||
1853 | |||
1854 | buffer = list_entry(head->next, struct netxen_rx_buffer, list); | ||
1855 | |||
1856 | if (!buffer->skb) { | ||
1857 | if (netxen_alloc_rx_skb(adapter, rds_ring, buffer)) | ||
1858 | break; | ||
1859 | } | ||
1860 | |||
1861 | count++; | ||
1862 | list_del(&buffer->list); | ||
1863 | |||
1864 | /* make a rcv descriptor */ | ||
1865 | pdesc = &rds_ring->desc_head[producer]; | ||
1866 | pdesc->addr_buffer = cpu_to_le64(buffer->dma); | ||
1867 | pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); | ||
1868 | pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); | ||
1869 | |||
1870 | producer = get_next_index(producer, rds_ring->num_desc); | ||
1871 | } | ||
1872 | |||
1873 | if (count) { | ||
1874 | rds_ring->producer = producer; | ||
1875 | NXWRIO(adapter, rds_ring->crb_rcv_producer, | ||
1876 | (producer-1) & (rds_ring->num_desc-1)); | ||
1877 | |||
1878 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
1879 | /* | ||
1880 | * Write a doorbell msg to tell phanmon of change in | ||
1881 | * receive ring producer | ||
1882 | * Only for firmware version < 4.0.0 | ||
1883 | */ | ||
1884 | netxen_set_msg_peg_id(msg, NETXEN_RCV_PEG_DB_ID); | ||
1885 | netxen_set_msg_privid(msg); | ||
1886 | netxen_set_msg_count(msg, | ||
1887 | ((producer - 1) & | ||
1888 | (rds_ring->num_desc - 1))); | ||
1889 | netxen_set_msg_ctxid(msg, adapter->portnum); | ||
1890 | netxen_set_msg_opcode(msg, NETXEN_RCV_PRODUCER(ringid)); | ||
1891 | NXWRIO(adapter, DB_NORMALIZE(adapter, | ||
1892 | NETXEN_RCV_PRODUCER_OFFSET), msg); | ||
1893 | } | ||
1894 | } | ||
1895 | } | ||
1896 | |||
1897 | static void | ||
1898 | netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter, | ||
1899 | struct nx_host_rds_ring *rds_ring) | ||
1900 | { | ||
1901 | struct rcv_desc *pdesc; | ||
1902 | struct netxen_rx_buffer *buffer; | ||
1903 | int producer, count = 0; | ||
1904 | struct list_head *head; | ||
1905 | |||
1906 | if (!spin_trylock(&rds_ring->lock)) | ||
1907 | return; | ||
1908 | |||
1909 | producer = rds_ring->producer; | ||
1910 | |||
1911 | head = &rds_ring->free_list; | ||
1912 | while (!list_empty(head)) { | ||
1913 | |||
1914 | buffer = list_entry(head->next, struct netxen_rx_buffer, list); | ||
1915 | |||
1916 | if (!buffer->skb) { | ||
1917 | if (netxen_alloc_rx_skb(adapter, rds_ring, buffer)) | ||
1918 | break; | ||
1919 | } | ||
1920 | |||
1921 | count++; | ||
1922 | list_del(&buffer->list); | ||
1923 | |||
1924 | /* make a rcv descriptor */ | ||
1925 | pdesc = &rds_ring->desc_head[producer]; | ||
1926 | pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); | ||
1927 | pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); | ||
1928 | pdesc->addr_buffer = cpu_to_le64(buffer->dma); | ||
1929 | |||
1930 | producer = get_next_index(producer, rds_ring->num_desc); | ||
1931 | } | ||
1932 | |||
1933 | if (count) { | ||
1934 | rds_ring->producer = producer; | ||
1935 | NXWRIO(adapter, rds_ring->crb_rcv_producer, | ||
1936 | (producer - 1) & (rds_ring->num_desc - 1)); | ||
1937 | } | ||
1938 | spin_unlock(&rds_ring->lock); | ||
1939 | } | ||
1940 | |||
1941 | void netxen_nic_clear_stats(struct netxen_adapter *adapter) | ||
1942 | { | ||
1943 | memset(&adapter->stats, 0, sizeof(adapter->stats)); | ||
1944 | } | ||
1945 | |||