--- a/block/cfq-iosched.c 2009-11-17 15:47:50.000000000 -0500 +++ b/block/cfq-iosched.c 2009-11-17 15:50:38.000000000 -0500 @@ -234,8 +234,17 @@ struct cfq_data { */ int rq_queued; int hw_tag; - int hw_tag_samples; - int rq_in_driver_peak; + + /* + * hw_tag can be + * -1 => indeterminate, (cfq will behave as if NCQ is present, + * to allow better detection) + * 1 => NCQ is present (hw_tag_est_depth is the estimated max depth) + * 0 => no NCQ + */ + int hw_tag_est_depth; + unsigned int hw_tag_samples; + /* * idle window management @@ -3199,8 +3208,11 @@ static void cfq_update_hw_tag(struct cfq { struct cfq_queue *cfqq = cfqd->active_queue; - if (rq_in_driver(cfqd) > cfqd->rq_in_driver_peak) - cfqd->rq_in_driver_peak = rq_in_driver(cfqd); + if (rq_in_driver(cfqd) > cfqd->hw_tag_est_depth) + cfqd->hw_tag_est_depth = rq_in_driver(cfqd); + + if (cfqd->hw_tag == 1) + return; if (cfqd->rq_queued <= CFQ_HW_QUEUE_MIN && rq_in_driver(cfqd) <= CFQ_HW_QUEUE_MIN) @@ -3219,13 +3231,10 @@ static void cfq_update_hw_tag(struct cfq if (cfqd->hw_tag_samples++ < 50) return; - if (cfqd->rq_in_driver_peak >= CFQ_HW_QUEUE_MIN) + if (cfqd->hw_tag_est_depth >= CFQ_HW_QUEUE_MIN) cfqd->hw_tag = 1; else cfqd->hw_tag = 0; - - cfqd->hw_tag_samples = 0; - cfqd->rq_in_driver_peak = 0; } static void cfq_completed_request(struct request_queue *q, struct request *rq) @@ -3661,7 +3670,7 @@ static void *cfq_init_queue(struct reque cfqd->cfq_slice_idle = cfq_slice_idle; cfqd->cfq_latency = 1; cfqd->cfq_group_idle = 1; - cfqd->hw_tag = 1; + cfqd->hw_tag = -1; cfqd->last_end_sync_rq = jiffies; return cfqd; }