patch-2.4.23 linux-2.4.23/arch/sparc64/kernel/pci_sabre.c

Next file: linux-2.4.23/arch/sparc64/kernel/pci_schizo.c
Previous file: linux-2.4.23/arch/sparc64/kernel/pci_psycho.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.22/arch/sparc64/kernel/pci_sabre.c linux-2.4.23/arch/sparc64/kernel/pci_sabre.c
@@ -219,6 +219,7 @@
 	 ((unsigned long)(REG)))
 
 static int hummingbird_p;
+static struct pci_bus *sabre_root_bus;
 
 static void *sabre_pci_config_mkaddr(struct pci_pbm_info *pbm,
 				     unsigned char bus,
@@ -630,7 +631,6 @@
 					   struct pci_dev *pdev,
 					   unsigned int ino)
 {
-	struct pci_controller_info *p = pbm->parent;
 	struct ino_bucket *bucket;
 	unsigned long imap, iclr;
 	unsigned long imap_off, iclr_off;
@@ -655,11 +655,11 @@
 	if (PIL_RESERVED(pil))
 		BUG();
 
-	imap = p->controller_regs + imap_off;
+	imap = pbm->controller_regs + imap_off;
 	imap += 4;
 
 	iclr_off = sabre_iclr_offset(ino);
-	iclr = p->controller_regs + iclr_off;
+	iclr = pbm->controller_regs + iclr_off;
 	iclr += 4;
 
 	if ((ino & 0x20) == 0)
@@ -737,7 +737,7 @@
 		sabre_write(iommu->iommu_control,
 			    (control | SABRE_IOMMUCTRL_DENAB));
 		for (i = 0; i < 16; i++) {
-			unsigned long base = p->controller_regs;
+			unsigned long base = p->pbm_A.controller_regs;
 
 			iommu_tag[i] =
 				sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL));
@@ -786,8 +786,8 @@
 static void sabre_ue_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct pci_controller_info *p = dev_id;
-	unsigned long afsr_reg = p->controller_regs + SABRE_UE_AFSR;
-	unsigned long afar_reg = p->controller_regs + SABRE_UECE_AFAR;
+	unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_UE_AFSR;
+	unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR;
 	unsigned long afsr, afar, error_bits;
 	int reported;
 
@@ -844,8 +844,8 @@
 static void sabre_ce_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct pci_controller_info *p = dev_id;
-	unsigned long afsr_reg = p->controller_regs + SABRE_CE_AFSR;
-	unsigned long afar_reg = p->controller_regs + SABRE_UECE_AFAR;
+	unsigned long afsr_reg = p->pbm_A.controller_regs + SABRE_CE_AFSR;
+	unsigned long afar_reg = p->pbm_A.controller_regs + SABRE_UECE_AFAR;
 	unsigned long afsr, afar, error_bits;
 	int reported;
 
@@ -895,6 +895,38 @@
 	printk("]\n");
 }
 
+static void sabre_pcierr_intr_other(struct pci_controller_info *p)
+{
+	unsigned long csr_reg, csr, csr_error_bits;
+	u16 stat;
+
+	csr_reg = p->pbm_A.controller_regs + SABRE_PCICTRL;
+	csr = sabre_read(csr_reg);
+	csr_error_bits =
+		csr & SABRE_PCICTRL_SERR;
+	if (csr_error_bits) {
+		/* Clear the errors.  */
+		sabre_write(csr_reg, csr);
+
+		/* Log 'em.  */
+		if (csr_error_bits & SABRE_PCICTRL_SERR)
+			printk("SABRE%d: PCI SERR signal asserted.\n",
+			       p->index);
+	}
+	pci_read_config_word(sabre_root_bus->self,
+			     PCI_STATUS, &stat);
+	if (stat & (PCI_STATUS_PARITY |
+		    PCI_STATUS_SIG_TARGET_ABORT |
+		    PCI_STATUS_REC_TARGET_ABORT |
+		    PCI_STATUS_REC_MASTER_ABORT |
+		    PCI_STATUS_SIG_SYSTEM_ERROR)) {
+		printk("SABRE%d: PCI bus error, PCI_STATUS[%04x]\n",
+		       p->index, stat);
+		pci_write_config_word(sabre_root_bus->self,
+				      PCI_STATUS, 0xffff);
+	}
+}
+
 static void sabre_pcierr_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct pci_controller_info *p = dev_id;
@@ -902,8 +934,8 @@
 	unsigned long afsr, afar, error_bits;
 	int reported;
 
-	afsr_reg = p->controller_regs + SABRE_PIOAFSR;
-	afar_reg = p->controller_regs + SABRE_PIOAFAR;
+	afsr_reg = p->pbm_A.controller_regs + SABRE_PIOAFSR;
+	afar_reg = p->pbm_A.controller_regs + SABRE_PIOAFAR;
 
 	/* Latch error status. */
 	afar = sabre_read(afar_reg);
@@ -916,7 +948,7 @@
 		 SABRE_PIOAFSR_SMA | SABRE_PIOAFSR_STA |
 		 SABRE_PIOAFSR_SRTRY | SABRE_PIOAFSR_SPERR);
 	if (!error_bits)
-		return;
+		return sabre_pcierr_intr_other(p);
 	sabre_write(afsr_reg, error_bits);
 
 	/* Log the error. */
@@ -995,8 +1027,8 @@
 static void __init sabre_register_error_handlers(struct pci_controller_info *p)
 {
 	struct pci_pbm_info *pbm = &p->pbm_A; /* arbitrary */
-	unsigned long base = p->controller_regs;
-	unsigned long irq, portid = p->portid;
+	unsigned long base = pbm->controller_regs;
+	unsigned long irq, portid = pbm->portid;
 	u64 tmp;
 
 	/* We clear the error bits in the appropriate AFSR before
@@ -1044,13 +1076,12 @@
 					 struct resource *root)
 {
 	struct pci_pbm_info *pbm = pci_bus2pbm[pdev->bus->number];
-	struct pci_controller_info *p = pbm->parent;
 	unsigned long base;
 
 	if (res->flags & IORESOURCE_IO)
-		base = p->controller_regs + SABRE_IOSPACE;
+		base = pbm->controller_regs + SABRE_IOSPACE;
 	else
-		base = p->controller_regs + SABRE_MEMSPACE;
+		base = pbm->controller_regs + SABRE_MEMSPACE;
 
 	res->start += base;
 	res->end += base;
@@ -1060,7 +1091,6 @@
 {
 	struct pcidev_cookie *pcp = pdev->sysdata;
 	struct pci_pbm_info *pbm = pcp->pbm;
-	struct pci_controller_info *p = pbm->parent;
 	struct resource *res;
 	unsigned long base;
 	u32 reg;
@@ -1078,9 +1108,9 @@
 
 	is_64bit = 0;
 	if (res->flags & IORESOURCE_IO)
-		base = p->controller_regs + SABRE_IOSPACE;
+		base = pbm->controller_regs + SABRE_IOSPACE;
 	else {
-		base = p->controller_regs + SABRE_MEMSPACE;
+		base = pbm->controller_regs + SABRE_MEMSPACE;
 		if ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
 		    == PCI_BASE_ADDRESS_MEM_TYPE_64)
 			is_64bit = 1;
@@ -1197,6 +1227,8 @@
 	pci_fixup_host_bridge_self(sabre_bus);
 	sabre_bus->self->sysdata = cookie;
 
+	sabre_root_bus = sabre_bus;
+
 	apb_init(p, sabre_bus);
 
 	sabres_scanned = 0;
@@ -1256,21 +1288,21 @@
 	iommu->iommu_cur_ctx = 0;
 
 	/* Register addresses. */
-	iommu->iommu_control  = p->controller_regs + SABRE_IOMMU_CONTROL;
-	iommu->iommu_tsbbase  = p->controller_regs + SABRE_IOMMU_TSBBASE;
-	iommu->iommu_flush    = p->controller_regs + SABRE_IOMMU_FLUSH;
-	iommu->write_complete_reg = p->controller_regs + SABRE_WRSYNC;
+	iommu->iommu_control  = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
+	iommu->iommu_tsbbase  = p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE;
+	iommu->iommu_flush    = p->pbm_A.controller_regs + SABRE_IOMMU_FLUSH;
+	iommu->write_complete_reg = p->pbm_A.controller_regs + SABRE_WRSYNC;
 	/* Sabre's IOMMU lacks ctx flushing. */
 	iommu->iommu_ctxflush = 0;
                                         
 	/* Invalidate TLB Entries. */
-	control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);
+	control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL);
 	control |= SABRE_IOMMUCTRL_DENAB;
-	sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
+	sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control);
 
 	for(i = 0; i < 16; i++) {
-		sabre_write(p->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0);
-		sabre_write(p->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0);
+		sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0);
+		sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0);
 	}
 
 	/* Leave diag mode enabled for full-flushing done
@@ -1287,9 +1319,9 @@
 	iommu->dma_addr_mask = dma_mask;
 	memset((char *)tsbbase, 0, PAGE_SIZE << order);
 
-	sabre_write(p->controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
+	sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_TSBBASE, __pa(tsbbase));
 
-	control = sabre_read(p->controller_regs + SABRE_IOMMU_CONTROL);
+	control = sabre_read(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL);
 	control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ);
 	control |= SABRE_IOMMUCTRL_ENAB;
 	switch(tsbsize) {
@@ -1306,7 +1338,7 @@
 		prom_halt();
 		break;
 	}
-	sabre_write(p->controller_regs + SABRE_IOMMU_CONTROL, control);
+	sabre_write(p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL, control);
 
 	/* We start with no consistent mappings. */
 	iommu->lowest_consistent_map =
@@ -1322,8 +1354,8 @@
 						   struct pci_pbm_info *pbm)
 {
 	char *name = pbm->name;
-	unsigned long ibase = p->controller_regs + SABRE_IOSPACE;
-	unsigned long mbase = p->controller_regs + SABRE_MEMSPACE;
+	unsigned long ibase = p->pbm_A.controller_regs + SABRE_IOSPACE;
+	unsigned long mbase = p->pbm_A.controller_regs + SABRE_MEMSPACE;
 	unsigned int devfn;
 	unsigned long first, last, i;
 	u8 *addr, map;
@@ -1416,6 +1448,7 @@
 			pbm = &p->pbm_B;
 		else
 			pbm = &p->pbm_A;
+		pbm->chip_type = PBM_CHIP_TYPE_SABRE;
 		pbm->parent = p;
 		pbm->prom_node = node;
 		pbm->pci_first_slot = 1;
@@ -1511,11 +1544,11 @@
 		pbm->io_space.name = pbm->mem_space.name = pbm->name;
 
 		/* Hack up top-level resources. */
-		pbm->io_space.start = p->controller_regs + SABRE_IOSPACE;
+		pbm->io_space.start = p->pbm_A.controller_regs + SABRE_IOSPACE;
 		pbm->io_space.end   = pbm->io_space.start + (1UL << 24) - 1UL;
 		pbm->io_space.flags = IORESOURCE_IO;
 
-		pbm->mem_space.start = p->controller_regs + SABRE_MEMSPACE;
+		pbm->mem_space.start = p->pbm_A.controller_regs + SABRE_MEMSPACE;
 		pbm->mem_space.end   = pbm->mem_space.start + (unsigned long)dma_begin - 1UL;
 		pbm->mem_space.flags = IORESOURCE_MEM;
 
@@ -1591,7 +1624,8 @@
 	pci_controller_root = p;
 	spin_unlock_irqrestore(&pci_controller_lock, flags);
 
-	p->portid = upa_portid;
+	p->pbm_A.portid = upa_portid;
+	p->pbm_B.portid = upa_portid;
 	p->index = pci_num_controllers++;
 	p->pbms_same_domain = 1;
 	p->scan_bus = sabre_scan_bus;
@@ -1614,30 +1648,31 @@
 	/*
 	 * First REG in property is base of entire SABRE register space.
 	 */
-	p->controller_regs = pr_regs[0].phys_addr;
-	pci_dma_wsync = p->controller_regs + SABRE_WRSYNC;
+	p->pbm_A.controller_regs = pr_regs[0].phys_addr;
+	p->pbm_B.controller_regs = pr_regs[0].phys_addr;
+	pci_dma_wsync = p->pbm_A.controller_regs + SABRE_WRSYNC;
 
 	printk("PCI: Found SABRE, main regs at %016lx, wsync at %016lx\n",
-	       p->controller_regs, pci_dma_wsync);
+	       p->pbm_A.controller_regs, pci_dma_wsync);
 
 	/* Clear interrupts */
 
 	/* PCI first */
 	for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8)
-		sabre_write(p->controller_regs + clear_irq, 0x0UL);
+		sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL);
 
 	/* Then OBIO */
 	for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8)
-		sabre_write(p->controller_regs + clear_irq, 0x0UL);
+		sabre_write(p->pbm_A.controller_regs + clear_irq, 0x0UL);
 
 	/* Error interrupts are enabled later after the bus scan. */
-	sabre_write(p->controller_regs + SABRE_PCICTRL,
+	sabre_write(p->pbm_A.controller_regs + SABRE_PCICTRL,
 		    (SABRE_PCICTRL_MRLEN   | SABRE_PCICTRL_SERR |
 		     SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN));
 
 	/* Now map in PCI config space for entire SABRE. */
 	p->pbm_A.config_space = p->pbm_B.config_space =
-		(p->controller_regs + SABRE_CONFIGSPACE);
+		(p->pbm_A.controller_regs + SABRE_CONFIGSPACE);
 	printk("SABRE: Shared PCI config space at %016lx\n",
 	       p->pbm_A.config_space);
 

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