diff options
author | Sritej Velaga <sritej.velaga@qlogic.com> | 2012-02-03 06:35:10 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-02-04 15:59:28 -0500 |
commit | 2dcd5d95ad6b281fca6f2d5e252bbf7e8e20655b (patch) | |
tree | 3deaaa4c47ca20b7f2113cc078b8bb3af1619ed2 | |
parent | e1f4c485cdb2b1d7aae172b731f6c2b403381ebb (diff) |
netxen_nic: fix cdrp race condition
Reading CRB registers(if reqd) before releasing the api lock.
Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic.h | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c | 149 |
2 files changed, 89 insertions, 72 deletions
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h index a876dffd7101..1b09ba172310 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic.h +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic.h | |||
@@ -686,6 +686,18 @@ struct netxen_recv_context { | |||
686 | dma_addr_t phys_addr; | 686 | dma_addr_t phys_addr; |
687 | }; | 687 | }; |
688 | 688 | ||
689 | struct _cdrp_cmd { | ||
690 | u32 cmd; | ||
691 | u32 arg1; | ||
692 | u32 arg2; | ||
693 | u32 arg3; | ||
694 | }; | ||
695 | |||
696 | struct netxen_cmd_args { | ||
697 | struct _cdrp_cmd req; | ||
698 | struct _cdrp_cmd rsp; | ||
699 | }; | ||
700 | |||
689 | /* New HW context creation */ | 701 | /* New HW context creation */ |
690 | 702 | ||
691 | #define NX_OS_CRB_RETRY_COUNT 4000 | 703 | #define NX_OS_CRB_RETRY_COUNT 4000 |
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c index a925392abd6f..d46e8cb394eb 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c | |||
@@ -48,28 +48,27 @@ netxen_poll_rsp(struct netxen_adapter *adapter) | |||
48 | } | 48 | } |
49 | 49 | ||
50 | static u32 | 50 | static u32 |
51 | netxen_issue_cmd(struct netxen_adapter *adapter, | 51 | netxen_issue_cmd(struct netxen_adapter *adapter, struct netxen_cmd_args *cmd) |
52 | u32 pci_fn, u32 version, u32 arg1, u32 arg2, u32 arg3, u32 cmd) | ||
53 | { | 52 | { |
54 | u32 rsp; | 53 | u32 rsp; |
55 | u32 signature = 0; | 54 | u32 signature = 0; |
56 | u32 rcode = NX_RCODE_SUCCESS; | 55 | u32 rcode = NX_RCODE_SUCCESS; |
57 | 56 | ||
58 | signature = NX_CDRP_SIGNATURE_MAKE(pci_fn, version); | 57 | signature = NX_CDRP_SIGNATURE_MAKE(adapter->ahw.pci_func, |
59 | 58 | NXHAL_VERSION); | |
60 | /* Acquire semaphore before accessing CRB */ | 59 | /* Acquire semaphore before accessing CRB */ |
61 | if (netxen_api_lock(adapter)) | 60 | if (netxen_api_lock(adapter)) |
62 | return NX_RCODE_TIMEOUT; | 61 | return NX_RCODE_TIMEOUT; |
63 | 62 | ||
64 | NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature); | 63 | NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature); |
65 | 64 | ||
66 | NXWR32(adapter, NX_ARG1_CRB_OFFSET, arg1); | 65 | NXWR32(adapter, NX_ARG1_CRB_OFFSET, cmd->req.arg1); |
67 | 66 | ||
68 | NXWR32(adapter, NX_ARG2_CRB_OFFSET, arg2); | 67 | NXWR32(adapter, NX_ARG2_CRB_OFFSET, cmd->req.arg2); |
69 | 68 | ||
70 | NXWR32(adapter, NX_ARG3_CRB_OFFSET, arg3); | 69 | NXWR32(adapter, NX_ARG3_CRB_OFFSET, cmd->req.arg3); |
71 | 70 | ||
72 | NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd)); | 71 | NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd->req.cmd)); |
73 | 72 | ||
74 | rsp = netxen_poll_rsp(adapter); | 73 | rsp = netxen_poll_rsp(adapter); |
75 | 74 | ||
@@ -83,8 +82,15 @@ netxen_issue_cmd(struct netxen_adapter *adapter, | |||
83 | 82 | ||
84 | printk(KERN_ERR "%s: failed card response code:0x%x\n", | 83 | printk(KERN_ERR "%s: failed card response code:0x%x\n", |
85 | netxen_nic_driver_name, rcode); | 84 | netxen_nic_driver_name, rcode); |
85 | } else if (rsp == NX_CDRP_RSP_OK) { | ||
86 | if (cmd->rsp.arg2) | ||
87 | cmd->rsp.arg2 = NXRD32(adapter, NX_ARG2_CRB_OFFSET); | ||
88 | if (cmd->rsp.arg3) | ||
89 | cmd->rsp.arg3 = NXRD32(adapter, NX_ARG3_CRB_OFFSET); | ||
86 | } | 90 | } |
87 | 91 | ||
92 | if (cmd->rsp.arg1) | ||
93 | cmd->rsp.arg1 = NXRD32(adapter, NX_ARG1_CRB_OFFSET); | ||
88 | /* Release semaphore */ | 94 | /* Release semaphore */ |
89 | netxen_api_unlock(adapter); | 95 | netxen_api_unlock(adapter); |
90 | 96 | ||
@@ -96,15 +102,16 @@ nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu) | |||
96 | { | 102 | { |
97 | u32 rcode = NX_RCODE_SUCCESS; | 103 | u32 rcode = NX_RCODE_SUCCESS; |
98 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; | 104 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; |
105 | struct netxen_cmd_args cmd; | ||
106 | |||
107 | memset(&cmd, 0, sizeof(cmd)); | ||
108 | cmd.req.cmd = NX_CDRP_CMD_SET_MTU; | ||
109 | cmd.req.arg1 = recv_ctx->context_id; | ||
110 | cmd.req.arg2 = mtu; | ||
111 | cmd.req.arg3 = 0; | ||
99 | 112 | ||
100 | if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE) | 113 | if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE) |
101 | rcode = netxen_issue_cmd(adapter, | 114 | netxen_issue_cmd(adapter, &cmd); |
102 | adapter->ahw.pci_func, | ||
103 | NXHAL_VERSION, | ||
104 | recv_ctx->context_id, | ||
105 | mtu, | ||
106 | 0, | ||
107 | NX_CDRP_CMD_SET_MTU); | ||
108 | 115 | ||
109 | if (rcode != NX_RCODE_SUCCESS) | 116 | if (rcode != NX_RCODE_SUCCESS) |
110 | return -EIO; | 117 | return -EIO; |
@@ -116,15 +123,14 @@ int | |||
116 | nx_fw_cmd_set_gbe_port(struct netxen_adapter *adapter, | 123 | nx_fw_cmd_set_gbe_port(struct netxen_adapter *adapter, |
117 | u32 speed, u32 duplex, u32 autoneg) | 124 | u32 speed, u32 duplex, u32 autoneg) |
118 | { | 125 | { |
119 | 126 | struct netxen_cmd_args cmd; | |
120 | return netxen_issue_cmd(adapter, | 127 | |
121 | adapter->ahw.pci_func, | 128 | memset(&cmd, 0, sizeof(cmd)); |
122 | NXHAL_VERSION, | 129 | cmd.req.cmd = NX_CDRP_CMD_CONFIG_GBE_PORT; |
123 | speed, | 130 | cmd.req.arg1 = speed; |
124 | duplex, | 131 | cmd.req.arg2 = duplex; |
125 | autoneg, | 132 | cmd.req.arg3 = autoneg; |
126 | NX_CDRP_CMD_CONFIG_GBE_PORT); | 133 | return netxen_issue_cmd(adapter, &cmd); |
127 | |||
128 | } | 134 | } |
129 | 135 | ||
130 | static int | 136 | static int |
@@ -139,6 +145,7 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) | |||
139 | nx_cardrsp_sds_ring_t *prsp_sds; | 145 | nx_cardrsp_sds_ring_t *prsp_sds; |
140 | struct nx_host_rds_ring *rds_ring; | 146 | struct nx_host_rds_ring *rds_ring; |
141 | struct nx_host_sds_ring *sds_ring; | 147 | struct nx_host_sds_ring *sds_ring; |
148 | struct netxen_cmd_args cmd; | ||
142 | 149 | ||
143 | dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; | 150 | dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; |
144 | u64 phys_addr; | 151 | u64 phys_addr; |
@@ -218,13 +225,12 @@ nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) | |||
218 | } | 225 | } |
219 | 226 | ||
220 | phys_addr = hostrq_phys_addr; | 227 | phys_addr = hostrq_phys_addr; |
221 | err = netxen_issue_cmd(adapter, | 228 | memset(&cmd, 0, sizeof(cmd)); |
222 | adapter->ahw.pci_func, | 229 | cmd.req.arg1 = (u32)(phys_addr >> 32); |
223 | NXHAL_VERSION, | 230 | cmd.req.arg2 = (u32)(phys_addr & 0xffffffff); |
224 | (u32)(phys_addr >> 32), | 231 | cmd.req.arg3 = rq_size; |
225 | (u32)(phys_addr & 0xffffffff), | 232 | cmd.req.cmd = NX_CDRP_CMD_CREATE_RX_CTX; |
226 | rq_size, | 233 | err = netxen_issue_cmd(adapter, &cmd); |
227 | NX_CDRP_CMD_CREATE_RX_CTX); | ||
228 | if (err) { | 234 | if (err) { |
229 | printk(KERN_WARNING | 235 | printk(KERN_WARNING |
230 | "Failed to create rx ctx in firmware%d\n", err); | 236 | "Failed to create rx ctx in firmware%d\n", err); |
@@ -273,15 +279,15 @@ static void | |||
273 | nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter) | 279 | nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter) |
274 | { | 280 | { |
275 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; | 281 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; |
282 | struct netxen_cmd_args cmd; | ||
276 | 283 | ||
277 | if (netxen_issue_cmd(adapter, | 284 | memset(&cmd, 0, sizeof(cmd)); |
278 | adapter->ahw.pci_func, | 285 | cmd.req.arg1 = recv_ctx->context_id; |
279 | NXHAL_VERSION, | 286 | cmd.req.arg2 = NX_DESTROY_CTX_RESET; |
280 | recv_ctx->context_id, | 287 | cmd.req.arg3 = 0; |
281 | NX_DESTROY_CTX_RESET, | 288 | cmd.req.cmd = NX_CDRP_CMD_DESTROY_RX_CTX; |
282 | 0, | ||
283 | NX_CDRP_CMD_DESTROY_RX_CTX)) { | ||
284 | 289 | ||
290 | if (netxen_issue_cmd(adapter, &cmd)) { | ||
285 | printk(KERN_WARNING | 291 | printk(KERN_WARNING |
286 | "%s: Failed to destroy rx ctx in firmware\n", | 292 | "%s: Failed to destroy rx ctx in firmware\n", |
287 | netxen_nic_driver_name); | 293 | netxen_nic_driver_name); |
@@ -302,6 +308,7 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) | |||
302 | dma_addr_t rq_phys_addr, rsp_phys_addr; | 308 | dma_addr_t rq_phys_addr, rsp_phys_addr; |
303 | struct nx_host_tx_ring *tx_ring = adapter->tx_ring; | 309 | struct nx_host_tx_ring *tx_ring = adapter->tx_ring; |
304 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; | 310 | struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; |
311 | struct netxen_cmd_args cmd; | ||
305 | 312 | ||
306 | rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t); | 313 | rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t); |
307 | rq_addr = pci_alloc_consistent(adapter->pdev, | 314 | rq_addr = pci_alloc_consistent(adapter->pdev, |
@@ -345,13 +352,12 @@ nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) | |||
345 | prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc); | 352 | prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc); |
346 | 353 | ||
347 | phys_addr = rq_phys_addr; | 354 | phys_addr = rq_phys_addr; |
348 | err = netxen_issue_cmd(adapter, | 355 | memset(&cmd, 0, sizeof(cmd)); |
349 | adapter->ahw.pci_func, | 356 | cmd.req.arg1 = (u32)(phys_addr >> 32); |
350 | NXHAL_VERSION, | 357 | cmd.req.arg2 = ((u32)phys_addr & 0xffffffff); |
351 | (u32)(phys_addr >> 32), | 358 | cmd.req.arg3 = rq_size; |
352 | ((u32)phys_addr & 0xffffffff), | 359 | cmd.req.cmd = NX_CDRP_CMD_CREATE_TX_CTX; |
353 | rq_size, | 360 | err = netxen_issue_cmd(adapter, &cmd); |
354 | NX_CDRP_CMD_CREATE_TX_CTX); | ||
355 | 361 | ||
356 | if (err == NX_RCODE_SUCCESS) { | 362 | if (err == NX_RCODE_SUCCESS) { |
357 | temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); | 363 | temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); |
@@ -380,14 +386,14 @@ out_free_rq: | |||
380 | static void | 386 | static void |
381 | nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter) | 387 | nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter) |
382 | { | 388 | { |
383 | if (netxen_issue_cmd(adapter, | 389 | struct netxen_cmd_args cmd; |
384 | adapter->ahw.pci_func, | 390 | |
385 | NXHAL_VERSION, | 391 | memset(&cmd, 0, sizeof(cmd)); |
386 | adapter->tx_context_id, | 392 | cmd.req.arg1 = adapter->tx_context_id; |
387 | NX_DESTROY_CTX_RESET, | 393 | cmd.req.arg2 = NX_DESTROY_CTX_RESET; |
388 | 0, | 394 | cmd.req.arg3 = 0; |
389 | NX_CDRP_CMD_DESTROY_TX_CTX)) { | 395 | cmd.req.cmd = NX_CDRP_CMD_DESTROY_TX_CTX; |
390 | 396 | if (netxen_issue_cmd(adapter, &cmd)) { | |
391 | printk(KERN_WARNING | 397 | printk(KERN_WARNING |
392 | "%s: Failed to destroy tx ctx in firmware\n", | 398 | "%s: Failed to destroy tx ctx in firmware\n", |
393 | netxen_nic_driver_name); | 399 | netxen_nic_driver_name); |
@@ -398,34 +404,33 @@ int | |||
398 | nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val) | 404 | nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val) |
399 | { | 405 | { |
400 | u32 rcode; | 406 | u32 rcode; |
401 | 407 | struct netxen_cmd_args cmd; | |
402 | rcode = netxen_issue_cmd(adapter, | 408 | |
403 | adapter->ahw.pci_func, | 409 | memset(&cmd, 0, sizeof(cmd)); |
404 | NXHAL_VERSION, | 410 | cmd.req.arg1 = reg; |
405 | reg, | 411 | cmd.req.arg2 = 0; |
406 | 0, | 412 | cmd.req.arg3 = 0; |
407 | 0, | 413 | cmd.req.cmd = NX_CDRP_CMD_READ_PHY; |
408 | NX_CDRP_CMD_READ_PHY); | 414 | cmd.rsp.arg1 = 1; |
409 | 415 | rcode = netxen_issue_cmd(adapter, &cmd); | |
410 | if (rcode != NX_RCODE_SUCCESS) | 416 | if (rcode != NX_RCODE_SUCCESS) |
411 | return -EIO; | 417 | return -EIO; |
412 | 418 | ||
413 | return NXRD32(adapter, NX_ARG1_CRB_OFFSET); | 419 | return cmd.rsp.arg1; |
414 | } | 420 | } |
415 | 421 | ||
416 | int | 422 | int |
417 | nx_fw_cmd_set_phy(struct netxen_adapter *adapter, u32 reg, u32 val) | 423 | nx_fw_cmd_set_phy(struct netxen_adapter *adapter, u32 reg, u32 val) |
418 | { | 424 | { |
419 | u32 rcode; | 425 | u32 rcode; |
420 | 426 | struct netxen_cmd_args cmd; | |
421 | rcode = netxen_issue_cmd(adapter, | 427 | |
422 | adapter->ahw.pci_func, | 428 | memset(&cmd, 0, sizeof(cmd)); |
423 | NXHAL_VERSION, | 429 | cmd.req.arg1 = reg; |
424 | reg, | 430 | cmd.req.arg2 = val; |
425 | val, | 431 | cmd.req.arg3 = 0; |
426 | 0, | 432 | cmd.req.cmd = NX_CDRP_CMD_WRITE_PHY; |
427 | NX_CDRP_CMD_WRITE_PHY); | 433 | rcode = netxen_issue_cmd(adapter, &cmd); |
428 | |||
429 | if (rcode != NX_RCODE_SUCCESS) | 434 | if (rcode != NX_RCODE_SUCCESS) |
430 | return -EIO; | 435 | return -EIO; |
431 | 436 | ||