patch-2.4.0-test3 linux/arch/sparc64/kernel/irq.c

Next file: linux/arch/sparc64/kernel/pci_sabre.c
Previous file: linux/arch/sparc64/kernel/binfmt_aout32.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.87 2000/05/09 17:40:13 davem Exp $
+/* $Id: irq.c,v 1.89 2000/06/30 10:18:38 davem Exp $
  * irq.c: UltraSparc IRQ handling/init/registry.
  *
  * Copyright (C) 1997  David S. Miller  (davem@caip.rutgers.edu)
@@ -62,6 +62,19 @@
 #define irq_work(__cpu, __pil)	&(cpu_data[(__cpu)].irq_worklists[(__pil)])
 #endif
 
+#ifdef CONFIG_PCI
+/* This is a table of physical addresses used to deal with SA_DMA_SYNC.
+ * It is used for PCI only to synchronize DMA transfers with IRQ delivery
+ * for devices behind busses other than APB on Sabre systems.
+ *
+ * Currently these physical addresses are just config space accesses
+ * to the command register for that device.
+ */
+unsigned long pci_dma_wsync;
+unsigned long dma_sync_reg_table[256];
+unsigned char dma_sync_reg_table_entry = 0;
+#endif
+
 /* This is based upon code in the 32-bit Sparc kernel written mostly by
  * David Redman (djhr@tadpole.co.uk).
  */
@@ -280,8 +293,6 @@
 			/*
 			 * Check wether we _should_ use DMA Write Sync
 			 * (for devices behind bridges behind APB). 
-			 *
-			 * XXX: Not implemented, yet.
 			 */
 			if (bucket->flags & IBF_DMA_SYNC)
 				irqflags |= SA_DMA_SYNC;
@@ -541,8 +552,8 @@
  * lives in the brlock table for cache reasons.
  */
 #ifndef CONFIG_SMP
-unsigned int local_irq_count;
-unsigned int local_bh_count;
+unsigned int __local_irq_count;
+unsigned int __local_bh_count;
 #else
 
 /* Who has global_irq_lock. */
@@ -594,14 +605,14 @@
 		spinlock_t *lock;
 
 		if (!irqs_running() &&
-		    (local_bh_count || !spin_is_locked(&global_bh_lock)))
+		    (local_bh_count(smp_processor_id()) || !spin_is_locked(&global_bh_lock)))
 			break;
 
 		br_write_unlock(BR_GLOBALIRQ_LOCK);
 		lock = &__br_write_locks[BR_GLOBALIRQ_LOCK].lock;
 		while (irqs_running() ||
 		       spin_is_locked(lock) ||
-		       (!local_bh_count && spin_is_locked(&global_bh_lock))) {
+		       (!local_bh_count(smp_processor_id()) && spin_is_locked(&global_bh_lock))) {
 			if (!--count) {
 				show("wait_on_irq");
 				count = (~0 >> 1);
@@ -624,7 +635,7 @@
 	if(flags == 0) {
 		int cpu = smp_processor_id();
 		__cli();
-		if (! local_irq_count)
+		if (! local_irq_count(cpu))
 			get_irqlock(cpu);
 	}
 }
@@ -633,7 +644,7 @@
 {
 	int cpu = smp_processor_id();
 
-	if (! local_irq_count)
+	if (! local_irq_count(cpu))
 		release_irqlock(cpu);
 	__sti();
 }
@@ -645,7 +656,7 @@
 	__save_flags(flags);
 	local_enabled = ((flags == 0) ? 1 : 0);
 	retval = 2 + local_enabled;
-	if (! local_irq_count) {
+	if (! local_irq_count(smp_processor_id())) {
 		if (local_enabled)
 			retval = 1;
 		if (global_irq_holder == (unsigned char) smp_processor_id())
@@ -719,14 +730,14 @@
 	/* 'cpu' is the MID (ie. UPAID), calculate the MID
 	 * of our buddy.
 	 */
-	if(should_forward != 0) {
+	if (should_forward != 0) {
 		buddy = cpu_number_map(cpu) + 1;
 		if (buddy >= NR_CPUS ||
 		    (buddy = cpu_logical_map(buddy)) == -1)
 			buddy = cpu_logical_map(0);
 
 		/* Voo-doo programming. */
-		if(cpu_data[buddy].idle_volume < FORWARD_VOLUME)
+		if (cpu_data[buddy].idle_volume < FORWARD_VOLUME)
 			should_forward = 0;
 		buddy <<= 26;
 	}
@@ -752,25 +763,29 @@
 #else
 	bp = __bucket(xchg32(irq_work(cpu, irq), 0));
 #endif
-	for( ; bp != NULL; bp = nbp) {
+	for ( ; bp != NULL; bp = nbp) {
 		unsigned char flags = bp->flags;
 
 		nbp = __bucket(bp->irq_chain);
-		if((flags & IBF_ACTIVE) != 0) {
-			if((flags & IBF_MULTI) == 0) {
+		if ((flags & IBF_ACTIVE) != 0) {
+			if ((flags & IBF_DMA_SYNC) != 0) {
+				upa_readl(dma_sync_reg_table[bp->synctab_ent]);
+				upa_readq(pci_dma_wsync);
+			}
+			if ((flags & IBF_MULTI) == 0) {
 				struct irqaction *ap = bp->irq_info;
 				ap->handler(__irq(bp), ap->dev_id, regs);
 			} else {
 				void **vector = (void **)bp->irq_info;
 				int ent;
-				for(ent = 0; ent < 4; ent++) {
+				for (ent = 0; ent < 4; ent++) {
 					struct irqaction *ap = vector[ent];
-					if(ap != NULL)
+					if (ap != NULL)
 						ap->handler(__irq(bp), ap->dev_id, regs);
 				}
 			}
 			/* Only the dummy bucket lacks IMAP/ICLR. */
-			if(bp->pil != 0) {
+			if (bp->pil != 0) {
 #ifdef CONFIG_SMP
 				/* Ok, here is what is going on:
 				 * 1) Retargeting IRQs on Starfire is very

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)