diff options
Diffstat (limited to 'drivers/net/netxen/netxen_nic_ctx.c')
-rw-r--r-- | drivers/net/netxen/netxen_nic_ctx.c | 793 |
1 files changed, 793 insertions, 0 deletions
diff --git a/drivers/net/netxen/netxen_nic_ctx.c b/drivers/net/netxen/netxen_nic_ctx.c new file mode 100644 index 00000000000..a925392abd6 --- /dev/null +++ b/drivers/net/netxen/netxen_nic_ctx.c | |||
@@ -0,0 +1,793 @@ | |||
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 "netxen_nic_hw.h" | ||
27 | #include "netxen_nic.h" | ||
28 | |||
29 | #define NXHAL_VERSION 1 | ||
30 | |||
31 | static u32 | ||
32 | netxen_poll_rsp(struct netxen_adapter *adapter) | ||
33 | { | ||
34 | u32 rsp = NX_CDRP_RSP_OK; | ||
35 | int timeout = 0; | ||
36 | |||
37 | do { | ||
38 | /* give atleast 1ms for firmware to respond */ | ||
39 | msleep(1); | ||
40 | |||
41 | if (++timeout > NX_OS_CRB_RETRY_COUNT) | ||
42 | return NX_CDRP_RSP_TIMEOUT; | ||
43 | |||
44 | rsp = NXRD32(adapter, NX_CDRP_CRB_OFFSET); | ||
45 | } while (!NX_CDRP_IS_RSP(rsp)); | ||
46 | |||
47 | return rsp; | ||
48 | } | ||
49 | |||
50 | static u32 | ||
51 | netxen_issue_cmd(struct netxen_adapter *adapter, | ||
52 | u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd) | ||
53 | { | ||
54 | u32 rsp; | ||
55 | u32 signature = 0; | ||
56 | u32 rcode = NX_RCODE_SUCCESS; | ||
57 | |||
58 | signature = NX_CDRP_SIGNATURE_MAKE(pci_fn, version); | ||
59 | |||
60 | /* Acquire semaphore before accessing CRB */ | ||
61 | if (netxen_api_lock(adapter)) | ||
62 | return NX_RCODE_TIMEOUT; | ||
63 | |||
64 | NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature); | ||
65 | |||
66 | NXWR32(adapter, NX_ARG1_CRB_OFFSET, arg1); | ||
67 | |||
68 | NXWR32(adapter, NX_ARG2_CRB_OFFSET, arg2); | ||
69 | |||
70 | NXWR32(adapter, NX_ARG3_CRB_OFFSET, arg3); | ||
71 | |||
72 | NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd)); | ||
73 | |||
74 | rsp = netxen_poll_rsp(adapter); | ||
75 | |||
76 | if (rsp == NX_CDRP_RSP_TIMEOUT) { | ||
77 | printk(KERN_ERR "%s: card response timeout.\n", | ||
78 | netxen_nic_driver_name); | ||
79 | |||
80 | rcode = NX_RCODE_TIMEOUT; | ||
81 | } else if (rsp == NX_CDRP_RSP_FAIL) { | ||
82 | rcode = NXRD32(adapter, NX_ARG1_CRB_OFFSET); | ||
83 | |||
84 | printk(KERN_ERR "%s: failed card response code:0x%x\n", | ||
85 | netxen_nic_driver_name, rcode); | ||
86 | } | ||
87 | |||
88 | /* Release semaphore */ | ||
89 | netxen_api_unlock(adapter); | ||
90 | |||
91 | return rcode; | ||
92 | } | ||
93 | |||
94 | int | ||
95 | nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu) | ||
96 | { | ||
97 | u32 rcode = NX_RCODE_SUCCESS; | ||
98 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; | ||
99 | |||
100 | if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE) | ||
101 | rcode = netxen_issue_cmd(adapter, | ||
102 | adapter->ahw.pci_func, | ||
103 | NXHAL_VERSION, | ||
104 | recv_ctx->context_id, | ||
105 | mtu, | ||
106 | 0, | ||
107 | NX_CDRP_CMD_SET_MTU); | ||
108 | |||
109 | if (rcode != NX_RCODE_SUCCESS) | ||
110 | return -EIO; | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | int | ||
116 | nx_fw_cmd_set_gbe_port(struct netxen_adapter *adapter, | ||
117 | u32 speed, u32 duplex, u32 autoneg) | ||
118 | { | ||
119 | |||
120 | return netxen_issue_cmd(adapter, | ||
121 | adapter->ahw.pci_func, | ||
122 | NXHAL_VERSION, | ||
123 | speed, | ||
124 | duplex, | ||
125 | autoneg, | ||
126 | NX_CDRP_CMD_CONFIG_GBE_PORT); | ||
127 | |||
128 | } | ||
129 | |||
130 | static int | ||
131 | nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) | ||
132 | { | ||
133 | void *addr; | ||
134 | nx_hostrq_rx_ctx_t *prq; | ||
135 | nx_cardrsp_rx_ctx_t *prsp; | ||
136 | nx_hostrq_rds_ring_t *prq_rds; | ||
137 | nx_hostrq_sds_ring_t *prq_sds; | ||
138 | nx_cardrsp_rds_ring_t *prsp_rds; | ||
139 | nx_cardrsp_sds_ring_t *prsp_sds; | ||
140 | struct nx_host_rds_ring *rds_ring; | ||
141 | struct nx_host_sds_ring *sds_ring; | ||
142 | |||
143 | dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; | ||
144 | u64 phys_addr; | ||
145 | |||
146 | int i, nrds_rings, nsds_rings; | ||
147 | size_t rq_size, rsp_size; | ||
148 | u32 cap, reg, val; | ||
149 | |||
150 | int err; | ||
151 | |||
152 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; | ||
153 | |||
154 | nrds_rings = adapter->max_rds_rings; | ||
155 | nsds_rings = adapter->max_sds_rings; | ||
156 | |||
157 | rq_size = | ||
158 | SIZEOF_HOSTRQ_RX(nx_hostrq_rx_ctx_t, nrds_rings, nsds_rings); | ||
159 | rsp_size = | ||
160 | SIZEOF_CARDRSP_RX(nx_cardrsp_rx_ctx_t, nrds_rings, nsds_rings); | ||
161 | |||
162 | addr = pci_alloc_consistent(adapter->pdev, | ||
163 | rq_size, &hostrq_phys_addr); | ||
164 | if (addr == NULL) | ||
165 | return -ENOMEM; | ||
166 | prq = addr; | ||
167 | |||
168 | addr = pci_alloc_consistent(adapter->pdev, | ||
169 | rsp_size, &cardrsp_phys_addr); | ||
170 | if (addr == NULL) { | ||
171 | err = -ENOMEM; | ||
172 | goto out_free_rq; | ||
173 | } | ||
174 | prsp = addr; | ||
175 | |||
176 | prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr); | ||
177 | |||
178 | cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN); | ||
179 | cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS); | ||
180 | |||
181 | prq->capabilities[0] = cpu_to_le32(cap); | ||
182 | prq->host_int_crb_mode = | ||
183 | cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED); | ||
184 | prq->host_rds_crb_mode = | ||
185 | cpu_to_le32(NX_HOST_RDS_CRB_MODE_UNIQUE); | ||
186 | |||
187 | prq->num_rds_rings = cpu_to_le16(nrds_rings); | ||
188 | prq->num_sds_rings = cpu_to_le16(nsds_rings); | ||
189 | prq->rds_ring_offset = cpu_to_le32(0); | ||
190 | |||
191 | val = le32_to_cpu(prq->rds_ring_offset) + | ||
192 | (sizeof(nx_hostrq_rds_ring_t) * nrds_rings); | ||
193 | prq->sds_ring_offset = cpu_to_le32(val); | ||
194 | |||
195 | prq_rds = (nx_hostrq_rds_ring_t *)(prq->data + | ||
196 | le32_to_cpu(prq->rds_ring_offset)); | ||
197 | |||
198 | for (i = 0; i < nrds_rings; i++) { | ||
199 | |||
200 | rds_ring = &recv_ctx->rds_rings[i]; | ||
201 | |||
202 | prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr); | ||
203 | prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc); | ||
204 | prq_rds[i].ring_kind = cpu_to_le32(i); | ||
205 | prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size); | ||
206 | } | ||
207 | |||
208 | prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + | ||
209 | le32_to_cpu(prq->sds_ring_offset)); | ||
210 | |||
211 | for (i = 0; i < nsds_rings; i++) { | ||
212 | |||
213 | sds_ring = &recv_ctx->sds_rings[i]; | ||
214 | |||
215 | prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr); | ||
216 | prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc); | ||
217 | prq_sds[i].msi_index = cpu_to_le16(i); | ||
218 | } | ||
219 | |||
220 | phys_addr = hostrq_phys_addr; | ||
221 | err = netxen_issue_cmd(adapter, | ||
222 | adapter->ahw.pci_func, | ||
223 | NXHAL_VERSION, | ||
224 | (u32)(phys_addr >> 32), | ||
225 | (u32)(phys_addr & 0xffffffff), | ||
226 | rq_size, | ||
227 | NX_CDRP_CMD_CREATE_RX_CTX); | ||
228 | if (err) { | ||
229 | printk(KERN_WARNING | ||
230 | "Failed to create rx ctx in firmware%d\n", err); | ||
231 | goto out_free_rsp; | ||
232 | } | ||
233 | |||
234 | |||
235 | prsp_rds = ((nx_cardrsp_rds_ring_t *) | ||
236 | &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]); | ||
237 | |||
238 | for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) { | ||
239 | rds_ring = &recv_ctx->rds_rings[i]; | ||
240 | |||
241 | reg = le32_to_cpu(prsp_rds[i].host_producer_crb); | ||
242 | rds_ring->crb_rcv_producer = netxen_get_ioaddr(adapter, | ||
243 | NETXEN_NIC_REG(reg - 0x200)); | ||
244 | } | ||
245 | |||
246 | prsp_sds = ((nx_cardrsp_sds_ring_t *) | ||
247 | &prsp->data[le32_to_cpu(prsp->sds_ring_offset)]); | ||
248 | |||
249 | for (i = 0; i < le16_to_cpu(prsp->num_sds_rings); i++) { | ||
250 | sds_ring = &recv_ctx->sds_rings[i]; | ||
251 | |||
252 | reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); | ||
253 | sds_ring->crb_sts_consumer = netxen_get_ioaddr(adapter, | ||
254 | NETXEN_NIC_REG(reg - 0x200)); | ||
255 | |||
256 | reg = le32_to_cpu(prsp_sds[i].interrupt_crb); | ||
257 | sds_ring->crb_intr_mask = netxen_get_ioaddr(adapter, | ||
258 | NETXEN_NIC_REG(reg - 0x200)); | ||
259 | } | ||
260 | |||
261 | recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); | ||
262 | recv_ctx->context_id = le16_to_cpu(prsp->context_id); | ||
263 | recv_ctx->virt_port = prsp->virt_port; | ||
264 | |||
265 | out_free_rsp: | ||
266 | pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr); | ||
267 | out_free_rq: | ||
268 | pci_free_consistent(adapter->pdev, rq_size, prq, hostrq_phys_addr); | ||
269 | return err; | ||
270 | } | ||
271 | |||
272 | static void | ||
273 | nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter) | ||
274 | { | ||
275 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; | ||
276 | |||
277 | if (netxen_issue_cmd(adapter, | ||
278 | adapter->ahw.pci_func, | ||
279 | NXHAL_VERSION, | ||
280 | recv_ctx->context_id, | ||
281 | NX_DESTROY_CTX_RESET, | ||
282 | 0, | ||
283 | NX_CDRP_CMD_DESTROY_RX_CTX)) { | ||
284 | |||
285 | printk(KERN_WARNING | ||
286 | "%s: Failed to destroy rx ctx in firmware\n", | ||
287 | netxen_nic_driver_name); | ||
288 | } | ||
289 | } | ||
290 | |||
291 | static int | ||
292 | nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) | ||
293 | { | ||
294 | nx_hostrq_tx_ctx_t *prq; | ||
295 | nx_hostrq_cds_ring_t *prq_cds; | ||
296 | nx_cardrsp_tx_ctx_t *prsp; | ||
297 | void *rq_addr, *rsp_addr; | ||
298 | size_t rq_size, rsp_size; | ||
299 | u32 temp; | ||
300 | int err = 0; | ||
301 | u64 offset, phys_addr; | ||
302 | dma_addr_t rq_phys_addr, rsp_phys_addr; | ||
303 | struct nx_host_tx_ring *tx_ring = adapter->tx_ring; | ||
304 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; | ||
305 | |||
306 | rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t); | ||
307 | rq_addr = pci_alloc_consistent(adapter->pdev, | ||
308 | rq_size, &rq_phys_addr); | ||
309 | if (!rq_addr) | ||
310 | return -ENOMEM; | ||
311 | |||
312 | rsp_size = SIZEOF_CARDRSP_TX(nx_cardrsp_tx_ctx_t); | ||
313 | rsp_addr = pci_alloc_consistent(adapter->pdev, | ||
314 | rsp_size, &rsp_phys_addr); | ||
315 | if (!rsp_addr) { | ||
316 | err = -ENOMEM; | ||
317 | goto out_free_rq; | ||
318 | } | ||
319 | |||
320 | memset(rq_addr, 0, rq_size); | ||
321 | prq = rq_addr; | ||
322 | |||
323 | memset(rsp_addr, 0, rsp_size); | ||
324 | prsp = rsp_addr; | ||
325 | |||
326 | prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr); | ||
327 | |||
328 | temp = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN | NX_CAP0_LSO); | ||
329 | prq->capabilities[0] = cpu_to_le32(temp); | ||
330 | |||
331 | prq->host_int_crb_mode = | ||
332 | cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED); | ||
333 | |||
334 | prq->interrupt_ctl = 0; | ||
335 | prq->msi_index = 0; | ||
336 | |||
337 | prq->dummy_dma_addr = cpu_to_le64(adapter->dummy_dma.phys_addr); | ||
338 | |||
339 | offset = recv_ctx->phys_addr + sizeof(struct netxen_ring_ctx); | ||
340 | prq->cmd_cons_dma_addr = cpu_to_le64(offset); | ||
341 | |||
342 | prq_cds = &prq->cds_ring; | ||
343 | |||
344 | prq_cds->host_phys_addr = cpu_to_le64(tx_ring->phys_addr); | ||
345 | prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc); | ||
346 | |||
347 | phys_addr = rq_phys_addr; | ||
348 | err = netxen_issue_cmd(adapter, | ||
349 | adapter->ahw.pci_func, | ||
350 | NXHAL_VERSION, | ||
351 | (u32)(phys_addr >> 32), | ||
352 | ((u32)phys_addr & 0xffffffff), | ||
353 | rq_size, | ||
354 | NX_CDRP_CMD_CREATE_TX_CTX); | ||
355 | |||
356 | if (err == NX_RCODE_SUCCESS) { | ||
357 | temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); | ||
358 | tx_ring->crb_cmd_producer = netxen_get_ioaddr(adapter, | ||
359 | NETXEN_NIC_REG(temp - 0x200)); | ||
360 | #if 0 | ||
361 | adapter->tx_state = | ||
362 | le32_to_cpu(prsp->host_ctx_state); | ||
363 | #endif | ||
364 | adapter->tx_context_id = | ||
365 | le16_to_cpu(prsp->context_id); | ||
366 | } else { | ||
367 | printk(KERN_WARNING | ||
368 | "Failed to create tx ctx in firmware%d\n", err); | ||
369 | err = -EIO; | ||
370 | } | ||
371 | |||
372 | pci_free_consistent(adapter->pdev, rsp_size, rsp_addr, rsp_phys_addr); | ||
373 | |||
374 | out_free_rq: | ||
375 | pci_free_consistent(adapter->pdev, rq_size, rq_addr, rq_phys_addr); | ||
376 | |||
377 | return err; | ||
378 | } | ||
379 | |||
380 | static void | ||
381 | nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter) | ||
382 | { | ||
383 | if (netxen_issue_cmd(adapter, | ||
384 | adapter->ahw.pci_func, | ||
385 | NXHAL_VERSION, | ||
386 | adapter->tx_context_id, | ||
387 | NX_DESTROY_CTX_RESET, | ||
388 | 0, | ||
389 | NX_CDRP_CMD_DESTROY_TX_CTX)) { | ||
390 | |||
391 | printk(KERN_WARNING | ||
392 | "%s: Failed to destroy tx ctx in firmware\n", | ||
393 | netxen_nic_driver_name); | ||
394 | } | ||
395 | } | ||
396 | |||
397 | int | ||
398 | nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val) | ||
399 | { | ||
400 | u32 rcode; | ||
401 | |||
402 | rcode = netxen_issue_cmd(adapter, | ||
403 | adapter->ahw.pci_func, | ||
404 | NXHAL_VERSION, | ||
405 | reg, | ||
406 | 0, | ||
407 | 0, | ||
408 | NX_CDRP_CMD_READ_PHY); | ||
409 | |||
410 | if (rcode != NX_RCODE_SUCCESS) | ||
411 | return -EIO; | ||
412 | |||
413 | return NXRD32(adapter, NX_ARG1_CRB_OFFSET); | ||
414 | } | ||
415 | |||
416 | int | ||
417 | nx_fw_cmd_set_phy(struct netxen_adapter *adapter, u32 reg, u32 val) | ||
418 | { | ||
419 | u32 rcode; | ||
420 | |||
421 | rcode = netxen_issue_cmd(adapter, | ||
422 | adapter->ahw.pci_func, | ||
423 | NXHAL_VERSION, | ||
424 | reg, | ||
425 | val, | ||
426 | 0, | ||
427 | NX_CDRP_CMD_WRITE_PHY); | ||
428 | |||
429 | if (rcode != NX_RCODE_SUCCESS) | ||
430 | return -EIO; | ||
431 | |||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | static u64 ctx_addr_sig_regs[][3] = { | ||
436 | {NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)}, | ||
437 | {NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)}, | ||
438 | {NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)}, | ||
439 | {NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)} | ||
440 | }; | ||
441 | |||
442 | #define CRB_CTX_ADDR_REG_LO(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][0]) | ||
443 | #define CRB_CTX_ADDR_REG_HI(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][2]) | ||
444 | #define CRB_CTX_SIGNATURE_REG(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][1]) | ||
445 | |||
446 | #define lower32(x) ((u32)((x) & 0xffffffff)) | ||
447 | #define upper32(x) ((u32)(((u64)(x) >> 32) & 0xffffffff)) | ||
448 | |||
449 | static struct netxen_recv_crb recv_crb_registers[] = { | ||
450 | /* Instance 0 */ | ||
451 | { | ||
452 | /* crb_rcv_producer: */ | ||
453 | { | ||
454 | NETXEN_NIC_REG(0x100), | ||
455 | /* Jumbo frames */ | ||
456 | NETXEN_NIC_REG(0x110), | ||
457 | /* LRO */ | ||
458 | NETXEN_NIC_REG(0x120) | ||
459 | }, | ||
460 | /* crb_sts_consumer: */ | ||
461 | { | ||
462 | NETXEN_NIC_REG(0x138), | ||
463 | NETXEN_NIC_REG_2(0x000), | ||
464 | NETXEN_NIC_REG_2(0x004), | ||
465 | NETXEN_NIC_REG_2(0x008), | ||
466 | }, | ||
467 | /* sw_int_mask */ | ||
468 | { | ||
469 | CRB_SW_INT_MASK_0, | ||
470 | NETXEN_NIC_REG_2(0x044), | ||
471 | NETXEN_NIC_REG_2(0x048), | ||
472 | NETXEN_NIC_REG_2(0x04c), | ||
473 | }, | ||
474 | }, | ||
475 | /* Instance 1 */ | ||
476 | { | ||
477 | /* crb_rcv_producer: */ | ||
478 | { | ||
479 | NETXEN_NIC_REG(0x144), | ||
480 | /* Jumbo frames */ | ||
481 | NETXEN_NIC_REG(0x154), | ||
482 | /* LRO */ | ||
483 | NETXEN_NIC_REG(0x164) | ||
484 | }, | ||
485 | /* crb_sts_consumer: */ | ||
486 | { | ||
487 | NETXEN_NIC_REG(0x17c), | ||
488 | NETXEN_NIC_REG_2(0x020), | ||
489 | NETXEN_NIC_REG_2(0x024), | ||
490 | NETXEN_NIC_REG_2(0x028), | ||
491 | }, | ||
492 | /* sw_int_mask */ | ||
493 | { | ||
494 | CRB_SW_INT_MASK_1, | ||
495 | NETXEN_NIC_REG_2(0x064), | ||
496 | NETXEN_NIC_REG_2(0x068), | ||
497 | NETXEN_NIC_REG_2(0x06c), | ||
498 | }, | ||
499 | }, | ||
500 | /* Instance 2 */ | ||
501 | { | ||
502 | /* crb_rcv_producer: */ | ||
503 | { | ||
504 | NETXEN_NIC_REG(0x1d8), | ||
505 | /* Jumbo frames */ | ||
506 | NETXEN_NIC_REG(0x1f8), | ||
507 | /* LRO */ | ||
508 | NETXEN_NIC_REG(0x208) | ||
509 | }, | ||
510 | /* crb_sts_consumer: */ | ||
511 | { | ||
512 | NETXEN_NIC_REG(0x220), | ||
513 | NETXEN_NIC_REG_2(0x03c), | ||
514 | NETXEN_NIC_REG_2(0x03c), | ||
515 | NETXEN_NIC_REG_2(0x03c), | ||
516 | }, | ||
517 | /* sw_int_mask */ | ||
518 | { | ||
519 | CRB_SW_INT_MASK_2, | ||
520 | NETXEN_NIC_REG_2(0x03c), | ||
521 | NETXEN_NIC_REG_2(0x03c), | ||
522 | NETXEN_NIC_REG_2(0x03c), | ||
523 | }, | ||
524 | }, | ||
525 | /* Instance 3 */ | ||
526 | { | ||
527 | /* crb_rcv_producer: */ | ||
528 | { | ||
529 | NETXEN_NIC_REG(0x22c), | ||
530 | /* Jumbo frames */ | ||
531 | NETXEN_NIC_REG(0x23c), | ||
532 | /* LRO */ | ||
533 | NETXEN_NIC_REG(0x24c) | ||
534 | }, | ||
535 | /* crb_sts_consumer: */ | ||
536 | { | ||
537 | NETXEN_NIC_REG(0x264), | ||
538 | NETXEN_NIC_REG_2(0x03c), | ||
539 | NETXEN_NIC_REG_2(0x03c), | ||
540 | NETXEN_NIC_REG_2(0x03c), | ||
541 | }, | ||
542 | /* sw_int_mask */ | ||
543 | { | ||
544 | CRB_SW_INT_MASK_3, | ||
545 | NETXEN_NIC_REG_2(0x03c), | ||
546 | NETXEN_NIC_REG_2(0x03c), | ||
547 | NETXEN_NIC_REG_2(0x03c), | ||
548 | }, | ||
549 | }, | ||
550 | }; | ||
551 | |||
552 | static int | ||
553 | netxen_init_old_ctx(struct netxen_adapter *adapter) | ||
554 | { | ||
555 | struct netxen_recv_context *recv_ctx; | ||
556 | struct nx_host_rds_ring *rds_ring; | ||
557 | struct nx_host_sds_ring *sds_ring; | ||
558 | struct nx_host_tx_ring *tx_ring; | ||
559 | int ring; | ||
560 | int port = adapter->portnum; | ||
561 | struct netxen_ring_ctx *hwctx; | ||
562 | u32 signature; | ||
563 | |||
564 | tx_ring = adapter->tx_ring; | ||
565 | recv_ctx = &adapter->recv_ctx; | ||
566 | hwctx = recv_ctx->hwctx; | ||
567 | |||
568 | hwctx->cmd_ring_addr = cpu_to_le64(tx_ring->phys_addr); | ||
569 | hwctx->cmd_ring_size = cpu_to_le32(tx_ring->num_desc); | ||
570 | |||
571 | |||
572 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | ||
573 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
574 | |||
575 | hwctx->rcv_rings[ring].addr = | ||
576 | cpu_to_le64(rds_ring->phys_addr); | ||
577 | hwctx->rcv_rings[ring].size = | ||
578 | cpu_to_le32(rds_ring->num_desc); | ||
579 | } | ||
580 | |||
581 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
582 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
583 | |||
584 | if (ring == 0) { | ||
585 | hwctx->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr); | ||
586 | hwctx->sts_ring_size = cpu_to_le32(sds_ring->num_desc); | ||
587 | } | ||
588 | hwctx->sts_rings[ring].addr = cpu_to_le64(sds_ring->phys_addr); | ||
589 | hwctx->sts_rings[ring].size = cpu_to_le32(sds_ring->num_desc); | ||
590 | hwctx->sts_rings[ring].msi_index = cpu_to_le16(ring); | ||
591 | } | ||
592 | hwctx->sts_ring_count = cpu_to_le32(adapter->max_sds_rings); | ||
593 | |||
594 | signature = (adapter->max_sds_rings > 1) ? | ||
595 | NETXEN_CTX_SIGNATURE_V2 : NETXEN_CTX_SIGNATURE; | ||
596 | |||
597 | NXWR32(adapter, CRB_CTX_ADDR_REG_LO(port), | ||
598 | lower32(recv_ctx->phys_addr)); | ||
599 | NXWR32(adapter, CRB_CTX_ADDR_REG_HI(port), | ||
600 | upper32(recv_ctx->phys_addr)); | ||
601 | NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), | ||
602 | signature | port); | ||
603 | return 0; | ||
604 | } | ||
605 | |||
606 | int netxen_alloc_hw_resources(struct netxen_adapter *adapter) | ||
607 | { | ||
608 | void *addr; | ||
609 | int err = 0; | ||
610 | int ring; | ||
611 | struct netxen_recv_context *recv_ctx; | ||
612 | struct nx_host_rds_ring *rds_ring; | ||
613 | struct nx_host_sds_ring *sds_ring; | ||
614 | struct nx_host_tx_ring *tx_ring; | ||
615 | |||
616 | struct pci_dev *pdev = adapter->pdev; | ||
617 | struct net_device *netdev = adapter->netdev; | ||
618 | int port = adapter->portnum; | ||
619 | |||
620 | recv_ctx = &adapter->recv_ctx; | ||
621 | tx_ring = adapter->tx_ring; | ||
622 | |||
623 | addr = pci_alloc_consistent(pdev, | ||
624 | sizeof(struct netxen_ring_ctx) + sizeof(uint32_t), | ||
625 | &recv_ctx->phys_addr); | ||
626 | if (addr == NULL) { | ||
627 | dev_err(&pdev->dev, "failed to allocate hw context\n"); | ||
628 | return -ENOMEM; | ||
629 | } | ||
630 | |||
631 | memset(addr, 0, sizeof(struct netxen_ring_ctx)); | ||
632 | recv_ctx->hwctx = addr; | ||
633 | recv_ctx->hwctx->ctx_id = cpu_to_le32(port); | ||
634 | recv_ctx->hwctx->cmd_consumer_offset = | ||
635 | cpu_to_le64(recv_ctx->phys_addr + | ||
636 | sizeof(struct netxen_ring_ctx)); | ||
637 | tx_ring->hw_consumer = | ||
638 | (__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx)); | ||
639 | |||
640 | /* cmd desc ring */ | ||
641 | addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring), | ||
642 | &tx_ring->phys_addr); | ||
643 | |||
644 | if (addr == NULL) { | ||
645 | dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n", | ||
646 | netdev->name); | ||
647 | err = -ENOMEM; | ||
648 | goto err_out_free; | ||
649 | } | ||
650 | |||
651 | tx_ring->desc_head = addr; | ||
652 | |||
653 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | ||
654 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
655 | addr = pci_alloc_consistent(adapter->pdev, | ||
656 | RCV_DESC_RINGSIZE(rds_ring), | ||
657 | &rds_ring->phys_addr); | ||
658 | if (addr == NULL) { | ||
659 | dev_err(&pdev->dev, | ||
660 | "%s: failed to allocate rds ring [%d]\n", | ||
661 | netdev->name, ring); | ||
662 | err = -ENOMEM; | ||
663 | goto err_out_free; | ||
664 | } | ||
665 | rds_ring->desc_head = addr; | ||
666 | |||
667 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) | ||
668 | rds_ring->crb_rcv_producer = | ||
669 | netxen_get_ioaddr(adapter, | ||
670 | recv_crb_registers[port].crb_rcv_producer[ring]); | ||
671 | } | ||
672 | |||
673 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
674 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
675 | |||
676 | addr = pci_alloc_consistent(adapter->pdev, | ||
677 | STATUS_DESC_RINGSIZE(sds_ring), | ||
678 | &sds_ring->phys_addr); | ||
679 | if (addr == NULL) { | ||
680 | dev_err(&pdev->dev, | ||
681 | "%s: failed to allocate sds ring [%d]\n", | ||
682 | netdev->name, ring); | ||
683 | err = -ENOMEM; | ||
684 | goto err_out_free; | ||
685 | } | ||
686 | sds_ring->desc_head = addr; | ||
687 | |||
688 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
689 | sds_ring->crb_sts_consumer = | ||
690 | netxen_get_ioaddr(adapter, | ||
691 | recv_crb_registers[port].crb_sts_consumer[ring]); | ||
692 | |||
693 | sds_ring->crb_intr_mask = | ||
694 | netxen_get_ioaddr(adapter, | ||
695 | recv_crb_registers[port].sw_int_mask[ring]); | ||
696 | } | ||
697 | } | ||
698 | |||
699 | |||
700 | if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
701 | if (test_and_set_bit(__NX_FW_ATTACHED, &adapter->state)) | ||
702 | goto done; | ||
703 | err = nx_fw_cmd_create_rx_ctx(adapter); | ||
704 | if (err) | ||
705 | goto err_out_free; | ||
706 | err = nx_fw_cmd_create_tx_ctx(adapter); | ||
707 | if (err) | ||
708 | goto err_out_free; | ||
709 | } else { | ||
710 | err = netxen_init_old_ctx(adapter); | ||
711 | if (err) | ||
712 | goto err_out_free; | ||
713 | } | ||
714 | |||
715 | done: | ||
716 | return 0; | ||
717 | |||
718 | err_out_free: | ||
719 | netxen_free_hw_resources(adapter); | ||
720 | return err; | ||
721 | } | ||
722 | |||
723 | void netxen_free_hw_resources(struct netxen_adapter *adapter) | ||
724 | { | ||
725 | struct netxen_recv_context *recv_ctx; | ||
726 | struct nx_host_rds_ring *rds_ring; | ||
727 | struct nx_host_sds_ring *sds_ring; | ||
728 | struct nx_host_tx_ring *tx_ring; | ||
729 | int ring; | ||
730 | |||
731 | int port = adapter->portnum; | ||
732 | |||
733 | if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
734 | if (!test_and_clear_bit(__NX_FW_ATTACHED, &adapter->state)) | ||
735 | goto done; | ||
736 | |||
737 | nx_fw_cmd_destroy_rx_ctx(adapter); | ||
738 | nx_fw_cmd_destroy_tx_ctx(adapter); | ||
739 | } else { | ||
740 | netxen_api_lock(adapter); | ||
741 | NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), | ||
742 | NETXEN_CTX_D3_RESET | port); | ||
743 | netxen_api_unlock(adapter); | ||
744 | } | ||
745 | |||
746 | /* Allow dma queues to drain after context reset */ | ||
747 | msleep(20); | ||
748 | |||
749 | done: | ||
750 | recv_ctx = &adapter->recv_ctx; | ||
751 | |||
752 | if (recv_ctx->hwctx != NULL) { | ||
753 | pci_free_consistent(adapter->pdev, | ||
754 | sizeof(struct netxen_ring_ctx) + | ||
755 | sizeof(uint32_t), | ||
756 | recv_ctx->hwctx, | ||
757 | recv_ctx->phys_addr); | ||
758 | recv_ctx->hwctx = NULL; | ||
759 | } | ||
760 | |||
761 | tx_ring = adapter->tx_ring; | ||
762 | if (tx_ring->desc_head != NULL) { | ||
763 | pci_free_consistent(adapter->pdev, | ||
764 | TX_DESC_RINGSIZE(tx_ring), | ||
765 | tx_ring->desc_head, tx_ring->phys_addr); | ||
766 | tx_ring->desc_head = NULL; | ||
767 | } | ||
768 | |||
769 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | ||
770 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
771 | |||
772 | if (rds_ring->desc_head != NULL) { | ||
773 | pci_free_consistent(adapter->pdev, | ||
774 | RCV_DESC_RINGSIZE(rds_ring), | ||
775 | rds_ring->desc_head, | ||
776 | rds_ring->phys_addr); | ||
777 | rds_ring->desc_head = NULL; | ||
778 | } | ||
779 | } | ||
780 | |||
781 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
782 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
783 | |||
784 | if (sds_ring->desc_head != NULL) { | ||
785 | pci_free_consistent(adapter->pdev, | ||
786 | STATUS_DESC_RINGSIZE(sds_ring), | ||
787 | sds_ring->desc_head, | ||
788 | sds_ring->phys_addr); | ||
789 | sds_ring->desc_head = NULL; | ||
790 | } | ||
791 | } | ||
792 | } | ||
793 | |||