]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/net/ethernet/emulex/benet/be_cmds.c
be2net: Fix be_cmd_if_create() to use MBOX if MCCQ is not created
[karo-tx-linux.git] / 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;
 }