Linux 6.9-rc1
[linux-2.6-microblaze.git] / block / bfq-iosched.c
index c740b41..4b88a54 100644 (file)
 #include "elevator.h"
 #include "blk.h"
 #include "blk-mq.h"
-#include "blk-mq-tag.h"
 #include "blk-mq-sched.h"
 #include "bfq-iosched.h"
 #include "blk-wbt.h"
@@ -377,15 +376,24 @@ static const unsigned long bfq_late_stable_merging = 600;
 #define RQ_BIC(rq)             ((struct bfq_io_cq *)((rq)->elv.priv[0]))
 #define RQ_BFQQ(rq)            ((rq)->elv.priv[1])
 
-struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, bool is_sync)
+struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, bool is_sync,
+                             unsigned int actuator_idx)
 {
-       return bic->bfqq[is_sync];
+       if (is_sync)
+               return bic->bfqq[1][actuator_idx];
+
+       return bic->bfqq[0][actuator_idx];
 }
 
 static void bfq_put_stable_ref(struct bfq_queue *bfqq);
 
-void bic_set_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq, bool is_sync)
+void bic_set_bfqq(struct bfq_io_cq *bic,
+                 struct bfq_queue *bfqq,
+                 bool is_sync,
+                 unsigned int actuator_idx)
 {
+       struct bfq_queue *old_bfqq = bic->bfqq[is_sync][actuator_idx];
+
        /*
         * If bfqq != NULL, then a non-stable queue merge between
         * bic->bfqq and bfqq is happening here. This causes troubles
@@ -399,9 +407,18 @@ void bic_set_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq, bool is_sync)
         * we cancel the stable merge if
         * bic->stable_merge_bfqq == bfqq.
         */
-       bic->bfqq[is_sync] = bfqq;
+       struct bfq_iocq_bfqq_data *bfqq_data = &bic->bfqq_data[actuator_idx];
+
+       /* Clear bic pointer if bfqq is detached from this bic */
+       if (old_bfqq && old_bfqq->bic == bic)
+               old_bfqq->bic = NULL;
 
-       if (bfqq && bic->stable_merge_bfqq == bfqq) {
+       if (is_sync)
+               bic->bfqq[1][actuator_idx] = bfqq;
+       else
+               bic->bfqq[0][actuator_idx] = bfqq;
+
+       if (bfqq && bfqq_data->stable_merge_bfqq == bfqq) {
                /*
                 * Actually, these same instructions are executed also
                 * in bfq_setup_cooperator, in case of abort or actual
@@ -410,9 +427,9 @@ void bic_set_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq, bool is_sync)
                 * did so, we would nest even more complexity in this
                 * function.
                 */
-               bfq_put_stable_ref(bic->stable_merge_bfqq);
+               bfq_put_stable_ref(bfqq_data->stable_merge_bfqq);
 
-               bic->stable_merge_bfqq = NULL;
+               bfqq_data->stable_merge_bfqq = NULL;
        }
 }
 
@@ -631,6 +648,8 @@ retry:
                                        sched_data->service_tree[i].wsum;
                        }
                }
+               if (!wsum)
+                       continue;
                limit = DIV_ROUND_CLOSEST(limit * entity->weight, wsum);
                if (entity->allocated >= limit) {
                        bfq_log_bfqq(bfqq->bfqd, bfqq,
@@ -672,9 +691,9 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
 {
        struct bfq_data *bfqd = data->q->elevator->elevator_data;
        struct bfq_io_cq *bic = bfq_bic_lookup(data->q);
-       struct bfq_queue *bfqq = bic ? bic_to_bfqq(bic, op_is_sync(opf)) : NULL;
        int depth;
        unsigned limit = data->q->nr_requests;
+       unsigned int act_idx;
 
        /* Sync reads have full depth available */
        if (op_is_sync(opf) && !op_is_write(opf)) {
@@ -684,14 +703,21 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
                limit = (limit * depth) >> bfqd->full_depth_shift;
        }
 
-       /*
-        * Does queue (or any parent entity) exceed number of requests that
-        * should be available to it? Heavily limit depth so that it cannot
-        * consume more available requests and thus starve other entities.
-        */
-       if (bfqq && bfqq_request_over_limit(bfqq, limit))
-               depth = 1;
+       for (act_idx = 0; bic && act_idx < bfqd->num_actuators; act_idx++) {
+               struct bfq_queue *bfqq =
+                       bic_to_bfqq(bic, op_is_sync(opf), act_idx);
 
+               /*
+                * Does queue (or any parent entity) exceed number of
+                * requests that should be available to it? Heavily
+                * limit depth so that it cannot consume more
+                * available requests and thus starve other entities.
+                */
+               if (bfqq && bfqq_request_over_limit(bfqq, limit)) {
+                       depth = 1;
+                       break;
+               }
+       }
        bfq_log(bfqd, "[%s] wr_busy %d sync %d depth %u",
                __func__, bfqd->wr_busy_queues, op_is_sync(opf), depth);
        if (depth)
@@ -820,7 +846,7 @@ bfq_pos_tree_add_move(struct bfq_data *bfqd, struct bfq_queue *bfqq)
  * much easier to maintain the needed state:
  * 1) all active queues have the same weight,
  * 2) all active queues belong to the same I/O-priority class,
- * 3) there are no active groups.
+ * 3) there is at most one active group.
  * In particular, the last condition is always true if hierarchical
  * support or the cgroups interface are not enabled, thus no state
  * needs to be maintained in this case.
@@ -852,7 +878,7 @@ static bool bfq_asymmetric_scenario(struct bfq_data *bfqd,
 
        return varied_queue_weights || multiple_classes_busy
 #ifdef CONFIG_BFQ_GROUP_IOSCHED
-              || bfqd->num_groups_with_pending_reqs > 0
+              || bfqd->num_groups_with_pending_reqs > 1
 #endif
                ;
 }
@@ -870,9 +896,9 @@ static bool bfq_asymmetric_scenario(struct bfq_data *bfqd,
  * In most scenarios, the rate at which nodes are created/destroyed
  * should be low too.
  */
-void bfq_weights_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq,
-                         struct rb_root_cached *root)
+void bfq_weights_tree_add(struct bfq_queue *bfqq)
 {
+       struct rb_root_cached *root = &bfqq->bfqd->queue_weights_tree;
        struct bfq_entity *entity = &bfqq->entity;
        struct rb_node **new = &(root->rb_root.rb_node), *parent = NULL;
        bool leftmost = true;
@@ -944,13 +970,14 @@ inc_counter:
  * See the comments to the function bfq_weights_tree_add() for considerations
  * about overhead.
  */
-void __bfq_weights_tree_remove(struct bfq_data *bfqd,
-                              struct bfq_queue *bfqq,
-                              struct rb_root_cached *root)
+void bfq_weights_tree_remove(struct bfq_queue *bfqq)
 {
+       struct rb_root_cached *root;
+
        if (!bfqq->weight_counter)
                return;
 
+       root = &bfqq->bfqd->queue_weights_tree;
        bfqq->weight_counter->num_active--;
        if (bfqq->weight_counter->num_active > 0)
                goto reset_entity_pointer;
@@ -963,59 +990,6 @@ reset_entity_pointer:
        bfq_put_queue(bfqq);
 }
 
-/*
- * Invoke __bfq_weights_tree_remove on bfqq and decrement the number
- * of active groups for each queue's inactive parent entity.
- */
-void bfq_weights_tree_remove(struct bfq_data *bfqd,
-                            struct bfq_queue *bfqq)
-{
-       struct bfq_entity *entity = bfqq->entity.parent;
-
-       for_each_entity(entity) {
-               struct bfq_sched_data *sd = entity->my_sched_data;
-
-               if (sd->next_in_service || sd->in_service_entity) {
-                       /*
-                        * entity is still active, because either
-                        * next_in_service or in_service_entity is not
-                        * NULL (see the comments on the definition of
-                        * next_in_service for details on why
-                        * in_service_entity must be checked too).
-                        *
-                        * As a consequence, its parent entities are
-                        * active as well, and thus this loop must
-                        * stop here.
-                        */
-                       break;
-               }
-
-               /*
-                * The decrement of num_groups_with_pending_reqs is
-                * not performed immediately upon the deactivation of
-                * entity, but it is delayed to when it also happens
-                * that the first leaf descendant bfqq of entity gets
-                * all its pending requests completed. The following
-                * instructions perform this delayed decrement, if
-                * needed. See the comments on
-                * num_groups_with_pending_reqs for details.
-                */
-               if (entity->in_groups_with_pending_reqs) {
-                       entity->in_groups_with_pending_reqs = false;
-                       bfqd->num_groups_with_pending_reqs--;
-               }
-       }
-
-       /*
-        * Next function is invoked last, because it causes bfqq to be
-        * freed if the following holds: bfqq is not in service and
-        * has no dispatched request. DO NOT use bfqq after the next
-        * function invocation.
-        */
-       __bfq_weights_tree_remove(bfqd, bfqq,
-                                 &bfqd->queue_weights_tree);
-}
-
 /*
  * Return expired entry, or NULL to just start from scratch in rbtree.
  */
@@ -1031,7 +1005,7 @@ static struct request *bfq_check_fifo(struct bfq_queue *bfqq,
 
        rq = rq_entry_fifo(bfqq->fifo.next);
 
-       if (rq == last || ktime_get_ns() < rq->fifo_time)
+       if (rq == last || blk_time_get_ns() < rq->fifo_time)
                return NULL;
 
        bfq_log_bfqq(bfqq->bfqd, bfqq, "check_fifo: returned %p", rq);
@@ -1120,9 +1094,6 @@ static unsigned int bfq_wr_duration(struct bfq_data *bfqd)
 {
        u64 dur;
 
-       if (bfqd->bfq_wr_max_time > 0)
-               return bfqd->bfq_wr_max_time;
-
        dur = bfqd->rate_dur_prod;
        do_div(dur, bfqd->peak_rate);
 
@@ -1164,36 +1135,39 @@ bfq_bfqq_resume_state(struct bfq_queue *bfqq, struct bfq_data *bfqd,
 {
        unsigned int old_wr_coeff = 1;
        bool busy = bfq_already_existing && bfq_bfqq_busy(bfqq);
+       unsigned int a_idx = bfqq->actuator_idx;
+       struct bfq_iocq_bfqq_data *bfqq_data = &bic->bfqq_data[a_idx];
 
-       if (bic->saved_has_short_ttime)
+       if (bfqq_data->saved_has_short_ttime)
                bfq_mark_bfqq_has_short_ttime(bfqq);
        else
                bfq_clear_bfqq_has_short_ttime(bfqq);
 
-       if (bic->saved_IO_bound)
+       if (bfqq_data->saved_IO_bound)
                bfq_mark_bfqq_IO_bound(bfqq);
        else
                bfq_clear_bfqq_IO_bound(bfqq);
 
-       bfqq->last_serv_time_ns = bic->saved_last_serv_time_ns;
-       bfqq->inject_limit = bic->saved_inject_limit;
-       bfqq->decrease_time_jif = bic->saved_decrease_time_jif;
+       bfqq->last_serv_time_ns = bfqq_data->saved_last_serv_time_ns;
+       bfqq->inject_limit = bfqq_data->saved_inject_limit;
+       bfqq->decrease_time_jif = bfqq_data->saved_decrease_time_jif;
 
-       bfqq->entity.new_weight = bic->saved_weight;
-       bfqq->ttime = bic->saved_ttime;
-       bfqq->io_start_time = bic->saved_io_start_time;
-       bfqq->tot_idle_time = bic->saved_tot_idle_time;
+       bfqq->entity.new_weight = bfqq_data->saved_weight;
+       bfqq->ttime = bfqq_data->saved_ttime;
+       bfqq->io_start_time = bfqq_data->saved_io_start_time;
+       bfqq->tot_idle_time = bfqq_data->saved_tot_idle_time;
        /*
         * Restore weight coefficient only if low_latency is on
         */
        if (bfqd->low_latency) {
                old_wr_coeff = bfqq->wr_coeff;
-               bfqq->wr_coeff = bic->saved_wr_coeff;
+               bfqq->wr_coeff = bfqq_data->saved_wr_coeff;
        }
-       bfqq->service_from_wr = bic->saved_service_from_wr;
-       bfqq->wr_start_at_switch_to_srt = bic->saved_wr_start_at_switch_to_srt;
-       bfqq->last_wr_start_finish = bic->saved_last_wr_start_finish;
-       bfqq->wr_cur_max_time = bic->saved_wr_cur_max_time;
+       bfqq->service_from_wr = bfqq_data->saved_service_from_wr;
+       bfqq->wr_start_at_switch_to_srt =
+               bfqq_data->saved_wr_start_at_switch_to_srt;
+       bfqq->last_wr_start_finish = bfqq_data->saved_last_wr_start_finish;
+       bfqq->wr_cur_max_time = bfqq_data->saved_wr_cur_max_time;
 
        if (bfqq->wr_coeff > 1 && (bfq_bfqq_in_large_burst(bfqq) ||
            time_is_before_jiffies(bfqq->last_wr_start_finish +
@@ -1812,6 +1786,33 @@ static bool bfq_bfqq_higher_class_or_weight(struct bfq_queue *bfqq,
        return bfqq_weight > in_serv_weight;
 }
 
+/*
+ * Get the index of the actuator that will serve bio.
+ */
+static unsigned int bfq_actuator_index(struct bfq_data *bfqd, struct bio *bio)
+{
+       unsigned int i;
+       sector_t end;
+
+       /* no search needed if one or zero ranges present */
+       if (bfqd->num_actuators == 1)
+               return 0;
+
+       /* bio_end_sector(bio) gives the sector after the last one */
+       end = bio_end_sector(bio) - 1;
+
+       for (i = 0; i < bfqd->num_actuators; i++) {
+               if (end >= bfqd->sector[i] &&
+                   end < bfqd->sector[i] + bfqd->nr_sectors[i])
+                       return i;
+       }
+
+       WARN_ONCE(true,
+                 "bfq_actuator_index: bio sector out of ranges: end=%llu\n",
+                 end);
+       return 0;
+}
+
 static bool bfq_better_to_idle(struct bfq_queue *bfqq);
 
 static void bfq_bfqq_handle_idle_busy_switch(struct bfq_data *bfqd,
@@ -1828,10 +1829,12 @@ static void bfq_bfqq_handle_idle_busy_switch(struct bfq_data *bfqd,
                 * bfq_bfqq_update_budg_for_activation for
                 * details on the usage of the next variable.
                 */
-               arrived_in_time =  ktime_get_ns() <=
+               arrived_in_time =  blk_time_get_ns() <=
                        bfqq->ttime.last_end_request +
                        bfqd->bfq_slice_idle * 3;
-
+       unsigned int act_idx = bfq_actuator_index(bfqd, rq->bio);
+       bool bfqq_non_merged_or_stably_merged =
+               bfqq->bic || RQ_BIC(rq)->bfqq_data[act_idx].stably_merged;
 
        /*
         * bfqq deserves to be weight-raised if:
@@ -1865,9 +1868,8 @@ static void bfq_bfqq_handle_idle_busy_switch(struct bfq_data *bfqd,
         */
        wr_or_deserves_wr = bfqd->low_latency &&
                (bfqq->wr_coeff > 1 ||
-                (bfq_bfqq_sync(bfqq) &&
-                 (bfqq->bic || RQ_BIC(rq)->stably_merged) &&
-                  (*interactive || soft_rt)));
+                (bfq_bfqq_sync(bfqq) && bfqq_non_merged_or_stably_merged &&
+                 (*interactive || soft_rt)));
 
        /*
         * Using the last flag, update budget and check whether bfqq
@@ -1925,7 +1927,7 @@ static void bfq_bfqq_handle_idle_busy_switch(struct bfq_data *bfqd,
        bfqq->service_from_backlogged = 0;
        bfq_clear_bfqq_softrt_update(bfqq);
 
-       bfq_add_bfqq_busy(bfqd, bfqq);
+       bfq_add_bfqq_busy(bfqq);
 
        /*
         * Expire in-service queue if preemption may be needed for
@@ -2135,14 +2137,16 @@ static void bfq_check_waker(struct bfq_data *bfqd, struct bfq_queue *bfqq,
        if (!bfqd->last_completed_rq_bfqq ||
            bfqd->last_completed_rq_bfqq == bfqq ||
            bfq_bfqq_has_short_ttime(bfqq) ||
-           now_ns - bfqd->last_completion >= 4 * NSEC_PER_MSEC)
+           now_ns - bfqd->last_completion >= 4 * NSEC_PER_MSEC ||
+           bfqd->last_completed_rq_bfqq == &bfqd->oom_bfqq ||
+           bfqq == &bfqd->oom_bfqq)
                return;
 
        /*
         * We reset waker detection logic also if too much time has passed
         * since the first detection. If wakeups are rare, pointless idling
         * doesn't hurt throughput that much. The condition below makes sure
-        * we do not uselessly idle blocking waker in more than 1/64 cases. 
+        * we do not uselessly idle blocking waker in more than 1/64 cases.
         */
        if (bfqd->last_completed_rq_bfqq !=
            bfqq->tentative_waker_bfqq ||
@@ -2204,7 +2208,7 @@ static void bfq_add_request(struct request *rq)
        struct request *next_rq, *prev;
        unsigned int old_wr_coeff = bfqq->wr_coeff;
        bool interactive = false;
-       u64 now_ns = ktime_get_ns();
+       u64 now_ns = blk_time_get_ns();
 
        bfq_log_bfqq(bfqd, bfqq, "add_request %d", rq_is_sync(rq));
        bfqq->queued[rq_is_sync(rq)]++;
@@ -2253,12 +2257,12 @@ static void bfq_add_request(struct request *rq)
                 *   elapsed.
                 */
                if (bfqq == bfqd->in_service_queue &&
-                   (bfqd->rq_in_driver == 0 ||
+                   (bfqd->tot_rq_in_driver == 0 ||
                     (bfqq->last_serv_time_ns > 0 &&
-                     bfqd->rqs_injected && bfqd->rq_in_driver > 0)) &&
+                     bfqd->rqs_injected && bfqd->tot_rq_in_driver > 0)) &&
                    time_is_before_eq_jiffies(bfqq->decrease_time_jif +
                                              msecs_to_jiffies(10))) {
-                       bfqd->last_empty_occupied_ns = ktime_get_ns();
+                       bfqd->last_empty_occupied_ns = blk_time_get_ns();
                        /*
                         * Start the state machine for measuring the
                         * total service time of rq: setting
@@ -2279,7 +2283,7 @@ static void bfq_add_request(struct request *rq)
                         * will be set in case injection is performed
                         * on bfqq before rq is completed).
                         */
-                       if (bfqd->rq_in_driver == 0)
+                       if (bfqd->tot_rq_in_driver == 0)
                                bfqd->rqs_injected = false;
                }
        }
@@ -2373,22 +2377,6 @@ static sector_t get_sdist(sector_t last_pos, struct request *rq)
        return 0;
 }
 
-#if 0 /* Still not clear if we can do without next two functions */
-static void bfq_activate_request(struct request_queue *q, struct request *rq)
-{
-       struct bfq_data *bfqd = q->elevator->elevator_data;
-
-       bfqd->rq_in_driver++;
-}
-
-static void bfq_deactivate_request(struct request_queue *q, struct request *rq)
-{
-       struct bfq_data *bfqd = q->elevator->elevator_data;
-
-       bfqd->rq_in_driver--;
-}
-#endif
-
 static void bfq_remove_request(struct request_queue *q,
                               struct request *rq)
 {
@@ -2419,7 +2407,7 @@ static void bfq_remove_request(struct request_queue *q,
                bfqq->next_rq = NULL;
 
                if (bfq_bfqq_busy(bfqq) && bfqq != bfqd->in_service_queue) {
-                       bfq_del_bfqq_busy(bfqd, bfqq, false);
+                       bfq_del_bfqq_busy(bfqq, false);
                        /*
                         * bfqq emptied. In normal operation, when
                         * bfqq is empty, bfqq->entity.service and
@@ -2478,7 +2466,8 @@ static bool bfq_bio_merge(struct request_queue *q, struct bio *bio,
                 */
                bfq_bic_update_cgroup(bic, bio);
 
-               bfqd->bio_bfqq = bic_to_bfqq(bic, op_is_sync(bio->bi_opf));
+               bfqd->bio_bfqq = bic_to_bfqq(bic, op_is_sync(bio->bi_opf),
+                                            bfq_actuator_index(bfqd, bio));
        } else {
                bfqd->bio_bfqq = NULL;
        }
@@ -2644,24 +2633,29 @@ static void bfq_bfqq_end_wr(struct bfq_queue *bfqq)
 void bfq_end_wr_async_queues(struct bfq_data *bfqd,
                             struct bfq_group *bfqg)
 {
-       int i, j;
+       int i, j, k;
 
-       for (i = 0; i < 2; i++)
-               for (j = 0; j < IOPRIO_NR_LEVELS; j++)
-                       if (bfqg->async_bfqq[i][j])
-                               bfq_bfqq_end_wr(bfqg->async_bfqq[i][j]);
-       if (bfqg->async_idle_bfqq)
-               bfq_bfqq_end_wr(bfqg->async_idle_bfqq);
+       for (k = 0; k < bfqd->num_actuators; k++) {
+               for (i = 0; i < 2; i++)
+                       for (j = 0; j < IOPRIO_NR_LEVELS; j++)
+                               if (bfqg->async_bfqq[i][j][k])
+                                       bfq_bfqq_end_wr(bfqg->async_bfqq[i][j][k]);
+               if (bfqg->async_idle_bfqq[k])
+                       bfq_bfqq_end_wr(bfqg->async_idle_bfqq[k]);
+       }
 }
 
 static void bfq_end_wr(struct bfq_data *bfqd)
 {
        struct bfq_queue *bfqq;
+       int i;
 
        spin_lock_irq(&bfqd->lock);
 
-       list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list)
-               bfq_bfqq_end_wr(bfqq);
+       for (i = 0; i < bfqd->num_actuators; i++) {
+               list_for_each_entry(bfqq, &bfqd->active_list[i], bfqq_list)
+                       bfq_bfqq_end_wr(bfqq);
+       }
        list_for_each_entry(bfqq, &bfqd->idle_list, bfqq_list)
                bfq_bfqq_end_wr(bfqq);
        bfq_end_wr_async(bfqd);
@@ -2854,6 +2848,40 @@ static bool bfq_may_be_close_cooperator(struct bfq_queue *bfqq,
 static bool idling_boosts_thr_without_issues(struct bfq_data *bfqd,
                                             struct bfq_queue *bfqq);
 
+static struct bfq_queue *
+bfq_setup_stable_merge(struct bfq_data *bfqd, struct bfq_queue *bfqq,
+                      struct bfq_queue *stable_merge_bfqq,
+                      struct bfq_iocq_bfqq_data *bfqq_data)
+{
+       int proc_ref = min(bfqq_process_refs(bfqq),
+                          bfqq_process_refs(stable_merge_bfqq));
+       struct bfq_queue *new_bfqq = NULL;
+
+       bfqq_data->stable_merge_bfqq = NULL;
+       if (idling_boosts_thr_without_issues(bfqd, bfqq) || proc_ref == 0)
+               goto out;
+
+       /* next function will take at least one ref */
+       new_bfqq = bfq_setup_merge(bfqq, stable_merge_bfqq);
+
+       if (new_bfqq) {
+               bfqq_data->stably_merged = true;
+               if (new_bfqq->bic) {
+                       unsigned int new_a_idx = new_bfqq->actuator_idx;
+                       struct bfq_iocq_bfqq_data *new_bfqq_data =
+                               &new_bfqq->bic->bfqq_data[new_a_idx];
+
+                       new_bfqq_data->stably_merged = true;
+               }
+       }
+
+out:
+       /* deschedule stable merge, because done or aborted here */
+       bfq_put_stable_ref(stable_merge_bfqq);
+
+       return new_bfqq;
+}
+
 /*
  * Attempt to schedule a merge of bfqq with the currently in-service
  * queue or with a close queue among the scheduled queues.  Return
@@ -2879,6 +2907,8 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
                     void *io_struct, bool request, struct bfq_io_cq *bic)
 {
        struct bfq_queue *in_service_bfqq, *new_bfqq;
+       unsigned int a_idx = bfqq->actuator_idx;
+       struct bfq_iocq_bfqq_data *bfqq_data = &bic->bfqq_data[a_idx];
 
        /* if a merge has already been setup, then proceed with that first */
        if (bfqq->new_bfqq)
@@ -2900,37 +2930,18 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
                 * stable merging) also if bic is associated with a
                 * sync queue, but this bfqq is async
                 */
-               if (bfq_bfqq_sync(bfqq) && bic->stable_merge_bfqq &&
+               if (bfq_bfqq_sync(bfqq) && bfqq_data->stable_merge_bfqq &&
                    !bfq_bfqq_just_created(bfqq) &&
                    time_is_before_jiffies(bfqq->split_time +
                                          msecs_to_jiffies(bfq_late_stable_merging)) &&
                    time_is_before_jiffies(bfqq->creation_time +
                                           msecs_to_jiffies(bfq_late_stable_merging))) {
                        struct bfq_queue *stable_merge_bfqq =
-                               bic->stable_merge_bfqq;
-                       int proc_ref = min(bfqq_process_refs(bfqq),
-                                          bfqq_process_refs(stable_merge_bfqq));
-
-                       /* deschedule stable merge, because done or aborted here */
-                       bfq_put_stable_ref(stable_merge_bfqq);
-
-                       bic->stable_merge_bfqq = NULL;
-
-                       if (!idling_boosts_thr_without_issues(bfqd, bfqq) &&
-                           proc_ref > 0) {
-                               /* next function will take at least one ref */
-                               struct bfq_queue *new_bfqq =
-                                       bfq_setup_merge(bfqq, stable_merge_bfqq);
-
-                               if (new_bfqq) {
-                                       bic->stably_merged = true;
-                                       if (new_bfqq->bic)
-                                               new_bfqq->bic->stably_merged =
-                                                                       true;
-                               }
-                               return new_bfqq;
-                       } else
-                               return NULL;
+                               bfqq_data->stable_merge_bfqq;
+
+                       return bfq_setup_stable_merge(bfqd, bfqq,
+                                                     stable_merge_bfqq,
+                                                     bfqq_data);
                }
        }
 
@@ -3025,6 +3036,8 @@ bfq_setup_cooperator(struct bfq_data *bfqd, struct bfq_queue *bfqq,
 static void bfq_bfqq_save_state(struct bfq_queue *bfqq)
 {
        struct bfq_io_cq *bic = bfqq->bic;
+       unsigned int a_idx = bfqq->actuator_idx;
+       struct bfq_iocq_bfqq_data *bfqq_data = &bic->bfqq_data[a_idx];
 
        /*
         * If !bfqq->bic, the queue is already shared or its requests
@@ -3034,18 +3047,21 @@ static void bfq_bfqq_save_state(struct bfq_queue *bfqq)
        if (!bic)
                return;
 
-       bic->saved_last_serv_time_ns = bfqq->last_serv_time_ns;
-       bic->saved_inject_limit = bfqq->inject_limit;
-       bic->saved_decrease_time_jif = bfqq->decrease_time_jif;
-
-       bic->saved_weight = bfqq->entity.orig_weight;
-       bic->saved_ttime = bfqq->ttime;
-       bic->saved_has_short_ttime = bfq_bfqq_has_short_ttime(bfqq);
-       bic->saved_IO_bound = bfq_bfqq_IO_bound(bfqq);
-       bic->saved_io_start_time = bfqq->io_start_time;
-       bic->saved_tot_idle_time = bfqq->tot_idle_time;
-       bic->saved_in_large_burst = bfq_bfqq_in_large_burst(bfqq);
-       bic->was_in_burst_list = !hlist_unhashed(&bfqq->burst_list_node);
+       bfqq_data->saved_last_serv_time_ns = bfqq->last_serv_time_ns;
+       bfqq_data->saved_inject_limit = bfqq->inject_limit;
+       bfqq_data->saved_decrease_time_jif = bfqq->decrease_time_jif;
+
+       bfqq_data->saved_weight = bfqq->entity.orig_weight;
+       bfqq_data->saved_ttime = bfqq->ttime;
+       bfqq_data->saved_has_short_ttime =
+               bfq_bfqq_has_short_ttime(bfqq);
+       bfqq_data->saved_IO_bound = bfq_bfqq_IO_bound(bfqq);
+       bfqq_data->saved_io_start_time = bfqq->io_start_time;
+       bfqq_data->saved_tot_idle_time = bfqq->tot_idle_time;
+       bfqq_data->saved_in_large_burst = bfq_bfqq_in_large_burst(bfqq);
+       bfqq_data->was_in_burst_list =
+               !hlist_unhashed(&bfqq->burst_list_node);
+
        if (unlikely(bfq_bfqq_just_created(bfqq) &&
                     !bfq_bfqq_in_large_burst(bfqq) &&
                     bfqq->bfqd->low_latency)) {
@@ -3058,17 +3074,21 @@ static void bfq_bfqq_save_state(struct bfq_queue *bfqq)
                 * to bfqq, so that to avoid that bfqq unjustly fails
                 * to enjoy weight raising if split soon.
                 */
-               bic->saved_wr_coeff = bfqq->bfqd->bfq_wr_coeff;
-               bic->saved_wr_start_at_switch_to_srt = bfq_smallest_from_now();
-               bic->saved_wr_cur_max_time = bfq_wr_duration(bfqq->bfqd);
-               bic->saved_last_wr_start_finish = jiffies;
+               bfqq_data->saved_wr_coeff = bfqq->bfqd->bfq_wr_coeff;
+               bfqq_data->saved_wr_start_at_switch_to_srt =
+                       bfq_smallest_from_now();
+               bfqq_data->saved_wr_cur_max_time =
+                       bfq_wr_duration(bfqq->bfqd);
+               bfqq_data->saved_last_wr_start_finish = jiffies;
        } else {
-               bic->saved_wr_coeff = bfqq->wr_coeff;
-               bic->saved_wr_start_at_switch_to_srt =
+               bfqq_data->saved_wr_coeff = bfqq->wr_coeff;
+               bfqq_data->saved_wr_start_at_switch_to_srt =
                        bfqq->wr_start_at_switch_to_srt;
-               bic->saved_service_from_wr = bfqq->service_from_wr;
-               bic->saved_last_wr_start_finish = bfqq->last_wr_start_finish;
-               bic->saved_wr_cur_max_time = bfqq->wr_cur_max_time;
+               bfqq_data->saved_service_from_wr =
+                       bfqq->service_from_wr;
+               bfqq_data->saved_last_wr_start_finish =
+                       bfqq->last_wr_start_finish;
+               bfqq_data->saved_wr_cur_max_time = bfqq->wr_cur_max_time;
        }
 }
 
@@ -3098,7 +3118,7 @@ void bfq_release_process_ref(struct bfq_data *bfqd, struct bfq_queue *bfqq)
         */
        if (bfq_bfqq_busy(bfqq) && RB_EMPTY_ROOT(&bfqq->sort_list) &&
            bfqq != bfqd->in_service_queue)
-               bfq_del_bfqq_busy(bfqd, bfqq, false);
+               bfq_del_bfqq_busy(bfqq, false);
 
        bfq_reassign_last_bfqq(bfqq, NULL);
 
@@ -3174,7 +3194,7 @@ bfq_merge_bfqqs(struct bfq_data *bfqd, struct bfq_io_cq *bic,
        /*
         * Merge queues (that is, let bic redirect its requests to new_bfqq)
         */
-       bic_set_bfqq(bic, new_bfqq, 1);
+       bic_set_bfqq(bic, new_bfqq, true, bfqq->actuator_idx);
        bfq_mark_bfqq_coop(new_bfqq);
        /*
         * new_bfqq now belongs to at least two bics (it is a shared queue):
@@ -3274,7 +3294,7 @@ static void bfq_set_budget_timeout(struct bfq_data *bfqd,
        else
                timeout_coeff = bfqq->entity.weight / bfqq->entity.orig_weight;
 
-       bfqd->last_budget_start = ktime_get();
+       bfqd->last_budget_start = blk_time_get();
 
        bfqq->budget_timeout = jiffies +
                bfqd->bfq_timeout * timeout_coeff;
@@ -3374,7 +3394,7 @@ static void bfq_arm_slice_timer(struct bfq_data *bfqd)
        else if (bfqq->wr_coeff > 1)
                sl = max_t(u32, sl, 20ULL * NSEC_PER_MSEC);
 
-       bfqd->last_idling_start = ktime_get();
+       bfqd->last_idling_start = blk_time_get();
        bfqd->last_idling_start_jiffies = jiffies;
 
        hrtimer_start(&bfqd->idle_slice_timer, ns_to_ktime(sl),
@@ -3413,7 +3433,7 @@ static void bfq_reset_rate_computation(struct bfq_data *bfqd,
                                       struct request *rq)
 {
        if (rq != NULL) { /* new rq dispatch now, reset accordingly */
-               bfqd->last_dispatch = bfqd->first_dispatch = ktime_get_ns();
+               bfqd->last_dispatch = bfqd->first_dispatch = blk_time_get_ns();
                bfqd->peak_rate_samples = 1;
                bfqd->sequential_samples = 0;
                bfqd->tot_sectors_dispatched = bfqd->last_rq_max_size =
@@ -3570,7 +3590,7 @@ reset_computation:
  */
 static void bfq_update_peak_rate(struct bfq_data *bfqd, struct request *rq)
 {
-       u64 now_ns = ktime_get_ns();
+       u64 now_ns = blk_time_get_ns();
 
        if (bfqd->peak_rate_samples == 0) { /* first dispatch */
                bfq_log(bfqd, "update_peak_rate: goto reset, samples %d",
@@ -3592,13 +3612,13 @@ static void bfq_update_peak_rate(struct bfq_data *bfqd, struct request *rq)
         * - start a new observation interval with this dispatch
         */
        if (now_ns - bfqd->last_dispatch > 100*NSEC_PER_MSEC &&
-           bfqd->rq_in_driver == 0)
+           bfqd->tot_rq_in_driver == 0)
                goto update_rate_and_reset;
 
        /* Update sampling information */
        bfqd->peak_rate_samples++;
 
-       if ((bfqd->rq_in_driver > 0 ||
+       if ((bfqd->tot_rq_in_driver > 0 ||
                now_ns - bfqd->last_completion < BFQ_MIN_TT)
            && !BFQ_RQ_SEEKY(bfqd, bfqd->last_position, rq))
                bfqd->sequential_samples++;
@@ -3863,10 +3883,8 @@ static bool idling_needed_for_service_guarantees(struct bfq_data *bfqd,
                return false;
 
        return (bfqq->wr_coeff > 1 &&
-               (bfqd->wr_busy_queues <
-                tot_busy_queues ||
-                bfqd->rq_in_driver >=
-                bfqq->dispatched + 4)) ||
+               (bfqd->wr_busy_queues < tot_busy_queues ||
+                bfqd->tot_rq_in_driver >= bfqq->dispatched + 4)) ||
                bfq_asymmetric_scenario(bfqd, bfqq) ||
                tot_busy_queues == 1;
 }
@@ -3908,7 +3926,7 @@ static bool __bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq,
                         */
                        bfqq->budget_timeout = jiffies;
 
-               bfq_del_bfqq_busy(bfqd, bfqq, true);
+               bfq_del_bfqq_busy(bfqq, true);
        } else {
                bfq_requeue_bfqq(bfqd, bfqq, true);
                /*
@@ -4132,8 +4150,7 @@ static void __bfq_bfqq_recalc_budget(struct bfq_data *bfqd,
  * function to evaluate the I/O speed of a process.
  */
 static bool bfq_bfqq_is_slow(struct bfq_data *bfqd, struct bfq_queue *bfqq,
-                                bool compensate, enum bfqq_expiration reason,
-                                unsigned long *delta_ms)
+                                bool compensate, unsigned long *delta_ms)
 {
        ktime_t delta_ktime;
        u32 delta_usecs;
@@ -4145,7 +4162,7 @@ static bool bfq_bfqq_is_slow(struct bfq_data *bfqd, struct bfq_queue *bfqq,
        if (compensate)
                delta_ktime = bfqd->last_idling_start;
        else
-               delta_ktime = ktime_get();
+               delta_ktime = blk_time_get();
        delta_ktime = ktime_sub(delta_ktime, bfqd->last_budget_start);
        delta_usecs = ktime_to_us(delta_ktime);
 
@@ -4329,7 +4346,7 @@ void bfq_bfqq_expire(struct bfq_data *bfqd,
        /*
         * Check whether the process is slow (see bfq_bfqq_is_slow).
         */
-       slow = bfq_bfqq_is_slow(bfqd, bfqq, compensate, reason, &delta);
+       slow = bfq_bfqq_is_slow(bfqd, bfqq, compensate, &delta);
 
        /*
         * As above explained, charge slow (typically seeky) and
@@ -4637,6 +4654,8 @@ bfq_choose_bfqq_for_injection(struct bfq_data *bfqd)
 {
        struct bfq_queue *bfqq, *in_serv_bfqq = bfqd->in_service_queue;
        unsigned int limit = in_serv_bfqq->inject_limit;
+       int i;
+
        /*
         * If
         * - bfqq is not weight-raised and therefore does not carry
@@ -4668,7 +4687,7 @@ bfq_choose_bfqq_for_injection(struct bfq_data *bfqd)
                )
                limit = 1;
 
-       if (bfqd->rq_in_driver >= limit)
+       if (bfqd->tot_rq_in_driver >= limit)
                return NULL;
 
        /*
@@ -4683,11 +4702,12 @@ bfq_choose_bfqq_for_injection(struct bfq_data *bfqd)
         *   (and re-added only if it gets new requests, but then it
         *   is assigned again enough budget for its new backlog).
         */
-       list_for_each_entry(bfqq, &bfqd->active_list, bfqq_list)
-               if (!RB_EMPTY_ROOT(&bfqq->sort_list) &&
-                   (in_serv_always_inject || bfqq->wr_coeff > 1) &&
-                   bfq_serv_to_charge(bfqq->next_rq, bfqq) <=
-                   bfq_bfqq_budget_left(bfqq)) {
+       for (i = 0; i < bfqd->num_actuators; i++) {
+               list_for_each_entry(bfqq, &bfqd->active_list[i], bfqq_list)
+                       if (!RB_EMPTY_ROOT(&bfqq->sort_list) &&
+                               (in_serv_always_inject || bfqq->wr_coeff > 1) &&
+                               bfq_serv_to_charge(bfqq->next_rq, bfqq) <=
+                               bfq_bfqq_budget_left(bfqq)) {
                        /*
                         * Allow for only one large in-flight request
                         * on non-rotational devices, for the
@@ -4707,27 +4727,80 @@ bfq_choose_bfqq_for_injection(struct bfq_data *bfqd)
                         */
                        if (blk_queue_nonrot(bfqd->queue) &&
                            blk_rq_sectors(bfqq->next_rq) >=
-                           BFQQ_SECT_THR_NONROT)
-                               limit = min_t(unsigned int, 1, limit);
-                       else
-                               limit = in_serv_bfqq->inject_limit;
-
-                       if (bfqd->rq_in_driver < limit) {
+                           BFQQ_SECT_THR_NONROT &&
+                           bfqd->tot_rq_in_driver >= 1)
+                               continue;
+                       else {
                                bfqd->rqs_injected = true;
                                return bfqq;
                        }
                }
+       }
+
+       return NULL;
+}
+
+static struct bfq_queue *
+bfq_find_active_bfqq_for_actuator(struct bfq_data *bfqd, int idx)
+{
+       struct bfq_queue *bfqq;
+
+       if (bfqd->in_service_queue &&
+           bfqd->in_service_queue->actuator_idx == idx)
+               return bfqd->in_service_queue;
+
+       list_for_each_entry(bfqq, &bfqd->active_list[idx], bfqq_list) {
+               if (!RB_EMPTY_ROOT(&bfqq->sort_list) &&
+                       bfq_serv_to_charge(bfqq->next_rq, bfqq) <=
+                               bfq_bfqq_budget_left(bfqq)) {
+                       return bfqq;
+               }
+       }
 
        return NULL;
 }
 
+/*
+ * Perform a linear scan of each actuator, until an actuator is found
+ * for which the following three conditions hold: the load of the
+ * actuator is below the threshold (see comments on
+ * actuator_load_threshold for details) and lower than that of the
+ * next actuator (comments on this extra condition below), and there
+ * is a queue that contains I/O for that actuator. On success, return
+ * that queue.
+ *
+ * Performing a plain linear scan entails a prioritization among
+ * actuators. The extra condition above breaks this prioritization and
+ * tends to distribute injection uniformly across actuators.
+ */
+static struct bfq_queue *
+bfq_find_bfqq_for_underused_actuator(struct bfq_data *bfqd)
+{
+       int i;
+
+       for (i = 0 ; i < bfqd->num_actuators; i++) {
+               if (bfqd->rq_in_driver[i] < bfqd->actuator_load_threshold &&
+                   (i == bfqd->num_actuators - 1 ||
+                    bfqd->rq_in_driver[i] < bfqd->rq_in_driver[i+1])) {
+                       struct bfq_queue *bfqq =
+                               bfq_find_active_bfqq_for_actuator(bfqd, i);
+
+                       if (bfqq)
+                               return bfqq;
+               }
+       }
+
+       return NULL;
+}
+
+
 /*
  * Select a queue for service.  If we have a current queue in service,
  * check whether to continue servicing it, or retrieve and set a new one.
  */
 static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd)
 {
-       struct bfq_queue *bfqq;
+       struct bfq_queue *bfqq, *inject_bfqq;
        struct request *next_rq;
        enum bfqq_expiration reason = BFQQE_BUDGET_TIMEOUT;
 
@@ -4749,6 +4822,15 @@ static struct bfq_queue *bfq_select_queue(struct bfq_data *bfqd)
                goto expire;
 
 check_queue:
+       /*
+        *  If some actuator is underutilized, but the in-service
+        *  queue does not contain I/O for that actuator, then try to
+        *  inject I/O for that actuator.
+        */
+       inject_bfqq = bfq_find_bfqq_for_underused_actuator(bfqd);
+       if (inject_bfqq && inject_bfqq != bfqq)
+               return inject_bfqq;
+
        /*
         * This loop is rarely executed more than once. Even when it
         * happens, it is much more convenient to re-execute this loop
@@ -4808,11 +4890,8 @@ check_queue:
         */
        if (bfq_bfqq_wait_request(bfqq) ||
            (bfqq->dispatched != 0 && bfq_better_to_idle(bfqq))) {
-               struct bfq_queue *async_bfqq =
-                       bfqq->bic && bfqq->bic->bfqq[0] &&
-                       bfq_bfqq_busy(bfqq->bic->bfqq[0]) &&
-                       bfqq->bic->bfqq[0]->next_rq ?
-                       bfqq->bic->bfqq[0] : NULL;
+               unsigned int act_idx = bfqq->actuator_idx;
+               struct bfq_queue *async_bfqq = NULL;
                struct bfq_queue *blocked_bfqq =
                        !hlist_empty(&bfqq->woken_list) ?
                        container_of(bfqq->woken_list.first,
@@ -4820,6 +4899,10 @@ check_queue:
                                     woken_list_node)
                        : NULL;
 
+               if (bfqq->bic && bfqq->bic->bfqq[0][act_idx] &&
+                   bfq_bfqq_busy(bfqq->bic->bfqq[0][act_idx]) &&
+                   bfqq->bic->bfqq[0][act_idx]->next_rq)
+                       async_bfqq = bfqq->bic->bfqq[0][act_idx];
                /*
                 * The next four mutually-exclusive ifs decide
                 * whether to try injection, and choose the queue to
@@ -4904,7 +4987,7 @@ check_queue:
                    icq_to_bic(async_bfqq->next_rq->elv.icq) == bfqq->bic &&
                    bfq_serv_to_charge(async_bfqq->next_rq, async_bfqq) <=
                    bfq_bfqq_budget_left(async_bfqq))
-                       bfqq = bfqq->bic->bfqq[0];
+                       bfqq = async_bfqq;
                else if (bfqq->waker_bfqq &&
                           bfq_bfqq_busy(bfqq->waker_bfqq) &&
                           bfqq->waker_bfqq->next_rq &&
@@ -5035,7 +5118,7 @@ static struct request *bfq_dispatch_rq_from_bfqq(struct bfq_data *bfqd,
        bfq_dispatch_remove(bfqd->queue, rq);
 
        if (bfqq != bfqd->in_service_queue)
-               goto return_rq;
+               return rq;
 
        /*
         * If weight raising has to terminate for bfqq, then next
@@ -5055,12 +5138,9 @@ static struct request *bfq_dispatch_rq_from_bfqq(struct bfq_data *bfqd,
         * belongs to CLASS_IDLE and other queues are waiting for
         * service.
         */
-       if (!(bfq_tot_busy_queues(bfqd) > 1 && bfq_class_idle(bfqq)))
-               goto return_rq;
-
-       bfq_bfqq_expire(bfqd, bfqq, false, BFQQE_BUDGET_EXHAUSTED);
+       if (bfq_tot_busy_queues(bfqd) > 1 && bfq_class_idle(bfqq))
+               bfq_bfqq_expire(bfqd, bfqq, false, BFQQE_BUDGET_EXHAUSTED);
 
-return_rq:
        return rq;
 }
 
@@ -5103,11 +5183,11 @@ static struct request *__bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
 
                /*
                 * We exploit the bfq_finish_requeue_request hook to
-                * decrement rq_in_driver, but
+                * decrement tot_rq_in_driver, but
                 * bfq_finish_requeue_request will not be invoked on
                 * this request. So, to avoid unbalance, just start
-                * this request, without incrementing rq_in_driver. As
-                * a negative consequence, rq_in_driver is deceptively
+                * this request, without incrementing tot_rq_in_driver. As
+                * a negative consequence, tot_rq_in_driver is deceptively
                 * lower than it should be while this request is in
                 * service. This may cause bfq_schedule_dispatch to be
                 * invoked uselessly.
@@ -5116,7 +5196,7 @@ static struct request *__bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
                 * bfq_finish_requeue_request hook, if defined, is
                 * probably invoked also on this request. So, by
                 * exploiting this hook, we could 1) increment
-                * rq_in_driver here, and 2) decrement it in
+                * tot_rq_in_driver here, and 2) decrement it in
                 * bfq_finish_requeue_request. Such a solution would
                 * let the value of the counter be always accurate,
                 * but it would entail using an extra interface
@@ -5145,7 +5225,7 @@ static struct request *__bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
         * Of course, serving one request at a time may cause loss of
         * throughput.
         */
-       if (bfqd->strict_guarantees && bfqd->rq_in_driver > 0)
+       if (bfqd->strict_guarantees && bfqd->tot_rq_in_driver > 0)
                goto exit;
 
        bfqq = bfq_select_queue(bfqd);
@@ -5156,7 +5236,8 @@ static struct request *__bfq_dispatch_request(struct blk_mq_hw_ctx *hctx)
 
        if (rq) {
 inc_in_driver_start_rq:
-               bfqd->rq_in_driver++;
+               bfqd->rq_in_driver[bfqq->actuator_idx]++;
+               bfqd->tot_rq_in_driver++;
 start_rq:
                rq->rq_flags |= RQF_STARTED;
        }
@@ -5255,9 +5336,7 @@ void bfq_put_queue(struct bfq_queue *bfqq)
        struct hlist_node *n;
        struct bfq_group *bfqg = bfqq_group(bfqq);
 
-       if (bfqq->bfqd)
-               bfq_log_bfqq(bfqq->bfqd, bfqq, "put_queue: %p %d",
-                            bfqq, bfqq->ref);
+       bfq_log_bfqq(bfqq->bfqd, bfqq, "put_queue: %p %d", bfqq, bfqq->ref);
 
        bfqq->ref--;
        if (bfqq->ref)
@@ -5321,9 +5400,13 @@ void bfq_put_queue(struct bfq_queue *bfqq)
                hlist_del_init(&item->woken_list_node);
        }
 
-       if (bfqq->bfqd && bfqq->bfqd->last_completed_rq_bfqq == bfqq)
+       if (bfqq->bfqd->last_completed_rq_bfqq == bfqq)
                bfqq->bfqd->last_completed_rq_bfqq = NULL;
 
+       WARN_ON_ONCE(!list_empty(&bfqq->fifo));
+       WARN_ON_ONCE(!RB_EMPTY_ROOT(&bfqq->sort_list));
+       WARN_ON_ONCE(bfqq->dispatched);
+
        kmem_cache_free(bfq_pool, bfqq);
        bfqg_and_blkg_put(bfqg);
 }
@@ -5345,8 +5428,6 @@ void bfq_put_cooperator(struct bfq_queue *bfqq)
         */
        __bfqq = bfqq->new_bfqq;
        while (__bfqq) {
-               if (__bfqq == bfqq)
-                       break;
                next = __bfqq->new_bfqq;
                bfq_put_queue(__bfqq);
                __bfqq = next;
@@ -5367,49 +5448,55 @@ static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
        bfq_release_process_ref(bfqd, bfqq);
 }
 
-static void bfq_exit_icq_bfqq(struct bfq_io_cq *bic, bool is_sync)
+static void bfq_exit_icq_bfqq(struct bfq_io_cq *bic, bool is_sync,
+                             unsigned int actuator_idx)
 {
-       struct bfq_queue *bfqq = bic_to_bfqq(bic, is_sync);
+       struct bfq_queue *bfqq = bic_to_bfqq(bic, is_sync, actuator_idx);
        struct bfq_data *bfqd;
 
        if (bfqq)
                bfqd = bfqq->bfqd; /* NULL if scheduler already exited */
 
        if (bfqq && bfqd) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&bfqd->lock, flags);
-               bfqq->bic = NULL;
+               bic_set_bfqq(bic, NULL, is_sync, actuator_idx);
                bfq_exit_bfqq(bfqd, bfqq);
-               bic_set_bfqq(bic, NULL, is_sync);
-               spin_unlock_irqrestore(&bfqd->lock, flags);
        }
 }
 
 static void bfq_exit_icq(struct io_cq *icq)
 {
        struct bfq_io_cq *bic = icq_to_bic(icq);
+       struct bfq_data *bfqd = bic_to_bfqd(bic);
+       unsigned long flags;
+       unsigned int act_idx;
+       /*
+        * If bfqd and thus bfqd->num_actuators is not available any
+        * longer, then cycle over all possible per-actuator bfqqs in
+        * next loop. We rely on bic being zeroed on creation, and
+        * therefore on its unused per-actuator fields being NULL.
+        */
+       unsigned int num_actuators = BFQ_MAX_ACTUATORS;
+       struct bfq_iocq_bfqq_data *bfqq_data = bic->bfqq_data;
 
-       if (bic->stable_merge_bfqq) {
-               struct bfq_data *bfqd = bic->stable_merge_bfqq->bfqd;
+       /*
+        * bfqd is NULL if scheduler already exited, and in that case
+        * this is the last time these queues are accessed.
+        */
+       if (bfqd) {
+               spin_lock_irqsave(&bfqd->lock, flags);
+               num_actuators = bfqd->num_actuators;
+       }
 
-               /*
-                * bfqd is NULL if scheduler already exited, and in
-                * that case this is the last time bfqq is accessed.
-                */
-               if (bfqd) {
-                       unsigned long flags;
+       for (act_idx = 0; act_idx < num_actuators; act_idx++) {
+               if (bfqq_data[act_idx].stable_merge_bfqq)
+                       bfq_put_stable_ref(bfqq_data[act_idx].stable_merge_bfqq);
 
-                       spin_lock_irqsave(&bfqd->lock, flags);
-                       bfq_put_stable_ref(bic->stable_merge_bfqq);
-                       spin_unlock_irqrestore(&bfqd->lock, flags);
-               } else {
-                       bfq_put_stable_ref(bic->stable_merge_bfqq);
-               }
+               bfq_exit_icq_bfqq(bic, true, act_idx);
+               bfq_exit_icq_bfqq(bic, false, act_idx);
        }
 
-       bfq_exit_icq_bfqq(bic, true);
-       bfq_exit_icq_bfqq(bic, false);
+       if (bfqd)
+               spin_unlock_irqrestore(&bfqd->lock, flags);
 }
 
 /*
@@ -5441,16 +5528,16 @@ bfq_set_next_ioprio_data(struct bfq_queue *bfqq, struct bfq_io_cq *bic)
                bfqq->new_ioprio_class = task_nice_ioclass(tsk);
                break;
        case IOPRIO_CLASS_RT:
-               bfqq->new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio);
+               bfqq->new_ioprio = IOPRIO_PRIO_LEVEL(bic->ioprio);
                bfqq->new_ioprio_class = IOPRIO_CLASS_RT;
                break;
        case IOPRIO_CLASS_BE:
-               bfqq->new_ioprio = IOPRIO_PRIO_DATA(bic->ioprio);
+               bfqq->new_ioprio = IOPRIO_PRIO_LEVEL(bic->ioprio);
                bfqq->new_ioprio_class = IOPRIO_CLASS_BE;
                break;
        case IOPRIO_CLASS_IDLE:
                bfqq->new_ioprio_class = IOPRIO_CLASS_IDLE;
-               bfqq->new_ioprio = 7;
+               bfqq->new_ioprio = IOPRIO_NR_LEVELS - 1;
                break;
        }
 
@@ -5486,23 +5573,27 @@ static void bfq_check_ioprio_change(struct bfq_io_cq *bic, struct bio *bio)
 
        bic->ioprio = ioprio;
 
-       bfqq = bic_to_bfqq(bic, false);
+       bfqq = bic_to_bfqq(bic, false, bfq_actuator_index(bfqd, bio));
        if (bfqq) {
-               bfq_release_process_ref(bfqd, bfqq);
+               struct bfq_queue *old_bfqq = bfqq;
+
                bfqq = bfq_get_queue(bfqd, bio, false, bic, true);
-               bic_set_bfqq(bic, bfqq, false);
+               bic_set_bfqq(bic, bfqq, false, bfq_actuator_index(bfqd, bio));
+               bfq_release_process_ref(bfqd, old_bfqq);
        }
 
-       bfqq = bic_to_bfqq(bic, true);
+       bfqq = bic_to_bfqq(bic, true, bfq_actuator_index(bfqd, bio));
        if (bfqq)
                bfq_set_next_ioprio_data(bfqq, bic);
 }
 
 static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
-                         struct bfq_io_cq *bic, pid_t pid, int is_sync)
+                         struct bfq_io_cq *bic, pid_t pid, int is_sync,
+                         unsigned int act_idx)
 {
-       u64 now_ns = ktime_get_ns();
+       u64 now_ns = blk_time_get_ns();
 
+       bfqq->actuator_idx = act_idx;
        RB_CLEAR_NODE(&bfqq->entity.rb_node);
        INIT_LIST_HEAD(&bfqq->fifo);
        INIT_HLIST_NODE(&bfqq->burst_list_node);
@@ -5562,22 +5653,24 @@ static void bfq_init_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
 
        /* first request is almost certainly seeky */
        bfqq->seek_history = 1;
+
+       bfqq->decrease_time_jif = jiffies;
 }
 
 static struct bfq_queue **bfq_async_queue_prio(struct bfq_data *bfqd,
                                               struct bfq_group *bfqg,
-                                              int ioprio_class, int ioprio)
+                                              int ioprio_class, int ioprio, int act_idx)
 {
        switch (ioprio_class) {
        case IOPRIO_CLASS_RT:
-               return &bfqg->async_bfqq[0][ioprio];
+               return &bfqg->async_bfqq[0][ioprio][act_idx];
        case IOPRIO_CLASS_NONE:
                ioprio = IOPRIO_BE_NORM;
                fallthrough;
        case IOPRIO_CLASS_BE:
-               return &bfqg->async_bfqq[1][ioprio];
+               return &bfqg->async_bfqq[1][ioprio][act_idx];
        case IOPRIO_CLASS_IDLE:
-               return &bfqg->async_idle_bfqq;
+               return &bfqg->async_idle_bfqq[act_idx];
        default:
                return NULL;
        }
@@ -5588,6 +5681,7 @@ bfq_do_early_stable_merge(struct bfq_data *bfqd, struct bfq_queue *bfqq,
                          struct bfq_io_cq *bic,
                          struct bfq_queue *last_bfqq_created)
 {
+       unsigned int a_idx = last_bfqq_created->actuator_idx;
        struct bfq_queue *new_bfqq =
                bfq_setup_merge(bfqq, last_bfqq_created);
 
@@ -5595,8 +5689,8 @@ bfq_do_early_stable_merge(struct bfq_data *bfqd, struct bfq_queue *bfqq,
                return bfqq;
 
        if (new_bfqq->bic)
-               new_bfqq->bic->stably_merged = true;
-       bic->stably_merged = true;
+               new_bfqq->bic->bfqq_data[a_idx].stably_merged = true;
+       bic->bfqq_data[a_idx].stably_merged = true;
 
        /*
         * Reusing merge functions. This implies that
@@ -5671,9 +5765,13 @@ static struct bfq_queue *bfq_do_or_sched_stable_merge(struct bfq_data *bfqd,
         * it has been set already, but too long ago, then move it
         * forward to bfqq. Finally, move also if bfqq belongs to a
         * different group than last_bfqq_created, or if bfqq has a
-        * different ioprio or ioprio_class. If none of these
-        * conditions holds true, then try an early stable merge or
-        * schedule a delayed stable merge.
+        * different ioprio, ioprio_class or actuator_idx. If none of
+        * these conditions holds true, then try an early stable merge
+        * or schedule a delayed stable merge. As for the condition on
+        * actuator_idx, the reason is that, if queues associated with
+        * different actuators are merged, then control is lost on
+        * each actuator. Therefore some actuator may be
+        * underutilized, and throughput may decrease.
         *
         * A delayed merge is scheduled (instead of performing an
         * early merge), in case bfqq might soon prove to be more
@@ -5691,7 +5789,8 @@ static struct bfq_queue *bfq_do_or_sched_stable_merge(struct bfq_data *bfqd,
                        bfqq->creation_time) ||
                bfqq->entity.parent != last_bfqq_created->entity.parent ||
                bfqq->ioprio != last_bfqq_created->ioprio ||
-               bfqq->ioprio_class != last_bfqq_created->ioprio_class)
+               bfqq->ioprio_class != last_bfqq_created->ioprio_class ||
+               bfqq->actuator_idx != last_bfqq_created->actuator_idx)
                *source_bfqq = bfqq;
        else if (time_after_eq(last_bfqq_created->creation_time +
                                 bfqd->bfq_burst_interval,
@@ -5721,7 +5820,8 @@ static struct bfq_queue *bfq_do_or_sched_stable_merge(struct bfq_data *bfqd,
                        /*
                         * Record the bfqq to merge to.
                         */
-                       bic->stable_merge_bfqq = last_bfqq_created;
+                       bic->bfqq_data[last_bfqq_created->actuator_idx].stable_merge_bfqq =
+                               last_bfqq_created;
                }
        }
 
@@ -5734,7 +5834,7 @@ static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd,
                                       struct bfq_io_cq *bic,
                                       bool respawn)
 {
-       const int ioprio = IOPRIO_PRIO_DATA(bic->ioprio);
+       const int ioprio = IOPRIO_PRIO_LEVEL(bic->ioprio);
        const int ioprio_class = IOPRIO_PRIO_CLASS(bic->ioprio);
        struct bfq_queue **async_bfqq = NULL;
        struct bfq_queue *bfqq;
@@ -5743,7 +5843,8 @@ static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd,
        bfqg = bfq_bio_bfqg(bfqd, bio);
        if (!is_sync) {
                async_bfqq = bfq_async_queue_prio(bfqd, bfqg, ioprio_class,
-                                                 ioprio);
+                                                 ioprio,
+                                                 bfq_actuator_index(bfqd, bio));
                bfqq = *async_bfqq;
                if (bfqq)
                        goto out;
@@ -5755,7 +5856,7 @@ static struct bfq_queue *bfq_get_queue(struct bfq_data *bfqd,
 
        if (bfqq) {
                bfq_init_bfqq(bfqd, bfqq, bic, current->pid,
-                             is_sync);
+                             is_sync, bfq_actuator_index(bfqd, bio));
                bfq_init_entity(&bfqq->entity, bfqg);
                bfq_log_bfqq(bfqd, bfqq, "allocated");
        } else {
@@ -5802,7 +5903,7 @@ static void bfq_update_io_thinktime(struct bfq_data *bfqd,
         */
        if (bfqq->dispatched || bfq_bfqq_busy(bfqq))
                return;
-       elapsed = ktime_get_ns() - bfqq->ttime.last_end_request;
+       elapsed = blk_time_get_ns() - bfqq->ttime.last_end_request;
        elapsed = min_t(u64, elapsed, 2ULL * bfqd->bfq_slice_idle);
 
        ttime->ttime_samples = (7*ttime->ttime_samples + 256) / 8;
@@ -6070,7 +6171,8 @@ static bool __bfq_insert_request(struct bfq_data *bfqd, struct request *rq)
                 * then complete the merge and redirect it to
                 * new_bfqq.
                 */
-               if (bic_to_bfqq(RQ_BIC(rq), 1) == bfqq)
+               if (bic_to_bfqq(RQ_BIC(rq), true,
+                               bfq_actuator_index(bfqd, rq->bio)) == bfqq)
                        bfq_merge_bfqqs(bfqd, RQ_BIC(rq),
                                        bfqq, new_bfqq);
 
@@ -6092,7 +6194,7 @@ static bool __bfq_insert_request(struct bfq_data *bfqd, struct request *rq)
        bfq_add_request(rq);
        idle_timer_disabled = waiting && !bfq_bfqq_wait_request(bfqq);
 
-       rq->fifo_time = ktime_get_ns() + bfqd->bfq_fifo_expire[rq_is_sync(rq)];
+       rq->fifo_time = blk_time_get_ns() + bfqd->bfq_fifo_expire[rq_is_sync(rq)];
        list_add_tail(&rq->queuelist, &bfqq->fifo);
 
        bfq_rq_enqueued(bfqd, bfqq, rq);
@@ -6135,7 +6237,7 @@ static inline void bfq_update_insert_stats(struct request_queue *q,
 static struct bfq_queue *bfq_init_rq(struct request *rq);
 
 static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
-                              bool at_head)
+                              blk_insert_t flags)
 {
        struct request_queue *q = hctx->queue;
        struct bfq_data *bfqd = q->elevator->elevator_data;
@@ -6158,11 +6260,10 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
 
        trace_block_rq_insert(rq);
 
-       if (!bfqq || at_head) {
-               if (at_head)
-                       list_add(&rq->queuelist, &bfqd->dispatch);
-               else
-                       list_add_tail(&rq->queuelist, &bfqd->dispatch);
+       if (flags & BLK_MQ_INSERT_AT_HEAD) {
+               list_add(&rq->queuelist, &bfqd->dispatch);
+       } else if (!bfqq) {
+               list_add_tail(&rq->queuelist, &bfqd->dispatch);
        } else {
                idle_timer_disabled = __bfq_insert_request(bfqd, rq);
                /*
@@ -6192,14 +6293,15 @@ static void bfq_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
 }
 
 static void bfq_insert_requests(struct blk_mq_hw_ctx *hctx,
-                               struct list_head *list, bool at_head)
+                               struct list_head *list,
+                               blk_insert_t flags)
 {
        while (!list_empty(list)) {
                struct request *rq;
 
                rq = list_first_entry(list, struct request, queuelist);
                list_del_init(&rq->queuelist);
-               bfq_insert_request(hctx, rq, at_head);
+               bfq_insert_request(hctx, rq, flags);
        }
 }
 
@@ -6208,7 +6310,7 @@ static void bfq_update_hw_tag(struct bfq_data *bfqd)
        struct bfq_queue *bfqq = bfqd->in_service_queue;
 
        bfqd->max_rq_in_driver = max_t(int, bfqd->max_rq_in_driver,
-                                      bfqd->rq_in_driver);
+                                      bfqd->tot_rq_in_driver);
 
        if (bfqd->hw_tag == 1)
                return;
@@ -6219,7 +6321,7 @@ static void bfq_update_hw_tag(struct bfq_data *bfqd)
         * sum is not exact, as it's not taking into account deactivated
         * requests.
         */
-       if (bfqd->rq_in_driver + bfqd->queued <= BFQ_HW_QUEUE_THRESHOLD)
+       if (bfqd->tot_rq_in_driver + bfqd->queued <= BFQ_HW_QUEUE_THRESHOLD)
                return;
 
        /*
@@ -6230,7 +6332,7 @@ static void bfq_update_hw_tag(struct bfq_data *bfqd)
        if (bfqq && bfq_bfqq_has_short_ttime(bfqq) &&
            bfqq->dispatched + bfqq->queued[0] + bfqq->queued[1] <
            BFQ_HW_QUEUE_THRESHOLD &&
-           bfqd->rq_in_driver < BFQ_HW_QUEUE_THRESHOLD)
+           bfqd->tot_rq_in_driver < BFQ_HW_QUEUE_THRESHOLD)
                return;
 
        if (bfqd->hw_tag_samples++ < BFQ_HW_QUEUE_SAMPLES)
@@ -6251,7 +6353,8 @@ static void bfq_completed_request(struct bfq_queue *bfqq, struct bfq_data *bfqd)
 
        bfq_update_hw_tag(bfqd);
 
-       bfqd->rq_in_driver--;
+       bfqd->rq_in_driver[bfqq->actuator_idx]--;
+       bfqd->tot_rq_in_driver--;
        bfqq->dispatched--;
 
        if (!bfqq->dispatched && !bfq_bfqq_busy(bfqq)) {
@@ -6263,10 +6366,11 @@ static void bfq_completed_request(struct bfq_queue *bfqq, struct bfq_data *bfqd)
                 */
                bfqq->budget_timeout = jiffies;
 
-               bfq_weights_tree_remove(bfqd, bfqq);
+               bfq_del_bfqq_in_groups_with_pending_reqs(bfqq);
+               bfq_weights_tree_remove(bfqq);
        }
 
-       now_ns = ktime_get_ns();
+       now_ns = blk_time_get_ns();
 
        bfqq->ttime.last_end_request = now_ns;
 
@@ -6370,7 +6474,7 @@ static void bfq_completed_request(struct bfq_queue *bfqq, struct bfq_data *bfqd)
                                        BFQQE_NO_MORE_REQUESTS);
        }
 
-       if (!bfqd->rq_in_driver)
+       if (!bfqd->tot_rq_in_driver)
                bfq_schedule_dispatch(bfqd);
 }
 
@@ -6481,7 +6585,7 @@ static void bfq_completed_request(struct bfq_queue *bfqq, struct bfq_data *bfqd)
 static void bfq_update_inject_limit(struct bfq_data *bfqd,
                                    struct bfq_queue *bfqq)
 {
-       u64 tot_time_ns = ktime_get_ns() - bfqd->last_empty_occupied_ns;
+       u64 tot_time_ns = blk_time_get_ns() - bfqd->last_empty_occupied_ns;
        unsigned int old_limit = bfqq->inject_limit;
 
        if (bfqq->last_serv_time_ns > 0 && bfqd->rqs_injected) {
@@ -6501,13 +6605,13 @@ static void bfq_update_inject_limit(struct bfq_data *bfqd,
         * conditions to do it, or we can lower the last base value
         * computed.
         *
-        * NOTE: (bfqd->rq_in_driver == 1) means that there is no I/O
+        * NOTE: (bfqd->tot_rq_in_driver == 1) means that there is no I/O
         * request in flight, because this function is in the code
         * path that handles the completion of a request of bfqq, and,
         * in particular, this function is executed before
-        * bfqd->rq_in_driver is decremented in such a code path.
+        * bfqd->tot_rq_in_driver is decremented in such a code path.
         */
-       if ((bfqq->last_serv_time_ns == 0 && bfqd->rq_in_driver == 1) ||
+       if ((bfqq->last_serv_time_ns == 0 && bfqd->tot_rq_in_driver == 1) ||
            tot_time_ns < bfqq->last_serv_time_ns) {
                if (bfqq->last_serv_time_ns == 0) {
                        /*
@@ -6517,7 +6621,7 @@ static void bfq_update_inject_limit(struct bfq_data *bfqd,
                        bfqq->inject_limit = max_t(unsigned int, 1, old_limit);
                }
                bfqq->last_serv_time_ns = tot_time_ns;
-       } else if (!bfqd->rqs_injected && bfqd->rq_in_driver == 1)
+       } else if (!bfqd->rqs_injected && bfqd->tot_rq_in_driver == 1)
                /*
                 * No I/O injected and no request still in service in
                 * the drive: these are the exact conditions for
@@ -6624,7 +6728,7 @@ bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq)
                return bfqq;
        }
 
-       bic_set_bfqq(bic, NULL, 1);
+       bic_set_bfqq(bic, NULL, true, bfqq->actuator_idx);
 
        bfq_put_cooperator(bfqq);
 
@@ -6638,7 +6742,9 @@ static struct bfq_queue *bfq_get_bfqq_handle_split(struct bfq_data *bfqd,
                                                   bool split, bool is_sync,
                                                   bool *new_queue)
 {
-       struct bfq_queue *bfqq = bic_to_bfqq(bic, is_sync);
+       unsigned int act_idx = bfq_actuator_index(bfqd, bio);
+       struct bfq_queue *bfqq = bic_to_bfqq(bic, is_sync, act_idx);
+       struct bfq_iocq_bfqq_data *bfqq_data = &bic->bfqq_data[act_idx];
 
        if (likely(bfqq && bfqq != &bfqd->oom_bfqq))
                return bfqq;
@@ -6650,14 +6756,14 @@ static struct bfq_queue *bfq_get_bfqq_handle_split(struct bfq_data *bfqd,
                bfq_put_queue(bfqq);
        bfqq = bfq_get_queue(bfqd, bio, is_sync, bic, split);
 
-       bic_set_bfqq(bic, bfqq, is_sync);
+       bic_set_bfqq(bic, bfqq, is_sync, act_idx);
        if (split && is_sync) {
-               if ((bic->was_in_burst_list && bfqd->large_burst) ||
-                   bic->saved_in_large_burst)
+               if ((bfqq_data->was_in_burst_list && bfqd->large_burst) ||
+                   bfqq_data->saved_in_large_burst)
                        bfq_mark_bfqq_in_large_burst(bfqq);
                else {
                        bfq_clear_bfqq_in_large_burst(bfqq);
-                       if (bic->was_in_burst_list)
+                       if (bfqq_data->was_in_burst_list)
                                /*
                                 * If bfqq was in the current
                                 * burst list before being
@@ -6746,19 +6852,20 @@ static struct bfq_queue *bfq_init_rq(struct request *rq)
        struct bfq_queue *bfqq;
        bool new_queue = false;
        bool bfqq_already_existing = false, split = false;
+       unsigned int a_idx = bfq_actuator_index(bfqd, bio);
 
        if (unlikely(!rq->elv.icq))
                return NULL;
 
        /*
-        * Assuming that elv.priv[1] is set only if everything is set
+        * Assuming that RQ_BFQQ(rq) is set only if everything is set
         * for this rq. This holds true, because this function is
         * invoked only for insertion or merging, and, after such
         * events, a request cannot be manipulated any longer before
         * being removed from bfq.
         */
-       if (rq->elv.priv[1])
-               return rq->elv.priv[1];
+       if (RQ_BFQQ(rq))
+               return RQ_BFQQ(rq);
 
        bic = icq_to_bic(rq->elv.icq);
 
@@ -6772,12 +6879,13 @@ static struct bfq_queue *bfq_init_rq(struct request *rq)
        if (likely(!new_queue)) {
                /* If the queue was seeky for too long, break it apart. */
                if (bfq_bfqq_coop(bfqq) && bfq_bfqq_split_coop(bfqq) &&
-                       !bic->stably_merged) {
+                       !bic->bfqq_data[a_idx].stably_merged) {
                        struct bfq_queue *old_bfqq = bfqq;
 
                        /* Update bic before losing reference to bfqq */
                        if (bfq_bfqq_in_large_burst(bfqq))
-                               bic->saved_in_large_burst = true;
+                               bic->bfqq_data[a_idx].saved_in_large_burst =
+                                       true;
 
                        bfqq = bfq_split_bfqq(bic, bfqq);
                        split = true;
@@ -6786,6 +6894,12 @@ static struct bfq_queue *bfq_init_rq(struct request *rq)
                                bfqq = bfq_get_bfqq_handle_split(bfqd, bic, bio,
                                                                 true, is_sync,
                                                                 NULL);
+                               if (unlikely(bfqq == &bfqd->oom_bfqq))
+                                       bfqq_already_existing = true;
+                       } else
+                               bfqq_already_existing = true;
+
+                       if (!bfqq_already_existing) {
                                bfqq->waker_bfqq = old_bfqq->waker_bfqq;
                                bfqq->tentative_waker_bfqq = NULL;
 
@@ -6799,8 +6913,7 @@ static struct bfq_queue *bfq_init_rq(struct request *rq)
                                if (bfqq->waker_bfqq)
                                        hlist_add_head(&bfqq->woken_list_node,
                                                       &bfqq->waker_bfqq->woken_list);
-                       } else
-                               bfqq_already_existing = true;
+                       }
                }
        }
 
@@ -6955,13 +7068,15 @@ static void __bfq_put_async_bfqq(struct bfq_data *bfqd,
  */
 void bfq_put_async_queues(struct bfq_data *bfqd, struct bfq_group *bfqg)
 {
-       int i, j;
+       int i, j, k;
 
-       for (i = 0; i < 2; i++)
-               for (j = 0; j < IOPRIO_NR_LEVELS; j++)
-                       __bfq_put_async_bfqq(bfqd, &bfqg->async_bfqq[i][j]);
+       for (k = 0; k < bfqd->num_actuators; k++) {
+               for (i = 0; i < 2; i++)
+                       for (j = 0; j < IOPRIO_NR_LEVELS; j++)
+                               __bfq_put_async_bfqq(bfqd, &bfqg->async_bfqq[i][j][k]);
 
-       __bfq_put_async_bfqq(bfqd, &bfqg->async_idle_bfqq);
+               __bfq_put_async_bfqq(bfqd, &bfqg->async_idle_bfqq[k]);
+       }
 }
 
 /*
@@ -7024,6 +7139,7 @@ static void bfq_exit_queue(struct elevator_queue *e)
 {
        struct bfq_data *bfqd = e->elevator_data;
        struct bfq_queue *bfqq, *n;
+       unsigned int actuator;
 
        hrtimer_cancel(&bfqd->idle_slice_timer);
 
@@ -7032,13 +7148,17 @@ static void bfq_exit_queue(struct elevator_queue *e)
                bfq_deactivate_bfqq(bfqd, bfqq, false, false);
        spin_unlock_irq(&bfqd->lock);
 
+       for (actuator = 0; actuator < bfqd->num_actuators; actuator++)
+               WARN_ON_ONCE(bfqd->rq_in_driver[actuator]);
+       WARN_ON_ONCE(bfqd->tot_rq_in_driver);
+
        hrtimer_cancel(&bfqd->idle_slice_timer);
 
        /* release oom-queue reference to root group */
        bfqg_and_blkg_put(bfqd->root_group);
 
 #ifdef CONFIG_BFQ_GROUP_IOSCHED
-       blkcg_deactivate_policy(bfqd->queue, &blkcg_policy_bfq);
+       blkcg_deactivate_policy(bfqd->queue->disk, &blkcg_policy_bfq);
 #else
        spin_lock_irq(&bfqd->lock);
        bfq_put_async_queues(bfqd, bfqd->root_group);
@@ -7047,7 +7167,8 @@ static void bfq_exit_queue(struct elevator_queue *e)
 #endif
 
        blk_stat_disable_accounting(bfqd->queue);
-       wbt_enable_default(bfqd->queue);
+       clear_bit(ELEVATOR_FLAG_DISABLE_WBT, &e->flags);
+       wbt_enable_default(bfqd->queue->disk);
 
        kfree(bfqd);
 }
@@ -7072,6 +7193,8 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
 {
        struct bfq_data *bfqd;
        struct elevator_queue *eq;
+       unsigned int i;
+       struct blk_independent_access_ranges *ia_ranges = q->disk->ia_ranges;
 
        eq = elevator_alloc(q, e);
        if (!eq)
@@ -7092,8 +7215,10 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
         * Our fallback bfqq if bfq_find_alloc_queue() runs into OOM issues.
         * Grab a permanent reference to it, so that the normal code flow
         * will not attempt to free it.
+        * Set zero as actuator index: we will pretend that
+        * all I/O requests are for the same actuator.
         */
-       bfq_init_bfqq(bfqd, &bfqd->oom_bfqq, NULL, 1, 0);
+       bfq_init_bfqq(bfqd, &bfqd->oom_bfqq, NULL, 1, 0, 0);
        bfqd->oom_bfqq.ref++;
        bfqd->oom_bfqq.new_ioprio = BFQ_DEFAULT_QUEUE_IOPRIO;
        bfqd->oom_bfqq.new_ioprio_class = IOPRIO_CLASS_BE;
@@ -7112,6 +7237,39 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
 
        bfqd->queue = q;
 
+       bfqd->num_actuators = 1;
+       /*
+        * If the disk supports multiple actuators, copy independent
+        * access ranges from the request queue structure.
+        */
+       spin_lock_irq(&q->queue_lock);
+       if (ia_ranges) {
+               /*
+                * Check if the disk ia_ranges size exceeds the current bfq
+                * actuator limit.
+                */
+               if (ia_ranges->nr_ia_ranges > BFQ_MAX_ACTUATORS) {
+                       pr_crit("nr_ia_ranges higher than act limit: iars=%d, max=%d.\n",
+                               ia_ranges->nr_ia_ranges, BFQ_MAX_ACTUATORS);
+                       pr_crit("Falling back to single actuator mode.\n");
+               } else {
+                       bfqd->num_actuators = ia_ranges->nr_ia_ranges;
+
+                       for (i = 0; i < bfqd->num_actuators; i++) {
+                               bfqd->sector[i] = ia_ranges->ia_range[i].sector;
+                               bfqd->nr_sectors[i] =
+                                       ia_ranges->ia_range[i].nr_sectors;
+                       }
+               }
+       }
+
+       /* Otherwise use single-actuator dev info */
+       if (bfqd->num_actuators == 1) {
+               bfqd->sector[0] = 0;
+               bfqd->nr_sectors[0] = get_capacity(q->disk);
+       }
+       spin_unlock_irq(&q->queue_lock);
+
        INIT_LIST_HEAD(&bfqd->dispatch);
 
        hrtimer_init(&bfqd->idle_slice_timer, CLOCK_MONOTONIC,
@@ -7119,9 +7277,12 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
        bfqd->idle_slice_timer.function = bfq_idle_slice_timer;
 
        bfqd->queue_weights_tree = RB_ROOT_CACHED;
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
        bfqd->num_groups_with_pending_reqs = 0;
+#endif
 
-       INIT_LIST_HEAD(&bfqd->active_list);
+       INIT_LIST_HEAD(&bfqd->active_list[0]);
+       INIT_LIST_HEAD(&bfqd->active_list[1]);
        INIT_LIST_HEAD(&bfqd->idle_list);
        INIT_HLIST_HEAD(&bfqd->burst_list);
 
@@ -7147,7 +7308,6 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
         */
        bfqd->bfq_wr_coeff = 30;
        bfqd->bfq_wr_rt_max_time = msecs_to_jiffies(300);
-       bfqd->bfq_wr_max_time = 0;
        bfqd->bfq_wr_min_idle_time = msecs_to_jiffies(2000);
        bfqd->bfq_wr_min_inter_arr_async = msecs_to_jiffies(500);
        bfqd->bfq_wr_max_softrt_rate = 7000; /*
@@ -7166,6 +7326,9 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
                ref_wr_duration[blk_queue_nonrot(bfqd->queue)];
        bfqd->peak_rate = ref_rate[blk_queue_nonrot(bfqd->queue)] * 2 / 3;
 
+       /* see comments on the definition of next field inside bfq_data */
+       bfqd->actuator_load_threshold = 4;
+
        spin_lock_init(&bfqd->lock);
 
        /*
@@ -7192,7 +7355,8 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
        /* We dispatch from request queue wide instead of hw queue */
        blk_queue_flag_set(QUEUE_FLAG_SQ_SCHED, q);
 
-       wbt_disable_default(q);
+       set_bit(ELEVATOR_FLAG_DISABLE_WBT, &eq->flags);
+       wbt_disable_default(q->disk);
        blk_stat_enable_accounting(q);
 
        return 0;