patch-2.1.131 linux/arch/alpha/kernel/bios32.c

Next file: linux/arch/alpha/kernel/process.c
Previous file: linux/arch/alpha/config.in
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.130/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
@@ -296,60 +296,82 @@
  * on SRM.  It is more trouble than it iw worth to conditionalize this.
  */
 
-static struct {
-	struct reset_irq {
-		struct pci_dev *dev;
-		u8 irq;
-	} irq[16];
-	int irq_count;
-
-	struct reset_io {
-		struct pci_dev *dev;
-		u8 reg;
-		u32 io;
-	} io[16];
-	int io_count;
-} srm_resets;
+struct srm_irq_reset {
+	struct srm_irq_reset *next;
+	struct pci_dev *dev;
+	u8 irq;
+} *srm_irq_resets;
+
+struct srm_io_reset {
+	struct srm_io_reset *next;
+	struct pci_dev *dev;
+	u32 io;
+	u8 reg;
+} *srm_io_resets;
 
 /* Apply the collected reset modifications.  */
 
 void
 reset_for_srm(void)
 {
-	struct pci_dev *dev;
-	int i;
+	struct srm_irq_reset *qreset;
+	struct srm_io_reset *ireset;
 
 	/* Reset any IRQs that we changed.  */
-	for (i = 0; i < srm_resets.irq_count; i++) {
-		dev = srm_resets.irq[i].dev;
-
-		pcibios_write_config_byte(dev->bus->number, dev->devfn,
+	for (qreset = srm_irq_resets; qreset ; qreset = qreset->next) {
+		pcibios_write_config_byte(qreset->dev->bus->number,
+					  qreset->dev->devfn,
 					  PCI_INTERRUPT_LINE,
-					  srm_resets.irq[i].irq);
+					  qreset->irq);
 #if 1
 		printk("reset_for_srm: bus %d slot 0x%x "
 		       "SRM IRQ 0x%x changed back from 0x%x\n",
-		       dev->bus->number, PCI_SLOT(dev->devfn),
-		       srm_resets.irq[i].irq, dev->irq);
+		       qreset->dev->bus->number,
+		       PCI_SLOT(qreset->dev->devfn),
+		       qreset->irq, qreset->dev->irq);
 #endif
 	}
 
 	/* Reset any IO addresses that we changed.  */
-	for (i = 0; i < srm_resets.io_count; i++) {
-		dev = srm_resets.io[i].dev;
-
-		pcibios_write_config_byte(dev->bus->number, dev->devfn,
-					  srm_resets.io[i].reg,
-					  srm_resets.io[i].io);
+	for (ireset = srm_io_resets; ireset ; ireset = ireset->next) {
+		pcibios_write_config_dword(ireset->dev->bus->number,
+					   ireset->dev->devfn,
+					   ireset->reg, ireset->io);
 #if 1
 		printk("reset_for_srm: bus %d slot 0x%x "
-		       "SRM IO restored to 0x%x\n",
-		       dev->bus->number, PCI_SLOT(dev->devfn),
-		       srm_resets.io[i].io);
+		       "SRM MEM/IO restored to 0x%x\n",
+		       ireset->dev->bus->number,
+		       PCI_SLOT(ireset->dev->devfn),
+		       ireset->io);
 #endif
 	}
 }
 
+static void
+new_irq_reset(struct pci_dev *dev, u8 irq)
+{
+	struct srm_irq_reset *n;
+	n = kmalloc(sizeof(*n), GFP_KERNEL);
+
+	n->next = srm_irq_resets;
+	n->dev = dev;
+	n->irq = irq;
+	srm_irq_resets = n;
+}
+
+static void
+new_io_reset(struct pci_dev *dev, u8 reg, u32 io)
+{
+	struct srm_io_reset *n;
+	n = kmalloc(sizeof(*n), GFP_KERNEL);
+
+	n->next = srm_io_resets;
+	n->dev = dev;
+	n->reg = reg;
+	n->io = io;
+	srm_io_resets = n;
+}
+
 
 /*
  * Disable PCI device DEV so that it does not respond to I/O or memory
@@ -426,6 +448,7 @@
 	struct pci_bus *bus;
 	unsigned short cmd;
 	unsigned int base, mask, size, off, idx;
+	unsigned int orig_base;
 	unsigned int alignto;
 	unsigned long handle;
 
@@ -467,6 +490,8 @@
 		 * Figure out how much space and of what type this
 		 * device wants.
 		 */
+		pcibios_read_config_dword(bus->number, dev->devfn, off,
+					  &orig_base);
 		pcibios_write_config_dword(bus->number, dev->devfn, off,
 					   0xffffffff);
 		pcibios_read_config_dword(bus->number, dev->devfn, off, &base);
@@ -504,8 +529,10 @@
 			alignto = MAX(0x800, size);
 			base = ALIGN(io_base, alignto);
 			io_base = base + size;
+
 			pcibios_write_config_dword(bus->number, dev->devfn, 
 						   off, base | 0x1);
+			new_io_reset(dev, off, orig_base);
 
 			handle = PCI_HANDLE(bus->number) | base | 1;
 			dev->base_address[idx] = handle;
@@ -582,8 +609,11 @@
 				}
 			}
 			mem_base = base + size;
+
 			pcibios_write_config_dword(bus->number, dev->devfn,
 						   off, base);
+			new_io_reset(dev, off, orig_base);
+
 			handle = PCI_HANDLE(bus->number) | base;
 			dev->base_address[idx] = handle;
 
@@ -596,9 +626,16 @@
 			 * addresses to be used.
 			 */
 			if (type == PCI_BASE_ADDRESS_MEM_TYPE_64) {
-				pcibios_write_config_dword(bus->number,
-							   dev->devfn,
-							   off+4, 0);
+				unsigned int orig_base2;
+				pcibios_read_config_dword(bus->number,
+							  dev->devfn,
+							  off+4, &orig_base2);
+				if (0 != orig_base2) {
+					pcibios_write_config_dword(bus->number,
+								   dev->devfn,
+								   off+4, 0);
+					new_io_reset (dev, off+4, orig_base2);
+				}
 				/* Bypass hi reg in the loop.  */
 				dev->base_address[++idx] = 0;
 
@@ -720,10 +757,9 @@
 					   PCI_IO_BASE, l);
 
 		/*
-		 * Also:
-		 *       clear out the upper 16 bits of IO base/limit.
-		 *       clear out the upper 32 bits of PREF base/limit.
-		*/
+		 * Clear out the upper 16 bits of IO base/limit.
+		 * Clear out the upper 32 bits of PREF base/limit.
+		 */
 		pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
 					   PCI_IO_BASE_UPPER16, 0);
 		pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
@@ -738,6 +774,7 @@
 		l = ((bmem & 0xfff00000) >> 16) | ((tmem - 1) & 0xfff00000);
 		pcibios_write_config_dword(bridge->bus->number, bridge->devfn,
 					   PCI_MEMORY_BASE, l);
+
 		/*
 		 * Turn off downstream PF memory address range, unless
 		 * there is a VGA behind this bridge, in which case, we
@@ -839,7 +876,6 @@
 {
 	struct pci_bus *bus = dev->bus;
 	unsigned int reg, orig_base, new_base, found_one = 0;
-	struct reset_io *ior;
 
 	for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4) {
 		/* Read the current setting, check for I/O space and >= 64K */
@@ -870,10 +906,7 @@
 		pcibios_write_config_dword(bus->number, dev->devfn,
 					   reg, new_base);
 
-		ior = &srm_resets.io[srm_resets.io_count++];
-		ior->dev = dev;
-		ior->reg = reg;
-		ior->io = orig_base;
+		new_io_reset(dev, reg, orig_base);
 		found_one++;
 	}
 
@@ -990,8 +1023,6 @@
 						 &irq_orig);
 
 			if (irq_orig != dev->irq) {
-				struct reset_irq *r;
-
 				DBG_DEVS(("common_pci_fixup: bus %d "
 					  "slot 0x%x SRM IRQ 0x%x "
 					  "changed to 0x%x\n",
@@ -999,9 +1030,7 @@
 					  PCI_SLOT(dev->devfn),
 					  irq_orig, dev->irq));
 
-				r = &srm_resets.irq[srm_resets.irq_count++];
-				r->dev = dev;
-				r->irq = irq_orig;
+				new_irq_reset(dev, irq_orig);
 			}
 		}
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov