patch-2.3.38 linux/drivers/scsi/scsi.c
Next file: linux/drivers/scsi/scsi.h
Previous file: linux/drivers/scsi/hosts.h
Back to the patch index
Back to the overall index
- Lines: 278
- Date:
Fri Jan 7 11:55:28 2000
- Orig file:
v2.3.37/linux/drivers/scsi/scsi.c
- Orig date:
Tue Jan 4 13:57:17 2000
diff -u --recursive --new-file v2.3.37/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
@@ -1,6 +1,6 @@
/*
* scsi.c Copyright (C) 1992 Drew Eckhardt
- * Copyright (C) 1993, 1994, 1995 Eric Youngdale
+ * Copyright (C) 1993, 1994, 1995, 1999 Eric Youngdale
*
* generic mid-level SCSI driver
* Initial versions: Drew Eckhardt
@@ -13,7 +13,7 @@
* Tommy Thorn <tthorn>
* Thomas Wuensche <tw@fgb1.fgb.mw.tu-muenchen.de>
*
- * Modified by Eric Youngdale eric@andante.jic.com or ericy@gnu.ai.mit.edu to
+ * Modified by Eric Youngdale eric@andante.org or ericy@gnu.ai.mit.edu to
* add scatter-gather, multiple outstanding request, and other
* enhancements.
*
@@ -85,7 +85,6 @@
/*
* Definitions and constants.
*/
-#define INTERNAL_ERROR (panic ("Internal error in file %s, line %d.\n", __FILE__, __LINE__))
/*
* PAGE_SIZE must be a multiple of the sector size (512). True
@@ -153,9 +152,6 @@
*/
unsigned int scsi_logging_level = 0;
-volatile struct Scsi_Host *host_active = NULL;
-
-
const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE] =
{
"Direct-Access ",
@@ -193,14 +189,6 @@
extern void scsi_old_done(Scsi_Cmnd * SCpnt);
extern void scsi_old_times_out(Scsi_Cmnd * SCpnt);
-#define SCSI_BLOCK(DEVICE, HOST) \
- ((HOST->block && host_active && HOST != host_active) \
- || ((HOST)->can_queue && HOST->host_busy >= HOST->can_queue) \
- || ((HOST)->host_blocked) \
- || ((DEVICE) != NULL && (DEVICE)->device_blocked) )
-
-
-
struct dev_info {
const char *vendor;
const char *model;
@@ -497,6 +485,7 @@
* things are quiet.
*/
atomic_inc(&shpnt->host_active);
+ atomic_inc(&SDpnt->device_active);
if (hardcoded == 1) {
Scsi_Device *oldSDpnt = SDpnt;
@@ -578,6 +567,7 @@
* so we know when everything is quiet.
*/
atomic_dec(&shpnt->host_active);
+ atomic_dec(&SDpnt->device_active);
leave:
@@ -1079,16 +1069,10 @@
|| SDpnt == device) {
continue;
}
- for (SCpnt = SDpnt->device_queue;
- SCpnt;
- SCpnt = SCpnt->next) {
- if (SCpnt->request.rq_status != RQ_INACTIVE) {
- break;
- }
- }
- if (SCpnt) {
- break;
- }
+ if( atomic_read(&SDpnt->device_active) != 0)
+ {
+ break;
+ }
}
if (SDpnt) {
/*
@@ -1174,6 +1158,7 @@
SCpnt->request.sem = NULL; /* And no one is waiting for this
* to complete */
atomic_inc(&SCpnt->host->host_active);
+ atomic_inc(&SCpnt->device->device_active);
SCpnt->buffer = NULL;
SCpnt->bufflen = 0;
@@ -1185,6 +1170,7 @@
SCpnt->transfersize = 0; /* No default transfer size */
SCpnt->cmd_len = 0;
+ SCpnt->result = 0;
SCpnt->underflow = 0; /* Do not flag underflow conditions */
SCpnt->resid = 0;
SCpnt->state = SCSI_STATE_INITIALIZING;
@@ -1226,10 +1212,13 @@
spin_lock_irqsave(&device_request_lock, flags);
+ SDpnt = SCpnt->device;
+
SCpnt->request.rq_status = RQ_INACTIVE;
SCpnt->state = SCSI_STATE_UNUSED;
SCpnt->owner = SCSI_OWNER_NOBODY;
atomic_dec(&SCpnt->host->host_active);
+ atomic_dec(&SDpnt->device_active);
SCSI_LOG_MLQUEUE(5, printk("Deactivating command for device %d (active=%d, failed=%d)\n",
SCpnt->target,
@@ -1252,8 +1241,6 @@
up(SCpnt->host->eh_wait);
}
- SDpnt = SCpnt->device;
-
spin_unlock_irqrestore(&device_request_lock, flags);
/*
@@ -1368,6 +1355,7 @@
if (rtn != 0) {
scsi_delete_timer(SCpnt);
scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_HOST_BUSY);
+ SCSI_LOG_MLQUEUE(3, printk("queuecommand : request rejected\n"));
}
} else {
spin_lock_irqsave(&io_request_lock, flags);
@@ -1439,7 +1427,6 @@
int timeout, int retries)
{
struct Scsi_Host *host = SCpnt->host;
- Scsi_Device *device = SCpnt->device;
ASSERT_LOCK(&io_request_lock, 0);
@@ -1694,6 +1681,8 @@
* from being sent to the device, so we shouldn't end up
* with tons of things being sent down that shouldn't be.
*/
+ SCSI_LOG_MLCOMPLETE(3, printk("Command rejected as device queue full, put on ml queue %p\n",
+ SCpnt));
scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_DEVICE_BUSY);
break;
default:
@@ -1758,6 +1747,13 @@
SCpnt->request_bufflen = SCpnt->bufflen;
SCpnt->use_sg = SCpnt->old_use_sg;
SCpnt->cmd_len = SCpnt->old_cmd_len;
+
+ /*
+ * Zero the sense information from the last time we tried
+ * this command.
+ */
+ memset((void *) SCpnt->sense_buffer, 0, sizeof SCpnt->sense_buffer);
+
return scsi_dispatch_cmd(SCpnt);
}
@@ -1781,6 +1777,14 @@
host->host_busy--; /* Indicate that we are free */
device->device_busy--; /* Decrement device usage counter. */
+ /*
+ * Clear the flags which say that the device/host is no longer
+ * capable of accepting new commands. These are set in scsi_queue.c
+ * for both the queue full condition on a device, and for a
+ * host full condition on the host.
+ */
+ host->host_blocked = FALSE;
+ device->device_blocked = FALSE;
/*
* If we have valid sense information, then some kind of recovery
@@ -3428,6 +3432,97 @@
}
#endif /* MODULE */
+
+/*
+ * Function: scsi_get_host_dev()
+ *
+ * Purpose: Create a Scsi_Device that points to the host adapter itself.
+ *
+ * Arguments: SHpnt - Host that needs a Scsi_Device
+ *
+ * Lock status: None assumed.
+ *
+ * Returns: Nothing
+ *
+ * Notes:
+ */
+Scsi_Device * scsi_get_host_dev(struct Scsi_Host * SHpnt)
+{
+ Scsi_Device * SDpnt;
+ Scsi_Cmnd * SCpnt;
+ /*
+ * Attach a single Scsi_Device to the Scsi_Host - this should
+ * be made to look like a "pseudo-device" that points to the
+ * HA itself. For the moment, we include it at the head of
+ * the host_queue itself - I don't think we want to show this
+ * to the HA in select_queue_depths(), as this would probably confuse
+ * matters.
+ * Note - this device is not accessible from any high-level
+ * drivers (including generics), which is probably not
+ * optimal. We can add hooks later to attach
+ */
+ SDpnt = (Scsi_Device *) kmalloc(sizeof(Scsi_Device),
+ GFP_ATOMIC);
+ memset(SDpnt, 0, sizeof(Scsi_Device));
+
+ SDpnt->host = SHpnt;
+ SDpnt->id = SHpnt->this_id;
+ SDpnt->type = -1;
+ SDpnt->queue_depth = 1;
+
+ SCpnt = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC);
+ memset(SCpnt, 0, sizeof(Scsi_Cmnd));
+ SCpnt->host = SHpnt;
+ SCpnt->device = SDpnt;
+ SCpnt->target = SDpnt->id;
+ SCpnt->state = SCSI_STATE_UNUSED;
+ SCpnt->owner = SCSI_OWNER_NOBODY;
+ SCpnt->request.rq_status = RQ_INACTIVE;
+
+ SDpnt->device_queue = SCpnt;
+
+ blk_init_queue(&SDpnt->request_queue, scsi_request_fn);
+ blk_queue_headactive(&SDpnt->request_queue, 0);
+ SDpnt->request_queue.queuedata = (void *) SDpnt;
+
+ SDpnt->online = TRUE;
+
+ /*
+ * Initialize the object that we will use to wait for command blocks.
+ */
+ init_waitqueue_head(&SDpnt->scpnt_wait);
+ return SDpnt;
+}
+
+/*
+ * Function: scsi_free_host_dev()
+ *
+ * Purpose: Create a Scsi_Device that points to the host adapter itself.
+ *
+ * Arguments: SHpnt - Host that needs a Scsi_Device
+ *
+ * Lock status: None assumed.
+ *
+ * Returns: Nothing
+ *
+ * Notes:
+ */
+void scsi_free_host_dev(Scsi_Device * SDpnt)
+{
+ if( SDpnt->id != SDpnt->host->this_id )
+ {
+ panic("Attempt to delete wrong device\n");
+ }
+
+ blk_cleanup_queue(&SDpnt->request_queue);
+
+ /*
+ * We only have a single SCpnt attached to this device. Free
+ * it now.
+ */
+ kfree(SDpnt->device_queue);
+ kfree(SDpnt);
+}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)