]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
be2net: Fix wrong status getting returned for MCC commands
authorPadmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
Wed, 25 Apr 2012 01:47:03 +0000 (01:47 +0000)
committerMaxim Uvarov <maxim.uvarov@oracle.com>
Mon, 7 May 2012 21:44:28 +0000 (14:44 -0700)
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/benet/be.h
drivers/net/benet/be_cmds.c
drivers/net/benet/be_cmds.h

index 2da89d5b1ae4e852ecf157514185a1302c9a83fc..ecf5be21a4a7f7e14ac55ee6ca709d1d98ffb22a 100644 (file)
@@ -159,6 +159,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);
index 3bc0b4b4030f348a874deb2cf9ae2c122b09b544..0a633a57a643719afec22a671bfd5866c132fc7e 100644 (file)
@@ -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) <<
@@ -1288,13 +1324,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;
@@ -1306,8 +1339,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:
index c627f0e6abaf2f15d3fcb54bbd4b92520b206661..ad7315eaf9b880c98480ca177693845276514874 100644 (file)
@@ -223,8 +223,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 */
 };