[Patch] IO-APIC 2.1.86-A

MOLNAR Ingo (mingo@chiara.csoma.elte.hu)
Thu, 12 Feb 1998 19:09:20 +0100 (CET)


this patch fixes two problems, neither directly an IO-APIC problem:

- SCSI subsystem assumes cli() protects the global 'request' queue
amongst IRQ handlers. This problem is only visible with multiple
SCSI cards/channels. [it would be nice if someone with more SCSI
knowledge could review this patch and comment on wether it's the
correct way, and wether there are other global structures that
have to be spinlock-protected]

- restore_flags() was broken in IRQ handlers

with this patch my system survived 4 hours of very heavy testing, paralell
EIDE (1 disk), SCSI (2 cards, 3 disks) and networking (1 interface) load.

-- mingo

--- 2.1.85/linux/drivers/scsi/scsi.h Mon Jan 12 09:39:25 1998
+++ linux/drivers/scsi/scsi.h Mon Feb 16 07:01:07 1998
@@ -685,7 +685,7 @@
#define INIT_SCSI_REQUEST \
if (!CURRENT) { \
CLEAR_INTR; \
- restore_flags(flags); \
+ spin_unlock_irqrestore(&current_lock,flags); \
return; \
} \
if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) \
--- 2.1.85/linux/drivers/scsi/sd.c Tue Jan 20 02:25:43 1998
+++ linux/drivers/scsi/sd.c Mon Feb 16 02:27:48 1998
@@ -508,6 +508,8 @@
* them to SCSI commands.
*/

+spinlock_t current_lock;
+
static void do_sd_request (void)
{
Scsi_Cmnd * SCpnt = NULL;
@@ -516,11 +518,11 @@
unsigned long flags;
int flag = 0;

- save_flags(flags);
while (1==1){
- cli();
+ spin_lock_irqsave(&current_lock, flags);
+
if (CURRENT != NULL && CURRENT->rq_status == RQ_INACTIVE) {
- restore_flags(flags);
+ spin_unlock_irqrestore(&current_lock, flags);
return;
}

@@ -535,6 +537,7 @@
*/
if( SDev->host->in_recovery )
{
+ spin_unlock_irqrestore(&current_lock, flags);
return;
}

@@ -554,6 +557,7 @@
*/
if( SDev->removable && !in_interrupt() )
{
+ spin_unlock(&current_lock);
scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, 0);
/* scsi_ioctl may allow CURRENT to change, so start over. */
SDev->was_reset = 0;
@@ -585,7 +589,7 @@
* Using a "sti()" gets rid of the latency problems but causes
* race conditions and crashes.
*/
- restore_flags(flags);
+ spin_unlock_irqrestore(&current_lock, flags);

/* This is a performance enhancement. We dig down into the request
* list and try to find a queueable request (i.e. device not busy,
@@ -603,7 +607,7 @@
if (!SCpnt && sd_template.nr_dev > 1){
struct request *req1;
req1 = NULL;
- cli();
+ spin_lock_irqsave(&current_lock, flags);
req = CURRENT;
while(req){
SCpnt = scsi_request_queueable(req,
@@ -618,7 +622,7 @@
else
req1->next = req->next;
}
- restore_flags(flags);
+ spin_unlock_irqrestore(&current_lock, flags);
}

if (!SCpnt) return; /* Could not find anything to do */
--- 2.1.85/linux/drivers/scsi/sr.c Tue Jan 20 02:25:43 1998
+++ linux/drivers/scsi/sr.c Mon Feb 16 07:04:28 1998
@@ -423,6 +423,9 @@
* translate them to SCSI commands.
*/

+/* FIXME!!!!!!!!! */
+extern spinlock_t current_lock;
+
static void do_sr_request (void)
{
Scsi_Cmnd * SCpnt = NULL;
--- 2.1.85/linux/arch/i386/kernel/irq.c Tue Feb 10 08:43:02 1998
+++ linux/arch/i386/kernel/irq.c Mon Feb 16 14:45:38 1998
@@ -570,22 +570,31 @@

unsigned long __global_save_flags(void)
{
- return global_irq_holder == (unsigned char) smp_processor_id();
+ if (!local_irq_count[smp_processor_id()])
+ return global_irq_holder == (unsigned char) smp_processor_id();
+ else {
+ unsigned long x;
+ __save_flags(x);
+ return x;
+ }
}

void __global_restore_flags(unsigned long flags)
{
- switch (flags) {
- case 0:
- __global_sti();
- break;
- case 1:
- __global_cli();
- break;
- default:
- printk("global_restore_flags: %08lx (%08lx)\n",
- flags, (&flags)[-1]);
- }
+ if (!local_irq_count[smp_processor_id()]) {
+ switch (flags) {
+ case 0:
+ __global_sti();
+ break;
+ case 1:
+ __global_cli();
+ break;
+ default:
+ printk("global_restore_flags: %08lx (%08lx)\n",
+ flags, (&flags)[-1]);
+ }
+ } else
+ __restore_flags(flags);
}

#endif

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu