233 lines
7.4 KiB
Diff
233 lines
7.4 KiB
Diff
From: Padmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
|
|
Date: Wed, 25 Apr 2012 01:47:03 +0000
|
|
Subject: [PATCH 49/58] be2net: Fix wrong status getting returned for MCC
|
|
commands
|
|
|
|
commit 652bf64622f32c938dd4a8738ba12d51dc9fbdd4 upstream.
|
|
|
|
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>
|
|
---
|
|
drivers/net/ethernet/emulex/benet/be.h | 5 ++
|
|
drivers/net/ethernet/emulex/benet/be_cmds.c | 81 ++++++++++++++++++---------
|
|
drivers/net/ethernet/emulex/benet/be_cmds.h | 8 ++-
|
|
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 ad69cf8..4bc18ef 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)
|
|
index_inc(&q->head, q->len);
|
|
}
|
|
|
|
+static inline void index_dec(u16 *index, u16 limit)
|
|
+{
|
|
+ *index = MODULO((*index - 1), limit);
|
|
+}
|
|
+
|
|
static inline void queue_tail_inc(struct be_queue_info *q)
|
|
{
|
|
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 4e07e58..2673081 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)
|
|
compl->flags = 0;
|
|
}
|
|
|
|
+static struct be_cmd_resp_hdr *be_decode_resp_hdr(u32 tag0, u32 tag1)
|
|
+{
|
|
+ unsigned long addr;
|
|
+
|
|
+ addr = tag1;
|
|
+ addr = ((addr << 16) << 16) | tag0;
|
|
+ return (void *)addr;
|
|
+}
|
|
+
|
|
static int be_mcc_compl_process(struct be_adapter *adapter,
|
|
- struct be_mcc_compl *compl)
|
|
+ struct be_mcc_compl *compl)
|
|
{
|
|
u16 compl_status, extd_status;
|
|
+ struct be_cmd_resp_hdr *resp_hdr;
|
|
+ u8 opcode = 0, subsystem = 0;
|
|
|
|
/* Just swap the status to host endian; mcc tag is opaquely copied
|
|
* from mcc_wrb */
|
|
@@ -73,32 +84,36 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
|
|
compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) &
|
|
CQE_STATUS_COMPL_MASK;
|
|
|
|
- if (((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) ||
|
|
- (compl->tag0 == OPCODE_COMMON_WRITE_OBJECT)) &&
|
|
- (compl->tag1 == CMD_SUBSYSTEM_COMMON)) {
|
|
+ resp_hdr = be_decode_resp_hdr(compl->tag0, compl->tag1);
|
|
+
|
|
+ if (resp_hdr) {
|
|
+ opcode = resp_hdr->opcode;
|
|
+ subsystem = resp_hdr->subsystem;
|
|
+ }
|
|
+
|
|
+ if (((opcode == OPCODE_COMMON_WRITE_FLASHROM) ||
|
|
+ (opcode == OPCODE_COMMON_WRITE_OBJECT)) &&
|
|
+ (subsystem == CMD_SUBSYSTEM_COMMON)) {
|
|
adapter->flash_status = compl_status;
|
|
complete(&adapter->flash_compl);
|
|
}
|
|
|
|
if (compl_status == MCC_STATUS_SUCCESS) {
|
|
- if (((compl->tag0 == OPCODE_ETH_GET_STATISTICS) ||
|
|
- (compl->tag0 == OPCODE_ETH_GET_PPORT_STATS)) &&
|
|
- (compl->tag1 == CMD_SUBSYSTEM_ETH)) {
|
|
+ if (((opcode == OPCODE_ETH_GET_STATISTICS) ||
|
|
+ (opcode == OPCODE_ETH_GET_PPORT_STATS)) &&
|
|
+ (subsystem == CMD_SUBSYSTEM_ETH)) {
|
|
be_parse_stats(adapter);
|
|
adapter->stats_cmd_sent = false;
|
|
}
|
|
- if (compl->tag0 ==
|
|
- OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES) {
|
|
- struct be_mcc_wrb *mcc_wrb =
|
|
- queue_index_node(&adapter->mcc_obj.q,
|
|
- compl->tag1);
|
|
+ if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES &&
|
|
+ subsystem == CMD_SUBSYSTEM_COMMON) {
|
|
struct be_cmd_resp_get_cntl_addnl_attribs *resp =
|
|
- embedded_payload(mcc_wrb);
|
|
+ (void *)resp_hdr;
|
|
adapter->drv_stats.be_on_die_temperature =
|
|
resp->on_die_temperature;
|
|
}
|
|
} else {
|
|
- if (compl->tag0 == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
|
|
+ if (opcode == OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES)
|
|
be_get_temp_freq = 0;
|
|
|
|
if (compl_status == MCC_STATUS_NOT_SUPPORTED ||
|
|
@@ -108,13 +123,13 @@ static int be_mcc_compl_process(struct be_adapter *adapter,
|
|
if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) {
|
|
dev_warn(&adapter->pdev->dev, "This domain(VM) is not "
|
|
"permitted to execute this cmd (opcode %d)\n",
|
|
- compl->tag0);
|
|
+ opcode);
|
|
} else {
|
|
extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) &
|
|
CQE_STATUS_EXTD_MASK;
|
|
dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:"
|
|
"status %d, extd-status %d\n",
|
|
- compl->tag0, compl_status, extd_status);
|
|
+ opcode, compl_status, extd_status);
|
|
}
|
|
}
|
|
done:
|
|
@@ -286,7 +301,7 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
|
|
if (i == mcc_timeout) {
|
|
dev_err(&adapter->pdev->dev, "FW not responding\n");
|
|
adapter->fw_timeout = true;
|
|
- return -1;
|
|
+ return -EIO;
|
|
}
|
|
return status;
|
|
}
|
|
@@ -294,8 +309,26 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
|
|
/* Notify MCC requests and wait for completion */
|
|
static int be_mcc_notify_wait(struct be_adapter *adapter)
|
|
{
|
|
+ int status;
|
|
+ struct be_mcc_wrb *wrb;
|
|
+ struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
|
|
+ u16 index = mcc_obj->q.head;
|
|
+ struct be_cmd_resp_hdr *resp;
|
|
+
|
|
+ index_dec(&index, mcc_obj->q.len);
|
|
+ wrb = queue_index_node(&mcc_obj->q, index);
|
|
+
|
|
+ resp = be_decode_resp_hdr(wrb->tag0, wrb->tag1);
|
|
+
|
|
be_mcc_notify(adapter);
|
|
- return be_mcc_wait_compl(adapter);
|
|
+
|
|
+ status = be_mcc_wait_compl(adapter);
|
|
+ if (status == -EIO)
|
|
+ goto out;
|
|
+
|
|
+ status = resp->status;
|
|
+out:
|
|
+ return status;
|
|
}
|
|
|
|
static 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,
|
|
struct be_mcc_wrb *wrb, struct be_dma_mem *mem)
|
|
{
|
|
struct be_sge *sge;
|
|
+ unsigned long addr = (unsigned long)req_hdr;
|
|
+ u64 req_addr = addr;
|
|
|
|
req_hdr->opcode = opcode;
|
|
req_hdr->subsystem = subsystem;
|
|
req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr));
|
|
req_hdr->version = 0;
|
|
|
|
- wrb->tag0 = opcode;
|
|
- wrb->tag1 = subsystem;
|
|
+ wrb->tag0 = req_addr & 0xFFFFFFFF;
|
|
+ wrb->tag1 = upper_32_bits(req_addr);
|
|
+
|
|
wrb->payload_length = cmd_len;
|
|
if (mem) {
|
|
wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) <<
|
|
@@ -1283,13 +1319,10 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter)
|
|
{
|
|
struct be_mcc_wrb *wrb;
|
|
struct be_cmd_req_get_cntl_addnl_attribs *req;
|
|
- u16 mccq_index;
|
|
int status;
|
|
|
|
spin_lock_bh(&adapter->mcc_lock);
|
|
|
|
- mccq_index = adapter->mcc_obj.q.head;
|
|
-
|
|
wrb = wrb_from_mccq(adapter);
|
|
if (!wrb) {
|
|
status = -EBUSY;
|
|
@@ -1301,8 +1334,6 @@ int be_cmd_get_die_temperature(struct be_adapter *adapter)
|
|
OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, sizeof(*req),
|
|
wrb, NULL);
|
|
|
|
- wrb->tag1 = mccq_index;
|
|
-
|
|
be_mcc_notify(adapter);
|
|
|
|
err:
|
|
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
|
|
index 3c54361..944f031 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 {
|
|
#define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */
|
|
#define RESP_HDR_INFO_SUBSYS_SHIFT 8 /* bits 8 - 15 */
|
|
struct be_cmd_resp_hdr {
|
|
- u32 info; /* dword 0 */
|
|
- u32 status; /* dword 1 */
|
|
+ u8 opcode; /* dword 0 */
|
|
+ u8 subsystem; /* dword 0 */
|
|
+ u8 rsvd[2]; /* dword 0 */
|
|
+ u8 status; /* dword 1 */
|
|
+ u8 add_status; /* dword 1 */
|
|
+ u8 rsvd1[2]; /* dword 1 */
|
|
u32 response_length; /* dword 2 */
|
|
u32 actual_resp_len; /* dword 3 */
|
|
};
|
|
--
|
|
1.7.10
|
|
|