be2net: Fix be_cmd_if_create() to use MBOX if MCCQ is not created
authorSathya Perla <sathya.perla@emulex.com>
Tue, 27 Aug 2013 11:27:33 +0000 (16:57 +0530)
committerDavid S. Miller <davem@davemloft.net>
Tue, 27 Aug 2013 19:57:05 +0000 (15:57 -0400)
Currently the IF_CREATE FW cmd is issued only *after* MCCQ is created as
it was coded to only use MCCQ. By fixing this, cmd_if_create() can be
called before MCCQ is created and the same routine for VF provisioning
can be called after.
This allows for consolidating all the queue create routines by moving
the be_cmd_if_create() call above all queue create calls in be_setup().

Signed-off-by: Sathya Perla <sathya.perla@emulex.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/emulex/benet/be_cmds.c

index 5458a4357ae046dc8b0109de6e50ad5db0240400..70d5db043f1e05d98d9c6caed0a5ecdcfc0b2580 100644 (file)
@@ -633,6 +633,12 @@ static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb)
        return &wrb->payload.sgl[0];
 }
 
+static inline void fill_wrb_tags(struct be_mcc_wrb *wrb,
+                                unsigned long addr)
+{
+       wrb->tag0 = addr & 0xFFFFFFFF;
+       wrb->tag1 = upper_32_bits(addr);
+}
 
 /* Don't touch the hdr after it's prepared */
 /* mem will be NULL for embedded commands */
@@ -641,17 +647,12 @@ 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 = req_addr & 0xFFFFFFFF;
-       wrb->tag1 = upper_32_bits(req_addr);
-
+       fill_wrb_tags(wrb, (ulong) req_hdr);
        wrb->payload_length = cmd_len;
        if (mem) {
                wrb->embedded |= (1 & MCC_WRB_SGE_CNT_MASK) <<
@@ -705,6 +706,78 @@ static struct be_mcc_wrb *wrb_from_mccq(struct be_adapter *adapter)
        return wrb;
 }
 
+static bool use_mcc(struct be_adapter *adapter)
+{
+       return adapter->mcc_obj.q.created;
+}
+
+/* Must be used only in process context */
+static int be_cmd_lock(struct be_adapter *adapter)
+{
+       if (use_mcc(adapter)) {
+               spin_lock_bh(&adapter->mcc_lock);
+               return 0;
+       } else {
+               return mutex_lock_interruptible(&adapter->mbox_lock);
+       }
+}
+
+/* Must be used only in process context */
+static void be_cmd_unlock(struct be_adapter *adapter)
+{
+       if (use_mcc(adapter))
+               spin_unlock_bh(&adapter->mcc_lock);
+       else
+               return mutex_unlock(&adapter->mbox_lock);
+}
+
+static struct be_mcc_wrb *be_cmd_copy(struct be_adapter *adapter,
+                                     struct be_mcc_wrb *wrb)
+{
+       struct be_mcc_wrb *dest_wrb;
+
+       if (use_mcc(adapter)) {
+               dest_wrb = wrb_from_mccq(adapter);
+               if (!dest_wrb)
+                       return NULL;
+       } else {
+               dest_wrb = wrb_from_mbox(adapter);
+       }
+
+       memcpy(dest_wrb, wrb, sizeof(*wrb));
+       if (wrb->embedded & cpu_to_le32(MCC_WRB_EMBEDDED_MASK))
+               fill_wrb_tags(dest_wrb, (ulong) embedded_payload(wrb));
+
+       return dest_wrb;
+}
+
+/* Must be used only in process context */
+static int be_cmd_notify_wait(struct be_adapter *adapter,
+                             struct be_mcc_wrb *wrb)
+{
+       struct be_mcc_wrb *dest_wrb;
+       int status;
+
+       status = be_cmd_lock(adapter);
+       if (status)
+               return status;
+
+       dest_wrb = be_cmd_copy(adapter, wrb);
+       if (!dest_wrb)
+               return -EBUSY;
+
+       if (use_mcc(adapter))
+               status = be_mcc_notify_wait(adapter);
+       else
+               status = be_mbox_notify_wait(adapter);
+
+       if (!status)
+               memcpy(wrb, dest_wrb, sizeof(*wrb));
+
+       be_cmd_unlock(adapter);
+       return status;
+}
+
 /* Tell fw we're about to start firing cmds by writing a
  * special pattern across the wrb hdr; uses mbox
  */
@@ -1290,44 +1363,32 @@ err:
 }
 
 /* Create an rx filtering policy configuration on an i/f
- * Uses MCCQ
+ * Will use MBOX only if MCCQ has not been created.
  */
 int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
                     u32 *if_handle, u32 domain)
 {
-       struct be_mcc_wrb *wrb;
+       struct be_mcc_wrb wrb = {0};
        struct be_cmd_req_if_create *req;
        int status;
 
-       spin_lock_bh(&adapter->mcc_lock);
-
-       wrb = wrb_from_mccq(adapter);
-       if (!wrb) {
-               status = -EBUSY;
-               goto err;
-       }
-       req = embedded_payload(wrb);
-
+       req = embedded_payload(&wrb);
        be_wrb_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
-               OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req), wrb, NULL);
+               OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req), &wrb, NULL);
        req->hdr.domain = domain;
        req->capability_flags = cpu_to_le32(cap_flags);
        req->enable_flags = cpu_to_le32(en_flags);
-
        req->pmac_invalid = true;
 
-       status = be_mcc_notify_wait(adapter);
+       status = be_cmd_notify_wait(adapter, &wrb);
        if (!status) {
-               struct be_cmd_resp_if_create *resp = embedded_payload(wrb);
+               struct be_cmd_resp_if_create *resp = embedded_payload(&wrb);
                *if_handle = le32_to_cpu(resp->interface_id);
 
                /* Hack to retrieve VF's pmac-id on BE3 */
                if (BE3_chip(adapter) && !be_physfn(adapter))
                        adapter->pmac_id[0] = le32_to_cpu(resp->pmac_id);
        }
-
-err:
-       spin_unlock_bh(&adapter->mcc_lock);
        return status;
 }