block: remove 'q' parameter from kblockd_schedule_*_work()
[linux-2.6-block.git] / drivers / scsi / scsi_lib.c
index 62ec84b42e31cfb77f1aad4e040da30e3a104ef6..91f99f4ce2e830c4683a93354aea564a55521ac2 100644 (file)
@@ -75,28 +75,6 @@ struct kmem_cache *scsi_sdb_cache;
  */
 #define SCSI_QUEUE_DELAY       3
 
-/*
- * Function:   scsi_unprep_request()
- *
- * Purpose:    Remove all preparation done for a request, including its
- *             associated scsi_cmnd, so that it can be requeued.
- *
- * Arguments:  req     - request to unprepare
- *
- * Lock status:        Assumed that no locks are held upon entry.
- *
- * Returns:    Nothing.
- */
-static void scsi_unprep_request(struct request *req)
-{
-       struct scsi_cmnd *cmd = req->special;
-
-       blk_unprep_request(req);
-       req->special = NULL;
-
-       scsi_put_command(cmd);
-}
-
 /**
  * __scsi_queue_insert - private queue insertion
  * @cmd: The SCSI command being requeued
@@ -161,7 +139,7 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy)
         */
        spin_lock_irqsave(q->queue_lock, flags);
        blk_requeue_request(q, cmd->request);
-       kblockd_schedule_work(q, &device->requeue_work);
+       kblockd_schedule_work(&device->requeue_work);
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
@@ -385,29 +363,12 @@ static inline int scsi_host_is_busy(struct Scsi_Host *shost)
        return 0;
 }
 
-/*
- * Function:   scsi_run_queue()
- *
- * Purpose:    Select a proper request queue to serve next
- *
- * Arguments:  q       - last request's queue
- *
- * Returns:     Nothing
- *
- * Notes:      The previous command was completely finished, start
- *             a new one if possible.
- */
-static void scsi_run_queue(struct request_queue *q)
+static void scsi_starved_list_run(struct Scsi_Host *shost)
 {
-       struct scsi_device *sdev = q->queuedata;
-       struct Scsi_Host *shost;
        LIST_HEAD(starved_list);
+       struct scsi_device *sdev;
        unsigned long flags;
 
-       shost = sdev->host;
-       if (scsi_target(sdev)->single_lun)
-               scsi_single_lun_run(sdev);
-
        spin_lock_irqsave(shost->host_lock, flags);
        list_splice_init(&shost->starved_list, &starved_list);
 
@@ -459,6 +420,28 @@ static void scsi_run_queue(struct request_queue *q)
        /* put any unprocessed entries back */
        list_splice(&starved_list, &shost->starved_list);
        spin_unlock_irqrestore(shost->host_lock, flags);
+}
+
+/*
+ * Function:   scsi_run_queue()
+ *
+ * Purpose:    Select a proper request queue to serve next
+ *
+ * Arguments:  q       - last request's queue
+ *
+ * Returns:     Nothing
+ *
+ * Notes:      The previous command was completely finished, start
+ *             a new one if possible.
+ */
+static void scsi_run_queue(struct request_queue *q)
+{
+       struct scsi_device *sdev = q->queuedata;
+
+       if (scsi_target(sdev)->single_lun)
+               scsi_single_lun_run(sdev);
+       if (!list_empty(&sdev->host->starved_list))
+               scsi_starved_list_run(sdev->host);
 
        blk_run_queue(q);
 }
@@ -497,16 +480,10 @@ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)
        struct request *req = cmd->request;
        unsigned long flags;
 
-       /*
-        * We need to hold a reference on the device to avoid the queue being
-        * killed after the unlock and before scsi_run_queue is invoked which
-        * may happen because scsi_unprep_request() puts the command which
-        * releases its reference on the device.
-        */
-       get_device(&sdev->sdev_gendev);
-
        spin_lock_irqsave(q->queue_lock, flags);
-       scsi_unprep_request(req);
+       blk_unprep_request(req);
+       req->special = NULL;
+       scsi_put_command(cmd);
        blk_requeue_request(q, req);
        spin_unlock_irqrestore(q->queue_lock, flags);
 
@@ -520,13 +497,9 @@ void scsi_next_command(struct scsi_cmnd *cmd)
        struct scsi_device *sdev = cmd->device;
        struct request_queue *q = sdev->request_queue;
 
-       /* need to hold a reference on the device before we let go of the cmd */
-       get_device(&sdev->sdev_gendev);
-
        scsi_put_command(cmd);
        scsi_run_queue(q);
 
-       /* ok to remove device now */
        put_device(&sdev->sdev_gendev);
 }
 
@@ -788,6 +761,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY,
              ACTION_DELAYED_RETRY} action;
        char *description = NULL;
+       unsigned long wait_for = (cmd->allowed + 1) * req->timeout;
 
        if (result) {
                sense_valid = scsi_command_normalize_sense(cmd, &sshdr);
@@ -989,6 +963,12 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                action = ACTION_FAIL;
        }
 
+       if (action != ACTION_FAIL &&
+           time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
+               action = ACTION_FAIL;
+               description = "Command timed out";
+       }
+
        switch (action) {
        case ACTION_FAIL:
                /* Give up and fail the remainder of the request */
@@ -1111,6 +1091,7 @@ err_exit:
        scsi_release_buffers(cmd);
        cmd->request->special = NULL;
        scsi_put_command(cmd);
+       put_device(&cmd->device->sdev_gendev);
        return error;
 }
 EXPORT_SYMBOL(scsi_init_io);
@@ -1121,9 +1102,15 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev,
        struct scsi_cmnd *cmd;
 
        if (!req->special) {
+               /* Bail if we can't get a reference to the device */
+               if (!get_device(&sdev->sdev_gendev))
+                       return NULL;
+
                cmd = scsi_get_command(sdev, GFP_ATOMIC);
-               if (unlikely(!cmd))
+               if (unlikely(!cmd)) {
+                       put_device(&sdev->sdev_gendev);
                        return NULL;
+               }
                req->special = cmd;
        } else {
                cmd = req->special;
@@ -1286,6 +1273,7 @@ int scsi_prep_return(struct request_queue *q, struct request *req, int ret)
                        struct scsi_cmnd *cmd = req->special;
                        scsi_release_buffers(cmd);
                        scsi_put_command(cmd);
+                       put_device(&cmd->device->sdev_gendev);
                        req->special = NULL;
                }
                break;
@@ -1543,16 +1531,14 @@ static void scsi_softirq_done(struct request *rq)
  * Lock status: IO request lock assumed to be held when called.
  */
 static void scsi_request_fn(struct request_queue *q)
+       __releases(q->queue_lock)
+       __acquires(q->queue_lock)
 {
        struct scsi_device *sdev = q->queuedata;
        struct Scsi_Host *shost;
        struct scsi_cmnd *cmd;
        struct request *req;
 
-       if(!get_device(&sdev->sdev_gendev))
-               /* We must be tearing the block queue down already */
-               return;
-
        /*
         * To start with, we keep looping until the queue is empty, or until
         * the host is no longer able to accept any more requests.
@@ -1641,7 +1627,7 @@ static void scsi_request_fn(struct request_queue *q)
                        goto out_delay;
        }
 
-       goto out;
+       return;
 
  not_ready:
        spin_unlock_irq(shost->host_lock);
@@ -1660,12 +1646,6 @@ static void scsi_request_fn(struct request_queue *q)
 out_delay:
        if (sdev->device_busy == 0)
                blk_delay_queue(q, SCSI_QUEUE_DELAY);
-out:
-       /* must be careful here...if we trigger the ->remove() function
-        * we cannot be holding the q lock */
-       spin_unlock_irq(q->queue_lock);
-       put_device(&sdev->sdev_gendev);
-       spin_lock_irq(q->queue_lock);
 }
 
 u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost)