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