Commit | Line | Data |
---|---|---|
d9e651bc | 1 | /* |
5d242f1c | 2 | * Copyright (C) 2003 - 2009 NetXen, Inc. |
13af7a6e | 3 | * Copyright (C) 2009 - QLogic Corporation. |
d9e651bc DP |
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 | |
0ab75ae8 | 17 | * along with this program; if not, see <http://www.gnu.org/licenses/>. |
d9e651bc DP |
18 | * |
19 | * The full GNU General Public License is included in this distribution | |
4d21fef4 | 20 | * in the file called "COPYING". |
d9e651bc | 21 | * |
d9e651bc DP |
22 | */ |
23 | ||
24 | #include "netxen_nic_hw.h" | |
25 | #include "netxen_nic.h" | |
d9e651bc DP |
26 | |
27 | #define NXHAL_VERSION 1 | |
28 | ||
d9e651bc DP |
29 | static u32 |
30 | netxen_poll_rsp(struct netxen_adapter *adapter) | |
31 | { | |
2edbb454 | 32 | u32 rsp = NX_CDRP_RSP_OK; |
d9e651bc DP |
33 | int timeout = 0; |
34 | ||
35 | do { | |
36 | /* give atleast 1ms for firmware to respond */ | |
37 | msleep(1); | |
38 | ||
39 | if (++timeout > NX_OS_CRB_RETRY_COUNT) | |
40 | return NX_CDRP_RSP_TIMEOUT; | |
41 | ||
f98a9f69 | 42 | rsp = NXRD32(adapter, NX_CDRP_CRB_OFFSET); |
d9e651bc DP |
43 | } while (!NX_CDRP_IS_RSP(rsp)); |
44 | ||
45 | return rsp; | |
46 | } | |
47 | ||
48 | static u32 | |
2dcd5d95 | 49 | netxen_issue_cmd(struct netxen_adapter *adapter, struct netxen_cmd_args *cmd) |
d9e651bc DP |
50 | { |
51 | u32 rsp; | |
52 | u32 signature = 0; | |
53 | u32 rcode = NX_RCODE_SUCCESS; | |
54 | ||
2dcd5d95 SV |
55 | signature = NX_CDRP_SIGNATURE_MAKE(adapter->ahw.pci_func, |
56 | NXHAL_VERSION); | |
d9e651bc DP |
57 | /* Acquire semaphore before accessing CRB */ |
58 | if (netxen_api_lock(adapter)) | |
59 | return NX_RCODE_TIMEOUT; | |
60 | ||
f98a9f69 | 61 | NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature); |
d9e651bc | 62 | |
2dcd5d95 | 63 | NXWR32(adapter, NX_ARG1_CRB_OFFSET, cmd->req.arg1); |
d9e651bc | 64 | |
2dcd5d95 | 65 | NXWR32(adapter, NX_ARG2_CRB_OFFSET, cmd->req.arg2); |
d9e651bc | 66 | |
2dcd5d95 | 67 | NXWR32(adapter, NX_ARG3_CRB_OFFSET, cmd->req.arg3); |
d9e651bc | 68 | |
2dcd5d95 | 69 | NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd->req.cmd)); |
d9e651bc DP |
70 | |
71 | rsp = netxen_poll_rsp(adapter); | |
72 | ||
73 | if (rsp == NX_CDRP_RSP_TIMEOUT) { | |
74 | printk(KERN_ERR "%s: card response timeout.\n", | |
75 | netxen_nic_driver_name); | |
76 | ||
77 | rcode = NX_RCODE_TIMEOUT; | |
78 | } else if (rsp == NX_CDRP_RSP_FAIL) { | |
f98a9f69 | 79 | rcode = NXRD32(adapter, NX_ARG1_CRB_OFFSET); |
d9e651bc DP |
80 | |
81 | printk(KERN_ERR "%s: failed card response code:0x%x\n", | |
82 | netxen_nic_driver_name, rcode); | |
2dcd5d95 | 83 | } else if (rsp == NX_CDRP_RSP_OK) { |
83f18a55 | 84 | cmd->rsp.cmd = NX_RCODE_SUCCESS; |
2dcd5d95 SV |
85 | if (cmd->rsp.arg2) |
86 | cmd->rsp.arg2 = NXRD32(adapter, NX_ARG2_CRB_OFFSET); | |
87 | if (cmd->rsp.arg3) | |
88 | cmd->rsp.arg3 = NXRD32(adapter, NX_ARG3_CRB_OFFSET); | |
d9e651bc DP |
89 | } |
90 | ||
2dcd5d95 SV |
91 | if (cmd->rsp.arg1) |
92 | cmd->rsp.arg1 = NXRD32(adapter, NX_ARG1_CRB_OFFSET); | |
d9e651bc DP |
93 | /* Release semaphore */ |
94 | netxen_api_unlock(adapter); | |
95 | ||
96 | return rcode; | |
97 | } | |
98 | ||
83f18a55 M |
99 | static int |
100 | netxen_get_minidump_template_size(struct netxen_adapter *adapter) | |
101 | { | |
102 | struct netxen_cmd_args cmd; | |
103 | memset(&cmd, 0, sizeof(cmd)); | |
104 | cmd.req.cmd = NX_CDRP_CMD_TEMP_SIZE; | |
105 | memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd)); | |
106 | netxen_issue_cmd(adapter, &cmd); | |
107 | if (cmd.rsp.cmd != NX_RCODE_SUCCESS) { | |
108 | dev_info(&adapter->pdev->dev, | |
109 | "Can't get template size %d\n", cmd.rsp.cmd); | |
110 | return -EIO; | |
111 | } | |
112 | adapter->mdump.md_template_size = cmd.rsp.arg2; | |
113 | adapter->mdump.md_template_ver = cmd.rsp.arg3; | |
114 | return 0; | |
115 | } | |
116 | ||
117 | static int | |
118 | netxen_get_minidump_template(struct netxen_adapter *adapter) | |
119 | { | |
120 | dma_addr_t md_template_addr; | |
121 | void *addr; | |
122 | u32 size; | |
123 | struct netxen_cmd_args cmd; | |
124 | size = adapter->mdump.md_template_size; | |
125 | ||
126 | if (size == 0) { | |
127 | dev_err(&adapter->pdev->dev, "Can not capture Minidump " | |
128 | "template. Invalid template size.\n"); | |
129 | return NX_RCODE_INVALID_ARGS; | |
130 | } | |
131 | ||
440c734f | 132 | addr = pci_zalloc_consistent(adapter->pdev, size, &md_template_addr); |
83f18a55 M |
133 | if (!addr) { |
134 | dev_err(&adapter->pdev->dev, "Unable to allocate dmable memory for template.\n"); | |
135 | return -ENOMEM; | |
136 | } | |
137 | ||
83f18a55 M |
138 | memset(&cmd, 0, sizeof(cmd)); |
139 | memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd)); | |
140 | cmd.req.cmd = NX_CDRP_CMD_GET_TEMP_HDR; | |
141 | cmd.req.arg1 = LSD(md_template_addr); | |
142 | cmd.req.arg2 = MSD(md_template_addr); | |
143 | cmd.req.arg3 |= size; | |
144 | netxen_issue_cmd(adapter, &cmd); | |
145 | ||
146 | if ((cmd.rsp.cmd == NX_RCODE_SUCCESS) && (size == cmd.rsp.arg2)) { | |
147 | memcpy(adapter->mdump.md_template, addr, size); | |
148 | } else { | |
149 | dev_err(&adapter->pdev->dev, "Failed to get minidump template, " | |
150 | "err_code : %d, requested_size : %d, actual_size : %d\n ", | |
151 | cmd.rsp.cmd, size, cmd.rsp.arg2); | |
152 | } | |
153 | pci_free_consistent(adapter->pdev, size, addr, md_template_addr); | |
154 | return 0; | |
155 | } | |
156 | ||
157 | static u32 | |
158 | netxen_check_template_checksum(struct netxen_adapter *adapter) | |
159 | { | |
160 | u64 sum = 0 ; | |
161 | u32 *buff = adapter->mdump.md_template; | |
162 | int count = adapter->mdump.md_template_size/sizeof(uint32_t) ; | |
163 | ||
164 | while (count-- > 0) | |
165 | sum += *buff++ ; | |
166 | while (sum >> 32) | |
167 | sum = (sum & 0xFFFFFFFF) + (sum >> 32) ; | |
168 | ||
169 | return ~sum; | |
170 | } | |
171 | ||
172 | int | |
173 | netxen_setup_minidump(struct netxen_adapter *adapter) | |
174 | { | |
175 | int err = 0, i; | |
176 | u32 *template, *tmp_buf; | |
177 | struct netxen_minidump_template_hdr *hdr; | |
178 | err = netxen_get_minidump_template_size(adapter); | |
179 | if (err) { | |
180 | adapter->mdump.fw_supports_md = 0; | |
181 | if ((err == NX_RCODE_CMD_INVALID) || | |
182 | (err == NX_RCODE_CMD_NOT_IMPL)) { | |
183 | dev_info(&adapter->pdev->dev, | |
184 | "Flashed firmware version does not support minidump, " | |
185 | "minimum version required is [ %u.%u.%u ].\n ", | |
186 | NX_MD_SUPPORT_MAJOR, NX_MD_SUPPORT_MINOR, | |
187 | NX_MD_SUPPORT_SUBVERSION); | |
188 | } | |
189 | return err; | |
190 | } | |
191 | ||
192 | if (!adapter->mdump.md_template_size) { | |
193 | dev_err(&adapter->pdev->dev, "Error : Invalid template size " | |
194 | ",should be non-zero.\n"); | |
195 | return -EIO; | |
196 | } | |
197 | adapter->mdump.md_template = | |
198 | kmalloc(adapter->mdump.md_template_size, GFP_KERNEL); | |
199 | ||
b2adaca9 | 200 | if (!adapter->mdump.md_template) |
83f18a55 | 201 | return -ENOMEM; |
83f18a55 M |
202 | |
203 | err = netxen_get_minidump_template(adapter); | |
204 | if (err) { | |
205 | if (err == NX_RCODE_CMD_NOT_IMPL) | |
206 | adapter->mdump.fw_supports_md = 0; | |
207 | goto free_template; | |
208 | } | |
209 | ||
210 | if (netxen_check_template_checksum(adapter)) { | |
211 | dev_err(&adapter->pdev->dev, "Minidump template checksum Error\n"); | |
212 | err = -EIO; | |
213 | goto free_template; | |
214 | } | |
215 | ||
216 | adapter->mdump.md_capture_mask = NX_DUMP_MASK_DEF; | |
217 | tmp_buf = (u32 *) adapter->mdump.md_template; | |
218 | template = (u32 *) adapter->mdump.md_template; | |
219 | for (i = 0; i < adapter->mdump.md_template_size/sizeof(u32); i++) | |
220 | *template++ = __le32_to_cpu(*tmp_buf++); | |
221 | hdr = (struct netxen_minidump_template_hdr *) | |
222 | adapter->mdump.md_template; | |
223 | adapter->mdump.md_capture_buff = NULL; | |
224 | adapter->mdump.fw_supports_md = 1; | |
458c2858 | 225 | adapter->mdump.md_enabled = 0; |
83f18a55 M |
226 | |
227 | return err; | |
228 | ||
229 | free_template: | |
230 | kfree(adapter->mdump.md_template); | |
231 | adapter->mdump.md_template = NULL; | |
232 | return err; | |
233 | } | |
234 | ||
235 | ||
9ad27643 DP |
236 | int |
237 | nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu) | |
d9e651bc DP |
238 | { |
239 | u32 rcode = NX_RCODE_SUCCESS; | |
becf46a0 | 240 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; |
2dcd5d95 SV |
241 | struct netxen_cmd_args cmd; |
242 | ||
243 | memset(&cmd, 0, sizeof(cmd)); | |
244 | cmd.req.cmd = NX_CDRP_CMD_SET_MTU; | |
245 | cmd.req.arg1 = recv_ctx->context_id; | |
246 | cmd.req.arg2 = mtu; | |
247 | cmd.req.arg3 = 0; | |
d9e651bc DP |
248 | |
249 | if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE) | |
2dcd5d95 | 250 | netxen_issue_cmd(adapter, &cmd); |
d9e651bc | 251 | |
9ad27643 DP |
252 | if (rcode != NX_RCODE_SUCCESS) |
253 | return -EIO; | |
254 | ||
255 | return 0; | |
d9e651bc DP |
256 | } |
257 | ||
bfd823bd SC |
258 | int |
259 | nx_fw_cmd_set_gbe_port(struct netxen_adapter *adapter, | |
260 | u32 speed, u32 duplex, u32 autoneg) | |
261 | { | |
2dcd5d95 SV |
262 | struct netxen_cmd_args cmd; |
263 | ||
264 | memset(&cmd, 0, sizeof(cmd)); | |
265 | cmd.req.cmd = NX_CDRP_CMD_CONFIG_GBE_PORT; | |
266 | cmd.req.arg1 = speed; | |
267 | cmd.req.arg2 = duplex; | |
268 | cmd.req.arg3 = autoneg; | |
269 | return netxen_issue_cmd(adapter, &cmd); | |
bfd823bd SC |
270 | } |
271 | ||
d9e651bc DP |
272 | static int |
273 | nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) | |
274 | { | |
275 | void *addr; | |
276 | nx_hostrq_rx_ctx_t *prq; | |
277 | nx_cardrsp_rx_ctx_t *prsp; | |
278 | nx_hostrq_rds_ring_t *prq_rds; | |
279 | nx_hostrq_sds_ring_t *prq_sds; | |
280 | nx_cardrsp_rds_ring_t *prsp_rds; | |
281 | nx_cardrsp_sds_ring_t *prsp_sds; | |
282 | struct nx_host_rds_ring *rds_ring; | |
d8b100c5 | 283 | struct nx_host_sds_ring *sds_ring; |
2dcd5d95 | 284 | struct netxen_cmd_args cmd; |
d9e651bc DP |
285 | |
286 | dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; | |
287 | u64 phys_addr; | |
288 | ||
289 | int i, nrds_rings, nsds_rings; | |
290 | size_t rq_size, rsp_size; | |
2edbb454 | 291 | u32 cap, reg, val; |
d9e651bc DP |
292 | |
293 | int err; | |
294 | ||
becf46a0 | 295 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; |
d9e651bc | 296 | |
d9e651bc | 297 | nrds_rings = adapter->max_rds_rings; |
d8b100c5 | 298 | nsds_rings = adapter->max_sds_rings; |
d9e651bc DP |
299 | |
300 | rq_size = | |
301 | SIZEOF_HOSTRQ_RX(nx_hostrq_rx_ctx_t, nrds_rings, nsds_rings); | |
302 | rsp_size = | |
303 | SIZEOF_CARDRSP_RX(nx_cardrsp_rx_ctx_t, nrds_rings, nsds_rings); | |
304 | ||
305 | addr = pci_alloc_consistent(adapter->pdev, | |
306 | rq_size, &hostrq_phys_addr); | |
307 | if (addr == NULL) | |
308 | return -ENOMEM; | |
43d620c8 | 309 | prq = addr; |
d9e651bc DP |
310 | |
311 | addr = pci_alloc_consistent(adapter->pdev, | |
312 | rsp_size, &cardrsp_phys_addr); | |
313 | if (addr == NULL) { | |
314 | err = -ENOMEM; | |
315 | goto out_free_rq; | |
316 | } | |
43d620c8 | 317 | prsp = addr; |
d9e651bc DP |
318 | |
319 | prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr); | |
320 | ||
321 | cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN); | |
322 | cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS); | |
323 | ||
01da0c2b RB |
324 | if (adapter->flags & NETXEN_FW_MSS_CAP) |
325 | cap |= NX_CAP0_HW_LRO_MSS; | |
326 | ||
d9e651bc DP |
327 | prq->capabilities[0] = cpu_to_le32(cap); |
328 | prq->host_int_crb_mode = | |
329 | cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED); | |
330 | prq->host_rds_crb_mode = | |
331 | cpu_to_le32(NX_HOST_RDS_CRB_MODE_UNIQUE); | |
332 | ||
333 | prq->num_rds_rings = cpu_to_le16(nrds_rings); | |
334 | prq->num_sds_rings = cpu_to_le16(nsds_rings); | |
2edbb454 DP |
335 | prq->rds_ring_offset = cpu_to_le32(0); |
336 | ||
337 | val = le32_to_cpu(prq->rds_ring_offset) + | |
d9e651bc | 338 | (sizeof(nx_hostrq_rds_ring_t) * nrds_rings); |
2edbb454 | 339 | prq->sds_ring_offset = cpu_to_le32(val); |
d9e651bc | 340 | |
2edbb454 DP |
341 | prq_rds = (nx_hostrq_rds_ring_t *)(prq->data + |
342 | le32_to_cpu(prq->rds_ring_offset)); | |
d9e651bc DP |
343 | |
344 | for (i = 0; i < nrds_rings; i++) { | |
345 | ||
346 | rds_ring = &recv_ctx->rds_rings[i]; | |
347 | ||
348 | prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr); | |
438627c7 | 349 | prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc); |
d9e651bc DP |
350 | prq_rds[i].ring_kind = cpu_to_le32(i); |
351 | prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size); | |
352 | } | |
353 | ||
2edbb454 DP |
354 | prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + |
355 | le32_to_cpu(prq->sds_ring_offset)); | |
d9e651bc | 356 | |
d8b100c5 DP |
357 | for (i = 0; i < nsds_rings; i++) { |
358 | ||
359 | sds_ring = &recv_ctx->sds_rings[i]; | |
360 | ||
361 | prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr); | |
362 | prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc); | |
363 | prq_sds[i].msi_index = cpu_to_le16(i); | |
364 | } | |
d9e651bc DP |
365 | |
366 | phys_addr = hostrq_phys_addr; | |
2dcd5d95 SV |
367 | memset(&cmd, 0, sizeof(cmd)); |
368 | cmd.req.arg1 = (u32)(phys_addr >> 32); | |
369 | cmd.req.arg2 = (u32)(phys_addr & 0xffffffff); | |
370 | cmd.req.arg3 = rq_size; | |
371 | cmd.req.cmd = NX_CDRP_CMD_CREATE_RX_CTX; | |
372 | err = netxen_issue_cmd(adapter, &cmd); | |
d9e651bc DP |
373 | if (err) { |
374 | printk(KERN_WARNING | |
375 | "Failed to create rx ctx in firmware%d\n", err); | |
376 | goto out_free_rsp; | |
377 | } | |
378 | ||
379 | ||
380 | prsp_rds = ((nx_cardrsp_rds_ring_t *) | |
2edbb454 | 381 | &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]); |
d9e651bc | 382 | |
2edbb454 | 383 | for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) { |
d9e651bc DP |
384 | rds_ring = &recv_ctx->rds_rings[i]; |
385 | ||
386 | reg = le32_to_cpu(prsp_rds[i].host_producer_crb); | |
195c5f98 AKS |
387 | rds_ring->crb_rcv_producer = netxen_get_ioaddr(adapter, |
388 | NETXEN_NIC_REG(reg - 0x200)); | |
d9e651bc DP |
389 | } |
390 | ||
391 | prsp_sds = ((nx_cardrsp_sds_ring_t *) | |
2edbb454 | 392 | &prsp->data[le32_to_cpu(prsp->sds_ring_offset)]); |
d9e651bc | 393 | |
d8b100c5 DP |
394 | for (i = 0; i < le16_to_cpu(prsp->num_sds_rings); i++) { |
395 | sds_ring = &recv_ctx->sds_rings[i]; | |
396 | ||
397 | reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); | |
195c5f98 AKS |
398 | sds_ring->crb_sts_consumer = netxen_get_ioaddr(adapter, |
399 | NETXEN_NIC_REG(reg - 0x200)); | |
d8b100c5 DP |
400 | |
401 | reg = le32_to_cpu(prsp_sds[i].interrupt_crb); | |
195c5f98 AKS |
402 | sds_ring->crb_intr_mask = netxen_get_ioaddr(adapter, |
403 | NETXEN_NIC_REG(reg - 0x200)); | |
d8b100c5 | 404 | } |
d9e651bc DP |
405 | |
406 | recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); | |
407 | recv_ctx->context_id = le16_to_cpu(prsp->context_id); | |
2edbb454 | 408 | recv_ctx->virt_port = prsp->virt_port; |
d9e651bc DP |
409 | |
410 | out_free_rsp: | |
411 | pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr); | |
412 | out_free_rq: | |
413 | pci_free_consistent(adapter->pdev, rq_size, prq, hostrq_phys_addr); | |
414 | return err; | |
415 | } | |
416 | ||
417 | static void | |
418 | nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter) | |
419 | { | |
becf46a0 | 420 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; |
2dcd5d95 | 421 | struct netxen_cmd_args cmd; |
d9e651bc | 422 | |
2dcd5d95 SV |
423 | memset(&cmd, 0, sizeof(cmd)); |
424 | cmd.req.arg1 = recv_ctx->context_id; | |
425 | cmd.req.arg2 = NX_DESTROY_CTX_RESET; | |
426 | cmd.req.arg3 = 0; | |
427 | cmd.req.cmd = NX_CDRP_CMD_DESTROY_RX_CTX; | |
d9e651bc | 428 | |
2dcd5d95 | 429 | if (netxen_issue_cmd(adapter, &cmd)) { |
d9e651bc DP |
430 | printk(KERN_WARNING |
431 | "%s: Failed to destroy rx ctx in firmware\n", | |
432 | netxen_nic_driver_name); | |
433 | } | |
434 | } | |
435 | ||
436 | static int | |
437 | nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) | |
438 | { | |
439 | nx_hostrq_tx_ctx_t *prq; | |
440 | nx_hostrq_cds_ring_t *prq_cds; | |
441 | nx_cardrsp_tx_ctx_t *prsp; | |
442 | void *rq_addr, *rsp_addr; | |
443 | size_t rq_size, rsp_size; | |
444 | u32 temp; | |
445 | int err = 0; | |
446 | u64 offset, phys_addr; | |
447 | dma_addr_t rq_phys_addr, rsp_phys_addr; | |
4ea528a1 DP |
448 | struct nx_host_tx_ring *tx_ring = adapter->tx_ring; |
449 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; | |
2dcd5d95 | 450 | struct netxen_cmd_args cmd; |
d9e651bc DP |
451 | |
452 | rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t); | |
453 | rq_addr = pci_alloc_consistent(adapter->pdev, | |
454 | rq_size, &rq_phys_addr); | |
455 | if (!rq_addr) | |
456 | return -ENOMEM; | |
457 | ||
458 | rsp_size = SIZEOF_CARDRSP_TX(nx_cardrsp_tx_ctx_t); | |
459 | rsp_addr = pci_alloc_consistent(adapter->pdev, | |
460 | rsp_size, &rsp_phys_addr); | |
461 | if (!rsp_addr) { | |
462 | err = -ENOMEM; | |
463 | goto out_free_rq; | |
464 | } | |
465 | ||
466 | memset(rq_addr, 0, rq_size); | |
43d620c8 | 467 | prq = rq_addr; |
d9e651bc DP |
468 | |
469 | memset(rsp_addr, 0, rsp_size); | |
43d620c8 | 470 | prsp = rsp_addr; |
d9e651bc DP |
471 | |
472 | prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr); | |
473 | ||
474 | temp = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN | NX_CAP0_LSO); | |
475 | prq->capabilities[0] = cpu_to_le32(temp); | |
476 | ||
477 | prq->host_int_crb_mode = | |
478 | cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED); | |
479 | ||
480 | prq->interrupt_ctl = 0; | |
481 | prq->msi_index = 0; | |
482 | ||
483 | prq->dummy_dma_addr = cpu_to_le64(adapter->dummy_dma.phys_addr); | |
484 | ||
4ea528a1 | 485 | offset = recv_ctx->phys_addr + sizeof(struct netxen_ring_ctx); |
d9e651bc DP |
486 | prq->cmd_cons_dma_addr = cpu_to_le64(offset); |
487 | ||
488 | prq_cds = &prq->cds_ring; | |
489 | ||
d877f1e3 DP |
490 | prq_cds->host_phys_addr = cpu_to_le64(tx_ring->phys_addr); |
491 | prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc); | |
d9e651bc DP |
492 | |
493 | phys_addr = rq_phys_addr; | |
2dcd5d95 SV |
494 | memset(&cmd, 0, sizeof(cmd)); |
495 | cmd.req.arg1 = (u32)(phys_addr >> 32); | |
496 | cmd.req.arg2 = ((u32)phys_addr & 0xffffffff); | |
497 | cmd.req.arg3 = rq_size; | |
498 | cmd.req.cmd = NX_CDRP_CMD_CREATE_TX_CTX; | |
499 | err = netxen_issue_cmd(adapter, &cmd); | |
d9e651bc DP |
500 | |
501 | if (err == NX_RCODE_SUCCESS) { | |
502 | temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); | |
195c5f98 AKS |
503 | tx_ring->crb_cmd_producer = netxen_get_ioaddr(adapter, |
504 | NETXEN_NIC_REG(temp - 0x200)); | |
d9e651bc DP |
505 | #if 0 |
506 | adapter->tx_state = | |
507 | le32_to_cpu(prsp->host_ctx_state); | |
508 | #endif | |
509 | adapter->tx_context_id = | |
510 | le16_to_cpu(prsp->context_id); | |
511 | } else { | |
512 | printk(KERN_WARNING | |
513 | "Failed to create tx ctx in firmware%d\n", err); | |
514 | err = -EIO; | |
515 | } | |
516 | ||
517 | pci_free_consistent(adapter->pdev, rsp_size, rsp_addr, rsp_phys_addr); | |
518 | ||
519 | out_free_rq: | |
520 | pci_free_consistent(adapter->pdev, rq_size, rq_addr, rq_phys_addr); | |
521 | ||
522 | return err; | |
523 | } | |
524 | ||
525 | static void | |
526 | nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter) | |
527 | { | |
2dcd5d95 SV |
528 | struct netxen_cmd_args cmd; |
529 | ||
530 | memset(&cmd, 0, sizeof(cmd)); | |
531 | cmd.req.arg1 = adapter->tx_context_id; | |
532 | cmd.req.arg2 = NX_DESTROY_CTX_RESET; | |
533 | cmd.req.arg3 = 0; | |
534 | cmd.req.cmd = NX_CDRP_CMD_DESTROY_TX_CTX; | |
535 | if (netxen_issue_cmd(adapter, &cmd)) { | |
d9e651bc DP |
536 | printk(KERN_WARNING |
537 | "%s: Failed to destroy tx ctx in firmware\n", | |
538 | netxen_nic_driver_name); | |
539 | } | |
540 | } | |
541 | ||
3ad4467c DP |
542 | int |
543 | nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val) | |
544 | { | |
545 | u32 rcode; | |
2dcd5d95 SV |
546 | struct netxen_cmd_args cmd; |
547 | ||
548 | memset(&cmd, 0, sizeof(cmd)); | |
549 | cmd.req.arg1 = reg; | |
550 | cmd.req.arg2 = 0; | |
551 | cmd.req.arg3 = 0; | |
552 | cmd.req.cmd = NX_CDRP_CMD_READ_PHY; | |
553 | cmd.rsp.arg1 = 1; | |
554 | rcode = netxen_issue_cmd(adapter, &cmd); | |
3ad4467c DP |
555 | if (rcode != NX_RCODE_SUCCESS) |
556 | return -EIO; | |
557 | ||
db608c12 SV |
558 | if (val == NULL) |
559 | return -EIO; | |
560 | ||
561 | *val = cmd.rsp.arg1; | |
562 | return 0; | |
3ad4467c DP |
563 | } |
564 | ||
565 | int | |
566 | nx_fw_cmd_set_phy(struct netxen_adapter *adapter, u32 reg, u32 val) | |
567 | { | |
568 | u32 rcode; | |
2dcd5d95 SV |
569 | struct netxen_cmd_args cmd; |
570 | ||
571 | memset(&cmd, 0, sizeof(cmd)); | |
572 | cmd.req.arg1 = reg; | |
573 | cmd.req.arg2 = val; | |
574 | cmd.req.arg3 = 0; | |
575 | cmd.req.cmd = NX_CDRP_CMD_WRITE_PHY; | |
576 | rcode = netxen_issue_cmd(adapter, &cmd); | |
3ad4467c DP |
577 | if (rcode != NX_RCODE_SUCCESS) |
578 | return -EIO; | |
579 | ||
580 | return 0; | |
581 | } | |
582 | ||
d9e651bc DP |
583 | static u64 ctx_addr_sig_regs[][3] = { |
584 | {NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)}, | |
585 | {NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)}, | |
586 | {NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)}, | |
587 | {NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)} | |
588 | }; | |
589 | ||
590 | #define CRB_CTX_ADDR_REG_LO(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][0]) | |
591 | #define CRB_CTX_ADDR_REG_HI(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][2]) | |
592 | #define CRB_CTX_SIGNATURE_REG(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][1]) | |
593 | ||
594 | #define lower32(x) ((u32)((x) & 0xffffffff)) | |
595 | #define upper32(x) ((u32)(((u64)(x) >> 32) & 0xffffffff)) | |
596 | ||
597 | static struct netxen_recv_crb recv_crb_registers[] = { | |
598 | /* Instance 0 */ | |
599 | { | |
600 | /* crb_rcv_producer: */ | |
601 | { | |
602 | NETXEN_NIC_REG(0x100), | |
603 | /* Jumbo frames */ | |
604 | NETXEN_NIC_REG(0x110), | |
605 | /* LRO */ | |
606 | NETXEN_NIC_REG(0x120) | |
607 | }, | |
608 | /* crb_sts_consumer: */ | |
f6d21f44 DP |
609 | { |
610 | NETXEN_NIC_REG(0x138), | |
611 | NETXEN_NIC_REG_2(0x000), | |
612 | NETXEN_NIC_REG_2(0x004), | |
613 | NETXEN_NIC_REG_2(0x008), | |
614 | }, | |
615 | /* sw_int_mask */ | |
616 | { | |
617 | CRB_SW_INT_MASK_0, | |
618 | NETXEN_NIC_REG_2(0x044), | |
619 | NETXEN_NIC_REG_2(0x048), | |
620 | NETXEN_NIC_REG_2(0x04c), | |
621 | }, | |
d9e651bc DP |
622 | }, |
623 | /* Instance 1 */ | |
624 | { | |
625 | /* crb_rcv_producer: */ | |
626 | { | |
627 | NETXEN_NIC_REG(0x144), | |
628 | /* Jumbo frames */ | |
629 | NETXEN_NIC_REG(0x154), | |
630 | /* LRO */ | |
631 | NETXEN_NIC_REG(0x164) | |
632 | }, | |
633 | /* crb_sts_consumer: */ | |
f6d21f44 DP |
634 | { |
635 | NETXEN_NIC_REG(0x17c), | |
636 | NETXEN_NIC_REG_2(0x020), | |
637 | NETXEN_NIC_REG_2(0x024), | |
638 | NETXEN_NIC_REG_2(0x028), | |
639 | }, | |
640 | /* sw_int_mask */ | |
641 | { | |
642 | CRB_SW_INT_MASK_1, | |
643 | NETXEN_NIC_REG_2(0x064), | |
644 | NETXEN_NIC_REG_2(0x068), | |
645 | NETXEN_NIC_REG_2(0x06c), | |
646 | }, | |
d9e651bc DP |
647 | }, |
648 | /* Instance 2 */ | |
649 | { | |
650 | /* crb_rcv_producer: */ | |
651 | { | |
652 | NETXEN_NIC_REG(0x1d8), | |
653 | /* Jumbo frames */ | |
654 | NETXEN_NIC_REG(0x1f8), | |
655 | /* LRO */ | |
656 | NETXEN_NIC_REG(0x208) | |
657 | }, | |
658 | /* crb_sts_consumer: */ | |
f6d21f44 DP |
659 | { |
660 | NETXEN_NIC_REG(0x220), | |
661 | NETXEN_NIC_REG_2(0x03c), | |
662 | NETXEN_NIC_REG_2(0x03c), | |
663 | NETXEN_NIC_REG_2(0x03c), | |
664 | }, | |
665 | /* sw_int_mask */ | |
666 | { | |
667 | CRB_SW_INT_MASK_2, | |
668 | NETXEN_NIC_REG_2(0x03c), | |
669 | NETXEN_NIC_REG_2(0x03c), | |
670 | NETXEN_NIC_REG_2(0x03c), | |
671 | }, | |
d9e651bc DP |
672 | }, |
673 | /* Instance 3 */ | |
674 | { | |
675 | /* crb_rcv_producer: */ | |
676 | { | |
677 | NETXEN_NIC_REG(0x22c), | |
678 | /* Jumbo frames */ | |
679 | NETXEN_NIC_REG(0x23c), | |
680 | /* LRO */ | |
681 | NETXEN_NIC_REG(0x24c) | |
682 | }, | |
683 | /* crb_sts_consumer: */ | |
f6d21f44 DP |
684 | { |
685 | NETXEN_NIC_REG(0x264), | |
686 | NETXEN_NIC_REG_2(0x03c), | |
687 | NETXEN_NIC_REG_2(0x03c), | |
688 | NETXEN_NIC_REG_2(0x03c), | |
689 | }, | |
690 | /* sw_int_mask */ | |
691 | { | |
692 | CRB_SW_INT_MASK_3, | |
693 | NETXEN_NIC_REG_2(0x03c), | |
694 | NETXEN_NIC_REG_2(0x03c), | |
695 | NETXEN_NIC_REG_2(0x03c), | |
696 | }, | |
d9e651bc DP |
697 | }, |
698 | }; | |
699 | ||
700 | static int | |
701 | netxen_init_old_ctx(struct netxen_adapter *adapter) | |
702 | { | |
703 | struct netxen_recv_context *recv_ctx; | |
704 | struct nx_host_rds_ring *rds_ring; | |
d8b100c5 | 705 | struct nx_host_sds_ring *sds_ring; |
d877f1e3 | 706 | struct nx_host_tx_ring *tx_ring; |
becf46a0 | 707 | int ring; |
f6d21f44 | 708 | int port = adapter->portnum; |
4ea528a1 | 709 | struct netxen_ring_ctx *hwctx; |
f6d21f44 | 710 | u32 signature; |
d9e651bc | 711 | |
4ea528a1 DP |
712 | tx_ring = adapter->tx_ring; |
713 | recv_ctx = &adapter->recv_ctx; | |
714 | hwctx = recv_ctx->hwctx; | |
715 | ||
f6d21f44 DP |
716 | hwctx->cmd_ring_addr = cpu_to_le64(tx_ring->phys_addr); |
717 | hwctx->cmd_ring_size = cpu_to_le32(tx_ring->num_desc); | |
d9e651bc | 718 | |
d9e651bc | 719 | |
becf46a0 DP |
720 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
721 | rds_ring = &recv_ctx->rds_rings[ring]; | |
d9e651bc | 722 | |
f6d21f44 | 723 | hwctx->rcv_rings[ring].addr = |
becf46a0 | 724 | cpu_to_le64(rds_ring->phys_addr); |
f6d21f44 | 725 | hwctx->rcv_rings[ring].size = |
438627c7 | 726 | cpu_to_le32(rds_ring->num_desc); |
d9e651bc DP |
727 | } |
728 | ||
f6d21f44 DP |
729 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
730 | sds_ring = &recv_ctx->sds_rings[ring]; | |
731 | ||
732 | if (ring == 0) { | |
733 | hwctx->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr); | |
734 | hwctx->sts_ring_size = cpu_to_le32(sds_ring->num_desc); | |
735 | } | |
736 | hwctx->sts_rings[ring].addr = cpu_to_le64(sds_ring->phys_addr); | |
737 | hwctx->sts_rings[ring].size = cpu_to_le32(sds_ring->num_desc); | |
738 | hwctx->sts_rings[ring].msi_index = cpu_to_le16(ring); | |
739 | } | |
740 | hwctx->sts_ring_count = cpu_to_le32(adapter->max_sds_rings); | |
741 | ||
742 | signature = (adapter->max_sds_rings > 1) ? | |
743 | NETXEN_CTX_SIGNATURE_V2 : NETXEN_CTX_SIGNATURE; | |
744 | ||
745 | NXWR32(adapter, CRB_CTX_ADDR_REG_LO(port), | |
4ea528a1 | 746 | lower32(recv_ctx->phys_addr)); |
f6d21f44 | 747 | NXWR32(adapter, CRB_CTX_ADDR_REG_HI(port), |
4ea528a1 | 748 | upper32(recv_ctx->phys_addr)); |
f6d21f44 DP |
749 | NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), |
750 | signature | port); | |
d9e651bc DP |
751 | return 0; |
752 | } | |
753 | ||
d9e651bc DP |
754 | int netxen_alloc_hw_resources(struct netxen_adapter *adapter) |
755 | { | |
d9e651bc DP |
756 | void *addr; |
757 | int err = 0; | |
becf46a0 | 758 | int ring; |
d9e651bc DP |
759 | struct netxen_recv_context *recv_ctx; |
760 | struct nx_host_rds_ring *rds_ring; | |
d8b100c5 | 761 | struct nx_host_sds_ring *sds_ring; |
4ea528a1 | 762 | struct nx_host_tx_ring *tx_ring; |
d8b100c5 DP |
763 | |
764 | struct pci_dev *pdev = adapter->pdev; | |
765 | struct net_device *netdev = adapter->netdev; | |
f6d21f44 | 766 | int port = adapter->portnum; |
d9e651bc | 767 | |
4ea528a1 DP |
768 | recv_ctx = &adapter->recv_ctx; |
769 | tx_ring = adapter->tx_ring; | |
770 | ||
d8b100c5 | 771 | addr = pci_alloc_consistent(pdev, |
d9e651bc | 772 | sizeof(struct netxen_ring_ctx) + sizeof(uint32_t), |
4ea528a1 | 773 | &recv_ctx->phys_addr); |
d9e651bc | 774 | if (addr == NULL) { |
d8b100c5 | 775 | dev_err(&pdev->dev, "failed to allocate hw context\n"); |
d9e651bc DP |
776 | return -ENOMEM; |
777 | } | |
4ea528a1 | 778 | |
d9e651bc | 779 | memset(addr, 0, sizeof(struct netxen_ring_ctx)); |
43d620c8 | 780 | recv_ctx->hwctx = addr; |
4ea528a1 DP |
781 | recv_ctx->hwctx->ctx_id = cpu_to_le32(port); |
782 | recv_ctx->hwctx->cmd_consumer_offset = | |
783 | cpu_to_le64(recv_ctx->phys_addr + | |
d9e651bc | 784 | sizeof(struct netxen_ring_ctx)); |
d877f1e3 | 785 | tx_ring->hw_consumer = |
d9e651bc DP |
786 | (__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx)); |
787 | ||
788 | /* cmd desc ring */ | |
d877f1e3 DP |
789 | addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring), |
790 | &tx_ring->phys_addr); | |
d9e651bc DP |
791 | |
792 | if (addr == NULL) { | |
d8b100c5 DP |
793 | dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n", |
794 | netdev->name); | |
bf445080 AKS |
795 | err = -ENOMEM; |
796 | goto err_out_free; | |
d9e651bc DP |
797 | } |
798 | ||
43d620c8 | 799 | tx_ring->desc_head = addr; |
d9e651bc | 800 | |
becf46a0 | 801 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
becf46a0 | 802 | rds_ring = &recv_ctx->rds_rings[ring]; |
d9e651bc | 803 | addr = pci_alloc_consistent(adapter->pdev, |
d8b100c5 | 804 | RCV_DESC_RINGSIZE(rds_ring), |
becf46a0 | 805 | &rds_ring->phys_addr); |
d9e651bc | 806 | if (addr == NULL) { |
d8b100c5 DP |
807 | dev_err(&pdev->dev, |
808 | "%s: failed to allocate rds ring [%d]\n", | |
809 | netdev->name, ring); | |
d9e651bc DP |
810 | err = -ENOMEM; |
811 | goto err_out_free; | |
812 | } | |
43d620c8 | 813 | rds_ring->desc_head = addr; |
d9e651bc | 814 | |
4f96b988 | 815 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) |
becf46a0 | 816 | rds_ring->crb_rcv_producer = |
195c5f98 AKS |
817 | netxen_get_ioaddr(adapter, |
818 | recv_crb_registers[port].crb_rcv_producer[ring]); | |
d9e651bc DP |
819 | } |
820 | ||
d8b100c5 DP |
821 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
822 | sds_ring = &recv_ctx->sds_rings[ring]; | |
823 | ||
824 | addr = pci_alloc_consistent(adapter->pdev, | |
825 | STATUS_DESC_RINGSIZE(sds_ring), | |
826 | &sds_ring->phys_addr); | |
827 | if (addr == NULL) { | |
828 | dev_err(&pdev->dev, | |
829 | "%s: failed to allocate sds ring [%d]\n", | |
830 | netdev->name, ring); | |
831 | err = -ENOMEM; | |
832 | goto err_out_free; | |
833 | } | |
43d620c8 | 834 | sds_ring->desc_head = addr; |
f6d21f44 | 835 | |
77c55390 AKS |
836 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { |
837 | sds_ring->crb_sts_consumer = | |
838 | netxen_get_ioaddr(adapter, | |
839 | recv_crb_registers[port].crb_sts_consumer[ring]); | |
f6d21f44 | 840 | |
77c55390 AKS |
841 | sds_ring->crb_intr_mask = |
842 | netxen_get_ioaddr(adapter, | |
843 | recv_crb_registers[port].sw_int_mask[ring]); | |
844 | } | |
becf46a0 | 845 | } |
becf46a0 | 846 | |
becf46a0 | 847 | |
4f96b988 | 848 | if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) { |
6a581e93 DP |
849 | if (test_and_set_bit(__NX_FW_ATTACHED, &adapter->state)) |
850 | goto done; | |
d9e651bc DP |
851 | err = nx_fw_cmd_create_rx_ctx(adapter); |
852 | if (err) | |
853 | goto err_out_free; | |
854 | err = nx_fw_cmd_create_tx_ctx(adapter); | |
855 | if (err) | |
856 | goto err_out_free; | |
857 | } else { | |
d9e651bc | 858 | err = netxen_init_old_ctx(adapter); |
cf981ffb DP |
859 | if (err) |
860 | goto err_out_free; | |
d9e651bc DP |
861 | } |
862 | ||
6a581e93 | 863 | done: |
d9e651bc DP |
864 | return 0; |
865 | ||
866 | err_out_free: | |
867 | netxen_free_hw_resources(adapter); | |
868 | return err; | |
869 | } | |
870 | ||
871 | void netxen_free_hw_resources(struct netxen_adapter *adapter) | |
872 | { | |
873 | struct netxen_recv_context *recv_ctx; | |
874 | struct nx_host_rds_ring *rds_ring; | |
d8b100c5 | 875 | struct nx_host_sds_ring *sds_ring; |
d877f1e3 | 876 | struct nx_host_tx_ring *tx_ring; |
becf46a0 | 877 | int ring; |
d9e651bc | 878 | |
f6d21f44 DP |
879 | int port = adapter->portnum; |
880 | ||
4f96b988 | 881 | if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) { |
6a581e93 DP |
882 | if (!test_and_clear_bit(__NX_FW_ATTACHED, &adapter->state)) |
883 | goto done; | |
884 | ||
d9e651bc | 885 | nx_fw_cmd_destroy_rx_ctx(adapter); |
cf981ffb | 886 | nx_fw_cmd_destroy_tx_ctx(adapter); |
f6d21f44 DP |
887 | } else { |
888 | netxen_api_lock(adapter); | |
889 | NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), | |
cf981ffb | 890 | NETXEN_CTX_D3_RESET | port); |
f6d21f44 | 891 | netxen_api_unlock(adapter); |
d9e651bc DP |
892 | } |
893 | ||
cf981ffb DP |
894 | /* Allow dma queues to drain after context reset */ |
895 | msleep(20); | |
896 | ||
6a581e93 | 897 | done: |
4ea528a1 DP |
898 | recv_ctx = &adapter->recv_ctx; |
899 | ||
900 | if (recv_ctx->hwctx != NULL) { | |
d9e651bc DP |
901 | pci_free_consistent(adapter->pdev, |
902 | sizeof(struct netxen_ring_ctx) + | |
903 | sizeof(uint32_t), | |
4ea528a1 DP |
904 | recv_ctx->hwctx, |
905 | recv_ctx->phys_addr); | |
906 | recv_ctx->hwctx = NULL; | |
d9e651bc DP |
907 | } |
908 | ||
4ea528a1 | 909 | tx_ring = adapter->tx_ring; |
d877f1e3 | 910 | if (tx_ring->desc_head != NULL) { |
d9e651bc | 911 | pci_free_consistent(adapter->pdev, |
d877f1e3 DP |
912 | TX_DESC_RINGSIZE(tx_ring), |
913 | tx_ring->desc_head, tx_ring->phys_addr); | |
914 | tx_ring->desc_head = NULL; | |
d9e651bc DP |
915 | } |
916 | ||
becf46a0 DP |
917 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
918 | rds_ring = &recv_ctx->rds_rings[ring]; | |
d9e651bc | 919 | |
becf46a0 | 920 | if (rds_ring->desc_head != NULL) { |
d9e651bc | 921 | pci_free_consistent(adapter->pdev, |
d8b100c5 | 922 | RCV_DESC_RINGSIZE(rds_ring), |
becf46a0 DP |
923 | rds_ring->desc_head, |
924 | rds_ring->phys_addr); | |
925 | rds_ring->desc_head = NULL; | |
d9e651bc DP |
926 | } |
927 | } | |
becf46a0 | 928 | |
d8b100c5 DP |
929 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
930 | sds_ring = &recv_ctx->sds_rings[ring]; | |
931 | ||
932 | if (sds_ring->desc_head != NULL) { | |
933 | pci_free_consistent(adapter->pdev, | |
934 | STATUS_DESC_RINGSIZE(sds_ring), | |
935 | sds_ring->desc_head, | |
936 | sds_ring->phys_addr); | |
937 | sds_ring->desc_head = NULL; | |
938 | } | |
becf46a0 | 939 | } |
d9e651bc DP |
940 | } |
941 |