aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPadmanabh Ratnakar <padmanabh.ratnakar@emulex.com>2012-04-24 21:47:03 -0400
committerDavid S. Miller <davem@davemloft.net>2012-04-26 05:03:31 -0400
commit652bf64622f32c938dd4a8738ba12d51dc9fbdd4 (patch)
tree20de774b4a367e09e487d81759e07d8787849a79 /drivers
parentd51ebd331166e102591e5c25805d8015df0e1e21 (diff)
be2net: Fix wrong status getting returned for MCC commands
MCC Response CQEs are processed as part of NAPI poll routine and also synchronously. If MCC completions are consumed by NAPI poll routine, wrong status is returned to synchronously waiting routine. Fix this by getting status of MCC command from command response instead of response CQEs. Signed-off-by: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ethernet/emulex/benet/be.h5
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.c81
-rw-r--r--drivers/net/ethernet/emulex/benet/be_cmds.h8
3 files changed, 67 insertions, 27 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index ad69cf89491..4bc18efb705 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -162,6 +162,11 @@ static inline void queue_head_inc(struct be_queue_info *q)
162 index_inc(&q->head, q->len); 162 index_inc(&q->head, q->len);
163} 163}
164 164
165static inline void index_dec(u16 *index, u16 limit)
166{
167 *index = MODULO((*index - 1), limit);
168}
169
165static inline void queue_tail_inc(struct be_queue_info *q) 170static inline void queue_tail_inc(struct be_queue_info *q)
166{ 171{
167 index_inc(&q->tail, q->len); 172 index_inc(&q->tail, q->len);
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 4e07e58286a..2673081aaf2 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -61,10 +61,21 @@ static inline void be_mcc_compl_use(struct be_mcc_compl *compl)
61 compl->flags = 0; 61 compl->flags = 0;
62} 62}
63 63
64static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1)
65{
66 unsigned long addr;
67
68 addr = tag1;
69 addr = ((addr << 16) << 16) | tag0;
70 return (void *)addr;
71}
72
64static int be_mcc_compl_process(struct be_adapter *adapter, 73static int be_mcc_compl_process(struct be_adapter *adapter,
65 struct be_mcc_compl *compl) 74 struct be_mcc_compl *compl)
66{ 75{
67 u16 compl_status, extd_status; 76 u16 compl_status, extd_status;
77 struct be_cmd_resp_hdr *resp_hdr;
78 u8 opcode = 0, subsystem = 0;
68 79
69 /* Just swap the status to host endian; mcc tag is opaquely copied 80 /* Just swap the status to host endian; mcc tag is opaquely copied
70 * from mcc_wrb */ 81 * from mcc_wrb */
@@ -73,32 +84,36 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
73 compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & 84 compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
74 CQE_STATUS_COMPL_MASK; 85 CQE_STATUS_COMPL_MASK;
75 86
76 if (((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) || 87 resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
77 (compl->tag0 == OPCODE_COMMON_WRITE_OBJECT)) && 88
78 (compl->tag1 == CMD_SUBSYSTEM_COMMON)) { 89 if (resp_hdr) {
90 opcode = resp_hdr->opcode;
91 subsystem = resp_hdr->subsystem;
92 }
93
94 if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) ||
95 (opcode == OPCODE_COMMON_WRITE_OBJECT)) &&
96 (subsystem == CMD_SUBSYSTEM_COMMON)) {
79 adapter->flash_status = compl_status; 97 adapter->flash_status = compl_status;
80 complete(&adapter->flash_compl); 98 complete(&adapter->flash_compl);
81 } 99 }
82 100
83 if (compl_status == MCC_STATUS_SUCCESS) { 101 if (compl_status == MCC_STATUS_SUCCESS) {
84 if (((compl->tag0 == OPCODE_ETH_GET_STATISTICS) || 102 if (((opcode == OPCODE_ETH_GET_STATISTICS) ||
85 (compl->tag0 == OPCODE_ETH_GET_PPORT_STATS)) && 103 (opcode == OPCODE_ETH_GET_PPORT_STATS)) &&
86 (compl->tag1 == CMD_SUBSYSTEM_ETH)) { 104 (subsystem == CMD_SUBSYSTEM_ETH)) {
87 be_parse_stats(adapter); 105 be_parse_stats(adapter);
88 adapter->stats_cmd_sent = false; 106 adapter->stats_cmd_sent = false;
89 } 107 }
90 if (compl->tag0 == 108 if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
91 OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) { 109 subsystem == CMD_SUBSYSTEM_COMMON) {
92 struct be_mcc_wrb *mcc_wrb =
93 queue_index_node(&adapter->mcc_obj.q,
94 compl->tag1);
95 struct be_cmd_resp_get_cntl_addnl_attribs *resp = 110 struct be_cmd_resp_get_cntl_addnl_attribs *resp =
96 embedded_payload(mcc_wrb); 111 (void *)resp_hdr;
97 adapter->drv_stats.be_on_die_temperature = 112 adapter->drv_stats.be_on_die_temperature =
98 resp->on_die_temperature; 113 resp->on_die_temperature;
99 } 114 }
100 } else { 115 } else {
101 if (compl->tag0 == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) 116 if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
102 be_get_temp_freq = 0; 117 be_get_temp_freq = 0;
103 118
104 if (compl_status == MCC_STATUS_NOT_SUPPORTED || 119 if (compl_status == MCC_STATUS_NOT_SUPPORTED ||
@@ -108,13 +123,13 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
108 if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) { 123 if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
109 dev_warn(&adapter->pdev->dev, "This domain(VM) is not " 124 dev_warn(&adapter->pdev->dev, "This domain(VM) is not "
110 "permitted to execute this cmd (opcode %d)\n", 125 "permitted to execute this cmd (opcode %d)\n",
111 compl->tag0); 126 opcode);
112 } else { 127 } else {
113 extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & 128 extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
114 CQE_STATUS_EXTD_MASK; 129 CQE_STATUS_EXTD_MASK;
115 dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:" 130 dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:"
116 "status %d, extd-status %d\n", 131 "status %d, extd-status %d\n",
117 compl->tag0, compl_status, extd_status); 132 opcode, compl_status, extd_status);
118 } 133 }
119 } 134 }
120done: 135done:
@@ -286,7 +301,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
286 if (i == mcc_timeout) { 301 if (i == mcc_timeout) {
287 dev_err(&adapter->pdev->dev, "FW not responding\n"); 302 dev_err(&adapter->pdev->dev, "FW not responding\n");
288 adapter->fw_timeout = true; 303 adapter->fw_timeout = true;
289 return -1; 304 return -EIO;
290 } 305 }
291 return status; 306 return status;
292} 307}
@@ -294,8 +309,26 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
294/* Notify MCC requests and wait for completion */ 309/* Notify MCC requests and wait for completion */
295static int be_mcc_notify_wait(struct be_adapter *adapter) 310static int be_mcc_notify_wait(struct be_adapter *adapter)
296{ 311{
312 int status;
313 struct be_mcc_wrb *wrb;
314 struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
315 u16 index = mcc_obj->q.head;
316 struct be_cmd_resp_hdr *resp;
317
318 index_dec(&index, mcc_obj->q.len);
319 wrb = queue_index_node(&mcc_obj->q, index);
320
321 resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1);
322
297 be_mcc_notify(adapter); 323 be_mcc_notify(adapter);
298 return be_mcc_wait_compl(adapter); 324
325 status = be_mcc_wait_compl(adapter);
326 if (status == -EIO)
327 goto out;
328
329 status = resp->status;
330out:
331 return status;
299} 332}
300 333
301static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db) 334static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
@@ -435,14 +468,17 @@ static void be_wrb_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr,
435 struct be_mcc_wrb *wrb, struct be_dma_mem *mem) 468 struct be_mcc_wrb *wrb, struct be_dma_mem *mem)
436{ 469{
437 struct be_sge *sge; 470 struct be_sge *sge;
471 unsigned long addr = (unsigned long)req_hdr;
472 u64 req_addr = addr;
438 473
439 req_hdr->opcode = opcode; 474 req_hdr->opcode = opcode;
440 req_hdr->subsystem = subsystem; 475 req_hdr->subsystem = subsystem;
441 req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); 476 req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
442 req_hdr->version = 0; 477 req_hdr->version = 0;
443 478
444 wrb->tag0 = opcode; 479 wrb->tag0 = req_addr & 0xFFFFFFFF;
445 wrb->tag1 = subsystem; 480 wrb->tag1 = upper_32_bits(req_addr);
481
446 wrb->payload_length = cmd_len; 482 wrb->payload_length = cmd_len;
447 if (mem) { 483 if (mem) {
448 wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) << 484 wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) <<
@@ -1283,13 +1319,10 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter)
1283{ 1319{
1284 struct be_mcc_wrb *wrb; 1320 struct be_mcc_wrb *wrb;
1285 struct be_cmd_req_get_cntl_addnl_attribs *req; 1321 struct be_cmd_req_get_cntl_addnl_attribs *req;
1286 u16 mccq_index;
1287 int status; 1322 int status;
1288 1323
1289 spin_lock_bh(&adapter->mcc_lock); 1324 spin_lock_bh(&adapter->mcc_lock);
1290 1325
1291 mccq_index = adapter->mcc_obj.q.head;
1292
1293 wrb = wrb_from_mccq(adapter); 1326 wrb = wrb_from_mccq(adapter);
1294 if (!wrb) { 1327 if (!wrb) {
1295 status = -EBUSY; 1328 status = -EBUSY;
@@ -1301,8 +1334,6 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter)
1301 OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, sizeof(*req), 1334 OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, sizeof(*req),
1302 wrb, NULL); 1335 wrb, NULL);
1303 1336
1304 wrb->tag1 = mccq_index;
1305
1306 be_mcc_notify(adapter); 1337 be_mcc_notify(adapter);
1307 1338
1308err: 1339err:
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 3c543610906..944f031bd31 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -225,8 +225,12 @@ struct be_cmd_req_hdr {
225#define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */ 225#define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */
226#define RESP_HDR_INFO_SUBSYS_SHIFT 8 /* bits 8 - 15 */ 226#define RESP_HDR_INFO_SUBSYS_SHIFT 8 /* bits 8 - 15 */
227struct be_cmd_resp_hdr { 227struct be_cmd_resp_hdr {
228 u32 info; /* dword 0 */ 228 u8 opcode; /* dword 0 */
229 u32 status; /* dword 1 */ 229 u8 subsystem; /* dword 0 */
230 u8 rsvd[2]; /* dword 0 */
231 u8 status; /* dword 1 */
232 u8 add_status; /* dword 1 */
233 u8 rsvd1[2]; /* dword 1 */
230 u32 response_length; /* dword 2 */ 234 u32 response_length; /* dword 2 */
231 u32 actual_resp_len; /* dword 3 */ 235 u32 actual_resp_len; /* dword 3 */
232}; 236};