[parisc-linux-cvs] DIFF -pa67 (Multi-IOMMU for SBA)

Grant Grundler grundler@puffin.external.hp.com
Tue, 23 Oct 2001 10:17:43 -0600


Sorry...forgot to post the diff for -pa67 *and* I forgot
to include the -pa## in the commit comments. *sigh*

grant


Index: Makefile
===================================================================
RCS file: /home/cvs/parisc/linux/Makefile,v
retrieving revision 1.178
diff -u -p -r1.178 Makefile
--- Makefile	2001/10/22 21:41:02	1.178
+++ Makefile	2001/10/23 05:59:33
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 9
-EXTRAVERSION = -pa66
+EXTRAVERSION = -pa67
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
Index: arch/parisc/kernel/lba_pci.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/lba_pci.c,v
retrieving revision 1.40
diff -u -p -r1.40 lba_pci.c
--- lba_pci.c	2001/10/17 14:14:12	1.40
+++ lba_pci.c	2001/10/23 05:59:34
@@ -1352,18 +1352,10 @@ lba_driver_callback(struct parisc_device
 	** Tell I/O SAPIC driver we have a IRQ handler/region.
 	*/
 	tmp_obj = iosapic_register(dev->hpa + LBA_IOSAPIC_BASE);
-#if 0	/* FIXME: some graphic cards (e.g. 103c:1005) don't have an IRT. */
-	if (NULL == tmp_obj) {
-		/* iosapic may have failed. But more likely the
-		** slot isn't occupied and thus has no IRT entries.
-		** iosapic_register looks for this iosapic in the IRT
-		** before bothering to allocating data structures
-		** we don't need.
-		*/
-		DBG(KERN_WARNING MODULE_NAME ": iosapic_register found no IRT entries for this HBA\n");
-		return (1);
-	}
-#endif
+
+	/* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't
+	**	have an IRT entry will get NULL back from iosapic code.
+	*/
 	
 	lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL);
 	if (NULL == lba_dev)
@@ -1385,6 +1377,7 @@ lba_driver_callback(struct parisc_device
 
 	lba_dev->hba.base_addr = dev->hpa;  /* faster access */
 	lba_dev->iosapic_obj = tmp_obj;  /* save interrupt handle */
+	lba_dev->hba.iommu = sba_get_iommu(dev);  /* get iommu data */
 
 	/* ------------ Second : initialize common stuff ---------- */
 	lba_common_init(lba_dev);
Index: arch/parisc/kernel/sba_iommu.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/sba_iommu.c,v
retrieving revision 1.52
diff -u -p -r1.52 sba_iommu.c
--- sba_iommu.c	2001/09/20 18:20:13	1.52
+++ sba_iommu.c	2001/10/23 05:59:34
@@ -15,7 +15,6 @@
 ** This module initializes the IOC (I/O Controller) found on B1000/C3000/
 ** J5000/J7000/N-class/L-class machines and their successors.
 **
-** FIXME: Multi-IOC support missing - depends on hp_device data
 ** FIXME: add DMA hint support programming in both sba and lba modules.
 */
 
@@ -292,7 +291,15 @@ static unsigned long sba_mem_ratio = 4;
 
 #ifdef DEBUG_SBA_INIT
 
-/* When __LP64__ isn't defined, READ_REG64() is two 32-bit reads */
+/* NOTE: When __LP64__ isn't defined, READ_REG64() is two 32-bit reads */
+
+/**
+ * sba_dump_ranges - debugging only - print ranges assigned to this IOA
+ * @hpa: base address of the sba
+ *
+ * Print the MMIO and IO Port address ranges forwarded by an Astro/Ike/RIO
+ * IO Adapter (aka Bus Converter).
+ */
 static void
 sba_dump_ranges(char *hpa)
 {
@@ -306,6 +313,12 @@ sba_dump_ranges(char *hpa)
 	DBG_INIT("IOS_DIRECT_ROUTE: %016lx\n", READ_REG64(hpa+IOS_DIRECT_ROUTE));
 }
 
+/**
+ * sba_dump_tlb - debugging only - print IOMMU operating parameters
+ * @hpa: base address of the IOMMU
+ *
+ * Print the size/location of the IO MMU PDIR.
+ */
 static void
 sba_dump_tlb(char *hpa)
 {
@@ -321,6 +334,14 @@ sba_dump_tlb(char *hpa)
 
 #ifdef ASSERT_PDIR_SANITY
 
+/**
+ * sba_dump_pdir_entry - debugging only - print one IOMMU PDIR entry
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @msg: text to print ont the output line.
+ * @pide: pdir index.
+ *
+ * Print one entry of the IO MMU PDIR in human readable form.
+ */
 static void
 sba_dump_pdir_entry(struct ioc *ioc, char *msg, uint pide)
 {
@@ -346,7 +367,13 @@ sba_dump_pdir_entry(struct ioc *ioc, cha
 }
 
 
-/* Verify the resource map and pdir state is consistent */
+/**
+ * sba_check_pdir - debugging only - consistency checker
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @msg: text to print ont the output line.
+ *
+ * Verify the resource map and pdir state is consistent
+ */
 static int
 sba_check_pdir(struct ioc *ioc, char *msg)
 {
@@ -383,6 +410,14 @@ sba_check_pdir(struct ioc *ioc, char *ms
 }
 
 
+/**
+ * sba_dump_sg - debugging only - print Scatter-Gather list
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @startsg: head of the SG list
+ * @nents: number of entries in SG list
+ *
+ * print the SG list so we can verify it's correct by hand.
+ */
 static void
 sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
 {
@@ -424,14 +459,16 @@ sba_dump_sg( struct ioc *ioc, struct sca
 #define RESMAP_MASK(n)    (~0UL << (BITS_PER_LONG - (n)))
 #define RESMAP_IDX_MASK   (sizeof(unsigned long) - 1)
 
-
-/*
-** Perf optimizations:
-** o search for log2(size) bits at a time.
-**
-** Search should use register width as "stride" to search the res_map. 
-*/
 
+/**
+ * sba_search_bitmap - find free space in IO PDIR resource bitmap
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @bits_wanted: number of entries we need.
+ *
+ * Find consecutive free bits in resource bitmap.
+ * Each bit represents one entry in the IO Pdir.
+ * Cool perf optimization: search for log2(size) bits at a time.
+ */
 static SBA_INLINE unsigned long
 sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
 {
@@ -506,6 +543,14 @@ sba_search_bitmap(struct ioc *ioc, unsig
 }
 
 
+/**
+ * sba_alloc_range - find free bits and mark them in IO PDIR resource bitmap
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @size: number of bytes to create a mapping for
+ *
+ * Given a size, find consecutive unmarked and then mark those bits in the
+ * resource bit map.
+ */
 static int
 sba_alloc_range(struct ioc *ioc, size_t size)
 {
@@ -561,9 +606,14 @@ sba_alloc_range(struct ioc *ioc, size_t 
 }
 
 
-/*
-** clear bits in the ioc's resource map
-*/
+/**
+ * sba_free_range - unmark bits in IO PDIR resource bitmap
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @iova: IO virtual address which was previously allocated.
+ * @size: number of bytes to create a mapping for
+ *
+ * clear bits in the ioc's resource map
+ */
 static SBA_INLINE void
 sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size)
 {
@@ -606,31 +656,36 @@ sba_free_range(struct ioc *ioc, dma_addr
 typedef unsigned long space_t;
 #define KERNEL_SPACE 0
 
-/*
-* SBA Mapping Routine
-*
-* Given a virtual address (vba, arg2) and space id, (sid, arg1)
-* sba_io_pdir_entry() loads the I/O PDIR entry pointed to by
-* pdir_ptr (arg0). Each IO Pdir entry consists of 8 bytes as
-* shown below (MSB == bit 0):
-*
-*  0                    19                                 51   55       63
-* +-+---------------------+----------------------------------+----+--------+
-* |V|        U            |            PPN[43:12]            | U  |   VI   |
-* +-+---------------------+----------------------------------+----+--------+
-*
-*  V  == Valid Bit
-*  U  == Unused
-* PPN == Physical Page Number
-* VI  == Virtual Index (aka Coherent Index)
-*
-* The physical address fields are filled with the results of the LPA
-* instruction.  The virtual index field is filled with the results of
-* of the LCI (Load Coherence Index) instruction.  The 8 bits used for
-* the virtual index are bits 12:19 of the value returned by LCI.
-*
-* We need to pre-swap the bytes since PCX-W is Big Endian.
-*/
+/**
+ * sba_io_pdir_entry - fill in one IO PDIR entry
+ * @pdir_ptr:  pointer to IO PDIR entry
+ * @sid: process Space ID
+ * @vba: Virtual CPU address of buffer to map
+ *
+ * SBA Mapping Routine
+ *
+ * Given a virtual address (vba, arg2) and space id, (sid, arg1)
+ * sba_io_pdir_entry() loads the I/O PDIR entry pointed to by
+ * pdir_ptr (arg0). Each IO Pdir entry consists of 8 bytes as
+ * shown below (MSB == bit 0):
+ *
+ *  0                    19                                 51   55       63
+ * +-+---------------------+----------------------------------+----+--------+
+ * |V|        U            |            PPN[43:12]            | U  |   VI   |
+ * +-+---------------------+----------------------------------+----+--------+
+ *
+ *  V  == Valid Bit
+ *  U  == Unused
+ * PPN == Physical Page Number
+ * VI  == Virtual Index (aka Coherent Index)
+ *
+ * The physical address fields are filled with the results of the LPA
+ * instruction.  The virtual index field is filled with the results of
+ * of the LCI (Load Coherence Index) instruction.  The 8 bits used for
+ * the virtual index are bits 12:19 of the value returned by LCI.
+ *
+ * We need to pre-swap the bytes since PCX-W is Big Endian.
+ */
 
 void SBA_INLINE
 sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba)
@@ -653,15 +708,22 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t
 }
 
 
-/***********************************************************
- * The Ike PCOM (Purge Command Register) is to purge
- * stale entries in the IO TLB when unmapping entries.
+/**
+ * sba_mark_invalid - invalidate one or more IO PDIR entries
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @iova:  IO Virtual Address mapped earlier
+ * @byte_cnt:  number of bytes this mapping covers.
  *
+ * Marking the IO PDIR entry(ies) as Invalid and invalidate
+ * corresponding IO TLB entry. The Ike PCOM (Purge Command Register)
+ * is to purge stale entries in the IO TLB when unmapping entries.
+ *
  * The PCOM register supports purging of multiple pages, with a minium
  * of 1 page and a maximum of 2GB. Hardware requires the address be
  * aligned to the size of the range being purged. The size of the range
- * must be a power of 2.
- ***********************************************************/
+ * must be a power of 2. The "Cool perf optimization" in the
+ * allocation routine helps keep that true.
+ */
 static SBA_INLINE void
 sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
 {
@@ -716,6 +778,13 @@ sba_mark_invalid(struct ioc *ioc, dma_ad
 	WRITE_REG(iovp, ioc->ioc_hpa+IOC_PCOM);
 }
 
+/**
+ * sba_dma_supported - PCI driver can query DMA support
+ * @dev: instance of PCI owned by the driver that's asking
+ * @mask:  number of address bits this PCI device can handle
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static int
 sba_dma_supported( struct pci_dev *dev, dma_addr_t mask)
 {
@@ -732,13 +801,19 @@ sba_dma_supported( struct pci_dev *dev, 
 }
 
 
-/*
-** map_single returns a fully formed IOVA
-*/
+/**
+ * sba_map_single - map one buffer and return IOVA for DMA
+ * @dev: instance of PCI owned by the driver that's asking.
+ * @addr:  driver buffer to map.
+ * @size:  number of bytes to map in driver buffer.
+ * @direction:  R/W or both.
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static dma_addr_t
 sba_map_single(struct pci_dev *dev, void *addr, size_t size, int direction)
 {
-	struct ioc *ioc = &sba_list->ioc[0];  /* FIXME : see Multi-IOC below */
+	struct ioc *ioc;
 	unsigned long flags; 
 	dma_addr_t iovp;
 	dma_addr_t offset;
@@ -747,6 +822,10 @@ sba_map_single(struct pci_dev *dev, void
 
 	ASSERT(size > 0);
 
+	ASSERT(dev->sysdata);
+	ioc = GET_IOC(dev);
+	ASSERT(ioc);
+
 	/* save offset bits */
 	offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK;
 
@@ -799,32 +878,33 @@ sba_map_single(struct pci_dev *dev, void
 }
 
 
+/**
+ * sba_unmap_single - unmap one IOVA and free resources
+ * @dev: instance of PCI owned by the driver that's asking.
+ * @iova:  IOVA of driver buffer previously mapped.
+ * @size:  number of bytes mapped in driver buffer.
+ * @direction:  R/W or both.
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static void
 sba_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, int direction)
 {
-#ifdef FIXME
-/* Multi-IOC (ie N-class) :  need to lookup IOC from dev
-** o If we can't know about lba PCI data structs, that eliminates ->sysdata.
-** o walking up pcidev->parent dead ends at elroy too
-** o leaves hashing dev->bus->number into some lookup.
-**   (may only work for N-class)
-** o use (struct pci_hba) and put fields in there for DMA.
-**   (ioc and per device dma_hint.)
-**
-** Last one seems the clearest and most promising.
-** sba_dma_supported() fill in those fields when the driver queries
-** the system for support.
-*/
-	struct ioc *ioc = (struct ioc *) ((struct pci_hba *) (dev->sysdata))->dma_data;
-#else
-	struct ioc *ioc = &sba_list->ioc[0];
-#endif
+	struct ioc *ioc;
 #ifdef DELAYED_RESOURCE_CNT
-	struct sba_dma_pair *d = &(ioc->saved[ioc->saved_cnt]);
+	struct sba_dma_pair *d;
 #endif
-
 	unsigned long flags; 
 	dma_addr_t offset;
+
+	ASSERT(dev->sysdata);
+	ioc = GET_IOC(dev);
+	ASSERT(ioc);
+
+#ifdef DELAYED_RESOURCE_CNT
+	*d = &(ioc->saved[ioc->saved_cnt]);
+#endif
+
 	offset = iova & ~IOVP_MASK;
 
 	DBG_RUN("%s() iovp 0x%lx/%x\n",
@@ -874,6 +954,14 @@ sba_unmap_single(struct pci_dev *dev, dm
 }
 
 
+/**
+ * sba_alloc_consistent - allocate/map shared mem for DMA
+ * @hwdev: instance of PCI owned by the driver that's asking.
+ * @size:  number of bytes mapped in driver buffer.
+ * @dma_handle:  IOVA of new buffer.
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static void *
 sba_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
 {
@@ -896,6 +984,15 @@ sba_alloc_consistent(struct pci_dev *hwd
 }
 
 
+/**
+ * sba_free_consistent - free/unmap shared mem for DMA
+ * @hwdev: instance of PCI owned by the driver that's asking.
+ * @size:  number of bytes mapped in driver buffer.
+ * @vaddr:  virtual address IOVA of "consistent" buffer.
+ * @dma_handler:  IO virtual address of "consistent" buffer.
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static void
 sba_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
 {
@@ -915,6 +1012,17 @@ sba_free_consistent(struct pci_dev *hwde
 int dump_run_sg = 0;
 #endif
 
+
+/**
+ * sba_fill_pdir - write allocated SG entries into IO PDIR
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @startsg:  list of IOVA/size pairs
+ * @nents: number of entries in startsg list
+ *
+ * Take preprocessed SG list and write corresponding entries
+ * in the IO PDIR.
+ */
+
 static SBA_INLINE int
 sba_fill_pdir(
 	struct ioc *ioc,
@@ -1001,15 +1109,20 @@ sba_fill_pdir(
 	(((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - PAGE_SHIFT)) == 0UL)
 
 
-/*
-** First pass is to walk the SG list and determine where the breaks are
-** in the DMA stream. Allocates PDIR entries but does not fill them.
-** Returns the number of DMA chunks.
-**
-** Doing the fill seperate from the coalescing/allocation keeps the
-** code simpler. Future enhancement could make one pass through
-** the sglist do both.
-*/
+/**
+ * sba_coalesce_chunks - preprocess the SG list
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @startsg:  list of IOVA/size pairs
+ * @nents: number of entries in startsg list
+ *
+ * First pass is to walk the SG list and determine where the breaks are
+ * in the DMA stream. Allocates PDIR entries but does not fill them.
+ * Returns the number of DMA chunks.
+ *
+ * Doing the fill seperate from the coalescing/allocation keeps the
+ * code simpler. Future enhancement could make one pass through
+ * the sglist do both.
+ */
 static SBA_INLINE int
 sba_coalesce_chunks( struct ioc *ioc,
 	struct scatterlist *startsg,
@@ -1125,19 +1238,28 @@ sba_coalesce_chunks( struct ioc *ioc,
 }
 
 
-/*
-** And this algorithm still generally only ends up coalescing entries
-** that happens to be on the same page due to how sglists are assembled.
-*/
+/**
+ * sba_map_sg - map Scatter/Gather list
+ * @dev: instance of PCI owned by the driver that's asking.
+ * @sglist:  array of buffer/length pairs
+ * @nents:  number of entries in list
+ * @direction:  R/W or both.
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static int
 sba_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
 {
-	struct ioc *ioc = &sba_list->ioc[0];  /* FIXME : see Multi-IOC below */
+	struct ioc *ioc;
 	int coalesced, filled = 0;
 	unsigned long flags;
 
 	DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents);
 
+	ASSERT(dev->sysdata);
+	ioc = GET_IOC(dev);
+	ASSERT(ioc);
+
 	/* Fast path single entry scatterlists. */
 	if (nents == 1) {
 		sg_dma_address(sglist)= sba_map_single(dev, sglist->address,
@@ -1197,10 +1319,19 @@ sba_map_sg(struct pci_dev *dev, struct s
 }
 
 
+/**
+ * sba_unmap_sg - unmap Scatter/Gather list
+ * @dev: instance of PCI owned by the driver that's asking.
+ * @sglist:  array of buffer/length pairs
+ * @nents:  number of entries in list
+ * @direction:  R/W or both.
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static void 
 sba_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
 {
-	struct ioc *ioc = &sba_list->ioc[0];  /* FIXME : see Multi-IOC below */
+	struct ioc *ioc;
 #ifdef ASSERT_PDIR_SANITY
 	unsigned long flags;
 #endif
@@ -1208,6 +1339,10 @@ sba_unmap_sg(struct pci_dev *dev, struct
 	DBG_RUN_SG("%s() START %d entries,  %p,%x\n",
 		__FUNCTION__, nents, sglist->address, sglist->length);
 
+	ASSERT(dev->sysdata);
+	ioc = GET_IOC(dev);
+	ASSERT(ioc);
+
 #ifdef CONFIG_PROC_FS
 	ioc->usg_calls++;
 #endif
@@ -1666,11 +1801,13 @@ sba_driver_callback(struct parisc_device
 		printk(KERN_ERR MODULE_NAME " - couldn't alloc sba_device\n");
 		return(1);
 	}
+
+	dev->sysdata = (void *) sba_dev;
 	memset(sba_dev, 0, sizeof(struct sba_device));
+
 	for(i=0; i<MAX_IOC; i++)
 		spin_lock_init(&(sba_dev->ioc[i].res_lock));
 
-
 	sba_dev->hw_rev = func_class;
 	sba_dev->iodc = &dev->id;
 	sba_dev->name = dev->name;
@@ -1700,10 +1837,8 @@ static struct parisc_device_id sba_tbl[]
 	{ HPHW_IOA, HVERSION_REV_ANY_ID, ASTRO_RUNWAY_PORT, 0xb },
 	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, ASTRO_ROPES_PORT, 0xb },
 	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, REO_MERCED_PORT, 0xc },
-#if 0
 	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_MERCED_PORT, 0xb },
 	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_ROPES_PORT, 0xb },
-#endif
 	{ 0, }
 };
 
@@ -1721,4 +1856,24 @@ static struct parisc_driver sba_driver =
 void __init sba_init(void)
 {
 	register_parisc_driver(&sba_driver);
+}
+
+
+/**
+ * sba_get_iommu - Assign the iommu pointer for the pci bus controller.
+ * @dev: The parisc device.
+ *
+ * This function searches through the registerd IOMMU's and returns the
+ * appropriate IOMMU data for the given parisc PCI controller.
+ */
+void * sba_get_iommu(struct parisc_device *pci_hba)
+{
+	struct sba_device *sba = (struct sba_device *) pci_hba->parent->sysdata;
+	char t = pci_hba->parent->id.hw_type;
+	int iocnum = (pci_hba->hw_path >> 3);	/* rope # */
+
+	if ((t!=HPHW_IOA) && (t!=HPHW_BCPORT))
+		BUG();
+
+	return &(sba->ioc[iocnum]);
 }
Index: arch/parisc/kernel/setup.c
===================================================================
RCS file: /home/cvs/parisc/linux/arch/parisc/kernel/setup.c,v
retrieving revision 1.93
diff -u -p -r1.93 setup.c
--- setup.c	2001/10/11 23:43:27	1.93
+++ setup.c	2001/10/23 05:59:34
@@ -195,15 +195,15 @@ void __init parisc_init(void)
 			boot_cpu_data.cpu_hz / 1000000,
 			boot_cpu_data.cpu_hz % 1000000	);
 
+	/* These are in a non-obvious order, will fix when we have an iotree */
 #if defined(CONFIG_IOSAPIC)
 	iosapic_init();
 #endif
-	/* These are in a non-obvious order, will fix when we have an iotree */
-#if defined(CONFIG_PCI_LBA)
-	lba_init();
-#endif
 #if defined(CONFIG_IOMMU_SBA)
 	sba_init();
+#endif
+#if defined(CONFIG_PCI_LBA)
+	lba_init();
 #endif
 #if defined(CONFIG_IOMMU_CCIO)
 	ccio_init();
Index: include/asm-parisc/hardware.h
===================================================================
RCS file: /home/cvs/parisc/linux/include/asm-parisc/hardware.h,v
retrieving revision 1.26
diff -u -p -r1.26 hardware.h
--- hardware.h	2001/10/22 21:38:06	1.26
+++ hardware.h	2001/10/23 05:59:35
@@ -30,6 +30,7 @@ struct parisc_device {
 	struct parisc_device *sibling;
 	struct parisc_device *child;
 	struct parisc_driver *driver;	/* Driver for this device */
+	void		*sysdata;	/* Driver instance private data */
 	char name[80];			/* The hardware description */
 	int		irq;
 
Index: include/asm-parisc/pci.h
===================================================================
RCS file: /home/cvs/parisc/linux/include/asm-parisc/pci.h,v
retrieving revision 1.32
diff -u -p -r1.32 pci.h
--- pci.h	2001/10/22 05:10:05	1.32
+++ pci.h	2001/10/23 05:59:35
@@ -240,4 +240,8 @@ struct pci_dev * ccio_get_fake(struct pa
 #define ccio_get_fake(dev) (NULL)
 #endif /* !CONFIG_IOMMU_CCIO */
 
+#ifdef CONFIG_IOMMU_SBA
+void * sba_get_iommu(struct parisc_device *dev);
+#endif
+
 #endif /* __ASM_PARISC_PCI_H */