[CPUFREQ] checkpatch cleanups for powernow-k7
[safe/jmp/linux-2.6] / drivers / scsi / scsi_error.c
index 221f31e..ad6a137 100644 (file)
@@ -112,69 +112,8 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
 }
 
 /**
- * scsi_add_timer - Start timeout timer for a single scsi command.
- * @scmd:      scsi command that is about to start running.
- * @timeout:   amount of time to allow this command to run.
- * @complete:  timeout function to call if timer isn't canceled.
- *
- * Notes:
- *    This should be turned into an inline function.  Each scsi command
- *    has its own timer, and as it is added to the queue, we set up the
- *    timer.  When the command completes, we cancel the timer.
- */
-void scsi_add_timer(struct scsi_cmnd *scmd, int timeout,
-                   void (*complete)(struct scsi_cmnd *))
-{
-
-       /*
-        * If the clock was already running for this command, then
-        * first delete the timer.  The timer handling code gets rather
-        * confused if we don't do this.
-        */
-       if (scmd->eh_timeout.function)
-               del_timer(&scmd->eh_timeout);
-
-       scmd->eh_timeout.data = (unsigned long)scmd;
-       scmd->eh_timeout.expires = jiffies + timeout;
-       scmd->eh_timeout.function = (void (*)(unsigned long)) complete;
-
-       SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p, time:"
-                                         " %d, (%p)\n", __FUNCTION__,
-                                         scmd, timeout, complete));
-
-       add_timer(&scmd->eh_timeout);
-}
-
-/**
- * scsi_delete_timer - Delete/cancel timer for a given function.
- * @scmd:      Cmd that we are canceling timer for
- *
- * Notes:
- *     This should be turned into an inline function.
- *
- * Return value:
- *     1 if we were able to detach the timer.  0 if we blew it, and the
- *     timer function has already started to run.
- */
-int scsi_delete_timer(struct scsi_cmnd *scmd)
-{
-       int rtn;
-
-       rtn = del_timer(&scmd->eh_timeout);
-
-       SCSI_LOG_ERROR_RECOVERY(5, printk("%s: scmd: %p,"
-                                        " rtn: %d\n", __FUNCTION__,
-                                        scmd, rtn));
-
-       scmd->eh_timeout.data = (unsigned long)NULL;
-       scmd->eh_timeout.function = NULL;
-
-       return rtn;
-}
-
-/**
  * scsi_times_out - Timeout function for normal scsi commands.
- * @scmd:      Cmd that is timing out.
+ * @req:       request that is timing out.
  *
  * Notes:
  *     We do not need to lock this.  There is the potential for a race
@@ -182,36 +121,25 @@ int scsi_delete_timer(struct scsi_cmnd *scmd)
  *     normal completion function determines that the timer has already
  *     fired, then it mustn't do anything.
  */
-void scsi_times_out(struct scsi_cmnd *scmd)
+enum blk_eh_timer_return scsi_times_out(struct request *req)
 {
-       enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
+       struct scsi_cmnd *scmd = req->special;
+       enum blk_eh_timer_return rtn = BLK_EH_NOT_HANDLED;
 
        scsi_log_completion(scmd, TIMEOUT_ERROR);
 
        if (scmd->device->host->transportt->eh_timed_out)
-               eh_timed_out = scmd->device->host->transportt->eh_timed_out;
+               rtn = scmd->device->host->transportt->eh_timed_out(scmd);
        else if (scmd->device->host->hostt->eh_timed_out)
-               eh_timed_out = scmd->device->host->hostt->eh_timed_out;
-       else
-               eh_timed_out = NULL;
-
-       if (eh_timed_out)
-               switch (eh_timed_out(scmd)) {
-               case EH_HANDLED:
-                       __scsi_done(scmd);
-                       return;
-               case EH_RESET_TIMER:
-                       scsi_add_timer(scmd, scmd->timeout_per_command,
-                                      scsi_times_out);
-                       return;
-               case EH_NOT_HANDLED:
-                       break;
-               }
+               rtn = scmd->device->host->hostt->eh_timed_out(scmd);
 
-       if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
+       if (unlikely(rtn == BLK_EH_NOT_HANDLED &&
+                    !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
                scmd->result |= DID_TIME_OUT << 16;
-               __scsi_done(scmd);
+               rtn = BLK_EH_HANDLED;
        }
+
+       return rtn;
 }
 
 /**
@@ -233,7 +161,7 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev)
 
        online = scsi_device_online(sdev);
 
-       SCSI_LOG_ERROR_RECOVERY(5, printk("%s: rtn: %d\n", __FUNCTION__,
+       SCSI_LOG_ERROR_RECOVERY(5, printk("%s: rtn: %d\n", __func__,
                                          online));
 
        return online;
@@ -271,7 +199,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
                        SCSI_LOG_ERROR_RECOVERY(3,
                                sdev_printk(KERN_INFO, sdev,
                                            "%s: cmds failed: %d, cancel: %d\n",
-                                           __FUNCTION__, cmd_failed,
+                                           __func__, cmd_failed,
                                            cmd_cancel));
                        cmd_cancel = 0;
                        cmd_failed = 0;
@@ -298,6 +226,7 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost,
  */
 static int scsi_check_sense(struct scsi_cmnd *scmd)
 {
+       struct scsi_device *sdev = scmd->device;
        struct scsi_sense_hdr sshdr;
 
        if (! scsi_command_normalize_sense(scmd, &sshdr))
@@ -306,6 +235,16 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
        if (scsi_sense_is_deferred(&sshdr))
                return NEEDS_RETRY;
 
+       if (sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh &&
+                       sdev->scsi_dh_data->scsi_dh->check_sense) {
+               int rc;
+
+               rc = sdev->scsi_dh_data->scsi_dh->check_sense(sdev, &sshdr);
+               if (rc != SCSI_RETURN_NOT_HANDLED)
+                       return rc;
+               /* handler does not care. Drop down to default handling */
+       }
+
        /*
         * Previous logic looked for FILEMARK, EOM or ILI which are
         * mainly associated with tapes and returned SUCCESS.
@@ -333,6 +272,9 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
                return /* soft_error */ SUCCESS;
 
        case ABORTED_COMMAND:
+               if (sshdr.asc == 0x10) /* DIF */
+                       return SUCCESS;
+
                return NEEDS_RETRY;
        case NOT_READY:
        case UNIT_ATTENTION:
@@ -377,7 +319,7 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
 
        case HARDWARE_ERROR:
                if (scmd->device->retry_hwerror)
-                       return NEEDS_RETRY;
+                       return ADD_TO_MLQUEUE;
                else
                        return SUCCESS;
 
@@ -459,7 +401,7 @@ static void scsi_eh_done(struct scsi_cmnd *scmd)
 
        SCSI_LOG_ERROR_RECOVERY(3,
                printk("%s scmd: %p result: %x\n",
-                       __FUNCTION__, scmd, scmd->result));
+                       __func__, scmd, scmd->result));
 
        eh_action = scmd->device->host->eh_action;
        if (eh_action)
@@ -476,7 +418,7 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd)
        int rtn;
 
        SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n",
-                                         __FUNCTION__));
+                                         __func__));
 
        if (!scmd->device->host->hostt->eh_host_reset_handler)
                return FAILED;
@@ -505,7 +447,7 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd)
        int rtn;
 
        SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n",
-                                         __FUNCTION__));
+                                         __func__));
 
        if (!scmd->device->host->hostt->eh_bus_reset_handler)
                return FAILED;
@@ -626,7 +568,7 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
  * @scmd:       SCSI command structure to hijack
  * @ses:        structure to save restore information
  * @cmnd:       CDB to send. Can be NULL if no new cmnd is needed
- * @cmnd_size:  size in bytes of @cmnd
+ * @cmnd_size:  size in bytes of @cmnd (must be <= BLK_MAX_CDB)
  * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored)
  *
  * This function is used to save a scsi command information before re-execution
@@ -648,12 +590,17 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
         * command.
         */
        ses->cmd_len = scmd->cmd_len;
-       memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd));
+       ses->cmnd = scmd->cmnd;
        ses->data_direction = scmd->sc_data_direction;
        ses->sdb = scmd->sdb;
        ses->next_rq = scmd->request->next_rq;
        ses->result = scmd->result;
+       ses->underflow = scmd->underflow;
+       ses->prot_op = scmd->prot_op;
 
+       scmd->prot_op = SCSI_PROT_NORMAL;
+       scmd->cmnd = ses->eh_cmnd;
+       memset(scmd->cmnd, 0, BLK_MAX_CDB);
        memset(&scmd->sdb, 0, sizeof(scmd->sdb));
        scmd->request->next_rq = NULL;
 
@@ -665,14 +612,13 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses,
                scmd->sdb.table.sgl = &ses->sense_sgl;
                scmd->sc_data_direction = DMA_FROM_DEVICE;
                scmd->sdb.table.nents = 1;
-               memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
                scmd->cmnd[0] = REQUEST_SENSE;
                scmd->cmnd[4] = scmd->sdb.length;
                scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
        } else {
                scmd->sc_data_direction = DMA_NONE;
                if (cmnd) {
-                       memset(scmd->cmnd, 0, sizeof(scmd->cmnd));
+                       BUG_ON(cmnd_size > BLK_MAX_CDB);
                        memcpy(scmd->cmnd, cmnd, cmnd_size);
                        scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
                }
@@ -705,11 +651,13 @@ void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses)
         * Restore original data
         */
        scmd->cmd_len = ses->cmd_len;
-       memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd));
+       scmd->cmnd = ses->cmnd;
        scmd->sc_data_direction = ses->data_direction;
        scmd->sdb = ses->sdb;
        scmd->request->next_rq = ses->next_rq;
        scmd->result = ses->result;
+       scmd->underflow = ses->underflow;
+       scmd->prot_op = ses->prot_op;
 }
 EXPORT_SYMBOL(scsi_eh_restore_cmnd);
 
@@ -754,7 +702,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
 
        SCSI_LOG_ERROR_RECOVERY(3,
                printk("%s: scmd: %p, timeleft: %ld\n",
-                       __FUNCTION__, scmd, timeleft));
+                       __func__, scmd, timeleft));
 
        /*
         * If there is time left scsi_eh_done got called, and we will
@@ -766,7 +714,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd,
                rtn = scsi_eh_completed_normally(scmd);
                SCSI_LOG_ERROR_RECOVERY(3,
                        printk("%s: scsi_eh_completed_normally %x\n",
-                              __FUNCTION__, rtn));
+                              __func__, rtn));
 
                switch (rtn) {
                case SUCCESS:
@@ -901,7 +849,7 @@ retry_tur:
        rtn = scsi_send_eh_cmnd(scmd, tur_command, 6, SENSE_TIMEOUT, 0);
 
        SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n",
-               __FUNCTION__, scmd, rtn));
+               __func__, scmd, rtn));
 
        switch (rtn) {
        case NEEDS_RETRY:
@@ -973,8 +921,7 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
                int i, rtn = NEEDS_RETRY;
 
                for (i = 0; rtn == NEEDS_RETRY && i < 2; i++)
-                       rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
-                                               scmd->device->timeout, 0);
+                       rtn = scsi_send_eh_cmnd(scmd, stu_command, 6, scmd->device->request_queue->rq_timeout, 0);
 
                if (rtn == SUCCESS)
                        return 0;
@@ -1106,10 +1053,10 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
                                struct list_head *done_q)
 {
        struct scsi_cmnd *scmd, *tgtr_scmd, *next;
-       unsigned int id;
+       unsigned int id = 0;
        int rtn;
 
-       for (id = 0; id <= shost->max_id; id++) {
+       do {
                tgtr_scmd = NULL;
                list_for_each_entry(scmd, work_q, eh_entry) {
                        if (id == scmd_id(scmd)) {
@@ -1117,8 +1064,18 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
                                break;
                        }
                }
+               if (!tgtr_scmd) {
+                       /* not one exactly equal; find the next highest */
+                       list_for_each_entry(scmd, work_q, eh_entry) {
+                               if (scmd_id(scmd) > id &&
+                                   (!tgtr_scmd ||
+                                    scmd_id(tgtr_scmd) > scmd_id(scmd)))
+                                               tgtr_scmd = scmd;
+                       }
+               }
                if (!tgtr_scmd)
-                       continue;
+                       /* no more commands, that's it */
+                       break;
 
                SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset "
                                                  "to target %d\n",
@@ -1137,7 +1094,8 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost,
                                                          " failed target: "
                                                          "%d\n",
                                                          current->comm, id));
-       }
+               id++;
+       } while(id != 0);
 
        return list_empty(work_q);
 }
@@ -1260,6 +1218,40 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q,
 }
 
 /**
+ * scsi_noretry_cmd - determinte if command should be failed fast
+ * @scmd:      SCSI cmd to examine.
+ */
+int scsi_noretry_cmd(struct scsi_cmnd *scmd)
+{
+       switch (host_byte(scmd->result)) {
+       case DID_OK:
+               break;
+       case DID_BUS_BUSY:
+               return blk_failfast_transport(scmd->request);
+       case DID_PARITY:
+               return blk_failfast_dev(scmd->request);
+       case DID_ERROR:
+               if (msg_byte(scmd->result) == COMMAND_COMPLETE &&
+                   status_byte(scmd->result) == RESERVATION_CONFLICT)
+                       return 0;
+               /* fall through */
+       case DID_SOFT_ERROR:
+               return blk_failfast_driver(scmd->request);
+       }
+
+       switch (status_byte(scmd->result)) {
+       case CHECK_CONDITION:
+               /*
+                * assume caller has checked sense and determinted
+                * the check condition was retryable.
+                */
+               return blk_failfast_dev(scmd->request);
+       }
+
+       return 0;
+}
+
+/**
  * scsi_decide_disposition - Disposition a cmd on return from LLD.
  * @scmd:      SCSI cmd to examine.
  *
@@ -1284,7 +1276,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
        if (!scsi_device_online(scmd->device)) {
                SCSI_LOG_ERROR_RECOVERY(5, printk("%s: device offline - report"
                                                  " as SUCCESS\n",
-                                                 __FUNCTION__));
+                                                 __func__));
                return SUCCESS;
        }
 
@@ -1331,7 +1323,21 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
 
        case DID_REQUEUE:
                return ADD_TO_MLQUEUE;
-
+       case DID_TRANSPORT_DISRUPTED:
+               /*
+                * LLD/transport was disrupted during processing of the IO.
+                * The transport class is now blocked/blocking,
+                * and the transport will decide what to do with the IO
+                * based on its timers and recovery capablilities if
+                * there are enough retries.
+                */
+               goto maybe_retry;
+       case DID_TRANSPORT_FAILFAST:
+               /*
+                * The transport decided to failfast the IO (most likely
+                * the fast io fail tmo fired), so send IO directly upwards.
+                */
+               return SUCCESS;
        case DID_ERROR:
                if (msg_byte(scmd->result) == COMMAND_COMPLETE &&
                    status_byte(scmd->result) == RESERVATION_CONFLICT)
@@ -1388,8 +1394,9 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
                return ADD_TO_MLQUEUE;
        case GOOD:
        case COMMAND_TERMINATED:
-       case TASK_ABORTED:
                return SUCCESS;
+       case TASK_ABORTED:
+               goto maybe_retry;
        case CHECK_CONDITION:
                rtn = scsi_check_sense(scmd);
                if (rtn == NEEDS_RETRY)
@@ -1424,7 +1431,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
         * even if the request is marked fast fail, we still requeue
         * for queue congestion conditions (QUEUE_FULL or BUSY) */
        if ((++scmd->retries) <= scmd->allowed
-           && !blk_noretry_request(scmd->request)) {
+           && !scsi_noretry_cmd(scmd)) {
                return NEEDS_RETRY;
        } else {
                /*
@@ -1499,7 +1506,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
         * ioctls to queued block devices.
         */
        SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n",
-                                         __FUNCTION__));
+                                         __func__));
 
        spin_lock_irqsave(shost->host_lock, flags);
        if (scsi_host_set_state(shost, SHOST_RUNNING))
@@ -1549,7 +1556,7 @@ void scsi_eh_flush_done_q(struct list_head *done_q)
        list_for_each_entry_safe(scmd, next, done_q, eh_entry) {
                list_del_init(&scmd->eh_entry);
                if (scsi_device_online(scmd->device) &&
-                   !blk_noretry_request(scmd->request) &&
+                   !scsi_noretry_cmd(scmd) &&
                    (++scmd->retries <= scmd->allowed)) {
                        SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush"
                                                          " retry cmd: %p\n",
@@ -1631,7 +1638,7 @@ int scsi_error_handler(void *data)
         * We use TASK_INTERRUPTIBLE so that the thread is not
         * counted against the load average as a running process.
         * We never actually get interrupted because kthread_run
-        * disables singal delivery for the created thread.
+        * disables signal delivery for the created thread.
         */
        set_current_state(TASK_INTERRUPTIBLE);
        while (!kthread_should_stop()) {
@@ -1771,11 +1778,11 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
        unsigned long flags;
        int rtn;
 
+       blk_rq_init(NULL, &req);
        scmd->request = &req;
-       memset(&scmd->eh_timeout, 0, sizeof(scmd->eh_timeout));
 
-       memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd));
-    
+       scmd->cmnd = req.cmd;
+
        scmd->scsi_done         = scsi_reset_provider_done_command;
        memset(&scmd->sdb, 0, sizeof(scmd->sdb));
 
@@ -1783,8 +1790,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
 
        scmd->sc_data_direction         = DMA_BIDIRECTIONAL;
 
-       init_timer(&scmd->eh_timeout);
-
        spin_lock_irqsave(shost->host_lock, flags);
        shost->tmf_in_progress = 1;
        spin_unlock_irqrestore(shost->host_lock, flags);
@@ -1822,7 +1827,7 @@ scsi_reset_provider(struct scsi_device *dev, int flag)
         */
        SCSI_LOG_ERROR_RECOVERY(3,
                printk("%s: waking up host to restart after TMF\n",
-               __FUNCTION__));
+               __func__));
 
        wake_up(&shost->host_wait);