gpu_resources.sdma_doorbell[1][i+1] =
                                adev->doorbell_index.sdma_engine[1] + 0x200 + (i >> 1);
                }
-               /* Doorbells 0x0e0-0ff and 0x2e0-2ff are reserved for
-                * SDMA, IH and VCN. So don't use them for the CP.
+
+               /* Since SOC15, BIF starts to statically use the
+                * lower 12 bits of doorbell addresses for routing
+                * based on settings in registers like
+                * SDMA0_DOORBELL_RANGE etc..
+                * In order to route a doorbell to CP engine, the lower
+                * 12 bits of its address has to be outside the range
+                * set for SDMA, VCN, and IH blocks.
                 */
-               gpu_resources.reserved_doorbell_mask = 0x1e0;
-               gpu_resources.reserved_doorbell_val  = 0x0e0;
+               gpu_resources.non_cp_doorbells_start =
+                               adev->doorbell_index.first_non_cp;
+               gpu_resources.non_cp_doorbells_end =
+                               adev->doorbell_index.last_non_cp;
 
                kgd2kfd_device_init(adev->kfd.dev, &gpu_resources);
        }
 
 
 #define KFD_KERNEL_QUEUE_SIZE 2048
 
+/*
+ * 512 = 0x200
+ * The doorbell index distance between SDMA RLC (2*i) and (2*i+1) in the
+ * same SDMA engine on SOC15, which has 8-byte doorbells for SDMA.
+ * 512 8-byte doorbell distance (i.e. one page away) ensures that SDMA RLC
+ * (2*i+1) doorbells (in terms of the lower 12 bit address) lie exactly in
+ * the OFFSET and SIZE set in registers like BIF_SDMA0_DOORBELL_RANGE.
+ */
+#define KFD_QUEUE_DOORBELL_MIRROR_OFFSET 512
+
+
 /*
  * Kernel module parameter to specify maximum number of supported queues per
  * device
 
        if (!qpd->doorbell_bitmap)
                return -ENOMEM;
 
-       /* Mask out any reserved doorbells */
-       for (i = 0; i < KFD_MAX_NUM_OF_QUEUES_PER_PROCESS; i++)
-               if ((dev->shared_resources.reserved_doorbell_mask & i) ==
-                   dev->shared_resources.reserved_doorbell_val) {
+       /* Mask out doorbells reserved for SDMA, IH, and VCN on SOC15. */
+       for (i = 0; i < KFD_MAX_NUM_OF_QUEUES_PER_PROCESS / 2; i++) {
+               if (i >= dev->shared_resources.non_cp_doorbells_start
+                       && i <= dev->shared_resources.non_cp_doorbells_end) {
                        set_bit(i, qpd->doorbell_bitmap);
-                       pr_debug("reserved doorbell 0x%03x\n", i);
+                       set_bit(i + KFD_QUEUE_DOORBELL_MIRROR_OFFSET,
+                               qpd->doorbell_bitmap);
+                       pr_debug("reserved doorbell 0x%03x and 0x%03x\n", i,
+                               i + KFD_QUEUE_DOORBELL_MIRROR_OFFSET);
                }
+       }
 
        return 0;
 }
 
        /* Doorbell assignments (SOC15 and later chips only). Only
         * specific doorbells are routed to each SDMA engine. Others
         * are routed to IH and VCN. They are not usable by the CP.
-        *
-        * Any doorbell number D that satisfies the following condition
-        * is reserved: (D & reserved_doorbell_mask) == reserved_doorbell_val
-        *
-        * KFD currently uses 1024 (= 0x3ff) doorbells per process. If
-        * doorbells 0x0e0-0x0ff and 0x2e0-0x2ff are reserved, that means
-        * mask would be set to 0x1e0 and val set to 0x0e0.
         */
        unsigned int sdma_doorbell[2][8];
-       unsigned int reserved_doorbell_mask;
-       unsigned int reserved_doorbell_val;
+
+       /* From SOC15 onward, the doorbell index range not usable for CP
+        * queues.
+        */
+       uint32_t non_cp_doorbells_start;
+       uint32_t non_cp_doorbells_end;
 
        /* Base address of doorbell aperture. */
        phys_addr_t doorbell_physical_address;