Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 17084
b: refs/heads/master
c: 1aea643
h: refs/heads/master
v: v3
  • Loading branch information
Jens Axboe committed Jan 9, 2006
1 parent d611adc commit 789d5c4
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 103 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ff856bad67cb65cb4dc4ef88b808804fc4265782
refs/heads/master: 1aea6434eebd25e532d2e5ddabf2733af4e1ff0b
109 changes: 8 additions & 101 deletions trunk/drivers/scsi/scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
#include "scsi_logging.h"

static void scsi_done(struct scsi_cmnd *cmd);
static int scsi_retry_command(struct scsi_cmnd *cmd);

/*
* Definitions and constants.
Expand Down Expand Up @@ -752,7 +751,7 @@ static void scsi_done(struct scsi_cmnd *cmd)
* isn't running --- used by scsi_times_out */
void __scsi_done(struct scsi_cmnd *cmd)
{
unsigned long flags;
struct request *rq = cmd->request;

/*
* Set the serial numbers back to zero
Expand All @@ -763,71 +762,14 @@ void __scsi_done(struct scsi_cmnd *cmd)
if (cmd->result)
atomic_inc(&cmd->device->ioerr_cnt);

BUG_ON(!rq);

/*
* Next, enqueue the command into the done queue.
* It is a per-CPU queue, so we just disable local interrupts
* and need no spinlock.
* The uptodate/nbytes values don't matter, as we allow partial
* completes and thus will check this in the softirq callback
*/
local_irq_save(flags);
list_add_tail(&cmd->eh_entry, &__get_cpu_var(scsi_done_q));
raise_softirq_irqoff(SCSI_SOFTIRQ);
local_irq_restore(flags);
}

/**
* scsi_softirq - Perform post-interrupt processing of finished SCSI commands.
*
* This is the consumer of the done queue.
*
* This is called with all interrupts enabled. This should reduce
* interrupt latency, stack depth, and reentrancy of the low-level
* drivers.
*/
static void scsi_softirq(struct softirq_action *h)
{
int disposition;
LIST_HEAD(local_q);

local_irq_disable();
list_splice_init(&__get_cpu_var(scsi_done_q), &local_q);
local_irq_enable();

while (!list_empty(&local_q)) {
struct scsi_cmnd *cmd = list_entry(local_q.next,
struct scsi_cmnd, eh_entry);
/* The longest time any command should be outstanding is the
* per command timeout multiplied by the number of retries.
*
* For a typical command, this is 2.5 minutes */
unsigned long wait_for
= cmd->allowed * cmd->timeout_per_command;
list_del_init(&cmd->eh_entry);

disposition = scsi_decide_disposition(cmd);
if (disposition != SUCCESS &&
time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
sdev_printk(KERN_ERR, cmd->device,
"timing out command, waited %lus\n",
wait_for/HZ);
disposition = SUCCESS;
}

scsi_log_completion(cmd, disposition);
switch (disposition) {
case SUCCESS:
scsi_finish_command(cmd);
break;
case NEEDS_RETRY:
scsi_retry_command(cmd);
break;
case ADD_TO_MLQUEUE:
scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
break;
default:
if (!scsi_eh_scmd_add(cmd, 0))
scsi_finish_command(cmd);
}
}
rq->completion_data = cmd;
blk_complete_request(rq);
}

/*
Expand All @@ -840,7 +782,7 @@ static void scsi_softirq(struct softirq_action *h)
* level drivers should not become re-entrant as a result of
* this.
*/
static int scsi_retry_command(struct scsi_cmnd *cmd)
int scsi_retry_command(struct scsi_cmnd *cmd)
{
/*
* Restore the SCSI command state.
Expand Down Expand Up @@ -1273,38 +1215,6 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery)
}
EXPORT_SYMBOL(scsi_device_cancel);

#ifdef CONFIG_HOTPLUG_CPU
static int scsi_cpu_notify(struct notifier_block *self,
unsigned long action, void *hcpu)
{
int cpu = (unsigned long)hcpu;

switch(action) {
case CPU_DEAD:
/* Drain scsi_done_q. */
local_irq_disable();
list_splice_init(&per_cpu(scsi_done_q, cpu),
&__get_cpu_var(scsi_done_q));
raise_softirq_irqoff(SCSI_SOFTIRQ);
local_irq_enable();
break;
default:
break;
}
return NOTIFY_OK;
}

static struct notifier_block __devinitdata scsi_cpu_nb = {
.notifier_call = scsi_cpu_notify,
};

#define register_scsi_cpu() register_cpu_notifier(&scsi_cpu_nb)
#define unregister_scsi_cpu() unregister_cpu_notifier(&scsi_cpu_nb)
#else
#define register_scsi_cpu()
#define unregister_scsi_cpu()
#endif /* CONFIG_HOTPLUG_CPU */

MODULE_DESCRIPTION("SCSI core");
MODULE_LICENSE("GPL");

Expand Down Expand Up @@ -1338,8 +1248,6 @@ static int __init init_scsi(void)
INIT_LIST_HEAD(&per_cpu(scsi_done_q, i));

devfs_mk_dir("scsi");
open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL);
register_scsi_cpu();
printk(KERN_NOTICE "SCSI subsystem initialized\n");
return 0;

Expand Down Expand Up @@ -1367,7 +1275,6 @@ static void __exit exit_scsi(void)
devfs_remove("scsi");
scsi_exit_procfs();
scsi_exit_queue();
unregister_scsi_cpu();
}

subsys_initcall(init_scsi);
Expand Down
36 changes: 36 additions & 0 deletions trunk/drivers/scsi/scsi_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1493,6 +1493,41 @@ static void scsi_kill_request(struct request *req, request_queue_t *q)
__scsi_done(cmd);
}

static void scsi_softirq_done(struct request *rq)
{
struct scsi_cmnd *cmd = rq->completion_data;
unsigned long wait_for = cmd->allowed * cmd->timeout_per_command;
int disposition;

INIT_LIST_HEAD(&cmd->eh_entry);

disposition = scsi_decide_disposition(cmd);
if (disposition != SUCCESS &&
time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) {
sdev_printk(KERN_ERR, cmd->device,
"timing out command, waited %lus\n",
wait_for/HZ);
disposition = SUCCESS;
}

scsi_log_completion(cmd, disposition);

switch (disposition) {
case SUCCESS:
scsi_finish_command(cmd);
break;
case NEEDS_RETRY:
scsi_retry_command(cmd);
break;
case ADD_TO_MLQUEUE:
scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY);
break;
default:
if (!scsi_eh_scmd_add(cmd, 0))
scsi_finish_command(cmd);
}
}

/*
* Function: scsi_request_fn()
*
Expand Down Expand Up @@ -1667,6 +1702,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev)
blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
blk_queue_segment_boundary(q, shost->dma_boundary);
blk_queue_issue_flush_fn(q, scsi_issue_flush_fn);
blk_queue_softirq_done(q, scsi_softirq_done);

if (!shost->use_clustering)
clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/scsi/scsi_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd,
struct scsi_request *sreq);
extern void __scsi_release_request(struct scsi_request *sreq);
extern void __scsi_done(struct scsi_cmnd *cmd);
extern int scsi_retry_command(struct scsi_cmnd *cmd);
#ifdef CONFIG_SCSI_LOGGING
void scsi_log_send(struct scsi_cmnd *cmd);
void scsi_log_completion(struct scsi_cmnd *cmd, int disposition);
Expand Down
1 change: 0 additions & 1 deletion trunk/include/linux/interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,6 @@ enum
NET_TX_SOFTIRQ,
NET_RX_SOFTIRQ,
BLOCK_SOFTIRQ,
SCSI_SOFTIRQ,
TASKLET_SOFTIRQ
};

Expand Down

0 comments on commit 789d5c4

Please sign in to comment.