Adds a new request queueing strategy that is more appropriate for some hardware and considerably cleans up queueing of others, too. This patch was inspired by a conversation with Arjan van de Ven at the kernel summit. The typical queueing loop in a driver looks like this: static void request_fn(request_queue_t *q) { controller *c = q->queuedata; while ((rq = elv_next_request(q))) { struct hw_cmd *hw_cmd = get_hw_cmd(c); if (!hw_cmd) break; /* various hw_cmd init stuff */ /* map rq to sg dma table */ entries = blk_rq_map_sg(q, rq, hw_cmd->sg_list); /* remove request from block queue */ blkdev_dequeue_request(rq); /* map the pages in the request for dma */ entries = pci_map_sg(c->pdev, hw_cmd->sg_list, entries, XX); /* add command to controller pending list */ add_hw_cmd(c, hw_cmd); } /* start io */ if (requests queued) start_io_on_queued_requests(c); /* if we couldn't get a hardware command because they are all in flight, mark the queue as full */ if (no_hardware_commands) blk_stop_queue(q); } Here the driver has to define its own queueing loop, and handle details such as removing block requests from the queue and stopping the queue hardware full conditions. The revised model is composed of two queueing functions: one for queueing a request, and one for comitting the queued requests. If we rewrite the queueing loop above for the new model, it looks like this: /* requests have been added to controller pending list, just send them off */ static void commit_fn(request_queue_t *q) { controller *c = q->queuedata; start_io_on_queued_requests(c); } /* queue one request. return 0 if queued, 1 if not */ static int queue_request_fn(request_queue_t *q, struct request *rq) { controller *c = q->queuedata; struct hw_cmd *hw_cmd; hw_cmd = get_hw_cmd(c); if (!hw_cmd) return 1; /* map rq to sg dma table */ entries = blk_rq_map_sg(q, rq, hw_cmd->sg_list); /* map the pages in the request for dma */ entries = pci_map_sg(c->pdev, hw_cmd->sg_list, entries, XX); /* add command to controller pending list */ add_hw_cmd(c, hw_cmd); return 0; } And that's it. Block layer internals take care of the boring details like stopping/starting the queue (it will be restarted on the next released request). Patch converts cpqarray/cciss to use this model, both of those should work fine I believe (not actually tested). Also attempted to fit SCSI into this model, not much care was taken there though. I'd be surprised if it boots. Jens (08/08/2003)