patch-1.3.35 linux/drivers/scsi/scsi.c
Next file: linux/drivers/scsi/scsi_ioctl.c
Previous file: linux/drivers/scsi/eata_dma_proc.c
Back to the patch index
Back to the overall index
- Lines: 618
- Date:
Mon Oct 16 08:57:43 1995
- Orig file:
v1.3.34/linux/drivers/scsi/scsi.c
- Orig date:
Fri Oct 13 14:44:33 1995
diff -u --recursive --new-file v1.3.34/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
@@ -68,6 +68,13 @@
static void print_inquiry(unsigned char *data);
static void scsi_times_out (Scsi_Cmnd * SCpnt, int pid);
+static unsigned char * dma_malloc_freelist = NULL;
+static int scsi_need_isa_bounce_buffers;
+static unsigned int dma_sectors = 0;
+unsigned int dma_free_sectors = 0;
+unsigned int need_isa_buffer = 0;
+static unsigned char ** dma_malloc_pages = NULL;
+
static int time_start;
static int time_elapsed;
static volatile struct Scsi_Host * host_active = NULL;
@@ -102,6 +109,7 @@
unsigned long scsi_pid = 0;
static unsigned char generic_sense[6] = {REQUEST_SENSE, 0,0,0, 255, 0};
+static void resize_dma_pool(void);
/* This variable is merely a hook so that we can debug the kernel with gdb. */
Scsi_Cmnd * last_cmnd = NULL;
@@ -192,10 +200,8 @@
/*
* This is what was previously known as the blacklist. The concept
- * has been expanded so that we can specify other
- * The blacklist is used to determine which devices cannot tolerate a
- * lun probe because of buggy firmware. Far too many for my liking,
- * which is why the default is now for there to be no lun scan.
+ * has been expanded so that we can specify other types of things we
+ * need to be aware of.
*/
static struct dev_info device_list[] =
{
@@ -394,7 +400,7 @@
if(scsi_devices) while(SDtail->next) SDtail = SDtail->next;
/* Make sure we have something that is valid for DMA purposes */
- scsi_result = ((current->pid == 0 || !shpnt->unchecked_isa_dma)
+ scsi_result = ((!dma_malloc_freelist || !shpnt->unchecked_isa_dma)
? &scsi_result0[0] : scsi_malloc(512));
if(scsi_result == NULL) {
@@ -455,33 +461,19 @@
SCpnt->lun = SDpnt->lun;
SCpnt->channel = SDpnt->channel;
- /* Used for mutex if loading devices after boot */
- SCpnt->request.sem = NULL;
- SCpnt->request.rq_status = RQ_SCSI_BUSY;
-
- scsi_do_cmd (SCpnt, (void *) scsi_cmd,
- (void *) scsi_result,
- 256, scan_scsis_done, SCSI_TIMEOUT + 4 * HZ, 5);
-
- /*
- * Wait for command to finish. Use simple wait if we are
- * booting, else do it right and use a mutex
- */
-
- if (current->pid == 0)
- while (SCpnt->request.rq_status != RQ_SCSI_DONE)
- barrier();
- else if (SCpnt->request.rq_status != RQ_SCSI_DONE) {
+ {
+ /*
+ * Do the actual command, and wait for it to finish
+ */
struct semaphore sem = MUTEX_LOCKED;
-
SCpnt->request.sem = &sem;
+ SCpnt->request.rq_status = RQ_SCSI_BUSY;
+ scsi_do_cmd (SCpnt, (void *) scsi_cmd,
+ (void *) scsi_result,
+ 256, scan_scsis_done, SCSI_TIMEOUT + 4 * HZ, 5);
down(&sem);
-
- /* Hmm.. Have to ask about this one */
- while (SCpnt->request.rq_status != RQ_SCSI_DONE)
- schedule();
}
-
+
#if defined(DEBUG) || defined(DEBUG_INIT)
printk("scsi: scan SCSIS id %d lun %d\n", dev, lun);
printk("scsi: return code %08x\n", SCpnt->result);
@@ -515,25 +507,16 @@
scsi_cmd[4] = 255;
scsi_cmd[5] = 0;
- SCpnt->request.rq_status = RQ_SCSI_BUSY;
SCpnt->cmd_len = 0;
- scsi_do_cmd (SCpnt, (void *) scsi_cmd,
- (void *) scsi_result,
- 256, scan_scsis_done, SCSI_TIMEOUT, 3);
-
- if (current->pid == 0)
- while (SCpnt->request.rq_status != RQ_SCSI_DONE)
- barrier();
- else if (SCpnt->request.rq_status != RQ_SCSI_DONE) {
+ {
struct semaphore sem = MUTEX_LOCKED;
-
SCpnt->request.sem = &sem;
+ SCpnt->request.rq_status = RQ_SCSI_BUSY;
+ scsi_do_cmd (SCpnt, (void *) scsi_cmd,
+ (void *) scsi_result,
+ 256, scan_scsis_done, SCSI_TIMEOUT, 3);
down(&sem);
-
- /* Hmm.. Have to ask about this one */
- while (SCpnt->request.rq_status != RQ_SCSI_DONE)
- schedule();
}
the_result = SCpnt->result;
@@ -689,24 +672,15 @@
scsi_cmd[4] = 0x2a;
scsi_cmd[5] = 0;
- SCpnt->request.rq_status = RQ_SCSI_BUSY;
SCpnt->cmd_len = 0;
-
- scsi_do_cmd (SCpnt, (void *) scsi_cmd,
- (void *) scsi_result, 0x2a,
- scan_scsis_done, SCSI_TIMEOUT, 3);
-
- if (current->pid == 0)
- while (SCpnt->request.rq_status != RQ_SCSI_DONE);
- else if (SCpnt->request.rq_status != RQ_SCSI_DONE) {
+ {
struct semaphore sem = MUTEX_LOCKED;
-
+ SCpnt->request.rq_status = RQ_SCSI_BUSY;
SCpnt->request.sem = &sem;
+ scsi_do_cmd (SCpnt, (void *) scsi_cmd,
+ (void *) scsi_result, 0x2a,
+ scan_scsis_done, SCSI_TIMEOUT, 3);
down(&sem);
-
- /* Hmm.. Have to ask about this one */
- while (SCpnt->request.rq_status != RQ_SCSI_DONE)
- schedule();
}
}
/* Add this device to the linked list at the end */
@@ -1324,38 +1298,6 @@
#endif
}
-
-
-/*
- * The scsi_done() function disables the timeout timer for the scsi host,
- * marks the host as not busy, and calls the user specified completion
- * function for that host's current command.
- */
-
-static void reset (Scsi_Cmnd * SCpnt)
-{
-#ifdef DEBUG
- printk("scsi: reset(%d, channel %d)\n", SCpnt->host->host_no,
- SCpnt->channel);
-#endif
-
- SCpnt->flags |= (WAS_RESET | IS_RESETTING);
- scsi_reset(SCpnt, FALSE);
-
-#ifdef DEBUG
- printk("performing request sense\n");
-#endif
-
-#if 0 /* FIXME - remove this when done */
- if(SCpnt->flags & NEEDS_JUMPSTART) {
- SCpnt->flags &= ~NEEDS_JUMPSTART;
- scsi_request_sense (SCpnt);
- }
-#endif
-}
-
-
-
static int check_sense (Scsi_Cmnd * SCpnt)
{
/* If there is no sense information, request it. If we have already
@@ -1493,7 +1435,7 @@
" failed, performing reset.\n",
SCpnt->host->host_no, SCpnt->channel, SCpnt->target,
SCpnt->lun);
- reset(SCpnt);
+ scsi_reset(SCpnt, FALSE);
return;
}
else
@@ -1594,7 +1536,7 @@
case RESERVATION_CONFLICT:
printk("scsi%d, channel %d : RESERVATION CONFLICT performing"
" reset.\n", SCpnt->host->host_no, SCpnt->channel);
- reset(SCpnt);
+ scsi_reset(SCpnt, FALSE);
return;
#if 0
exit = DRIVER_SOFT | SUGGEST_ABORT;
@@ -1709,7 +1651,7 @@
{
printk("scsi%d channel %d : resetting for second half of retries.\n",
SCpnt->host->host_no, SCpnt->channel);
- reset(SCpnt);
+ scsi_reset(SCpnt, FALSE);
break;
}
@@ -1928,13 +1870,16 @@
*/
SCpnt1 = host->host_queue;
while(SCpnt1) {
- if( SCpnt->request.rq_status != RQ_INACTIVE
- && (SCpnt->flags & WAS_RESET) == 0 )
+ if( SCpnt1->request.rq_status != RQ_INACTIVE
+ && (SCpnt1->flags & (WAS_RESET | IS_RESETTING)) == 0 )
+ {
break;
+ }
SCpnt1 = SCpnt1->next;
}
- if( SCpnt1 == NULL )
+ if( SCpnt1 == NULL ) {
SCpnt->host->suggest_bus_reset = TRUE;
+ }
/*
@@ -1942,8 +1887,9 @@
* definitely request it. This usually occurs because a
* BUS_DEVICE_RESET times out.
*/
- if( bus_reset_flag )
+ if( bus_reset_flag ) {
SCpnt->host->suggest_bus_reset = TRUE;
+ }
while (1) {
save_flags(flags);
@@ -1970,7 +1916,7 @@
!(SCpnt1->internal_timeout & IN_ABORT))
scsi_abort(SCpnt1, DID_RESET, SCpnt->pid);
#endif
- SCpnt1->flags |= IS_RESETTING;
+ SCpnt1->flags |= (WAS_RESET | IS_RESETTING);
}
SCpnt1 = SCpnt1->next;
}
@@ -1984,6 +1930,7 @@
if (!host->block) host->host_busy++;
restore_flags(flags);
host->last_reset = jiffies;
+ SCpnt->flags |= (WAS_RESET | IS_RESETTING);
temp = host->hostt->reset(SCpnt);
host->last_reset = jiffies;
if (!host->block) host->host_busy--;
@@ -2176,13 +2123,6 @@
return oldto;
}
-
-static unsigned char * dma_malloc_freelist = NULL;
-static int scsi_need_isa_bounce_buffers;
-static unsigned int dma_sectors = 0;
-unsigned int dma_free_sectors = 0;
-unsigned int need_isa_buffer = 0;
-static unsigned char ** dma_malloc_pages = NULL;
#define MALLOC_PAGEBITS 12
static int scsi_register_host(Scsi_Host_Template *);
@@ -2341,11 +2281,9 @@
int scsi_dev_init(void)
{
- struct Scsi_Host * host = NULL;
Scsi_Device * SDpnt;
struct Scsi_Host * shpnt;
struct Scsi_Device_Template * sdtpnt;
- int i;
#ifdef FOO_ON_YOU
return;
#endif
@@ -2391,50 +2329,13 @@
}
- if (scsi_devicelist)
- dma_sectors = 16; /* Base value we use */
-
- if (high_memory-1 > ISA_DMA_THRESHOLD)
- scsi_need_isa_bounce_buffers = 1;
- else
- scsi_need_isa_bounce_buffers = 0;
-
- for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) {
- host = SDpnt->host;
-
- if(SDpnt->type != TYPE_TAPE)
- dma_sectors += ((host->sg_tablesize *
- sizeof(struct scatterlist) + 511) >> 9) *
- host->cmd_per_lun;
-
- if(host->unchecked_isa_dma &&
- high_memory - 1 > ISA_DMA_THRESHOLD &&
- SDpnt->type != TYPE_TAPE) {
- dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize *
- host->cmd_per_lun;
- need_isa_buffer++;
- }
- }
-
- dma_sectors = (dma_sectors + 15) & 0xfff0;
- dma_free_sectors = dma_sectors; /* This must be a multiple of 16 */
-
- if (dma_sectors)
- {
- dma_malloc_freelist = (unsigned char *)
- scsi_init_malloc(dma_sectors >> 3, GFP_ATOMIC);
- memset(dma_malloc_freelist, 0, dma_sectors >> 3);
-
- dma_malloc_pages = (unsigned char **)
- scsi_init_malloc(dma_sectors >> 1, GFP_ATOMIC);
- memset(dma_malloc_pages, 0, dma_sectors >> 1);
+ /*
+ * This should build the DMA pool.
+ */
+ resize_dma_pool();
- for(i=0; i< dma_sectors >> 3; i++)
- dma_malloc_pages[i] = (unsigned char *)
- scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
-
- }
- /* OK, now we finish the initialization by doing spin-up, read
+ /*
+ * OK, now we finish the initialization by doing spin-up, read
* capacity, etc, etc
*/
for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
@@ -2576,6 +2477,126 @@
}
#endif
+/*
+ * Go through the device list and recompute the most appropriate size
+ * for the dma pool. Then grab more memory (as required).
+ */
+static void resize_dma_pool(void)
+{
+ int i;
+ struct Scsi_Host * shpnt;
+ struct Scsi_Host * host = NULL;
+ Scsi_Device * SDpnt;
+ unsigned long flags;
+ unsigned char * new_dma_malloc_freelist = NULL;
+ unsigned int new_dma_sectors = 0;
+ unsigned int new_need_isa_buffer = 0;
+ unsigned char ** new_dma_malloc_pages = NULL;
+
+ if( !scsi_devices )
+ {
+ /*
+ * Free up the DMA pool.
+ */
+ if( dma_free_sectors != dma_sectors )
+ panic("SCSI DMA pool memory leak\n");
+
+ for(i=0; i < dma_sectors >> 3; i++)
+ scsi_init_free(dma_malloc_pages[i], PAGE_SIZE);
+ if (dma_malloc_pages)
+ scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
+ dma_malloc_pages = NULL;
+ if (dma_malloc_freelist)
+ scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
+ dma_malloc_freelist = NULL;
+ dma_sectors = 0;
+ dma_free_sectors = 0;
+ return;
+ }
+ /* Next, check to see if we need to extend the DMA buffer pool */
+
+ new_dma_sectors = 16; /* Base value we use */
+
+ if (high_memory-1 > ISA_DMA_THRESHOLD)
+ scsi_need_isa_bounce_buffers = 1;
+ else
+ scsi_need_isa_bounce_buffers = 0;
+
+ if (scsi_devicelist)
+ for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next)
+ new_dma_sectors += 8; /* Increment for each host */
+
+ for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) {
+ host = SDpnt->host;
+
+ if(SDpnt->type != TYPE_TAPE)
+ new_dma_sectors += ((host->sg_tablesize *
+ sizeof(struct scatterlist) + 511) >> 9) *
+ host->cmd_per_lun;
+
+ if(host->unchecked_isa_dma &&
+ scsi_need_isa_bounce_buffers &&
+ SDpnt->type != TYPE_TAPE) {
+ new_dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize *
+ host->cmd_per_lun;
+ new_need_isa_buffer++;
+ }
+ }
+
+ new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
+
+ /*
+ * We never shrink the buffers - this leads to
+ * race conditions that I would rather not even think
+ * about right now.
+ */
+ if( new_dma_sectors < dma_sectors )
+ new_dma_sectors = dma_sectors;
+
+ if (new_dma_sectors)
+ {
+ new_dma_malloc_freelist = (unsigned char *)
+ scsi_init_malloc(new_dma_sectors >> 3, GFP_ATOMIC);
+ memset(new_dma_malloc_freelist, 0, new_dma_sectors >> 3);
+
+ new_dma_malloc_pages = (unsigned char **)
+ scsi_init_malloc(new_dma_sectors >> 1, GFP_ATOMIC);
+ memset(new_dma_malloc_pages, 0, new_dma_sectors >> 1);
+ }
+
+ /*
+ * If we need more buffers, expand the list.
+ */
+ if( new_dma_sectors > dma_sectors ) {
+ for(i=dma_sectors >> 3; i< new_dma_sectors >> 3; i++)
+ new_dma_malloc_pages[i] = (unsigned char *)
+ scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
+ }
+
+ /* When we dick with the actual DMA list, we need to
+ * protect things
+ */
+ save_flags(flags);
+ cli();
+ if (dma_malloc_freelist)
+ {
+ memcpy(new_dma_malloc_freelist, dma_malloc_freelist, dma_sectors >> 3);
+ scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
+ }
+ dma_malloc_freelist = new_dma_malloc_freelist;
+
+ if (dma_malloc_pages)
+ {
+ memcpy(new_dma_malloc_pages, dma_malloc_pages, dma_sectors >> 1);
+ scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
+ }
+
+ dma_free_sectors += new_dma_sectors - dma_sectors;
+ dma_malloc_pages = new_dma_malloc_pages;
+ dma_sectors = new_dma_sectors;
+ need_isa_buffer = new_need_isa_buffer;
+ restore_flags(flags);
+}
/*
* This entry point should be called by a loadable module if it is trying
@@ -2585,11 +2606,8 @@
{
int pcount;
struct Scsi_Host * shpnt;
- struct Scsi_Host * host = NULL;
- unsigned long flags;
Scsi_Device * SDpnt;
struct Scsi_Device_Template * sdtpnt;
- int i;
const char * name;
if (tpnt->next || !tpnt->detect) return 1;/* Must be already loaded, or
@@ -2653,90 +2671,12 @@
if(SDpnt->attached) scsi_build_commandblocks(SDpnt);
}
- /* Next, check to see if we need to extend the DMA buffer pool */
- {
- unsigned char * new_dma_malloc_freelist = NULL;
- unsigned int new_dma_sectors = 0;
- unsigned int new_need_isa_buffer = 0;
- unsigned char ** new_dma_malloc_pages = NULL;
-
- new_dma_sectors = 16; /* Base value we use */
- if (scsi_devicelist)
- for(shpnt=scsi_hostlist; shpnt; shpnt = shpnt->next)
- new_dma_sectors += 8; /* Increment for each host */
-
- for (SDpnt=scsi_devices; SDpnt; SDpnt = SDpnt->next) {
- host = SDpnt->host;
-
- if(SDpnt->type != TYPE_TAPE)
- new_dma_sectors += ((host->sg_tablesize *
- sizeof(struct scatterlist) + 511) >> 9) *
- host->cmd_per_lun;
-
- if(host->unchecked_isa_dma &&
- scsi_need_isa_bounce_buffers &&
- SDpnt->type != TYPE_TAPE) {
- new_dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize *
- host->cmd_per_lun;
- new_need_isa_buffer++;
- }
- }
-
- new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
-
/*
- * We never shrink the buffers - this leads to
- * race conditions that I would rather not even think
- * about right now.
- */
- if( new_dma_sectors < dma_sectors )
- new_dma_sectors = dma_sectors;
-
- if (new_dma_sectors)
- {
- new_dma_malloc_freelist = (unsigned char *)
- scsi_init_malloc(new_dma_sectors >> 3, GFP_ATOMIC);
- memset(new_dma_malloc_freelist, 0, new_dma_sectors >> 3);
-
- new_dma_malloc_pages = (unsigned char **)
- scsi_init_malloc(new_dma_sectors >> 1, GFP_ATOMIC);
- memset(new_dma_malloc_pages, 0, new_dma_sectors >> 1);
- }
+ * Now that we have all of the devices, resize the DMA pool,
+ * as required. */
+ resize_dma_pool();
- /*
- * If we need more buffers, expand the list.
- */
- if( new_dma_sectors > dma_sectors ) {
- for(i=dma_sectors >> 3; i< new_dma_sectors >> 3; i++)
- new_dma_malloc_pages[i] = (unsigned char *)
- scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
- }
-
- /* When we dick with the actual DMA list, we need to
- * protect things
- */
- save_flags(flags);
- cli();
- if (dma_malloc_freelist)
- {
- memcpy(new_dma_malloc_freelist, dma_malloc_freelist, dma_sectors >> 3);
- scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
- }
- dma_malloc_freelist = new_dma_malloc_freelist;
-
- if (dma_malloc_pages)
- {
- memcpy(new_dma_malloc_pages, dma_malloc_pages, dma_sectors >> 1);
- scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
- }
- dma_free_sectors += new_dma_sectors - dma_sectors;
- dma_malloc_pages = new_dma_malloc_pages;
- dma_sectors = new_dma_sectors;
- need_isa_buffer = new_need_isa_buffer;
- restore_flags(flags);
- }
-
/* This does any final handling that is required. */
for(sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
if(sdtpnt->finish && sdtpnt->nr_dev)
@@ -2749,7 +2689,7 @@
(scsi_init_memory_start - scsi_memory_lower_value) / 1024,
(scsi_memory_upper_value - scsi_init_memory_start) / 1024);
#endif
-
+
MOD_INC_USE_COUNT;
return 0;
}
@@ -2869,6 +2809,14 @@
shpnt = sh1;
}
+ /*
+ * If there are absolutely no more hosts left, it is safe
+ * to completely nuke the DMA pool. The resize operation will
+ * do the right thing and free everything.
+ */
+ if( !scsi_devices )
+ resize_dma_pool();
+
printk ("scsi : %d host%s.\n", next_scsi_host,
(next_scsi_host == 1) ? "" : "s");
@@ -3165,13 +3113,8 @@
/*
* Free up the DMA pool.
*/
- for(i=0; i < dma_sectors >> 3; i++)
- scsi_init_free(dma_malloc_pages[i], PAGE_SIZE);
- if (dma_malloc_pages)
- scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
- if (dma_malloc_freelist)
- scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
-
+ resize_dma_pool();
+
timer_table[SCSI_TIMER].fn = NULL;
timer_table[SCSI_TIMER].expires = 0;
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this