block: row: Don't notify URGENT if there are un-completed urgent req

When ROW scheduler reports to the block layer that there is an urgent
request pending, the device driver may decide to stop the transmission
of the current request in order to handle the urgent one. If the current
transmitted request is an urgent request - we don't want it to be
stopped.
Due to the above ROW scheduler won't notify of an urgent request if
there are urgent requests in flight.

Change-Id: I2fa186d911b908ec7611682b378b9cdc48637ac7
Signed-off-by: Tatyana Brokhman <tlinder@codeaurora.org>
diff --git a/block/row-iosched.c b/block/row-iosched.c
index 6dd6a03..5c44b11 100644
--- a/block/row-iosched.c
+++ b/block/row-iosched.c
@@ -165,6 +165,8 @@
  * @nr_reqs: nr_reqs[0] holds the number of all READ requests in
  *			scheduler, nr_reqs[1] holds the number of all WRITE
  *			requests in scheduler
+ * @nr_urgent_in_flight: number of uncompleted urgent requests
+ *			(both reads and writes)
  * @cycle_flags:	used for marking unserved queueus
  *
  */
@@ -175,6 +177,7 @@
 
 	struct idling_data		rd_idle_data;
 	unsigned int			nr_reqs[2];
+	unsigned int			nr_urgent_in_flight;
 
 	unsigned int			cycle_flags;
 };
@@ -303,6 +306,7 @@
 		row_log_rowq(rd, rqueue->prio,
 			"added urgent request (total on queue=%d)",
 			rqueue->nr_req);
+		rq->cmd_flags |= REQ_URGENT;
 	} else
 		row_log_rowq(rd, rqueue->prio,
 			"added request (total on queue=%d)", rqueue->nr_req);
@@ -341,6 +345,20 @@
 	return 0;
 }
 
+static void row_completed_req(struct request_queue *q, struct request *rq)
+{
+	struct row_data *rd = q->elevator->elevator_data;
+
+	 if (rq->cmd_flags & REQ_URGENT) {
+		if (!rd->nr_urgent_in_flight) {
+			pr_err("ROW BUG: %s() nr_urgent_in_flight = 0",
+				__func__);
+			return;
+		}
+		rd->nr_urgent_in_flight--;
+	}
+}
+
 /**
  * row_urgent_pending() - Return TRUE if there is an urgent
  *			  request on scheduler
@@ -351,7 +369,20 @@
 	struct row_data *rd = q->elevator->elevator_data;
 	int i;
 
-	for (i = 0; i < ROWQ_MAX_PRIO; i++)
+	if (rd->nr_urgent_in_flight) {
+		row_log(rd->dispatch_queue, "%d urgent requests in flight",
+			rd->nr_urgent_in_flight);
+		return false;
+	}
+
+	for (i = ROWQ_HIGH_PRIO_IDX; i < ROWQ_REG_PRIO_IDX; i++)
+		if (!list_empty(&rd->row_queues[i].fifo)) {
+			row_log_rowq(rd, i,
+				"Urgent (high prio) request pending");
+			return true;
+		}
+
+	for (i = ROWQ_REG_PRIO_IDX; i < ROWQ_MAX_PRIO; i++)
 		if (row_queues_def[i].is_urgent && row_rowq_unserved(rd, i) &&
 		    !list_empty(&rd->row_queues[i].fifo)) {
 			row_log_rowq(rd, i, "Urgent request pending");
@@ -398,6 +429,8 @@
 	row_clear_rowq_unserved(rd, queue_idx);
 	row_log_rowq(rd, queue_idx, " Dispatched request nr_disp = %d",
 		     rd->row_queues[queue_idx].nr_dispatched);
+	if (rq->cmd_flags & REQ_URGENT)
+		rd->nr_urgent_in_flight++;
 }
 
 /*
@@ -642,6 +675,7 @@
 	rdata->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO;
 	rdata->dispatch_queue = q;
 
+	rdata->nr_urgent_in_flight = 0;
 	rdata->nr_reqs[READ] = rdata->nr_reqs[WRITE] = 0;
 
 	return rdata;
@@ -708,6 +742,7 @@
 				rq->rq_disk->disk_name, __func__);
 			q_type = ROWQ_PRIO_REG_WRITE;
 		}
+		rq->cmd_flags |= REQ_URGENT;
 		break;
 	case IOPRIO_CLASS_IDLE:
 		if (data_dir == READ)
@@ -864,6 +899,7 @@
 		.elevator_add_req_fn		= row_add_request,
 		.elevator_reinsert_req_fn	= row_reinsert_req,
 		.elevator_is_urgent_fn		= row_urgent_pending,
+		.elevator_completed_req_fn	= row_completed_req,
 		.elevator_former_req_fn		= elv_rb_former_request,
 		.elevator_latter_req_fn		= elv_rb_latter_request,
 		.elevator_set_req_fn		= row_set_request,