diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/net/qlcnic/qlcnic_ctx.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_ctx.c')
-rw-r--r-- | drivers/net/qlcnic/qlcnic_ctx.c | 681 |
1 files changed, 408 insertions, 273 deletions
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c index cc5d861d9a12..bab041a5c758 100644 --- a/drivers/net/qlcnic/qlcnic_ctx.c +++ b/drivers/net/qlcnic/qlcnic_ctx.c | |||
@@ -1,25 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2009 - QLogic Corporation. | 2 | * QLogic qlcnic NIC Driver |
3 | * All rights reserved. | 3 | * Copyright (c) 2009-2010 QLogic Corporation |
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version 2 | ||
8 | * of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, | ||
18 | * MA 02111-1307, USA. | ||
19 | * | ||
20 | * The full GNU General Public License is included in this distribution | ||
21 | * in the file called "COPYING". | ||
22 | * | 4 | * |
5 | * See LICENSE.qlcnic for copyright and licensing details. | ||
23 | */ | 6 | */ |
24 | 7 | ||
25 | #include "qlcnic.h" | 8 | #include "qlcnic.h" |
@@ -81,14 +64,105 @@ qlcnic_issue_cmd(struct qlcnic_adapter *adapter, | |||
81 | return rcode; | 64 | return rcode; |
82 | } | 65 | } |
83 | 66 | ||
67 | static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u16 temp_size) | ||
68 | { | ||
69 | uint64_t sum = 0; | ||
70 | int count = temp_size / sizeof(uint32_t); | ||
71 | while (count-- > 0) | ||
72 | sum += *temp_buffer++; | ||
73 | while (sum >> 32) | ||
74 | sum = (sum & 0xFFFFFFFF) + (sum >> 32); | ||
75 | return ~sum; | ||
76 | } | ||
77 | |||
78 | int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) | ||
79 | { | ||
80 | int err, i; | ||
81 | u16 temp_size; | ||
82 | void *tmp_addr; | ||
83 | u32 version, csum, *template, *tmp_buf; | ||
84 | struct qlcnic_hardware_context *ahw; | ||
85 | struct qlcnic_dump_template_hdr *tmpl_hdr, *tmp_tmpl; | ||
86 | dma_addr_t tmp_addr_t = 0; | ||
87 | |||
88 | ahw = adapter->ahw; | ||
89 | err = qlcnic_issue_cmd(adapter, | ||
90 | adapter->ahw->pci_func, | ||
91 | adapter->fw_hal_version, | ||
92 | 0, | ||
93 | 0, | ||
94 | 0, | ||
95 | QLCNIC_CDRP_CMD_TEMP_SIZE); | ||
96 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
97 | err = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); | ||
98 | dev_err(&adapter->pdev->dev, | ||
99 | "Failed to get template size %d\n", err); | ||
100 | err = -EIO; | ||
101 | return err; | ||
102 | } | ||
103 | version = QLCRD32(adapter, QLCNIC_ARG3_CRB_OFFSET); | ||
104 | temp_size = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); | ||
105 | if (!temp_size) | ||
106 | return -EIO; | ||
107 | |||
108 | tmp_addr = dma_alloc_coherent(&adapter->pdev->dev, temp_size, | ||
109 | &tmp_addr_t, GFP_KERNEL); | ||
110 | if (!tmp_addr) { | ||
111 | dev_err(&adapter->pdev->dev, | ||
112 | "Can't get memory for FW dump template\n"); | ||
113 | return -ENOMEM; | ||
114 | } | ||
115 | err = qlcnic_issue_cmd(adapter, | ||
116 | adapter->ahw->pci_func, | ||
117 | adapter->fw_hal_version, | ||
118 | LSD(tmp_addr_t), | ||
119 | MSD(tmp_addr_t), | ||
120 | temp_size, | ||
121 | QLCNIC_CDRP_CMD_GET_TEMP_HDR); | ||
122 | |||
123 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
124 | dev_err(&adapter->pdev->dev, | ||
125 | "Failed to get mini dump template header %d\n", err); | ||
126 | err = -EIO; | ||
127 | goto error; | ||
128 | } | ||
129 | tmp_tmpl = (struct qlcnic_dump_template_hdr *) tmp_addr; | ||
130 | csum = qlcnic_temp_checksum((uint32_t *) tmp_addr, temp_size); | ||
131 | if (csum) { | ||
132 | dev_err(&adapter->pdev->dev, | ||
133 | "Template header checksum validation failed\n"); | ||
134 | err = -EIO; | ||
135 | goto error; | ||
136 | } | ||
137 | ahw->fw_dump.tmpl_hdr = vzalloc(temp_size); | ||
138 | if (!ahw->fw_dump.tmpl_hdr) { | ||
139 | err = -EIO; | ||
140 | goto error; | ||
141 | } | ||
142 | tmp_buf = (u32 *) tmp_addr; | ||
143 | template = (u32 *) ahw->fw_dump.tmpl_hdr; | ||
144 | for (i = 0; i < temp_size/sizeof(u32); i++) | ||
145 | *template++ = __le32_to_cpu(*tmp_buf++); | ||
146 | |||
147 | tmpl_hdr = ahw->fw_dump.tmpl_hdr; | ||
148 | if (tmpl_hdr->cap_mask > QLCNIC_DUMP_MASK_DEF && | ||
149 | tmpl_hdr->cap_mask <= QLCNIC_DUMP_MASK_MAX) | ||
150 | tmpl_hdr->drv_cap_mask = tmpl_hdr->cap_mask; | ||
151 | else | ||
152 | tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF; | ||
153 | error: | ||
154 | dma_free_coherent(&adapter->pdev->dev, temp_size, tmp_addr, tmp_addr_t); | ||
155 | return err; | ||
156 | } | ||
157 | |||
84 | int | 158 | int |
85 | qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu) | 159 | qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu) |
86 | { | 160 | { |
87 | struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; | 161 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
88 | 162 | ||
89 | if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) { | 163 | if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) { |
90 | if (qlcnic_issue_cmd(adapter, | 164 | if (qlcnic_issue_cmd(adapter, |
91 | adapter->ahw.pci_func, | 165 | adapter->ahw->pci_func, |
92 | adapter->fw_hal_version, | 166 | adapter->fw_hal_version, |
93 | recv_ctx->context_id, | 167 | recv_ctx->context_id, |
94 | mtu, | 168 | mtu, |
@@ -119,12 +193,12 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
119 | dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; | 193 | dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; |
120 | u64 phys_addr; | 194 | u64 phys_addr; |
121 | 195 | ||
122 | int i, nrds_rings, nsds_rings; | 196 | u8 i, nrds_rings, nsds_rings; |
123 | size_t rq_size, rsp_size; | 197 | size_t rq_size, rsp_size; |
124 | u32 cap, reg, val, reg2; | 198 | u32 cap, reg, val, reg2; |
125 | int err; | 199 | int err; |
126 | 200 | ||
127 | struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; | 201 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
128 | 202 | ||
129 | nrds_rings = adapter->max_rds_rings; | 203 | nrds_rings = adapter->max_rds_rings; |
130 | nsds_rings = adapter->max_sds_rings; | 204 | nsds_rings = adapter->max_sds_rings; |
@@ -136,14 +210,14 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
136 | SIZEOF_CARDRSP_RX(struct qlcnic_cardrsp_rx_ctx, nrds_rings, | 210 | SIZEOF_CARDRSP_RX(struct qlcnic_cardrsp_rx_ctx, nrds_rings, |
137 | nsds_rings); | 211 | nsds_rings); |
138 | 212 | ||
139 | addr = pci_alloc_consistent(adapter->pdev, | 213 | addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size, |
140 | rq_size, &hostrq_phys_addr); | 214 | &hostrq_phys_addr, GFP_KERNEL); |
141 | if (addr == NULL) | 215 | if (addr == NULL) |
142 | return -ENOMEM; | 216 | return -ENOMEM; |
143 | prq = (struct qlcnic_hostrq_rx_ctx *)addr; | 217 | prq = (struct qlcnic_hostrq_rx_ctx *)addr; |
144 | 218 | ||
145 | addr = pci_alloc_consistent(adapter->pdev, | 219 | addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size, |
146 | rsp_size, &cardrsp_phys_addr); | 220 | &cardrsp_phys_addr, GFP_KERNEL); |
147 | if (addr == NULL) { | 221 | if (addr == NULL) { |
148 | err = -ENOMEM; | 222 | err = -ENOMEM; |
149 | goto out_free_rq; | 223 | goto out_free_rq; |
@@ -168,7 +242,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
168 | 242 | ||
169 | prq->num_rds_rings = cpu_to_le16(nrds_rings); | 243 | prq->num_rds_rings = cpu_to_le16(nrds_rings); |
170 | prq->num_sds_rings = cpu_to_le16(nsds_rings); | 244 | prq->num_sds_rings = cpu_to_le16(nsds_rings); |
171 | prq->rds_ring_offset = cpu_to_le32(0); | 245 | prq->rds_ring_offset = 0; |
172 | 246 | ||
173 | val = le32_to_cpu(prq->rds_ring_offset) + | 247 | val = le32_to_cpu(prq->rds_ring_offset) + |
174 | (sizeof(struct qlcnic_hostrq_rds_ring) * nrds_rings); | 248 | (sizeof(struct qlcnic_hostrq_rds_ring) * nrds_rings); |
@@ -204,7 +278,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
204 | 278 | ||
205 | phys_addr = hostrq_phys_addr; | 279 | phys_addr = hostrq_phys_addr; |
206 | err = qlcnic_issue_cmd(adapter, | 280 | err = qlcnic_issue_cmd(adapter, |
207 | adapter->ahw.pci_func, | 281 | adapter->ahw->pci_func, |
208 | adapter->fw_hal_version, | 282 | adapter->fw_hal_version, |
209 | (u32)(phys_addr >> 32), | 283 | (u32)(phys_addr >> 32), |
210 | (u32)(phys_addr & 0xffffffff), | 284 | (u32)(phys_addr & 0xffffffff), |
@@ -224,7 +298,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
224 | rds_ring = &recv_ctx->rds_rings[i]; | 298 | rds_ring = &recv_ctx->rds_rings[i]; |
225 | 299 | ||
226 | reg = le32_to_cpu(prsp_rds[i].host_producer_crb); | 300 | reg = le32_to_cpu(prsp_rds[i].host_producer_crb); |
227 | rds_ring->crb_rcv_producer = adapter->ahw.pci_base0 + reg; | 301 | rds_ring->crb_rcv_producer = adapter->ahw->pci_base0 + reg; |
228 | } | 302 | } |
229 | 303 | ||
230 | prsp_sds = ((struct qlcnic_cardrsp_sds_ring *) | 304 | prsp_sds = ((struct qlcnic_cardrsp_sds_ring *) |
@@ -236,8 +310,8 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
236 | reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); | 310 | reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); |
237 | reg2 = le32_to_cpu(prsp_sds[i].interrupt_crb); | 311 | reg2 = le32_to_cpu(prsp_sds[i].interrupt_crb); |
238 | 312 | ||
239 | sds_ring->crb_sts_consumer = adapter->ahw.pci_base0 + reg; | 313 | sds_ring->crb_sts_consumer = adapter->ahw->pci_base0 + reg; |
240 | sds_ring->crb_intr_mask = adapter->ahw.pci_base0 + reg2; | 314 | sds_ring->crb_intr_mask = adapter->ahw->pci_base0 + reg2; |
241 | } | 315 | } |
242 | 316 | ||
243 | recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); | 317 | recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); |
@@ -245,19 +319,20 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
245 | recv_ctx->virt_port = prsp->virt_port; | 319 | recv_ctx->virt_port = prsp->virt_port; |
246 | 320 | ||
247 | out_free_rsp: | 321 | out_free_rsp: |
248 | pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr); | 322 | dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp, |
323 | cardrsp_phys_addr); | ||
249 | out_free_rq: | 324 | out_free_rq: |
250 | pci_free_consistent(adapter->pdev, rq_size, prq, hostrq_phys_addr); | 325 | dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr); |
251 | return err; | 326 | return err; |
252 | } | 327 | } |
253 | 328 | ||
254 | static void | 329 | static void |
255 | qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter) | 330 | qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter) |
256 | { | 331 | { |
257 | struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; | 332 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
258 | 333 | ||
259 | if (qlcnic_issue_cmd(adapter, | 334 | if (qlcnic_issue_cmd(adapter, |
260 | adapter->ahw.pci_func, | 335 | adapter->ahw->pci_func, |
261 | adapter->fw_hal_version, | 336 | adapter->fw_hal_version, |
262 | recv_ctx->context_id, | 337 | recv_ctx->context_id, |
263 | QLCNIC_DESTROY_CTX_RESET, | 338 | QLCNIC_DESTROY_CTX_RESET, |
@@ -291,14 +366,14 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) | |||
291 | *(tx_ring->hw_consumer) = 0; | 366 | *(tx_ring->hw_consumer) = 0; |
292 | 367 | ||
293 | rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx); | 368 | rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx); |
294 | rq_addr = pci_alloc_consistent(adapter->pdev, | 369 | rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size, |
295 | rq_size, &rq_phys_addr); | 370 | &rq_phys_addr, GFP_KERNEL); |
296 | if (!rq_addr) | 371 | if (!rq_addr) |
297 | return -ENOMEM; | 372 | return -ENOMEM; |
298 | 373 | ||
299 | rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx); | 374 | rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx); |
300 | rsp_addr = pci_alloc_consistent(adapter->pdev, | 375 | rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size, |
301 | rsp_size, &rsp_phys_addr); | 376 | &rsp_phys_addr, GFP_KERNEL); |
302 | if (!rsp_addr) { | 377 | if (!rsp_addr) { |
303 | err = -ENOMEM; | 378 | err = -ENOMEM; |
304 | goto out_free_rq; | 379 | goto out_free_rq; |
@@ -330,7 +405,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) | |||
330 | 405 | ||
331 | phys_addr = rq_phys_addr; | 406 | phys_addr = rq_phys_addr; |
332 | err = qlcnic_issue_cmd(adapter, | 407 | err = qlcnic_issue_cmd(adapter, |
333 | adapter->ahw.pci_func, | 408 | adapter->ahw->pci_func, |
334 | adapter->fw_hal_version, | 409 | adapter->fw_hal_version, |
335 | (u32)(phys_addr >> 32), | 410 | (u32)(phys_addr >> 32), |
336 | ((u32)phys_addr & 0xffffffff), | 411 | ((u32)phys_addr & 0xffffffff), |
@@ -339,7 +414,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) | |||
339 | 414 | ||
340 | if (err == QLCNIC_RCODE_SUCCESS) { | 415 | if (err == QLCNIC_RCODE_SUCCESS) { |
341 | temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); | 416 | temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); |
342 | tx_ring->crb_cmd_producer = adapter->ahw.pci_base0 + temp; | 417 | tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp; |
343 | 418 | ||
344 | adapter->tx_context_id = | 419 | adapter->tx_context_id = |
345 | le16_to_cpu(prsp->context_id); | 420 | le16_to_cpu(prsp->context_id); |
@@ -349,10 +424,11 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) | |||
349 | err = -EIO; | 424 | err = -EIO; |
350 | } | 425 | } |
351 | 426 | ||
352 | pci_free_consistent(adapter->pdev, rsp_size, rsp_addr, rsp_phys_addr); | 427 | dma_free_coherent(&adapter->pdev->dev, rsp_size, rsp_addr, |
428 | rsp_phys_addr); | ||
353 | 429 | ||
354 | out_free_rq: | 430 | out_free_rq: |
355 | pci_free_consistent(adapter->pdev, rq_size, rq_addr, rq_phys_addr); | 431 | dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr); |
356 | 432 | ||
357 | return err; | 433 | return err; |
358 | } | 434 | } |
@@ -361,7 +437,7 @@ static void | |||
361 | qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter) | 437 | qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter) |
362 | { | 438 | { |
363 | if (qlcnic_issue_cmd(adapter, | 439 | if (qlcnic_issue_cmd(adapter, |
364 | adapter->ahw.pci_func, | 440 | adapter->ahw->pci_func, |
365 | adapter->fw_hal_version, | 441 | adapter->fw_hal_version, |
366 | adapter->tx_context_id, | 442 | adapter->tx_context_id, |
367 | QLCNIC_DESTROY_CTX_RESET, | 443 | QLCNIC_DESTROY_CTX_RESET, |
@@ -374,33 +450,15 @@ qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter) | |||
374 | } | 450 | } |
375 | 451 | ||
376 | int | 452 | int |
377 | qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val) | 453 | qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config) |
378 | { | ||
379 | |||
380 | if (qlcnic_issue_cmd(adapter, | ||
381 | adapter->ahw.pci_func, | ||
382 | adapter->fw_hal_version, | ||
383 | reg, | ||
384 | 0, | ||
385 | 0, | ||
386 | QLCNIC_CDRP_CMD_READ_PHY)) { | ||
387 | |||
388 | return -EIO; | ||
389 | } | ||
390 | |||
391 | return QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); | ||
392 | } | ||
393 | |||
394 | int | ||
395 | qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val) | ||
396 | { | 454 | { |
397 | return qlcnic_issue_cmd(adapter, | 455 | return qlcnic_issue_cmd(adapter, |
398 | adapter->ahw.pci_func, | 456 | adapter->ahw->pci_func, |
399 | adapter->fw_hal_version, | 457 | adapter->fw_hal_version, |
400 | reg, | 458 | config, |
401 | val, | ||
402 | 0, | 459 | 0, |
403 | QLCNIC_CDRP_CMD_WRITE_PHY); | 460 | 0, |
461 | QLCNIC_CDRP_CMD_CONFIG_PORT); | ||
404 | } | 462 | } |
405 | 463 | ||
406 | int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) | 464 | int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) |
@@ -415,20 +473,19 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) | |||
415 | 473 | ||
416 | struct pci_dev *pdev = adapter->pdev; | 474 | struct pci_dev *pdev = adapter->pdev; |
417 | 475 | ||
418 | recv_ctx = &adapter->recv_ctx; | 476 | recv_ctx = adapter->recv_ctx; |
419 | tx_ring = adapter->tx_ring; | 477 | tx_ring = adapter->tx_ring; |
420 | 478 | ||
421 | tx_ring->hw_consumer = (__le32 *)pci_alloc_consistent(pdev, sizeof(u32), | 479 | tx_ring->hw_consumer = (__le32 *) dma_alloc_coherent(&pdev->dev, |
422 | &tx_ring->hw_cons_phys_addr); | 480 | sizeof(u32), &tx_ring->hw_cons_phys_addr, GFP_KERNEL); |
423 | if (tx_ring->hw_consumer == NULL) { | 481 | if (tx_ring->hw_consumer == NULL) { |
424 | dev_err(&pdev->dev, "failed to allocate tx consumer\n"); | 482 | dev_err(&pdev->dev, "failed to allocate tx consumer\n"); |
425 | return -ENOMEM; | 483 | return -ENOMEM; |
426 | } | 484 | } |
427 | *(tx_ring->hw_consumer) = 0; | ||
428 | 485 | ||
429 | /* cmd desc ring */ | 486 | /* cmd desc ring */ |
430 | addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring), | 487 | addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring), |
431 | &tx_ring->phys_addr); | 488 | &tx_ring->phys_addr, GFP_KERNEL); |
432 | 489 | ||
433 | if (addr == NULL) { | 490 | if (addr == NULL) { |
434 | dev_err(&pdev->dev, "failed to allocate tx desc ring\n"); | 491 | dev_err(&pdev->dev, "failed to allocate tx desc ring\n"); |
@@ -440,9 +497,9 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) | |||
440 | 497 | ||
441 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 498 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
442 | rds_ring = &recv_ctx->rds_rings[ring]; | 499 | rds_ring = &recv_ctx->rds_rings[ring]; |
443 | addr = pci_alloc_consistent(adapter->pdev, | 500 | addr = dma_alloc_coherent(&adapter->pdev->dev, |
444 | RCV_DESC_RINGSIZE(rds_ring), | 501 | RCV_DESC_RINGSIZE(rds_ring), |
445 | &rds_ring->phys_addr); | 502 | &rds_ring->phys_addr, GFP_KERNEL); |
446 | if (addr == NULL) { | 503 | if (addr == NULL) { |
447 | dev_err(&pdev->dev, | 504 | dev_err(&pdev->dev, |
448 | "failed to allocate rds ring [%d]\n", ring); | 505 | "failed to allocate rds ring [%d]\n", ring); |
@@ -456,9 +513,9 @@ int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) | |||
456 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 513 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
457 | sds_ring = &recv_ctx->sds_rings[ring]; | 514 | sds_ring = &recv_ctx->sds_rings[ring]; |
458 | 515 | ||
459 | addr = pci_alloc_consistent(adapter->pdev, | 516 | addr = dma_alloc_coherent(&adapter->pdev->dev, |
460 | STATUS_DESC_RINGSIZE(sds_ring), | 517 | STATUS_DESC_RINGSIZE(sds_ring), |
461 | &sds_ring->phys_addr); | 518 | &sds_ring->phys_addr, GFP_KERNEL); |
462 | if (addr == NULL) { | 519 | if (addr == NULL) { |
463 | dev_err(&pdev->dev, | 520 | dev_err(&pdev->dev, |
464 | "failed to allocate sds ring [%d]\n", ring); | 521 | "failed to allocate sds ring [%d]\n", ring); |
@@ -480,6 +537,11 @@ int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter) | |||
480 | { | 537 | { |
481 | int err; | 538 | int err; |
482 | 539 | ||
540 | if (adapter->flags & QLCNIC_NEED_FLR) { | ||
541 | pci_reset_function(adapter->pdev); | ||
542 | adapter->flags &= ~QLCNIC_NEED_FLR; | ||
543 | } | ||
544 | |||
483 | err = qlcnic_fw_cmd_create_rx_ctx(adapter); | 545 | err = qlcnic_fw_cmd_create_rx_ctx(adapter); |
484 | if (err) | 546 | if (err) |
485 | return err; | 547 | return err; |
@@ -513,11 +575,11 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) | |||
513 | struct qlcnic_host_tx_ring *tx_ring; | 575 | struct qlcnic_host_tx_ring *tx_ring; |
514 | int ring; | 576 | int ring; |
515 | 577 | ||
516 | recv_ctx = &adapter->recv_ctx; | 578 | recv_ctx = adapter->recv_ctx; |
517 | 579 | ||
518 | tx_ring = adapter->tx_ring; | 580 | tx_ring = adapter->tx_ring; |
519 | if (tx_ring->hw_consumer != NULL) { | 581 | if (tx_ring->hw_consumer != NULL) { |
520 | pci_free_consistent(adapter->pdev, | 582 | dma_free_coherent(&adapter->pdev->dev, |
521 | sizeof(u32), | 583 | sizeof(u32), |
522 | tx_ring->hw_consumer, | 584 | tx_ring->hw_consumer, |
523 | tx_ring->hw_cons_phys_addr); | 585 | tx_ring->hw_cons_phys_addr); |
@@ -525,7 +587,7 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) | |||
525 | } | 587 | } |
526 | 588 | ||
527 | if (tx_ring->desc_head != NULL) { | 589 | if (tx_ring->desc_head != NULL) { |
528 | pci_free_consistent(adapter->pdev, | 590 | dma_free_coherent(&adapter->pdev->dev, |
529 | TX_DESC_RINGSIZE(tx_ring), | 591 | TX_DESC_RINGSIZE(tx_ring), |
530 | tx_ring->desc_head, tx_ring->phys_addr); | 592 | tx_ring->desc_head, tx_ring->phys_addr); |
531 | tx_ring->desc_head = NULL; | 593 | tx_ring->desc_head = NULL; |
@@ -535,7 +597,7 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) | |||
535 | rds_ring = &recv_ctx->rds_rings[ring]; | 597 | rds_ring = &recv_ctx->rds_rings[ring]; |
536 | 598 | ||
537 | if (rds_ring->desc_head != NULL) { | 599 | if (rds_ring->desc_head != NULL) { |
538 | pci_free_consistent(adapter->pdev, | 600 | dma_free_coherent(&adapter->pdev->dev, |
539 | RCV_DESC_RINGSIZE(rds_ring), | 601 | RCV_DESC_RINGSIZE(rds_ring), |
540 | rds_ring->desc_head, | 602 | rds_ring->desc_head, |
541 | rds_ring->phys_addr); | 603 | rds_ring->phys_addr); |
@@ -547,7 +609,7 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) | |||
547 | sds_ring = &recv_ctx->sds_rings[ring]; | 609 | sds_ring = &recv_ctx->sds_rings[ring]; |
548 | 610 | ||
549 | if (sds_ring->desc_head != NULL) { | 611 | if (sds_ring->desc_head != NULL) { |
550 | pci_free_consistent(adapter->pdev, | 612 | dma_free_coherent(&adapter->pdev->dev, |
551 | STATUS_DESC_RINGSIZE(sds_ring), | 613 | STATUS_DESC_RINGSIZE(sds_ring), |
552 | sds_ring->desc_head, | 614 | sds_ring->desc_head, |
553 | sds_ring->phys_addr); | 615 | sds_ring->phys_addr); |
@@ -556,32 +618,6 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) | |||
556 | } | 618 | } |
557 | } | 619 | } |
558 | 620 | ||
559 | /* Set MAC address of a NIC partition */ | ||
560 | int qlcnic_set_mac_address(struct qlcnic_adapter *adapter, u8* mac) | ||
561 | { | ||
562 | int err = 0; | ||
563 | u32 arg1, arg2, arg3; | ||
564 | |||
565 | arg1 = adapter->ahw.pci_func | BIT_9; | ||
566 | arg2 = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24); | ||
567 | arg3 = mac[4] | (mac[5] << 16); | ||
568 | |||
569 | err = qlcnic_issue_cmd(adapter, | ||
570 | adapter->ahw.pci_func, | ||
571 | adapter->fw_hal_version, | ||
572 | arg1, | ||
573 | arg2, | ||
574 | arg3, | ||
575 | QLCNIC_CDRP_CMD_MAC_ADDRESS); | ||
576 | |||
577 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
578 | dev_err(&adapter->pdev->dev, | ||
579 | "Failed to set mac address%d\n", err); | ||
580 | err = -EIO; | ||
581 | } | ||
582 | |||
583 | return err; | ||
584 | } | ||
585 | 621 | ||
586 | /* Get MAC address of a NIC partition */ | 622 | /* Get MAC address of a NIC partition */ |
587 | int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) | 623 | int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) |
@@ -589,9 +625,9 @@ int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) | |||
589 | int err; | 625 | int err; |
590 | u32 arg1; | 626 | u32 arg1; |
591 | 627 | ||
592 | arg1 = adapter->ahw.pci_func | BIT_8; | 628 | arg1 = adapter->ahw->pci_func | BIT_8; |
593 | err = qlcnic_issue_cmd(adapter, | 629 | err = qlcnic_issue_cmd(adapter, |
594 | adapter->ahw.pci_func, | 630 | adapter->ahw->pci_func, |
595 | adapter->fw_hal_version, | 631 | adapter->fw_hal_version, |
596 | arg1, | 632 | arg1, |
597 | 0, | 633 | 0, |
@@ -620,15 +656,15 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter, | |||
620 | void *nic_info_addr; | 656 | void *nic_info_addr; |
621 | size_t nic_size = sizeof(struct qlcnic_info); | 657 | size_t nic_size = sizeof(struct qlcnic_info); |
622 | 658 | ||
623 | nic_info_addr = pci_alloc_consistent(adapter->pdev, | 659 | nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, |
624 | nic_size, &nic_dma_t); | 660 | &nic_dma_t, GFP_KERNEL); |
625 | if (!nic_info_addr) | 661 | if (!nic_info_addr) |
626 | return -ENOMEM; | 662 | return -ENOMEM; |
627 | memset(nic_info_addr, 0, nic_size); | 663 | memset(nic_info_addr, 0, nic_size); |
628 | 664 | ||
629 | nic_info = (struct qlcnic_info *) nic_info_addr; | 665 | nic_info = (struct qlcnic_info *) nic_info_addr; |
630 | err = qlcnic_issue_cmd(adapter, | 666 | err = qlcnic_issue_cmd(adapter, |
631 | adapter->ahw.pci_func, | 667 | adapter->ahw->pci_func, |
632 | adapter->fw_hal_version, | 668 | adapter->fw_hal_version, |
633 | MSD(nic_dma_t), | 669 | MSD(nic_dma_t), |
634 | LSD(nic_dma_t), | 670 | LSD(nic_dma_t), |
@@ -661,7 +697,8 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter, | |||
661 | err = -EIO; | 697 | err = -EIO; |
662 | } | 698 | } |
663 | 699 | ||
664 | pci_free_consistent(adapter->pdev, nic_size, nic_info_addr, nic_dma_t); | 700 | dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr, |
701 | nic_dma_t); | ||
665 | return err; | 702 | return err; |
666 | } | 703 | } |
667 | 704 | ||
@@ -677,8 +714,8 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) | |||
677 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | 714 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) |
678 | return err; | 715 | return err; |
679 | 716 | ||
680 | nic_info_addr = pci_alloc_consistent(adapter->pdev, nic_size, | 717 | nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, |
681 | &nic_dma_t); | 718 | &nic_dma_t, GFP_KERNEL); |
682 | if (!nic_info_addr) | 719 | if (!nic_info_addr) |
683 | return -ENOMEM; | 720 | return -ENOMEM; |
684 | 721 | ||
@@ -697,7 +734,7 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) | |||
697 | nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw); | 734 | nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw); |
698 | 735 | ||
699 | err = qlcnic_issue_cmd(adapter, | 736 | err = qlcnic_issue_cmd(adapter, |
700 | adapter->ahw.pci_func, | 737 | adapter->ahw->pci_func, |
701 | adapter->fw_hal_version, | 738 | adapter->fw_hal_version, |
702 | MSD(nic_dma_t), | 739 | MSD(nic_dma_t), |
703 | LSD(nic_dma_t), | 740 | LSD(nic_dma_t), |
@@ -710,7 +747,8 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) | |||
710 | err = -EIO; | 747 | err = -EIO; |
711 | } | 748 | } |
712 | 749 | ||
713 | pci_free_consistent(adapter->pdev, nic_size, nic_info_addr, nic_dma_t); | 750 | dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr, |
751 | nic_dma_t); | ||
714 | return err; | 752 | return err; |
715 | } | 753 | } |
716 | 754 | ||
@@ -725,15 +763,15 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, | |||
725 | size_t npar_size = sizeof(struct qlcnic_pci_info); | 763 | size_t npar_size = sizeof(struct qlcnic_pci_info); |
726 | size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC; | 764 | size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC; |
727 | 765 | ||
728 | pci_info_addr = pci_alloc_consistent(adapter->pdev, pci_size, | 766 | pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size, |
729 | &pci_info_dma_t); | 767 | &pci_info_dma_t, GFP_KERNEL); |
730 | if (!pci_info_addr) | 768 | if (!pci_info_addr) |
731 | return -ENOMEM; | 769 | return -ENOMEM; |
732 | memset(pci_info_addr, 0, pci_size); | 770 | memset(pci_info_addr, 0, pci_size); |
733 | 771 | ||
734 | npar = (struct qlcnic_pci_info *) pci_info_addr; | 772 | npar = (struct qlcnic_pci_info *) pci_info_addr; |
735 | err = qlcnic_issue_cmd(adapter, | 773 | err = qlcnic_issue_cmd(adapter, |
736 | adapter->ahw.pci_func, | 774 | adapter->ahw->pci_func, |
737 | adapter->fw_hal_version, | 775 | adapter->fw_hal_version, |
738 | MSD(pci_info_dma_t), | 776 | MSD(pci_info_dma_t), |
739 | LSD(pci_info_dma_t), | 777 | LSD(pci_info_dma_t), |
@@ -742,15 +780,15 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, | |||
742 | 780 | ||
743 | if (err == QLCNIC_RCODE_SUCCESS) { | 781 | if (err == QLCNIC_RCODE_SUCCESS) { |
744 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) { | 782 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++, pci_info++) { |
745 | pci_info->id = le32_to_cpu(npar->id); | 783 | pci_info->id = le16_to_cpu(npar->id); |
746 | pci_info->active = le32_to_cpu(npar->active); | 784 | pci_info->active = le16_to_cpu(npar->active); |
747 | pci_info->type = le32_to_cpu(npar->type); | 785 | pci_info->type = le16_to_cpu(npar->type); |
748 | pci_info->default_port = | 786 | pci_info->default_port = |
749 | le32_to_cpu(npar->default_port); | 787 | le16_to_cpu(npar->default_port); |
750 | pci_info->tx_min_bw = | 788 | pci_info->tx_min_bw = |
751 | le32_to_cpu(npar->tx_min_bw); | 789 | le16_to_cpu(npar->tx_min_bw); |
752 | pci_info->tx_max_bw = | 790 | pci_info->tx_max_bw = |
753 | le32_to_cpu(npar->tx_max_bw); | 791 | le16_to_cpu(npar->tx_max_bw); |
754 | memcpy(pci_info->mac, npar->mac, ETH_ALEN); | 792 | memcpy(pci_info->mac, npar->mac, ETH_ALEN); |
755 | } | 793 | } |
756 | } else { | 794 | } else { |
@@ -759,227 +797,324 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, | |||
759 | err = -EIO; | 797 | err = -EIO; |
760 | } | 798 | } |
761 | 799 | ||
762 | pci_free_consistent(adapter->pdev, pci_size, pci_info_addr, | 800 | dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr, |
763 | pci_info_dma_t); | 801 | pci_info_dma_t); |
764 | return err; | 802 | return err; |
765 | } | 803 | } |
766 | 804 | ||
767 | /* Reset a NIC partition */ | 805 | /* Configure eSwitch for port mirroring */ |
768 | 806 | int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, | |
769 | int qlcnic_reset_partition(struct qlcnic_adapter *adapter, u8 func_no) | 807 | u8 enable_mirroring, u8 pci_func) |
770 | { | 808 | { |
771 | int err = -EIO; | 809 | int err = -EIO; |
810 | u32 arg1; | ||
772 | 811 | ||
773 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | 812 | if (adapter->op_mode != QLCNIC_MGMT_FUNC || |
813 | !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) | ||
774 | return err; | 814 | return err; |
775 | 815 | ||
816 | arg1 = id | (enable_mirroring ? BIT_4 : 0); | ||
817 | arg1 |= pci_func << 8; | ||
818 | |||
776 | err = qlcnic_issue_cmd(adapter, | 819 | err = qlcnic_issue_cmd(adapter, |
777 | adapter->ahw.pci_func, | 820 | adapter->ahw->pci_func, |
778 | adapter->fw_hal_version, | 821 | adapter->fw_hal_version, |
779 | func_no, | 822 | arg1, |
780 | 0, | 823 | 0, |
781 | 0, | 824 | 0, |
782 | QLCNIC_CDRP_CMD_RESET_NPAR); | 825 | QLCNIC_CDRP_CMD_SET_PORTMIRRORING); |
783 | 826 | ||
784 | if (err != QLCNIC_RCODE_SUCCESS) { | 827 | if (err != QLCNIC_RCODE_SUCCESS) { |
785 | dev_err(&adapter->pdev->dev, | 828 | dev_err(&adapter->pdev->dev, |
786 | "Failed to issue reset partition%d\n", err); | 829 | "Failed to configure port mirroring%d on eswitch:%d\n", |
787 | err = -EIO; | 830 | pci_func, id); |
831 | } else { | ||
832 | dev_info(&adapter->pdev->dev, | ||
833 | "Configured eSwitch %d for port mirroring:%d\n", | ||
834 | id, pci_func); | ||
788 | } | 835 | } |
789 | 836 | ||
790 | return err; | 837 | return err; |
791 | } | 838 | } |
792 | 839 | ||
793 | /* Get eSwitch Capabilities */ | 840 | int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, |
794 | int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *adapter, u8 port, | 841 | const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) { |
795 | struct qlcnic_eswitch *eswitch) | ||
796 | { | ||
797 | int err = -EIO; | ||
798 | u32 arg1, arg2; | ||
799 | 842 | ||
800 | if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) | 843 | size_t stats_size = sizeof(struct __qlcnic_esw_statistics); |
801 | return err; | 844 | struct __qlcnic_esw_statistics *stats; |
845 | dma_addr_t stats_dma_t; | ||
846 | void *stats_addr; | ||
847 | u32 arg1; | ||
848 | int err; | ||
802 | 849 | ||
803 | err = qlcnic_issue_cmd(adapter, | 850 | if (esw_stats == NULL) |
804 | adapter->ahw.pci_func, | 851 | return -ENOMEM; |
805 | adapter->fw_hal_version, | ||
806 | port, | ||
807 | 0, | ||
808 | 0, | ||
809 | QLCNIC_CDRP_CMD_GET_ESWITCH_CAPABILITY); | ||
810 | 852 | ||
811 | if (err == QLCNIC_RCODE_SUCCESS) { | 853 | if (adapter->op_mode != QLCNIC_MGMT_FUNC && |
812 | arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); | 854 | func != adapter->ahw->pci_func) { |
813 | arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); | ||
814 | |||
815 | eswitch->port = arg1 & 0xf; | ||
816 | eswitch->active_vports = LSB(arg2); | ||
817 | eswitch->max_ucast_filters = MSB(arg2); | ||
818 | eswitch->max_active_vlans = LSB(MSW(arg2)); | ||
819 | if (arg1 & BIT_6) | ||
820 | eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING; | ||
821 | if (arg1 & BIT_7) | ||
822 | eswitch->flags |= QLCNIC_SWITCH_PROMISC_MODE; | ||
823 | if (arg1 & BIT_8) | ||
824 | eswitch->flags |= QLCNIC_SWITCH_PORT_MIRRORING; | ||
825 | } else { | ||
826 | dev_err(&adapter->pdev->dev, | 855 | dev_err(&adapter->pdev->dev, |
827 | "Failed to get eswitch capabilities%d\n", err); | 856 | "Not privilege to query stats for func=%d", func); |
857 | return -EIO; | ||
828 | } | 858 | } |
829 | 859 | ||
830 | return err; | 860 | stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size, |
831 | } | 861 | &stats_dma_t, GFP_KERNEL); |
862 | if (!stats_addr) { | ||
863 | dev_err(&adapter->pdev->dev, "Unable to allocate memory\n"); | ||
864 | return -ENOMEM; | ||
865 | } | ||
866 | memset(stats_addr, 0, stats_size); | ||
832 | 867 | ||
833 | /* Get current status of eswitch */ | 868 | arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12; |
834 | int qlcnic_get_eswitch_status(struct qlcnic_adapter *adapter, u8 port, | 869 | arg1 |= rx_tx << 15 | stats_size << 16; |
835 | struct qlcnic_eswitch *eswitch) | ||
836 | { | ||
837 | int err = -EIO; | ||
838 | u32 arg1, arg2; | ||
839 | |||
840 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
841 | return err; | ||
842 | 870 | ||
843 | err = qlcnic_issue_cmd(adapter, | 871 | err = qlcnic_issue_cmd(adapter, |
844 | adapter->ahw.pci_func, | 872 | adapter->ahw->pci_func, |
845 | adapter->fw_hal_version, | 873 | adapter->fw_hal_version, |
846 | port, | 874 | arg1, |
847 | 0, | 875 | MSD(stats_dma_t), |
848 | 0, | 876 | LSD(stats_dma_t), |
849 | QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS); | 877 | QLCNIC_CDRP_CMD_GET_ESWITCH_STATS); |
850 | 878 | ||
851 | if (err == QLCNIC_RCODE_SUCCESS) { | 879 | if (!err) { |
852 | arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); | 880 | stats = (struct __qlcnic_esw_statistics *)stats_addr; |
853 | arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); | 881 | esw_stats->context_id = le16_to_cpu(stats->context_id); |
854 | 882 | esw_stats->version = le16_to_cpu(stats->version); | |
855 | eswitch->port = arg1 & 0xf; | 883 | esw_stats->size = le16_to_cpu(stats->size); |
856 | eswitch->active_vports = LSB(arg2); | 884 | esw_stats->multicast_frames = |
857 | eswitch->active_ucast_filters = MSB(arg2); | 885 | le64_to_cpu(stats->multicast_frames); |
858 | eswitch->active_vlans = LSB(MSW(arg2)); | 886 | esw_stats->broadcast_frames = |
859 | if (arg1 & BIT_6) | 887 | le64_to_cpu(stats->broadcast_frames); |
860 | eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING; | 888 | esw_stats->unicast_frames = le64_to_cpu(stats->unicast_frames); |
861 | if (arg1 & BIT_8) | 889 | esw_stats->dropped_frames = le64_to_cpu(stats->dropped_frames); |
862 | eswitch->flags |= QLCNIC_SWITCH_PORT_MIRRORING; | 890 | esw_stats->local_frames = le64_to_cpu(stats->local_frames); |
863 | 891 | esw_stats->errors = le64_to_cpu(stats->errors); | |
864 | } else { | 892 | esw_stats->numbytes = le64_to_cpu(stats->numbytes); |
865 | dev_err(&adapter->pdev->dev, | ||
866 | "Failed to get eswitch status%d\n", err); | ||
867 | } | 893 | } |
868 | 894 | ||
895 | dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr, | ||
896 | stats_dma_t); | ||
869 | return err; | 897 | return err; |
870 | } | 898 | } |
871 | 899 | ||
872 | /* Enable/Disable eSwitch */ | 900 | int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch, |
873 | int qlcnic_toggle_eswitch(struct qlcnic_adapter *adapter, u8 id, u8 enable) | 901 | const u8 rx_tx, struct __qlcnic_esw_statistics *esw_stats) { |
902 | |||
903 | struct __qlcnic_esw_statistics port_stats; | ||
904 | u8 i; | ||
905 | int ret = -EIO; | ||
906 | |||
907 | if (esw_stats == NULL) | ||
908 | return -ENOMEM; | ||
909 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
910 | return -EIO; | ||
911 | if (adapter->npars == NULL) | ||
912 | return -EIO; | ||
913 | |||
914 | memset(esw_stats, 0, sizeof(u64)); | ||
915 | esw_stats->unicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL; | ||
916 | esw_stats->multicast_frames = QLCNIC_ESW_STATS_NOT_AVAIL; | ||
917 | esw_stats->broadcast_frames = QLCNIC_ESW_STATS_NOT_AVAIL; | ||
918 | esw_stats->dropped_frames = QLCNIC_ESW_STATS_NOT_AVAIL; | ||
919 | esw_stats->errors = QLCNIC_ESW_STATS_NOT_AVAIL; | ||
920 | esw_stats->local_frames = QLCNIC_ESW_STATS_NOT_AVAIL; | ||
921 | esw_stats->numbytes = QLCNIC_ESW_STATS_NOT_AVAIL; | ||
922 | esw_stats->context_id = eswitch; | ||
923 | |||
924 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | ||
925 | if (adapter->npars[i].phy_port != eswitch) | ||
926 | continue; | ||
927 | |||
928 | memset(&port_stats, 0, sizeof(struct __qlcnic_esw_statistics)); | ||
929 | if (qlcnic_get_port_stats(adapter, i, rx_tx, &port_stats)) | ||
930 | continue; | ||
931 | |||
932 | esw_stats->size = port_stats.size; | ||
933 | esw_stats->version = port_stats.version; | ||
934 | QLCNIC_ADD_ESW_STATS(esw_stats->unicast_frames, | ||
935 | port_stats.unicast_frames); | ||
936 | QLCNIC_ADD_ESW_STATS(esw_stats->multicast_frames, | ||
937 | port_stats.multicast_frames); | ||
938 | QLCNIC_ADD_ESW_STATS(esw_stats->broadcast_frames, | ||
939 | port_stats.broadcast_frames); | ||
940 | QLCNIC_ADD_ESW_STATS(esw_stats->dropped_frames, | ||
941 | port_stats.dropped_frames); | ||
942 | QLCNIC_ADD_ESW_STATS(esw_stats->errors, | ||
943 | port_stats.errors); | ||
944 | QLCNIC_ADD_ESW_STATS(esw_stats->local_frames, | ||
945 | port_stats.local_frames); | ||
946 | QLCNIC_ADD_ESW_STATS(esw_stats->numbytes, | ||
947 | port_stats.numbytes); | ||
948 | ret = 0; | ||
949 | } | ||
950 | return ret; | ||
951 | } | ||
952 | |||
953 | int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw, | ||
954 | const u8 port, const u8 rx_tx) | ||
874 | { | 955 | { |
875 | int err = -EIO; | 956 | |
876 | u32 arg1, arg2; | 957 | u32 arg1; |
877 | struct qlcnic_eswitch *eswitch; | ||
878 | 958 | ||
879 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | 959 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) |
880 | return err; | 960 | return -EIO; |
881 | 961 | ||
882 | eswitch = &adapter->eswitch[id]; | 962 | if (func_esw == QLCNIC_STATS_PORT) { |
883 | if (!eswitch) | 963 | if (port >= QLCNIC_MAX_PCI_FUNC) |
884 | return err; | 964 | goto err_ret; |
965 | } else if (func_esw == QLCNIC_STATS_ESWITCH) { | ||
966 | if (port >= QLCNIC_NIU_MAX_XG_PORTS) | ||
967 | goto err_ret; | ||
968 | } else { | ||
969 | goto err_ret; | ||
970 | } | ||
885 | 971 | ||
886 | arg1 = eswitch->port | (enable ? BIT_4 : 0); | 972 | if (rx_tx > QLCNIC_QUERY_TX_COUNTER) |
887 | arg2 = eswitch->active_vports | (eswitch->max_ucast_filters << 8) | | 973 | goto err_ret; |
888 | (eswitch->max_active_vlans << 16); | 974 | |
889 | err = qlcnic_issue_cmd(adapter, | 975 | arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12; |
890 | adapter->ahw.pci_func, | 976 | arg1 |= BIT_14 | rx_tx << 15; |
977 | |||
978 | return qlcnic_issue_cmd(adapter, | ||
979 | adapter->ahw->pci_func, | ||
891 | adapter->fw_hal_version, | 980 | adapter->fw_hal_version, |
892 | arg1, | 981 | arg1, |
893 | arg2, | ||
894 | 0, | 982 | 0, |
895 | QLCNIC_CDRP_CMD_TOGGLE_ESWITCH); | 983 | 0, |
896 | 984 | QLCNIC_CDRP_CMD_GET_ESWITCH_STATS); | |
897 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
898 | dev_err(&adapter->pdev->dev, | ||
899 | "Failed to enable eswitch%d\n", eswitch->port); | ||
900 | eswitch->flags &= ~QLCNIC_SWITCH_ENABLE; | ||
901 | err = -EIO; | ||
902 | } else { | ||
903 | eswitch->flags |= QLCNIC_SWITCH_ENABLE; | ||
904 | dev_info(&adapter->pdev->dev, | ||
905 | "Enabled eSwitch for port %d\n", eswitch->port); | ||
906 | } | ||
907 | 985 | ||
908 | return err; | 986 | err_ret: |
987 | dev_err(&adapter->pdev->dev, "Invalid argument func_esw=%d port=%d" | ||
988 | "rx_ctx=%d\n", func_esw, port, rx_tx); | ||
989 | return -EIO; | ||
909 | } | 990 | } |
910 | 991 | ||
911 | /* Configure eSwitch for port mirroring */ | 992 | static int |
912 | int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, | 993 | __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, |
913 | u8 enable_mirroring, u8 pci_func) | 994 | u32 *arg1, u32 *arg2) |
914 | { | 995 | { |
915 | int err = -EIO; | 996 | int err = -EIO; |
916 | u32 arg1; | 997 | u8 pci_func; |
917 | 998 | pci_func = (*arg1 >> 8); | |
918 | if (adapter->op_mode != QLCNIC_MGMT_FUNC || | ||
919 | !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) | ||
920 | return err; | ||
921 | |||
922 | arg1 = id | (enable_mirroring ? BIT_4 : 0); | ||
923 | arg1 |= pci_func << 8; | ||
924 | |||
925 | err = qlcnic_issue_cmd(adapter, | 999 | err = qlcnic_issue_cmd(adapter, |
926 | adapter->ahw.pci_func, | 1000 | adapter->ahw->pci_func, |
927 | adapter->fw_hal_version, | 1001 | adapter->fw_hal_version, |
928 | arg1, | 1002 | *arg1, |
929 | 0, | 1003 | 0, |
930 | 0, | 1004 | 0, |
931 | QLCNIC_CDRP_CMD_SET_PORTMIRRORING); | 1005 | QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG); |
932 | 1006 | ||
933 | if (err != QLCNIC_RCODE_SUCCESS) { | 1007 | if (err == QLCNIC_RCODE_SUCCESS) { |
934 | dev_err(&adapter->pdev->dev, | 1008 | *arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); |
935 | "Failed to configure port mirroring%d on eswitch:%d\n", | 1009 | *arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); |
936 | pci_func, id); | ||
937 | } else { | ||
938 | dev_info(&adapter->pdev->dev, | 1010 | dev_info(&adapter->pdev->dev, |
939 | "Configured eSwitch %d for port mirroring:%d\n", | 1011 | "eSwitch port config for pci func %d\n", pci_func); |
940 | id, pci_func); | 1012 | } else { |
1013 | dev_err(&adapter->pdev->dev, | ||
1014 | "Failed to get eswitch port config for pci func %d\n", | ||
1015 | pci_func); | ||
941 | } | 1016 | } |
942 | |||
943 | return err; | 1017 | return err; |
944 | } | 1018 | } |
945 | 1019 | /* Configure eSwitch port | |
946 | /* Configure eSwitch port */ | 1020 | op_mode = 0 for setting default port behavior |
947 | int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, u8 id, | 1021 | op_mode = 1 for setting vlan id |
948 | int vlan_tagging, u8 discard_tagged, u8 promsc_mode, | 1022 | op_mode = 2 for deleting vlan id |
949 | u8 mac_learn, u8 pci_func, u16 vlan_id) | 1023 | op_type = 0 for vlan_id |
1024 | op_type = 1 for port vlan_id | ||
1025 | */ | ||
1026 | int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, | ||
1027 | struct qlcnic_esw_func_cfg *esw_cfg) | ||
950 | { | 1028 | { |
951 | int err = -EIO; | 1029 | int err = -EIO; |
952 | u32 arg1; | 1030 | u32 arg1, arg2 = 0; |
953 | struct qlcnic_eswitch *eswitch; | 1031 | u8 pci_func; |
954 | 1032 | ||
955 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | 1033 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) |
956 | return err; | 1034 | return err; |
1035 | pci_func = esw_cfg->pci_func; | ||
1036 | arg1 = (adapter->npars[pci_func].phy_port & BIT_0); | ||
1037 | arg1 |= (pci_func << 8); | ||
957 | 1038 | ||
958 | eswitch = &adapter->eswitch[id]; | 1039 | if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2)) |
959 | if (!(eswitch->flags & QLCNIC_SWITCH_ENABLE)) | ||
960 | return err; | 1040 | return err; |
961 | 1041 | arg1 &= ~(0x0ff << 8); | |
962 | arg1 = eswitch->port | (discard_tagged ? BIT_4 : 0); | 1042 | arg1 |= (pci_func << 8); |
963 | arg1 |= (promsc_mode ? BIT_6 : 0) | (mac_learn ? BIT_7 : 0); | 1043 | arg1 &= ~(BIT_2 | BIT_3); |
964 | arg1 |= pci_func << 8; | 1044 | switch (esw_cfg->op_mode) { |
965 | if (vlan_tagging) | 1045 | case QLCNIC_PORT_DEFAULTS: |
966 | arg1 |= BIT_5 | (vlan_id << 16); | 1046 | arg1 |= (BIT_4 | BIT_6 | BIT_7); |
1047 | arg2 |= (BIT_0 | BIT_1); | ||
1048 | if (adapter->capabilities & QLCNIC_FW_CAPABILITY_TSO) | ||
1049 | arg2 |= (BIT_2 | BIT_3); | ||
1050 | if (!(esw_cfg->discard_tagged)) | ||
1051 | arg1 &= ~BIT_4; | ||
1052 | if (!(esw_cfg->promisc_mode)) | ||
1053 | arg1 &= ~BIT_6; | ||
1054 | if (!(esw_cfg->mac_override)) | ||
1055 | arg1 &= ~BIT_7; | ||
1056 | if (!(esw_cfg->mac_anti_spoof)) | ||
1057 | arg2 &= ~BIT_0; | ||
1058 | if (!(esw_cfg->offload_flags & BIT_0)) | ||
1059 | arg2 &= ~(BIT_1 | BIT_2 | BIT_3); | ||
1060 | if (!(esw_cfg->offload_flags & BIT_1)) | ||
1061 | arg2 &= ~BIT_2; | ||
1062 | if (!(esw_cfg->offload_flags & BIT_2)) | ||
1063 | arg2 &= ~BIT_3; | ||
1064 | break; | ||
1065 | case QLCNIC_ADD_VLAN: | ||
1066 | arg1 |= (BIT_2 | BIT_5); | ||
1067 | arg1 |= (esw_cfg->vlan_id << 16); | ||
1068 | break; | ||
1069 | case QLCNIC_DEL_VLAN: | ||
1070 | arg1 |= (BIT_3 | BIT_5); | ||
1071 | arg1 &= ~(0x0ffff << 16); | ||
1072 | break; | ||
1073 | default: | ||
1074 | return err; | ||
1075 | } | ||
967 | 1076 | ||
968 | err = qlcnic_issue_cmd(adapter, | 1077 | err = qlcnic_issue_cmd(adapter, |
969 | adapter->ahw.pci_func, | 1078 | adapter->ahw->pci_func, |
970 | adapter->fw_hal_version, | 1079 | adapter->fw_hal_version, |
971 | arg1, | 1080 | arg1, |
972 | 0, | 1081 | arg2, |
973 | 0, | 1082 | 0, |
974 | QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH); | 1083 | QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH); |
975 | 1084 | ||
976 | if (err != QLCNIC_RCODE_SUCCESS) { | 1085 | if (err != QLCNIC_RCODE_SUCCESS) { |
977 | dev_err(&adapter->pdev->dev, | 1086 | dev_err(&adapter->pdev->dev, |
978 | "Failed to configure eswitch port%d\n", eswitch->port); | 1087 | "Failed to configure eswitch pci func %d\n", pci_func); |
979 | } else { | 1088 | } else { |
980 | dev_info(&adapter->pdev->dev, | 1089 | dev_info(&adapter->pdev->dev, |
981 | "Configured eSwitch for port %d\n", eswitch->port); | 1090 | "Configured eSwitch for pci func %d\n", pci_func); |
982 | } | 1091 | } |
983 | 1092 | ||
984 | return err; | 1093 | return err; |
985 | } | 1094 | } |
1095 | |||
1096 | int | ||
1097 | qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, | ||
1098 | struct qlcnic_esw_func_cfg *esw_cfg) | ||
1099 | { | ||
1100 | u32 arg1, arg2; | ||
1101 | u8 phy_port; | ||
1102 | if (adapter->op_mode == QLCNIC_MGMT_FUNC) | ||
1103 | phy_port = adapter->npars[esw_cfg->pci_func].phy_port; | ||
1104 | else | ||
1105 | phy_port = adapter->physical_port; | ||
1106 | arg1 = phy_port; | ||
1107 | arg1 |= (esw_cfg->pci_func << 8); | ||
1108 | if (__qlcnic_get_eswitch_port_config(adapter, &arg1, &arg2)) | ||
1109 | return -EIO; | ||
1110 | |||
1111 | esw_cfg->discard_tagged = !!(arg1 & BIT_4); | ||
1112 | esw_cfg->host_vlan_tag = !!(arg1 & BIT_5); | ||
1113 | esw_cfg->promisc_mode = !!(arg1 & BIT_6); | ||
1114 | esw_cfg->mac_override = !!(arg1 & BIT_7); | ||
1115 | esw_cfg->vlan_id = LSW(arg1 >> 16); | ||
1116 | esw_cfg->mac_anti_spoof = (arg2 & 0x1); | ||
1117 | esw_cfg->offload_flags = ((arg2 >> 1) & 0x7); | ||
1118 | |||
1119 | return 0; | ||
1120 | } | ||