Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[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 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