return fqtree_find(&p->retire_table, fqid);
 }
 
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+static void **qman_fq_lookup_table;
+static size_t qman_fq_lookup_table_size;
+
+int qman_setup_fq_lookup_table(size_t num_entries)
+{
+       num_entries++;
+       /* Allocate 1 more entry since the first entry is not used */
+       qman_fq_lookup_table = vmalloc((num_entries * sizeof(void *)));
+       if (!qman_fq_lookup_table) {
+               pr_err("QMan: Could not allocate fq lookup table\n");
+               return -ENOMEM;
+       }
+       memset(qman_fq_lookup_table, 0, num_entries * sizeof(void *));
+       qman_fq_lookup_table_size = num_entries;
+       pr_debug("QMan: Allocated lookup table at %p, entry count %lu\n",
+               qman_fq_lookup_table,
+                       (unsigned long)qman_fq_lookup_table_size);
+       return 0;
+}
+
+/* global structure that maintains fq object mapping */
+static DEFINE_SPINLOCK(fq_hash_table_lock);
+
+static int find_empty_fq_table_entry(u32 *entry, struct qman_fq *fq)
+{
+       u32 i;
+
+       spin_lock(&fq_hash_table_lock);
+       /* Can't use index zero because this has special meaning
+        * in context_b field.
+        */
+       for (i = 1; i < qman_fq_lookup_table_size; i++) {
+               if (qman_fq_lookup_table[i] == NULL) {
+                       *entry = i;
+                       qman_fq_lookup_table[i] = fq;
+                       spin_unlock(&fq_hash_table_lock);
+                       return 0;
+               }
+       }
+       spin_unlock(&fq_hash_table_lock);
+       return -ENOMEM;
+}
+
+static void clear_fq_table_entry(u32 entry)
+{
+       spin_lock(&fq_hash_table_lock);
+       DPAA_BUG_ON(entry >= qman_fq_lookup_table_size);
+       qman_fq_lookup_table[entry] = NULL;
+       spin_unlock(&fq_hash_table_lock);
+}
+
+static inline struct qman_fq *get_fq_table_entry(u32 entry)
+{
+       DPAA_BUG_ON(entry >= qman_fq_lookup_table_size);
+       return qman_fq_lookup_table[entry];
+}
+#endif
+
 static inline void cpu_to_hw_fqd(struct qm_fqd *fqd)
 {
        /* Byteswap the FQD to HW format */
                                break;
                        case QM_MR_VERB_FQPN:
                                /* Parked */
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+                               fq = get_fq_table_entry(
+                                       be32_to_cpu(msg->fq.contextB));
+#else
                                fq = (void *)(uintptr_t)
                                        be32_to_cpu(msg->fq.contextB);
+#endif
                                fq_state_change(p, fq, msg, verb);
                                if (fq->cb.fqs)
                                        fq->cb.fqs(p, fq, &swapped_msg);
                        }
                } else {
                        /* Its a software ERN */
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+                       fq = get_fq_table_entry(be32_to_cpu(msg->ern.tag));
+#else
                        fq = (void *)(uintptr_t)be32_to_cpu(msg->ern.tag);
+#endif
                        fq->cb.ern(p, fq, &swapped_msg);
                }
                num++;
                                clear_vdqcr(p, fq);
                } else {
                        /* SDQCR: context_b points to the FQ */
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+                       fq = get_fq_table_entry(dq->contextB);
+#else
                        fq = (void *)(uintptr_t)dq->contextB;
+#endif
                        /* Now let the callback do its stuff */
                        res = fq->cb.dqrr(p, fq, dq);
                        /*
        fq->flags = flags;
        fq->state = qman_fq_state_oos;
        fq->cgr_groupid = 0;
-
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+       if (unlikely(find_empty_fq_table_entry(&fq->key, fq))) {
+               pr_info("Find empty table entry failed\n");
+               return -ENOMEM;
+       }
+#endif
        if (!(flags & QMAN_FQ_FLAG_AS_IS) || (flags & QMAN_FQ_FLAG_NO_MODIFY))
                return 0;
        /* Everything else is AS_IS support */
        case qman_fq_state_oos:
                if (fq_isset(fq, QMAN_FQ_FLAG_DYNAMIC_FQID))
                        qman_release_fqid(fq->fqid);
-
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+               clear_fq_table_entry(fq->key);
+#endif
                return;
        default:
                break;
                dma_addr_t phys_fq;
 
                mcc->initfq.we_mask |= QM_INITFQ_WE_CONTEXTB;
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+               mcc->initfq.fqd.context_b = fq->key;
+#else
                mcc->initfq.fqd.context_b = (u32)(uintptr_t)fq;
+#endif
                /*
                 *  and the physical address - NB, if the user wasn't trying to
                 * set CONTEXTA, clear the stashing settings.
                        msg.verb = QM_MR_VERB_FQRNI;
                        msg.fq.fqs = mcr->alterfq.fqs;
                        msg.fq.fqid = fq->fqid;
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+                       msg.fq.contextB = fq->key;
+#else
                        msg.fq.contextB = (u32)(uintptr_t)fq;
+#endif
                        fq->cb.fqs(p, fq, &msg);
                }
        } else if (res == QM_MCR_RESULT_PENDING) {
                                        QM_EQCR_DCA_PARK : 0) |
                        ((flags >> 8) & QM_EQCR_DCA_IDXMASK);
        eq->fqid = cpu_to_be32(fq->fqid);
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+       eq->tag = cpu_to_be32(fq->key);
+#else
        eq->tag = cpu_to_be32((u32)(uintptr_t)fq);
+#endif
        eq->fd = *fd;
        cpu_to_hw_fd(&eq->fd);
        return eq;
        /* try to send as many frames as possible */
        while (eqcr->available && frames_to_send--) {
                eq->fqid = cpu_to_be32(fq->fqid);
+#ifdef CONFIG_FSL_QMAN_FQ_LOOKUP
+               eq->tag = cpu_to_be32(fq->key);
+#else
                eq->tag = cpu_to_be32((u32)(uintptr_t)fq);
+#endif
                eq->fd.opaque_addr = fd->opaque_addr;
                eq->fd.addr = cpu_to_be40(fd->addr);
                eq->fd.status = cpu_to_be32(fd->status);