[parisc-linux-cvs] Re: DIFF 2.4.18-pa14
Grant Grundler
grundler@dsl2.external.hp.com
Fri, 05 Apr 2002 01:08:58 -0700
Grant Grundler wrote:
> Log message:
> 2.4.18-pa14 PA8700/SBA bug fix (no, we don't support PA8700 yet)
> o add bug fix for older revs of PA8700 on SBA systems
> o made IO PDIR allocation smarter: iopdir_size ~= phys_hostmem/num_iommu
> o cleanup 64-bit reads/debug info
> o disabled /proc/bus/runway/bitmap since "cat"ing that file will crash
> the system (exceeds 4k of output).
Kills some of the TODO Items I had.
Still outstanding:
o try using (maybe only PAT) PDC for PCI config cycles
o cleanup J6000 hack to use "old" PCI config access method
o fix warning about "Ignoring enabled ELMMIO BASE" so it only shows
up if the SBA is directing addresses down that rope.
Index: Makefile
===================================================================
RCS file: /var/cvs/linux/Makefile,v
retrieving revision 1.284
diff -u -p -r1.284 Makefile
--- Makefile 2002/04/03 03:11:01 1.284
+++ Makefile 2002/04/05 07:43:09
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 18
-EXTRAVERSION = -pa13
+EXTRAVERSION = -pa14
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
Index: arch/parisc/kernel/cache.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/cache.c,v
retrieving revision 1.20
diff -u -p -r1.20 cache.c
--- arch/parisc/kernel/cache.c 2001/11/29 20:53:44 1.20
+++ arch/parisc/kernel/cache.c 2002/04/05 07:43:10
@@ -186,13 +186,11 @@ cache_init(void)
}
#endif
- if (pdc_model_capabilities(&capabilities) == 0) {
- if ((capabilities & PDC_MODEL_NVA_MASK) == PDC_MODEL_NVA_UNSUPPORTED) {
- printk(KERN_WARNING "Only equivalent aliasing supported\n");
+ if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) == PDC_MODEL_NVA_UNSUPPORTED) {
+ printk(KERN_WARNING "Only equivalent aliasing supported\n");
#ifndef CONFIG_SMP
- panic("SMP kernel required to avoid non-equivalent aliasing");
+ panic("SMP kernel required to avoid non-equivalent aliasing");
#endif
- }
}
}
Index: arch/parisc/kernel/drivers.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/drivers.c,v
retrieving revision 1.45
diff -u -p -r1.45 drivers.c
--- arch/parisc/kernel/drivers.c 2002/02/28 07:11:20 1.45
+++ arch/parisc/kernel/drivers.c 2002/04/05 07:43:10
@@ -142,6 +142,26 @@ int register_parisc_driver(struct parisc
return 0;
}
+/**
+ * count_parisc_driver - count # of devices this driver would match
+ * @driver: the PA-RISC driver to try
+ *
+ * Use by IOMMU support to "guess" the right size IOPdir.
+ * Formula is something like memsize/(num_iommu * entry_size).
+ */
+int count_parisc_driver(struct parisc_driver *driver)
+{
+ struct parisc_device *device;
+ int cnt = 0;
+
+ for_each_padev(device) {
+ if (match_device(driver, device))
+ cnt++;
+ }
+
+ return cnt;
+}
+
/**
Index: arch/parisc/kernel/lba_pci.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/lba_pci.c,v
retrieving revision 1.49
diff -u -p -r1.49 lba_pci.c
--- arch/parisc/kernel/lba_pci.c 2002/03/07 21:13:11 1.49
+++ arch/parisc/kernel/lba_pci.c 2002/04/05 07:43:12
@@ -63,12 +63,6 @@
#undef FBB_SUPPORT /* Fast Back-Back xfers - NOT READY YET */
-#ifdef __LP64__
-/* workarounds for brokeness in PAT PDC
-** Hopefully these can/will go away as new PDC revs become available.
-*/
-#define PDC_PAT_BUG
-#endif
#ifdef DEBUG_LBA
#define DBG(x...) printk(x)
@@ -240,9 +234,7 @@ static u32 lba_t32;
#define READ_REG8(addr) readb(addr)
#define READ_REG16(addr) readw(addr)
#define READ_REG32(addr) readl(addr)
-#if BITS_PER_LONG > 32
#define READ_REG64(addr) readq(addr)
-#endif
#define WRITE_REG8(value, addr) writeb(value, addr)
#define WRITE_REG16(value, addr) writew(value, addr)
#define WRITE_REG32(value, addr) writel(value, addr)
@@ -1208,7 +1200,7 @@ lba_legacy_resources(struct parisc_devic
r->start &= ~1;
r->end = r->start;
r->end += ~READ_REG32(pa_dev->hpa + LBA_ELMMIO_MASK);
- printk(KERN_DEBUG "WARNING: Ignoring enabled ELMMIO BASE 0x%0x SIZE 0x%x\n",
+ printk(KERN_DEBUG "WARNING: Ignoring enabled ELMMIO BASE 0x%0lx SIZE 0x%lx\n",
r->start,
r->end + 1);
@@ -1243,11 +1235,9 @@ static int __init
lba_hw_init(struct lba_device *d)
{
u32 stat;
-#ifdef PDC_PAT_BUG
- u32 bus_reset;
-#endif
+ u32 bus_reset; /* PDC_PAT_BUG */
-#ifdef DEBUG_LBA_PAT
+#if 1
printk(KERN_DEBUG "LBA %p STAT_CTL %Lx ERROR_CFG %Lx STATUS %Lx DMA_CTL %Lx\n",
d->hba.base_addr,
READ_REG64(d->hba.base_addr + LBA_STAT_CTL),
@@ -1259,23 +1249,29 @@ lba_hw_init(struct lba_device *d)
READ_REG64(d->hba.base_addr + LBA_ARB_PRI),
READ_REG64(d->hba.base_addr + LBA_ARB_MODE),
READ_REG64(d->hba.base_addr + LBA_ARB_MTLT) );
+ printk(KERN_DEBUG " HINT cfg 0x%Lx\n",
+ READ_REG64(d->hba.base_addr + LBA_HINT_CFG));
+ printk(KERN_DEBUG " HINT reg ");
+ { int i;
+ for (i=LBA_HINT_BASE; i< (14*8 + LBA_HINT_BASE); i+=8)
+ printk(" %Lx", READ_REG64(d->hba.base_addr + i));
+ }
+ printk("\n");
#endif /* DEBUG_LBA_PAT */
#ifdef __LP64__
#warning FIXME add support for PDC_PAT_IO "Get slot status" - OLAR support
#endif
-#ifdef PDC_PAT_BUG
- /* Bug exhibited with PDC rev 40.48 on L2000 */
+ /* PDC_PAT_BUG: exhibited in rev 40.48 on L2000 */
bus_reset = READ_REG32(d->hba.base_addr + LBA_STAT_CTL + 4) & 1;
if (bus_reset) {
- BUG();
+ printk(KERN_DEBUG "NOTICE: PCI bus reset still asserted! (clearing)\n");
}
-#endif
stat = READ_REG32(d->hba.base_addr + LBA_ERROR_CONFIG);
if (stat & LBA_SMART_MODE) {
- BUG(); /* should be off be default */
+ printk(KERN_DEBUG "NOTICE: LBA in SMART mode! (cleared)\n");
stat &= ~LBA_SMART_MODE;
WRITE_REG32(stat, d->hba.base_addr + LBA_ERROR_CONFIG);
}
@@ -1284,7 +1280,6 @@ lba_hw_init(struct lba_device *d)
stat = READ_REG32(d->hba.base_addr + LBA_STAT_CTL);
WRITE_REG32(stat | HF_ENABLE, d->hba.base_addr + LBA_STAT_CTL);
-#ifdef PDC_PAT_BUG
/*
** Writing a zero to STAT_CTL.rf (bit 0) will clear reset signal
** if it's not already set. If we just cleared the PCI Bus Reset
@@ -1292,11 +1287,10 @@ lba_hw_init(struct lba_device *d)
*/
if (bus_reset)
mdelay(pci_post_reset_delay);
-#endif
if (0 == READ_REG32(d->hba.base_addr + LBA_ARB_MASK)) {
/*
- ** Bug exhibited with PDC rev 40.48 on L2000.
+ ** PDC_PAT_BUG: PDC rev 40.48 on L2000.
** B2000/C3600/J6000 also have this problem?
**
** Elroys with hot pluggable slots don't get configured
@@ -1304,7 +1298,7 @@ lba_hw_init(struct lba_device *d)
** and we can't master transactions on the bus if it's
** not at least one. 0x3 enables elroy and first slot.
*/
- BUG();
+ printk(KERN_DEBUG "NOTICE: Enabling PCI Arbitration\n");
WRITE_REG32(0x3, d->hba.base_addr + LBA_ARB_MASK);
}
Index: arch/parisc/kernel/processor.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/processor.c,v
retrieving revision 1.9
diff -u -p -r1.9 processor.c
--- arch/parisc/kernel/processor.c 2001/11/29 20:53:44 1.9
+++ arch/parisc/kernel/processor.c 2002/04/05 07:43:12
@@ -187,6 +187,10 @@ void __init collect_boot_cpu_data(void)
boot_cpu_data.pdc.cpuid & 31,
boot_cpu_data.pdc.cpuid);
+ if (pdc_model_capabilities(&boot_cpu_data.pdc.capabilities) == PDC_OK)
+ printk(KERN_INFO "capabilities 0x%lx\n",
+ boot_cpu_data.pdc.capabilities);
+
if (pdc_model_sysmodel(boot_cpu_data.pdc.sys_model_name) == PDC_OK)
printk(KERN_INFO "model %s\n",
boot_cpu_data.pdc.sys_model_name);
Index: arch/parisc/kernel/sba_iommu.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/sba_iommu.c,v
retrieving revision 1.65
diff -u -p -r1.65 sba_iommu.c
--- arch/parisc/kernel/sba_iommu.c 2002/03/07 21:13:11 1.65
+++ arch/parisc/kernel/sba_iommu.c 2002/04/05 07:43:13
@@ -123,9 +123,11 @@
#define IKE_IOC_OFFSET(p) ((p+2)*SBA_FUNC_SIZE)
#define IOC_CTRL 0x8 /* IOC_CTRL offset */
-#define IOC_CTRL_TE (0x1 << 0) /* TOC Enable */
-#define IOC_CTRL_RM (0x1 << 8) /* Real Mode */
-#define IOC_CTRL_NC (0x1 << 9) /* Non Coherent Mode */
+#define IOC_CTRL_TC (1 << 0) /* TOC Enable */
+#define IOC_CTRL_CE (1 << 1) /* Coalesce Enable */
+#define IOC_CTRL_DE (1 << 2) /* Dillon Enable */
+#define IOC_CTRL_RM (1 << 8) /* Real Mode */
+#define IOC_CTRL_NC (1 << 9) /* Non Coherent Mode */
#define MAX_IOC 2 /* per Ike. Astro only has 1 */
@@ -252,11 +254,16 @@ struct sba_device {
static struct sba_device *sba_list;
-static int sba_count;
/* Ratio of Host MEM to IOV Space size */
-static unsigned long sba_mem_ratio = 4;
+static unsigned long sba_mem_ratio = 8;
+/* global count of IOMMUs in the system */
+static unsigned int global_ioc_cnt = 0;
+
+/* PA8700 (Piranha 2.2) bug workaround */
+static unsigned long piranha_bad_128k = 0;
+
/* Looks nice and keeps the compiler happy */
#define SBA_DEV(d) ((struct sba_device *) (d))
@@ -297,16 +304,16 @@ static unsigned long sba_mem_ratio = 4;
* IO Adapter (aka Bus Converter).
*/
static void
-sba_dump_ranges(char *hpa)
+sba_dump_ranges(unsigned long hpa)
{
- DBG_INIT("SBA at 0x%p\n", hpa);
- DBG_INIT("IOS_DIST_BASE : %016lx\n", READ_REG64(hpa+IOS_DIST_BASE));
- DBG_INIT("IOS_DIST_MASK : %016lx\n", READ_REG64(hpa+IOS_DIST_MASK));
- DBG_INIT("IOS_DIST_ROUTE : %016lx\n", READ_REG64(hpa+IOS_DIST_ROUTE));
+ DBG_INIT("SBA at 0x%lx\n", hpa);
+ DBG_INIT("IOS_DIST_BASE : %Lx\n", READ_REG64(hpa+IOS_DIST_BASE));
+ DBG_INIT("IOS_DIST_MASK : %Lx\n", READ_REG64(hpa+IOS_DIST_MASK));
+ DBG_INIT("IOS_DIST_ROUTE : %Lx\n", READ_REG64(hpa+IOS_DIST_ROUTE));
DBG_INIT("\n");
- DBG_INIT("IOS_DIRECT_BASE : %016lx\n", READ_REG64(hpa+IOS_DIRECT_BASE));
- DBG_INIT("IOS_DIRECT_MASK : %016lx\n", READ_REG64(hpa+IOS_DIRECT_MASK));
- DBG_INIT("IOS_DIRECT_ROUTE: %016lx\n", READ_REG64(hpa+IOS_DIRECT_ROUTE));
+ DBG_INIT("IOS_DIRECT_BASE : %Lx\n", READ_REG64(hpa+IOS_DIRECT_BASE));
+ DBG_INIT("IOS_DIRECT_MASK : %Lx\n", READ_REG64(hpa+IOS_DIRECT_MASK));
+ DBG_INIT("IOS_DIRECT_ROUTE: %Lx\n", READ_REG64(hpa+IOS_DIRECT_ROUTE));
}
/**
@@ -316,13 +323,13 @@ sba_dump_ranges(char *hpa)
* Print the size/location of the IO MMU PDIR.
*/
static void
-sba_dump_tlb(char *hpa)
+sba_dump_tlb(unsigned long hpa)
{
- DBG_INIT("IO TLB at 0x%p\n", hpa);
- DBG_INIT("IOC_IBASE : %016lx\n", READ_REG64(hpa+IOC_IBASE));
- DBG_INIT("IOC_IMASK : %016lx\n", READ_REG64(hpa+IOC_IMASK));
- DBG_INIT("IOC_TCNFG : %016lx\n", READ_REG64(hpa+IOC_TCNFG));
- DBG_INIT("IOC_PDIR_BASE: %016lx\n", READ_REG64(hpa+IOC_PDIR_BASE));
+ DBG_INIT("IO TLB at 0x%lx\n", hpa);
+ DBG_INIT("IOC_IBASE : %Lx\n", READ_REG64(hpa+IOC_IBASE));
+ DBG_INIT("IOC_IMASK : %Lx\n", READ_REG64(hpa+IOC_IMASK));
+ DBG_INIT("IOC_TCNFG : %Lx\n", READ_REG64(hpa+IOC_TCNFG));
+ DBG_INIT("IOC_PDIR_BASE: %Lx\n", READ_REG64(hpa+IOC_PDIR_BASE));
DBG_INIT("\n");
}
#endif
@@ -726,7 +733,7 @@ sba_mark_invalid(struct ioc *ioc, dma_ad
u32 iovp = (u32) SBA_IOVP(ioc,iova);
/* Even though this is a big-endian machine, the entries
- ** in the iopdir are swapped. That's why we clear the byte
+ ** in the iopdir are little endian. That's why we clear the byte
** at +7 instead of at +0.
*/
int off = PDIR_INDEX(iovp)*sizeof(u64)+7;
@@ -1421,6 +1428,102 @@ PAT_MOD(mod)->mod_info.ioc = PAT
* Initialization and claim
*
***************************************************************/
+#define PIRANHA_ADDR_MASK 0x00160000UL /* bit 17,18,20 */
+#define PIRANHA_ADDR_VAL 0x00060000UL /* bit 17,18 on */
+static void *
+sba_alloc_pdir(unsigned int pdir_size)
+{
+ unsigned long pdir_base;
+ unsigned long pdir_order = get_order(pdir_size);
+
+ pdir_base = __get_free_pages(GFP_KERNEL, pdir_order);
+ if (NULL == (void *) pdir_base)
+ panic("sba_ioc_init() could not allocate I/O Page Table\n");
+
+ /* If this is not PA8700 (PCX-W2)
+ ** OR newer than ver 2.2
+ ** OR in a system that doesn't need VINDEX bits from SBA,
+ **
+ ** then we aren't exposed to the HW bug.
+ */
+ if ( ((boot_cpu_data.pdc.cpuid >> 5) & 0x7f) != 0x13
+ || (boot_cpu_data.pdc.versions > 0x202)
+ || (boot_cpu_data.pdc.capabilities & 0x08L) )
+ return (void *) pdir_base;
+
+ /*
+ * PA8700 (PCX-W2, aka piranha) silent data corruption fix
+ *
+ * An interaction between PA8700 CPU (Ver 2.2 or older) and
+ * Ike/Astro can cause silent data corruption. This is only
+ * a problem if the I/O PDIR is located in memory such that
+ * (little-endian) bits 17 and 18 are on and bit 20 is off.
+ *
+ * Since the max IO Pdir size is 2MB, by cleverly allocating the
+ * right physical address, we can either avoid (IOPDIR <= 1MB)
+ * or minimize (2MB IO Pdir) the problem if we restrict the
+ * IO Pdir to a maximum size of 2MB-128K (1902K).
+ *
+ * Because we always allocate 2^N sized IO pdirs, either of the
+ * "bad" regions will be the last 128K if at all. That's easy
+ * to test for.
+ *
+ */
+ if (pdir_order <= (19-12)) {
+ if (((virt_to_phys(pdir_base)+pdir_size-1) & PIRANHA_ADDR_MASK) == PIRANHA_ADDR_VAL) {
+ /* allocate a new one on 512k alignment */
+ unsigned long new_pdir = __get_free_pages(GFP_KERNEL, (19-12));
+ /* release original */
+ free_pages(pdir_base, pdir_order);
+
+ pdir_base = new_pdir;
+
+ /* release excess */
+ while (pdir_order < (19-12)) {
+ new_pdir += pdir_size;
+ free_pages(new_pdir, pdir_order);
+ pdir_order +=1;
+ pdir_size <<=1;
+ }
+ }
+ } else {
+ /*
+ ** 1MB or 2MB Pdir
+ ** Needs to be aligned on an "odd" 1MB boundary.
+ */
+ unsigned long new_pdir = __get_free_pages(GFP_KERNEL, pdir_order+1); /* 2 or 4MB */
+
+ /* release original */
+ free_pages( pdir_base, pdir_order);
+
+ /* release first 1MB */
+ free_pages(new_pdir, 20-12);
+
+ pdir_base = new_pdir + 1024*1024;
+
+ if (pdir_order > (20-12)) {
+ /*
+ ** 2MB Pdir.
+ **
+ ** Flag tells init_bitmap() to mark bad 128k as used
+ ** and to reduce the size by 128k.
+ */
+ piranha_bad_128k = 1;
+
+ new_pdir += 3*1024*1024;
+ /* release last 1MB */
+ free_pages(new_pdir, 20-12);
+
+ /* release unusable 128KB */
+ free_pages(new_pdir - 128*1024 , 17-12);
+
+ pdir_size -= 128*1024;
+ }
+ }
+
+ memset((void *) pdir_base, 0, pdir_size);
+ return (void *) pdir_base;
+}
static void
@@ -1430,7 +1533,6 @@ sba_ioc_init(struct parisc_device *sba,
extern void lba_set_iregs(struct parisc_device *, u32, u32);
u32 iova_space_size, iova_space_mask;
- void * pdir_base;
int pdir_size, iov_order;
unsigned long physmem;
struct parisc_device *lba;
@@ -1448,22 +1550,24 @@ sba_ioc_init(struct parisc_device *sba,
** While we have 32-bits "IOVA" space, top two 2 bits are used
** for DMA hints - ergo only 30 bits max.
*/
- /* limit IOVA space size to 1MB-1GB */
physmem = num_physpages << PAGE_SHIFT;
- if (physmem < (sba_mem_ratio*1024*1024)) {
+ iova_space_size = (u32) (physmem/(sba_mem_ratio*global_ioc_cnt));
+
+ /* limit IOVA space size to 1MB-1GB */
+ if (iova_space_size < 1024*1024) {
iova_space_size = 1024*1024;
+ }
#ifdef __LP64__
- } else if (physmem > (sba_mem_ratio*512*1024*1024)) {
+ else if (iova_space_size > 512*1024*1024) {
iova_space_size = 512*1024*1024;
-#endif
- } else {
- iova_space_size = (u32) (physmem/sba_mem_ratio);
}
+#endif
/*
** iova space must be log2() in size.
** thus, pdir/res_map will also be log2().
+ ** PIRANHA BUG: Exception is when IO Pdir is 2MB (gets reduced)
*/
iov_order = get_order(iova_space_size >> (IOVP_SHIFT-PAGE_SHIFT));
ASSERT(iov_order <= (30 - IOVP_SHIFT)); /* iova_space_size <= 1GB */
@@ -1472,12 +1576,12 @@ sba_ioc_init(struct parisc_device *sba,
ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64);
- ASSERT(pdir_size < 4*1024*1024); /* max pdir size < 4MB */
+ ASSERT(pdir_size < 4*1024*1024); /* max pdir size == 2MB */
/* Verify it's a power of two */
ASSERT((1 << get_order(pdir_size)) == (pdir_size >> PAGE_SHIFT));
- DBG_INIT("%s() hpa 0x%p mem %dMB IOV %dMB (%d bits) PDIR size 0x%0x\n",
+ DBG_INIT("%s() hpa 0x%lx mem %dMB IOV %dMB (%d bits) PDIR size 0x%0x\n",
__FUNCTION__, ioc->ioc_hpa, (int) (physmem>>20),
iova_space_size>>20, iov_order + PAGE_SHIFT, pdir_size);
@@ -1485,22 +1589,14 @@ sba_ioc_init(struct parisc_device *sba,
ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
- ioc->pdir_base =
- pdir_base = (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size));
- if (NULL == pdir_base)
- {
- panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__);
- }
- memset(pdir_base, 0, pdir_size);
+ ioc->pdir_base = sba_alloc_pdir(pdir_size);
DBG_INIT("%s() pdir %p size %x hint_shift_pdir %x hint_mask_pdir %lx\n",
- __FUNCTION__, pdir_base, pdir_size,
+ __FUNCTION__, ioc->pdir_base, pdir_size,
ioc->hint_shift_pdir, ioc->hint_mask_pdir);
-
- ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base);
- WRITE_REG64(virt_to_phys(pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE);
- DBG_INIT(" base %p\n", pdir_base);
+ ASSERT((((unsigned long) ioc->pdir_base) & PAGE_MASK) == (unsigned long) ioc->pdir_base);
+ WRITE_REG64(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE);
/* build IMASK for IOC and Elroy */
iova_space_mask = 0xffffffff;
@@ -1570,16 +1666,16 @@ sba_hw_init(struct sba_device *sba_dev)
u64 ioc_ctl;
ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL);
- DBG_INIT("%s() hpa 0x%p ioc_ctl 0x%016lx ->",
+ DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->",
__FUNCTION__, sba_dev->sba_hpa, ioc_ctl);
- ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC);
- ASSERT(ioc_ctl & IOC_CTRL_TE); /* astro: firmware enables this */
+ ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC | IOC_CTRL_CE);
+ ioc_ctl |= IOC_CTRL_TC; /* Astro: firmware enables this */
WRITE_REG(ioc_ctl, sba_dev->sba_hpa+IOC_CTRL);
#ifdef DEBUG_SBA_INIT
- ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL);
- DBG_INIT(" 0x%016lx\n", ioc_ctl);
+ ioc_ctl = READ_REG64(sba_dev->sba_hpa+IOC_CTRL);
+ DBG_INIT(" 0x%Lx\n", ioc_ctl);
#endif
if (IS_ASTRO(sba_dev->iodc)) {
@@ -1624,7 +1720,6 @@ sba_common_init(struct sba_device *sba_d
*/
sba_dev->next = sba_list;
sba_list = sba_dev;
- sba_count++;
for(i=0; i< sba_dev->num_ioc; i++) {
int res_size;
@@ -1636,6 +1731,12 @@ sba_common_init(struct sba_device *sba_d
#endif
/* resource map size dictated by pdir_size */
res_size = sba_dev->ioc[i].pdir_size/sizeof(u64); /* entries */
+
+ /* Second part of PIRANHA BUG */
+ if (piranha_bad_128k) {
+ res_size -= (128*1024)/sizeof(u64);
+ }
+
res_size >>= 3; /* convert bit count to byte count */
DBG_INIT("%s() res_size 0x%x\n",
__FUNCTION__, res_size);
@@ -1664,6 +1765,21 @@ sba_common_init(struct sba_device *sba_d
sba_dev->ioc[i].pdir_base[0] = 0xeeffc0addbba0080ULL;
#endif
+ /* Third (and last) part of PIRANHA BUG */
+ if (piranha_bad_128k) {
+ /* region from +1408K to +1536 is un-usable. */
+
+ int idx_start = (1408*1024/sizeof(u64)) >> 3;
+ int idx_end = (1536*1024/sizeof(u64)) >> 3;
+ long *p_start = (long *) &(sba_dev->ioc[i].res_map[idx_start]);
+ long *p_end = (long *) &(sba_dev->ioc[i].res_map[idx_end]);
+
+ /* mark that part of the io pdir busy */
+ while (p_start < p_end)
+ *p_start++ = -1;
+
+ }
+
#ifdef DEBUG_DMB_TRAP
iterate_pages( sba_dev->ioc[i].res_map, res_size,
set_data_memory_break, 0);
@@ -1735,6 +1851,8 @@ static int sba_proc_info(char *buf, char
return strlen(buf);
}
+#if 0
+/* XXX too much output - exceeds 4k limit and needs to be re-written */
static int
sba_resource_map(char *buf, char **start, off_t offset, int len)
{
@@ -1753,8 +1871,31 @@ sba_resource_map(char *buf, char **start
return strlen(buf);
}
-#endif
+#endif /* 0 */
+#endif /* CONFIG_PROC_FS */
+static struct parisc_device_id sba_tbl[] = {
+ { HPHW_IOA, HVERSION_REV_ANY_ID, ASTRO_RUNWAY_PORT, 0xb },
+ { HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_MERCED_PORT, 0xc },
+ { HPHW_BCPORT, HVERSION_REV_ANY_ID, REO_MERCED_PORT, 0xc },
+ { HPHW_BCPORT, HVERSION_REV_ANY_ID, REOG_MERCED_PORT, 0xc },
+/* These two entries commented out because we don't find them in a
+ * buswalk yet. If/when we do, they would cause us to think we had
+ * many more SBAs then we really do.
+ * { HPHW_BCPORT, HVERSION_REV_ANY_ID, ASTRO_ROPES_PORT, 0xc },
+ * { HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_ROPES_PORT, 0xc },
+ */
+ { 0, }
+};
+
+int sba_driver_callback(struct parisc_device *);
+
+static struct parisc_driver sba_driver = {
+ name: MODULE_NAME,
+ id_table: sba_tbl,
+ probe: sba_driver_callback,
+};
+
/*
** Determine if lba should claim this chip (return 0) or not (return 1).
** If so, initialize the chip and tell other partners in crime they
@@ -1772,36 +1913,47 @@ sba_driver_callback(struct parisc_device
sba_dump_ranges(dev->hpa);
#endif
+ /* Read HW Rev First */
+ func_class = READ_REG(dev->hpa + SBA_FCLASS);
+
if (IS_ASTRO(&dev->id)) {
+ unsigned long fclass;
static char astro_rev[]="Astro ?.?";
- /* Read HW Rev First */
- func_class = READ_REG(dev->hpa);
+ /* Astro is broken...Read HW Rev First */
+ fclass = READ_REG(dev->hpa);
- astro_rev[6] = '1' + (char) (func_class & 0x7);
- astro_rev[8] = '0' + (char) ((func_class & 0x18) >> 3);
+ astro_rev[6] = '1' + (char) (fclass & 0x7);
+ astro_rev[8] = '0' + (char) ((fclass & 0x18) >> 3);
version = astro_rev;
+
} else if (IS_IKE(&dev->id)) {
static char ike_rev[]="Ike rev ?";
- /* Read HW Rev First */
- func_class = READ_REG(dev->hpa + SBA_FCLASS);
-
ike_rev[8] = '0' + (char) (func_class & 0xff);
version = ike_rev;
} else {
static char reo_rev[]="REO rev ?";
- /* Read HW Rev First */
- func_class = READ_REG(dev->hpa + SBA_FCLASS);
-
reo_rev[8] = '0' + (char) (func_class & 0xff);
version = reo_rev;
}
+ if (!global_ioc_cnt) {
+ global_ioc_cnt = count_parisc_driver(&sba_driver);
+
+ /* Only Astro has one IOC per SBA */
+ if (!IS_ASTRO(&dev->id))
+ global_ioc_cnt *= 2;
+ }
+
printk(KERN_INFO "%s found %s at 0x%lx\n",
MODULE_NAME, version, dev->hpa);
+#ifdef DEBUG_SBA_INIT
+ sba_dump_tlb(dev->hpa);
+#endif
+
sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
if (NULL == sba_dev) {
printk(KERN_ERR MODULE_NAME " - couldn't alloc sba_device\n");
@@ -1834,30 +1986,12 @@ sba_driver_callback(struct parisc_device
} else {
create_proc_info_entry("Reo", 0, proc_runway_root, sba_proc_info);
}
+#if 0
create_proc_info_entry("bitmap", 0, proc_runway_root, sba_resource_map);
#endif
+#endif
return 0;
}
-
-static struct parisc_device_id sba_tbl[] = {
- { HPHW_IOA, HVERSION_REV_ANY_ID, ASTRO_RUNWAY_PORT, 0xb },
- { HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_MERCED_PORT, 0xc },
- { HPHW_BCPORT, HVERSION_REV_ANY_ID, REO_MERCED_PORT, 0xc },
- { HPHW_BCPORT, HVERSION_REV_ANY_ID, REOG_MERCED_PORT, 0xc },
-/* These two entries commented out because we don't find them in a
- * buswalk yet. If/when we do, they would cause us to think we had
- * many more SBAs then we really do.
- * { HPHW_BCPORT, HVERSION_REV_ANY_ID, ASTRO_ROPES_PORT, 0xc },
- * { HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_ROPES_PORT, 0xc },
- */
- { 0, }
-};
-
-static struct parisc_driver sba_driver = {
- name: MODULE_NAME,
- id_table: sba_tbl,
- probe: sba_driver_callback,
-};
/*
** One time initialization to let the world know the SBA was found.
Index: include/asm-parisc/hardware.h
===================================================================
RCS file: /var/cvs/linux/include/asm-parisc/hardware.h,v
retrieving revision 1.36
diff -u -p -r1.36 hardware.h
--- include/asm-parisc/hardware.h 2002/02/28 07:11:20 1.36
+++ include/asm-parisc/hardware.h 2002/04/05 07:43:17
@@ -139,6 +139,7 @@ extern struct parisc_device *alloc_pa_de
struct hardware_path *path);
extern int register_parisc_device(struct parisc_device *dev);
extern int register_parisc_driver(struct parisc_driver *driver);
+extern int count_parisc_driver(struct parisc_driver *driver);
extern int unregister_parisc_driver(struct parisc_driver *driver);
extern void walk_central_bus(void);
extern void fixup_child_irqs(struct parisc_device *parent, int irqbase,
Index: include/asm-parisc/io.h
===================================================================
RCS file: /var/cvs/linux/include/asm-parisc/io.h,v
retrieving revision 1.27
diff -u -p -r1.27 io.h
--- include/asm-parisc/io.h 2002/02/25 23:06:48 1.27
+++ include/asm-parisc/io.h 2002/04/05 07:43:17
@@ -92,7 +92,7 @@ extern __inline__ unsigned long long __r
: "=r" (ret) : "r" (addr) );
#else
/* two reads may have side effects.. */
- ret = (unsigned long long) __raw_readl(addr) << 32;
+ ret = ((u64) __raw_readl(addr)) << 32;
ret |= __raw_readl(addr+4);
#endif
return ret;
@@ -142,16 +142,20 @@ extern __inline__ void __raw_writeq(unsi
#define readb(addr) (*(volatile unsigned char *) (addr))
#define readw(addr) (*(volatile unsigned short *) (addr))
#define readl(addr) (*(volatile unsigned int *) (addr))
+#define readq(addr) (*(volatile u64 *) (addr))
#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b))
#define writew(b,addr) (*(volatile unsigned short *) (addr) = (b))
#define writel(b,addr) (*(volatile unsigned int *) (addr) = (b))
+#define writeq(b,addr) (*(volatile u64 *) (addr) = (b))
#else /* !USE_HPPA_IOREMAP */
-#define readb(addr) __raw_readb((unsigned long)addr)
-#define readw(addr) le16_to_cpu(__raw_readw((unsigned long)addr))
-#define readl(addr) le32_to_cpu(__raw_readl((unsigned long)addr))
-#define writeb(b,addr) __raw_writeb(b,(unsigned long)addr)
-#define writew(b,addr) __raw_writew(cpu_to_le16(b),(unsigned long)addr)
-#define writel(b,addr) __raw_writel(cpu_to_le32(b),(unsigned long)addr)
+#define readb(addr) __raw_readb((unsigned long)(addr))
+#define readw(addr) le16_to_cpu(__raw_readw((unsigned long)(addr)))
+#define readl(addr) le32_to_cpu(__raw_readl((unsigned long)(addr)))
+#define readq(addr) le64_to_cpu(__raw_readq((unsigned long)(addr)))
+#define writeb(b,addr) __raw_writeb(b,(unsigned long)(addr))
+#define writew(b,addr) __raw_writew(cpu_to_le16(b),(unsigned long)(addr))
+#define writel(b,addr) __raw_writel(cpu_to_le32(b),(unsigned long)(addr))
+#define writeq(b,addr) __raw_writeq(cpu_to_le64(b),(unsigned long)(addr))
#endif /* !USE_HPPA_IOREMAP */
extern void memcpy_fromio(void *dest, unsigned long src, int count);
Index: include/asm-parisc/processor.h
===================================================================
RCS file: /var/cvs/linux/include/asm-parisc/processor.h,v
retrieving revision 1.52
diff -u -p -r1.52 processor.h
--- include/asm-parisc/processor.h 2001/11/10 00:10:49 1.52
+++ include/asm-parisc/processor.h 2002/04/05 07:43:17
@@ -57,6 +57,7 @@ struct system_cpuinfo_parisc {
struct pdc_model model;
unsigned long versions;
unsigned long cpuid;
+ unsigned long capabilities;
char sys_model_name[81]; /* PDC-ROM returnes this model name */
} pdc;