All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [parisc-linux] [patch 2/2] backport of sba sg list management to ccio-dma
@ 2007-11-28  8:25 Joel Soete
  2007-11-29 18:50 ` Grant Grundler
  0 siblings, 1 reply; 20+ messages in thread
From: Joel Soete @ 2007-11-28  8:25 UTC (permalink / raw)
  To: grundler; +Cc: parisc-linux

> On Tue, Nov 27, 2007 at 01:48:32PM +0100, Joel Soete wrote:
> > grr even thought I read well:
> > "[snip]
> > Hardware Implications
> > Cache memory is defined as a small, high-speed block of memory located close
> > to the processor. On the HP PA 7200 and PA8000 processors, a portion of the
> > software virtual address (called the virtual index) is used as the cache
lookup.
> > [snip]"
> > 
> > That's what confusing me, sorry.
> 
> You need to read about "VIVT" caches (Virtual Indexed, Virtual Tagged).
> The "Virtual Index" bits have to be provided by any cache coherent traffic
> in order to be cache coherent. That's how the caches know _where_ in the
> cache to find potential hits for a given cacheline.
> 
For sure I need more reading but imho this paper is already clear on subject:
my understanding (in short terms) is that cpu cache entry should be the same
virtual address as DMA cache else it would need additional stuff to check
physical address, right?

> ...
> > >  AFAIK U2/U-Turn both are fixed
> > > on which page size the support. That would work fine with linux since we
> > > just increase the base page size (e.g. 16k or 64k pages for IA64).
> > >
> > Well, reading further, even thought it seems to be 'programmable':
> > "[snip]
> > A second feature of this scheme is that it helps limit the overhead of the I/O
> > page directory. Recall that the I/O page directory contains all active address
> > translations and must be memory-resident. I/O page directory size is equal to
> > the size of one entry times 2^k, where k is the number of chain ID bits plus
> > the number of block ID bits. The division between the chain ID and the block
> > ID is programmable, as is the total number of bits (k), so software can reduce
> > the memory overhead of the I/O page directory for systems with smaller I/O
> > subsystems if we guarantee that the leading address bits are zero for these
> > smaller systems.
> > [snip]"
> > 
> > That said I discover a difference between my d380 and c110 config:
> > for c110 no CONFIG_EISA support,
> > for d380 CONFIG_EISA yes
> 
> EISA introduces a different IOMMU that we haven't written any code for.
> We need the "WAX ERS" IIRC.
> parisc-linux currently does not support DMA by EISA devices.
> 
That's for this last reason that I disable it in the config of my c110 (but I
don't remember why I didn't reproduce it on the d380?)
 
> ...
> > So make a difference in HINT_STOP_MOST value.
> > Anyway, may be could it help to delay also a bit issue on c110 as on d380 (may
> > be enough to re-install the system?)
> 
> You can try it and see if it helps.
> I don't have U2/U-Turn ERS anymore and thus can not review
> the original source of information.
> 
The hp engineer who help us to maintain our park of hp9000 made a few effort
to look for ERS doc but without success.

> > That siad, the above mentioned paper spoke about "Atomic or locked mode": is
> > it this HINT_STOP_MOST which enable this mode?
> 
> Sorry - I don't know. My guess is the ERS probably has that info.
> 
No worry, I just continue to play with this driver because this is the only
type of box on which I can still play p-l :-)

> 
> ...
> > What's your idea (afaik a500 didn't use ccio nor ncr53c720)?
> 
> You mean "Why test on a500 given A500 doesn't use ccio"?
> Just to make sure it's not a generic problem.
> 
I guess but would like to be sure that well undertood ;-)

> In general, I was expecting James Bottomley to have seen issues
> with ccio when testing on his C360 (in the past, not recently).
> 
I remember to have some few feedback from jejb but don't remember if he could
reproduce this test?

> hth,
> grant
> 
> 
In the mean time I will continue my reading, ...

Many thanks for your attention,
    J.
---
Pack Scarlet One, ADSL 6 Mbps + Telephonie, a partir de EUR 29,95...
http://www.scarlet.be/

_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux

^ permalink raw reply	[flat|nested] 20+ messages in thread
* Re: [parisc-linux] [patch 2/2] backport of sba sg list management to ccio-dma
@ 2007-11-27 12:48 Joel Soete
  2007-11-27 21:47 ` Grant Grundler
  0 siblings, 1 reply; 20+ messages in thread
From: Joel Soete @ 2007-11-27 12:48 UTC (permalink / raw)
  To: grundler; +Cc: parisc-linux

> On Mon, Nov 26, 2007 at 09:48:48AM +0100, Joel Soete wrote:
> ...
> > > The 12-bits per page (4k pages) is hard wired for the PA1.1 machines.
> > >
> > Ok but paper spoke of pa7200 (pa1.1) _and_ pa8000 (afaik pa2.0), so aware of
> > new cpu capability, but my understanding is that I/O page size seems to me it
> > could be different then cpu page size and would be fixed to 4k because of
> > "Block ID" size of 12bits?
> 
> J/K first released with PA1.1. PA8000 (PA2.0) was release Jan 2006
>  (See http://www.openpa.net/pa-risc_processors.html#xu) and I think this
> paper was originally targeted at PA1.1. The reference to (12-bit) is probably
> just a "bug" in updating the paper for PA2.0.
> 
grr even thought I read well:
"[snip]
Hardware Implications
Cache memory is defined as a small, high-speed block of memory located close
to the processor. On the HP PA 7200 and PA8000 processors, a portion of the
software virtual address (called the virtual index) is used as the cache lookup.
[snip]"

That's what confusing me, sorry.

> > That said, paper only spoke of J/K model.
> > C1xx and Dxxx are model which looks like J but some subtitle difference could
> > exist.
> 
> C1XX is UP. Dxxx is _very_ similar to J (SMP and many of the same IO options).
> 
> > > Right. PA2.0 machines can support variable page sizes and parisc-linux
> > > has "almost working" support bigger page sizes.
> > >
> > What's up for hpux?
> 
> Can you be more specific?
> hpux definitely support variable page sizes 

Exactely what am I curious about ;-)

>(Look for "POP" == Performance
> Optimized Pagesize in HP literature in mid-late 1990's).
Ok I will have a look.

> But HPUX ccio driver
> continues to use 4K pages because the IO TLB can't change the page size
> for each TLB entry like the CPU TLB can.
Nice to know ;-)

>  AFAIK U2/U-Turn both are fixed
> on which page size the support. That would work fine with linux since we
> just increase the base page size (e.g. 16k or 64k pages for IA64).
> 
Well, reading further, even thought it seems to be 'programmable':
"[snip]
A second feature of this scheme is that it helps limit the overhead of the I/O
page directory. Recall that the I/O page directory contains all active address
translations and must be memory-resident. I/O page directory size is equal to
the size of one entry times 2^k, where k is the number of chain ID bits plus
the number of block ID bits. The division between the chain ID and the block
ID is programmable, as is the total number of bits (k), so software can reduce
the memory overhead of the I/O page directory for systems with smaller I/O
subsystems if we guarantee that the leading address bits are zero for these
smaller systems.
[snip]"

That said I discover a difference between my d380 and c110 config:
for c110 no CONFIG_EISA support,
for d380 CONFIG_EISA yes

which is in fact a hack like mentioned in comments:
/*
** DMA "Page Type" and Hints
[snip]
** o STOP_MOST is needed for atomicity across cachelines.
**   Apparently only "some EISA devices" need this.
**   Using CONFIG_ISA is hack. Only the IOA with EISA under it needs
**   to use this hint iff the EISA devices needs this feature.
**   According to the U2 ERS, STOP_MOST enabled pages hurt performance.
[snip]
**
** FIXME: the default hints need to be per GSC device - not global.
**
** HP-UX dorks: linux device driver programming model is totally different
**    than HP-UX's. HP-UX always sets HINT_PREFETCH since it's drivers
**    do special things to work on non-coherent platforms...linux has to
**    be much more careful with this.
*/
#define IOPDIR_VALID    0x01UL
#define HINT_SAFE_DMA   0x02UL  /* used for pci_alloc_consistent() pages */
#ifdef CONFIG_EISA
#define HINT_STOP_MOST  0x04UL  /* LSL support */
#else
#define HINT_STOP_MOST  0x00UL  /* only needed for "some EISA devices" */
#endif
#define HINT_UDPATE_ENB 0x08UL  /* not used/supported by U2 */
#define HINT_PREFETCH   0x10UL  /* for outbound pages which are not SAFE */
[snip]"

So make a difference in HINT_STOP_MOST value.
Anyway, may be could it help to delay also a bit issue on c110 as on d380 (may
be enough to re-install the system?)

That siad, the above mentioned paper spoke about "Atomic or locked mode": is
it this HINT_STOP_MOST which enable this mode?


> > > > # while true ; do nice -n -3 tar -xspf linux-2.6.11-rc3-pa3.tar ; nice -n
> > > > -3 rm -rf linux-2.6.11-rc3-pa3 ; date ; done
> > >
> > > Sorry...same questions again:
> > > 	SMP or UP kernel?
> > Sorry UP only (one pb at a time)
> > [that said, my personal experiments with linux kernel (as well as hppa as
> > i386) don't make me expect a lot of smp stuff]
> > 
> > > 	Which kernel version?
> > >
> > Currently 2.6.23-pa (kyle's pa git tree)
> > (but pb was there since the beginning of 2.6. IIRC I made only very few test
> > with 2.4)
> 
> hrm. ok...I'll try the same on one of my a500's and see if that's
> reproduceable there as well.
> 
What's your idea (afaik a500 didn't use ccio nor ncr53c720)?

Thanks again,
    J.
> hth,
> grant
> 
> 
---
Pack Scarlet One, ADSL 6 Mbps + Telephonie, a partir de EUR 29,95...
http://www.scarlet.be/

_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux

^ permalink raw reply	[flat|nested] 20+ messages in thread
* Re: [parisc-linux] [patch 2/2] backport of sba sg list management to ccio-dma
@ 2007-11-26  8:48 Joel Soete
  2007-11-26 23:27 ` Grant Grundler
  0 siblings, 1 reply; 20+ messages in thread
From: Joel Soete @ 2007-11-26  8:48 UTC (permalink / raw)
  To: grundler; +Cc: kyle, parisc-linux

> On Sat, Nov 24, 2007 at 08:36:03PM +0000, Joel Soete wrote:
> > Hello Grant, Kyle,
> >
> > I finaly find an interesting paper on this Runway bc:
> > <http://www.hpl.hp.com/hpjournal/96feb/feb96a6.htm>
> 
> Yeah, I read that article around the time it was published.
> I was fortunate to have worked with Todd Kjos in the same group.
> 
Clear and accurate paper ;-)

> > I read it but i don't yet understand it in deep but this detail:
> > "The lower 12 bits of the address must be left alone because of the 4K-byte 
> > page size defined by the architecture."
> >
> > make me think that the IOVP_SHIFT of this ccio-dma driver would be always 
> > 12 what ever could be the PAGE_SHIFT
> 
> The 12-bits per page (4k pages) is hard wired for the PA1.1 machines. 
> 
Ok but paper spoke of pa7200 (pa1.1) _and_ pa8000 (afaik pa2.0), so aware of
new cpu capability, but my understanding is that I/O page size seems to me it
could be different then cpu page size and would be fixed to 4k because of
"Block ID" size of 12bits?

That said, paper only spoke of J/K model.
C1xx and Dxxx are model which looks like J but some subtitle difference could
exist.

> > (it's not yet possible but for pa8000 and later it could be greater)?
> 
> Right. PA2.0 machines can support variable page sizes and parisc-linux
> has "almost working" support bigger page sizes.
> 
What's up for hpux?

> > That said for the moment IOVP_SHIF == PAGE_SHIFT so couldn't be the reason 
> > of the followings issues.
> 
> Right, there might be other caching issues still though.
> 
> > On my d380, I reach to re-iterate some stress test on scsi ncr53c720 and 
> > LASI 53c700 with a simple read/write loop like:
> > # while true ; do nice -n -3 tar -xspf linux-2.6.11-rc3-pa3.tar ; nice -n 
> > -3 rm -rf linux-2.6.11-rc3-pa3 ; date ; done
> 
> Sorry...same questions again:
> 	SMP or UP kernel?
Sorry UP only (one pb at a time)
[that said, my personal experiments with linux kernel (as well as hppa as
i386) don't make me expect a lot of smp stuff]

> 	Which kernel version?
> 
Currently 2.6.23-pa (kyle's pa git tree)
(but pb was there since the beginning of 2.6. IIRC I made only very few test
with 2.4)

> 
> > With a fs build on a disk connected to a 53c710 hba, with or without my bp 
> > patch, unfortunately I always got same errors after some loop's occurence:
> > scsi3: (3:0) phase mismatch at 01e8, phase IO CD MSG BSY REQ MSG IN
> >  scsi3: Bus Reset detected, executing command 10a304e0, slot 10a0864c, dsp 
> > 001681e8[01e8]
> >   failing command because of reset, slot 10a08520, cmnd 10a30720
> ...
> > [snip]
> >
> > (this same disk connected to same lasi 53c710 of a b180 i.e. without 
> > ccio-dma could loop severall days without showing any issue)
> 
> B180 is using uncached memory for it's control data and this has a
> very different CPU timing. It's hard to say if the problem is a
> memory ordering issue in zalon support or a bug in ccio driver.
> 
> sorry, can't be more precise than that.
> 
No pb, thanks any way for your attention,

    J.
> cheers,
> grant
> 
> > datazone - block = 1714387061, count = 1
> > [snip]
> >
> > With the original ccio-dma driver it occures after few occurence of the 
> > loop (about 5) but my patch only delay the pb to several houres (not 
> > useless work but not yet enough).
> >
> > Any way fs is corrupted and this bring me to next major issue with my c110 
> > (using same ncr53c720, lasi 53c710 and ccio-dma drivers as d380). This box 
> > was sleeping till about a year, so I removed additional ram kit of 512Mb 
> > for another usage and restored original ram of 64Mb, but internal boot disk 
> > stay unchanged connected to the ncr53c720 hba.
> > When I tried to reboot it some weeks ago with an existing & known working 
> > kernels (from the time system still own 512Mb; e.g. 2.6.8.1-pa7, 
> > 2.6.14-pa0, 2.6.19), it started to make a fsck obviously but this always 
> > sadely (fsck generating a fs corrution, well not directly but by border 
> > effect) ended by fs corruption too. That's only with the very old debian 
> > install kernel 2.4.17-32 that I reach to reboot this system to install 
> > latest 2.6.23-pa.orig and 2.6.23-pa+patch kernels. I could also reach to 
> > reboot this box with latest mentioned kernels but as soon as I launched an 
> > 'apt-get dist-upgrade' (after a update obviously) fs corruption occured 
> > again. I was inocently expecting that after some reboot, fsck and renew 
> > dist-upgrade, I would finaly recover a system operational like my d380. But 
> > I was wrong and after 2 or 3 reboot this box became not-bootable anymore 
> > (having lost too much critical files on the root fs :_().
> >
> > [Sade sade sade to me: in 10 years of linux, it's the very first time I 
> > lost a system because of sw issue :__(]
> >
> > All this story to say in summary, a d380 with 256Mb of ram works more or 
> > less fine (if I don't stress scsi disk) but a c110 with few 64Mb is not 
> > usable at all (with either original or patched 2.6.23-pa kernels)?
> >
> > I have the filing that some cache coherency (I/O, mem??) lakes somewhere 
> > but I didn't understand where/what is the code that do it now, so if you 
> > have some more time to pin point it to me, I would greatly appreciate.
> >
> > TIA,
> > 	J.
> >
> 
> 
---
Pack Scarlet One, ADSL 6 Mbps + Telephonie, a partir de EUR 29,95...
http://www.scarlet.be/

_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux

^ permalink raw reply	[flat|nested] 20+ messages in thread
* Re: [parisc-linux] [patch 2/2] backport of sba sg list management to ccio-dma
@ 2007-10-23 16:15 Joel Soete
  0 siblings, 0 replies; 20+ messages in thread
From: Joel Soete @ 2007-10-23 16:15 UTC (permalink / raw)
  To: grundler; +Cc: kyle, parisc-linux

> On Sat, Oct 20, 2007 at 01:23:28PM -0400, Kyle McMartin wrote:
> > On Sat, Oct 20, 2007 at 05:21:44PM +0000, Joel Soete wrote:
> > > Hello Kyle,
> > > 
> > > Hppay that you finaly receive it ;-)
> > > (btw sorry for boucing)
> > > 
> > 
> > I've looked over the code, and it looks fine to me. Will wait for an ack
> > from Grant though, since I have no ability to test ccio :/
> 
> We both have access to the FtC test ring - but I think we are also both
> too lazy to build a kernel and test it on a remote box. :)
> 
> In general I'm ok with this code since I trust Joel is testing
> it with both NIC and storage devices and I'm too lazy to.
> 
> Some comments/requests/ideas below but nothing critical.
> 
> Apologies that I'm cut/pasting from the mailing list archive:
>    
http://lists.parisc-linux.org/pipermail/parisc-linux/2007-October/031998.html
> 
> I didn't have the original mail in my inbox anymore.
> 
> 
> +static CCIO_INLINE int
> +get_iovp_order(unsigned long size)
> +{
> +	int order;
> +
> +	size = (size - 1) >> (IOVP_SHIFT - 1);
> +	order = -1;
> +	do {
> +		size >>= 1;
> +		order++;
> +	} while (size);
> +	return order;
> +}
> 
> Would this be faster if written to use "ffs()"?
> 
This seems to be better fls then ffs like:
int get_iovp_order_faster(unsigned long size)
{
	return fls((size - 1) >> (IOVP_SHIFT));
}

Even thought following test seems to be ok:
	unsigned int a;
	unsigned long ul;

	/* for proof of concept
	*/
	for (ul=0; ul<536870914; ul++) {
		if ( get_iovp_order(ul) != get_iovp_order_faster(ul) ) {
			printf("get_iovp_order(%ld) = %ld (0x%x)\n\n", ul, a = get_iovp_order(ul), a);
			printf("get_iovp_order_faster(%ld) = %ld (0x%x)\n\n", ul, a =
get_iovp_order_faster(ul), a);
			exit (1);
		}
	}

But what would give the kernel generic (include/asm-generic/page.h: this is
what get_iovp_order() is if IOVP_SHIFT==PAGE_SHIFT) get_order(0): 0?
the answer is 20 for paric and ia32?
 
> 
> ...
> +#define ROUNDUP(x, y)		((x + ((y)-1)) & ~((y)-1))
> 
> ROUNDUP got replace in SBA with ALIGN(). Please use ALIGN instead.

Yes I figure it out later sorry.
 
> 
> ...
> +	} else {
> +		/*
> +		** Search the resource bit map on well-aligned values.
> +		** "o" is the alignment.
> +		** We need the alignment to invalidate I/O TLB using
> +		** xxx HW features in the unmap path.
> +		*/
> +		unsigned long o = 1 << get_iovp_order(pages_wanted << IOVP_SHIFT);
> +		uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o);
> +		unsigned long mask;
> 
> CCIO doesn't have this feature AFAIK. The comment only applies to SBA.
> Please remove the second sentence of the comment.
Ok.

> Searching on "well-aligned" values is still a good idea.
> 
> 
> NOTE: Each 8 consecutive CCIO IO PDIR mappings land on the same IO TLB entry.
> 
> To avoid thrashing the IO TLB, ideally CCIO code will do the following:
> 
> o map_sg (ie storage devices) use 8 bit alignment (ie each mapping start
>  on a new byte boundary).  Traditional block storage can complete the
>  IOs out of order and in parallel (via different controllers). This
>  would thrash one IO TLB entry if 8 seperate 4K DMA mappings are inflight
>  at the same time.
> 
> o map_single() (ie NICs) to just use the next available bit for a given
>   PCI device.  NIC DMA patterns (at least for a given stream) are linear.
>   The ccio_map_single() should track the last bitmap octet used for both
>   DMA_TO_DEVICE and FROM_DEVICE for each PCI device.
>   Once that octet is "used", find the next 8 bit field in the bitmap that
>   is available.
> 
> For a single NIC and one or two SCSI controllers, this probably doesn't
> make much difference unless you start measuring latency. Throughput
> should be nearly the same.
> 
> My guess is the biggest perf gain will come from reducing the number
> of "sync" ops by implementing DELAYED_RESOURCE_CNT. 
> 
> 
> ...
>  #ifdef CCIO_SEARCH_TIME
> +	udelay(100);
> 
> Did you want to keep udelay() call?
> 
Most probably not (just need more test)

> 
> ...
> +#else /* DELAYED_RESOURCE_CNT == 0 */
> +
> +	ccio_free_range(ioc, iova, size);
> +
> +	/* force fdc's to be visible now */
> +	asm volatile("sync" :: );
> +
> +#endif /* DELAYED_RESOURCE_CNT == 0 */
> 
> Does the asm("sync") need to be outside the #endif ?
> Please make sure "sync" is called exactly once IFF 
> the IO PDIR is modified.
> 
Well understand but this check stay hard to me (but I will try to spend a bit
more time to check)

> 
> ...
> +#ifdef CCIO_MAP_STATS
> +		ioc->usg_pages += sg_dma_len(sglist) >> IOVP_SHIFT;
> +		ioc->usingle_calls--;   /* kluge since call is unmap_sg() */
> +#endif
> 
> I wouldn't add MAP_STATS here.
> They aren't enabled in SBA becuase they impact performance too much.
> I expect that will always be true and would seriously consider removing
> MAP_STATS code from SBA as well. Timing the bitmap search is
> probably the only critical bit of info that really matters. 
> And that's for developement/testing only.
> 
mmm, I would so let stay here but with just additional comment to prevent to
activate it outside this developement/testing context?

> hth,
> grant
> 
Yes, tx a lot,
    J.

>
---
Pack Scarlet One, ADSL 6 Mbps + Telephonie, a partir de EUR 29,95...
http://www.scarlet.be/

_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux

^ permalink raw reply	[flat|nested] 20+ messages in thread
[parent not found: <4714E800.50709@scarlet.be>]
* [parisc-linux] [patch 2/2] backport of sba sg list management to ccio-dma
@ 2007-10-16 16:34 Joel Soete
  0 siblings, 0 replies; 20+ messages in thread
From: Joel Soete @ 2007-10-16 16:34 UTC (permalink / raw)
  To: parisc-linux, Kyle McMartin, Grant Grundler

[-- Attachment #1: Type: text/plain, Size: 342 bytes --]

And here is the main hunk:

This consist of 'backporting' to ccio of the most of Grant's work on sg list
management of sba-iommu.

According to some stress test on d380 it makes ncr driver more stable; improve
network perf on my d380 (from 110 to 430 kb/s);
(would allow in a next step merge some hunk of sba code in iommu-helper.h)

Tia,
J.

[-- Attachment #2: bp-sba_sg-2-ccio-dma.c.patch --]
[-- Type: text/x-patch, Size: 21952 bytes --]

Index: linux-current/drivers/parisc/ccio-dma.c
===================================================================
--- linux-current.orig/drivers/parisc/ccio-dma.c	2007-10-15 10:48:27.000000000 +0000
+++ linux-current/drivers/parisc/ccio-dma.c	2007-10-15 14:15:03.000000000 +0000
@@ -51,6 +51,7 @@
 #include <asm/io.h>
 #include <asm/hardware.h>       /* for register_module() */
 #include <asm/parisc-device.h>
+#include <asm/delay.h>
 
 /*
 ** Choose "ccio" since that's what HP-UX calls it.
@@ -102,7 +103,11 @@
 #define DBG_RUN_SG(x...)
 #endif
 
-#define CCIO_INLINE		inline
+#undef DMA_CHUNK_SIZE
+#define DMA_CHUNK_SIZE		(BITS_PER_LONG * IOVP_SIZE)
+#define DELAYED_RESOURCE_CNT	16
+
+#define CCIO_INLINE		__inline__
 #define WRITE_U32(value, addr)	__raw_writel(value, addr)
 #define READ_U32(addr)		__raw_readl(addr)
 
@@ -134,7 +139,7 @@
 	uint32_t	io_pdir_base;	/* Offset  7 */
 	uint32_t	io_io_low_hv;	/* Offset  8 */
 	uint32_t	io_io_high_hv;	/* Offset  9 */
-        uint32_t unused4[1];
+	uint32_t unused4[1];
 	uint32_t	io_chain_id_mask;/* Offset 11 */
 	uint32_t unused5[2];
 	uint32_t	io_io_low;	/* Offset 14 */
@@ -227,16 +232,28 @@
 ** returns before issuing subsequent writes.
 */
 
+typedef unsigned long	address_t;
+
 struct ioc {
 	struct ioa_registers __iomem *ioc_regs;	/* I/O MMU base address */
 	u8		*res_map;		/* resource map, bit == pdir entry */
 	u64		*pdir_base;		/* physical base address */
 	u32		pdir_size; 		/* bytes, function of IOV Space size */
-	u32		res_hint;		/* next available IOVP -
+	address_t	*res_hint;		/* next available IOVP -
 						   circular search */
-	u32		res_size;		/* size of resource map in bytes */
 	spinlock_t	res_lock;
 
+	uint32_t	res_bitshift;		/* from the LEFT! */
+	u32		res_size;		/* size of resource map in bytes */
+
+#if DELAYED_RESOURCE_CNT > 0
+	int             saved_cnt;
+	struct ioc_dma_pair {
+		dma_addr_t      iova;
+		size_t          size;
+	} saved[DELAYED_RESOURCE_CNT];
+#endif
+
 #ifdef CCIO_SEARCH_TIME
 #define CCIO_SEARCH_SAMPLE 0x100
 	unsigned long	avg_search[CCIO_SEARCH_SAMPLE];
@@ -259,7 +276,7 @@
 	u32		chainid_shift;	/* specify bit location of chain_id */
 	struct ioc	*next;		/* Linked list of discovered iocs */
 	const char	*name;		/* device name from firmware */
-	unsigned int	hw_path;	/* the hardware path this ioc is associatd with */
+	uint32_t	hw_path;	/* the hardware path this ioc is associatd with */
 	struct pci_dev	*fake_pci_dev;	/* the fake pci_dev for non-pci devs */
 	struct resource	mmio_region[2];	/* The "routed" MMIO regions */
 };
@@ -290,45 +307,115 @@
 #define CCIO_IOVA(iovp,offset)	((iovp) | (offset))
 #define CCIO_IOVP(iova)		((iova) & IOVP_MASK)
 
+#define PDIR_ENTRY_SIZE		sizeof(u64)
 #define PDIR_INDEX(iovp)	((iovp)>>IOVP_SHIFT)
+
+#define RESMAP_MASK(n)		(~0UL << (BITS_PER_LONG - (n)))
+#define RESMAP_IDX_MASK		(sizeof(unsigned long) - 1)
+
+/**
+ * For most cases the normal get_order is sufficient, however it limits us
+ * to PAGE_SIZE being the minimum mapping alignment and TC flush granularity.
+ * It only incurs about 1 clock cycle to use this one with the static variable
+ * and makes the code more intuitive.
+ */
+static CCIO_INLINE int
+get_iovp_order(unsigned long size)
+{
+	int order;
+
+	size = (size - 1) >> (IOVP_SHIFT - 1);
+	order = -1;
+	do {
+		size >>= 1;
+		order++;
+	} while (size);
+	return order;
+}
+
 #define MKIOVP(pdir_idx)	((long)(pdir_idx) << IOVP_SHIFT)
-#define MKIOVA(iovp,offset)	(dma_addr_t)((long)iovp | (long)offset)
+#define MKIOVA(iovp, offset)	(dma_addr_t)((long)iovp | (long)offset)
+#define ROUNDUP(x, y)		((x + ((y)-1)) & ~((y)-1))
 
-/*
-** Don't worry about the 150% average search length on a miss.
-** If the search wraps around, and passes the res_hint, it will
-** cause the kernel to panic anyhow.
-*/
-#define CCIO_SEARCH_LOOP(ioc, res_idx, mask, size)  \
-       for(; res_ptr < res_end; ++res_ptr) { \
-               if(0 == (*res_ptr & mask)) { \
-                       *res_ptr |= mask; \
-                       res_idx = (unsigned int)((unsigned long)res_ptr - (unsigned long)ioc->res_map); \
-                       ioc->res_hint = res_idx + (size >> 3); \
-                       goto resource_found; \
-               } \
-       }
-
-#define CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, size) \
-       u##size *res_ptr = (u##size *)&((ioc)->res_map[ioa->res_hint & ~((size >> 3) - 1)]); \
-       u##size *res_end = (u##size *)&(ioc)->res_map[ioa->res_size]; \
-       CCIO_SEARCH_LOOP(ioc, res_idx, mask, size); \
-       res_ptr = (u##size *)&(ioc)->res_map[0]; \
-       CCIO_SEARCH_LOOP(ioa, res_idx, mask, size);
+/**
+ * ccio_search_bitmap - find free space in IO PDIR resource bitmap
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @pages_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 CCIO_INLINE address_t
+ccio_search_bitmap(struct ioc *ioc, unsigned long pages_wanted)
+{
+	address_t *res_ptr = ioc->res_hint;
+	address_t *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]);
+	address_t pide = ~0UL;
+
+	if (pages_wanted > (BITS_PER_LONG/2)) {
+		/* Search word at a time - no mask needed */
+		for(; res_ptr < res_end; ++res_ptr) {
+			if (*res_ptr == 0) {
+				*res_ptr = RESMAP_MASK(pages_wanted);
+				pide = ((address_t)res_ptr - (address_t)ioc->res_map);
+				pide <<= 3;     /* convert to bit address */
+				break;
+			}
+		}
+		/* point to the next word on next pass */
+		res_ptr++;
+		ioc->res_bitshift = 0;
+	} else {
+		/*
+		** Search the resource bit map on well-aligned values.
+		** "o" is the alignment.
+		** We need the alignment to invalidate I/O TLB using
+		** xxx HW features in the unmap path.
+		*/
+		unsigned long o = 1 << get_iovp_order(pages_wanted << IOVP_SHIFT);
+		uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o);
+		unsigned long mask;
 
-/*
-** Find available bit in this ioa's resource map.
-** Use a "circular" search:
-**   o Most IOVA's are "temporary" - avg search time should be small.
-** o keep a history of what happened for debugging
-** o KISS.
-**
-** Perf optimizations:
-** o search for log2(size) bits at a time.
-** o search for available resource bits using byte/word/whatever.
-** o use different search for "large" (eg > 4 pages) or "very large"
-**   (eg > 16 pages) mappings.
-*/
+		if (bitshiftcnt >= BITS_PER_LONG) {
+			bitshiftcnt = 0;
+			res_ptr++;
+		}
+		mask = RESMAP_MASK(pages_wanted) >> bitshiftcnt;
+
+		DBG_RES("%s() o %ld %p", __FUNCTION__, o, res_ptr);
+		while(res_ptr < res_end)
+		{
+			DBG_RES("    %p %lx %lx\n", res_ptr, mask, *res_ptr);
+			WARN_ON(mask == 0);
+			if(((*res_ptr) & mask) == 0) {
+				*res_ptr |= mask;     /* mark resources busy! */
+				pide = ((address_t)res_ptr - (address_t)ioc->res_map);
+				pide <<= 3;     /* convert to bit address */
+				pide += bitshiftcnt;
+				break;
+			}
+			mask >>= o;
+			bitshiftcnt += o;
+			if (mask == 0) {
+				mask = RESMAP_MASK(pages_wanted);
+				bitshiftcnt=0;
+				res_ptr++;
+			}
+		}
+		/* look in the same word on the next pass */
+		ioc->res_bitshift = bitshiftcnt + pages_wanted;
+	}
+
+	/* wrapped ? */
+	if (res_end <= res_ptr) {
+		ioc->res_hint = (address_t *) ioc->res_map;
+		ioc->res_bitshift = 0;
+	} else {
+		ioc->res_hint = res_ptr;
+	}
+	return (pide);
+}
 
 /**
  * ccio_alloc_range - Allocate pages in the ioc's resource map.
@@ -347,7 +434,9 @@
 #ifdef CCIO_SEARCH_TIME
 	unsigned long cr_start = mfctl(16);
 #endif
-	
+
+	unsigned long	pide;
+
 	BUG_ON(pages_needed == 0);
 	BUG_ON((pages_needed * IOVP_SIZE) > DMA_CHUNK_SIZE);
 
@@ -359,44 +448,19 @@
 	** ggg sacrifices another 710 to the computer gods.
 	*/
 
-	if (pages_needed <= 8) {
-		/*
-		 * LAN traffic will not thrash the TLB IFF the same NIC
-		 * uses 8 adjacent pages to map seperate payload data.
-		 * ie the same byte in the resource bit map.
-		 */
-#if 0
-		/* FIXME: bit search should shift it's way through
-		 * an unsigned long - not byte at a time. As it is now,
-		 * we effectively allocate this byte to this mapping.
-		 */
-		unsigned long mask = ~(~0UL >> pages_needed);
-		CCIO_FIND_FREE_MAPPING(ioc, res_idx, mask, 8);
-#else
-		CCIO_FIND_FREE_MAPPING(ioc, res_idx, 0xff, 8);
-#endif
-	} else if (pages_needed <= 16) {
-		CCIO_FIND_FREE_MAPPING(ioc, res_idx, 0xffff, 16);
-	} else if (pages_needed <= 32) {
-		CCIO_FIND_FREE_MAPPING(ioc, res_idx, ~(unsigned int)0, 32);
-#ifdef __LP64__
-	} else if (pages_needed <= 64) {
-		CCIO_FIND_FREE_MAPPING(ioc, res_idx, ~0UL, 64);
-#endif
-	} else {
-		panic("%s: %s() Too many pages to map. pages_needed: %u\n",
-		       __FILE__,  __FUNCTION__, pages_needed);
+	pide = ccio_search_bitmap(ioc, pages_needed);
+	if (pide >= (ioc->res_size << 3)) {
+		pide = ccio_search_bitmap(ioc, pages_needed);
+		if (pide >= (ioc->res_size << 3))
+			panic("%s: %s() I/O MMU is out of mapping resources.\n", __FILE__,
+				__FUNCTION__);
 	}
 
-	panic("%s: %s() I/O MMU is out of mapping resources.\n", __FILE__,
-	      __FUNCTION__);
-	
-resource_found:
-	
 	DBG_RES("%s() res_idx %d res_hint: %d\n",
 		__FUNCTION__, res_idx, ioc->res_hint);
 
 #ifdef CCIO_SEARCH_TIME
+	udelay(100);
 	{
 		unsigned long cr_end = mfctl(16);
 		unsigned long tmp = cr_end - cr_start;
@@ -412,14 +476,9 @@
 	/*
 	** return the bit address.
 	*/
-	return res_idx << 3;
+	return (pide);
 }
 
-#define CCIO_FREE_MAPPINGS(ioc, res_idx, mask, size) \
-        u##size *res_ptr = (u##size *)&((ioc)->res_map[res_idx]); \
-        BUG_ON((*res_ptr & mask) != mask); \
-        *res_ptr &= ~(mask);
-
 /**
  * ccio_free_range - Free pages from the ioc's resource map.
  * @ioc: The I/O Controller.
@@ -430,42 +489,33 @@
  * This function frees the resouces allocated for the iova.
  */
 static void
-ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped)
+ccio_free_range(struct ioc *ioc, dma_addr_t iova, size_t size)
 {
 	unsigned long iovp = CCIO_IOVP(iova);
-	unsigned int res_idx = PDIR_INDEX(iovp) >> 3;
-
-	BUG_ON(pages_mapped == 0);
-	BUG_ON((pages_mapped * IOVP_SIZE) > DMA_CHUNK_SIZE);
-	BUG_ON(pages_mapped > BITS_PER_LONG);
 
-	DBG_RES("%s():  res_idx: %d pages_mapped %d\n",
-		__FUNCTION__, res_idx, pages_mapped);
+	unsigned int pide = PDIR_INDEX(iovp);
+	unsigned int ridx = pide >> 3;
+	unsigned long *res_ptr = (unsigned long *) &((ioc)->res_map[ridx & ~RESMAP_IDX_MASK]);
+
+	/* was: unsigned int pages_mapped = size >> IOVP_SHIFT; */
+	int bits_not_wanted = size >> IOVP_SHIFT;
+
+	/* 3-bits "bit" address plus 2 (or 3) bits for "byte" == bit in word */
+	unsigned long m = RESMAP_MASK(bits_not_wanted) >> (pide & (BITS_PER_LONG - 1));
+
+	BUG_ON(size == 0);
+	BUG_ON(size > DMA_CHUNK_SIZE);
+	BUG_ON(bits_not_wanted > BITS_PER_LONG);
+
+	DBG_RES("%s( ,%x,%x) %x/%lx %x %p %lx\n",
+		__FUNCTION__, (uint) iova, size,
+		bits_not_wanted, m, pide, res_ptr, *res_ptr);
 
 #ifdef CCIO_MAP_STATS
-	ioc->used_pages -= pages_mapped;
+	ioc->used_pages -= bits_not_wanted;
 #endif
 
-	if(pages_mapped <= 8) {
-#if 0
-		/* see matching comments in alloc_range */
-		unsigned long mask = ~(~0UL >> pages_mapped);
-		CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 8);
-#else
-		CCIO_FREE_MAPPINGS(ioc, res_idx, 0xff, 8);
-#endif
-	} else if(pages_mapped <= 16) {
-		CCIO_FREE_MAPPINGS(ioc, res_idx, 0xffff, 16);
-	} else if(pages_mapped <= 32) {
-		CCIO_FREE_MAPPINGS(ioc, res_idx, ~(unsigned int)0, 32);
-#ifdef __LP64__
-	} else if(pages_mapped <= 64) {
-		CCIO_FREE_MAPPINGS(ioc, res_idx, ~0UL, 64);
-#endif
-	} else {
-		panic("%s:%s() Too many pages to unmap.\n", __FILE__,
-		      __FUNCTION__);
-	}
+	*res_ptr &= ~m;
 }
 
 /****************************************************************
@@ -664,32 +714,45 @@
 static CCIO_INLINE void
 ccio_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
 {
-	u32 iovp = (u32)CCIO_IOVP(iova);
+	uint32_t iovp = (uint32_t)CCIO_IOVP(iova);
+	u64 *pdir_ptr = &ioc->pdir_base[PDIR_INDEX(iovp)];
 	size_t saved_byte_cnt;
 
 	/* round up to nearest page size */
 	saved_byte_cnt = byte_cnt = ALIGN(byte_cnt, IOVP_SIZE);
 
-	while(byte_cnt > 0) {
-		/* invalidate one page at a time */
-		unsigned int idx = PDIR_INDEX(iovp);
-		char *pdir_ptr = (char *) &(ioc->pdir_base[idx]);
+	if (byte_cnt > IOVP_SIZE)
+	{
+		/* set "size" field for PCOM */
+		iovp |= get_iovp_order(byte_cnt) + IOVP_SHIFT;
 
-		BUG_ON(idx >= (ioc->pdir_size / sizeof(u64)));
-		pdir_ptr[7] = 0;	/* clear only VALID bit */
-		/*
-		** FIXME: PCX_W platforms don't need FDC/SYNC. (eg C360)
-		**   PCX-U/U+ do. (eg C200/C240)
-		** See PDC_MODEL/option 0/SW_CAP for "Non-coherent IO-PDIR bit".
-		**
-		** Hopefully someone figures out how to patch (NOP) the
-		** FDC/SYNC out at boot time.
-		*/
-		asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr[7]));
+		do {
+			/* clear I/O Pdir entry "valid" bit first */
+			((unsigned char *) pdir_ptr)[7] = 0;
+			/*
+			** FIXME: PCX_W platforms don't need FDC/SYNC. (eg C360)
+			**   PCX-U/U+ do. (eg C200/C240)
+			** See PDC_MODEL/option 0/SW_CAP for "Non-coherent IO-PDIR bit".
+			**
+			** Hopefully someone figures out how to patch (NOP) the
+			** FDC/SYNC out at boot time.
+			*/
+			asm volatile("fdc %%r0(%0)" : : "r" (pdir_ptr[7]));
+
+			pdir_ptr++;
+			byte_cnt -= IOVP_SIZE;
+		} while (byte_cnt > IOVP_SIZE);
+	} else
+		iovp |= IOVP_SHIFT;     /* set "size" field for PCOM */
 
-		iovp     += IOVP_SIZE;
-		byte_cnt -= IOVP_SIZE;
-	}
+	/*
+	** clear I/O PDIR entry "valid" bit.
+	** We have to R/M/W the cacheline regardless how much of the
+	** pdir entry that we clobber.
+	** The rest of the entry would be useful for debugging if we
+	** could dump core on HPMC.
+	*/
+	((unsigned char *) pdir_ptr)[7] = 0;
 
 	asm volatile("sync");
 	ccio_clear_io_tlb(ioc, CCIO_IOVP(iova), saved_byte_cnt);
@@ -711,7 +774,7 @@
 static int
 ccio_dma_supported(struct device *dev, u64 mask)
 {
-	if(dev == NULL) {
+	if(!dev) {
 		printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n");
 		BUG();
 		return 0;
@@ -783,6 +846,9 @@
 		size -= IOVP_SIZE;
 	}
 
+	/* force FDC ops in io_pdir_entry() to be visible to IOMMU */
+	asm volatile("sync" :: );
+
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
 
 	/* form complete address */
@@ -803,6 +869,9 @@
 		  enum dma_data_direction direction)
 {
 	struct ioc *ioc;
+#if DELAYED_RESOURCE_CNT > 0
+	struct ioc_dma_pair *d;
+#endif
 	unsigned long flags;
 	dma_addr_t offset = iova & ~IOVP_MASK;
 	
@@ -824,7 +893,30 @@
 #endif
 
 	ccio_mark_invalid(ioc, iova, size);
-	ccio_free_range(ioc, iova, (size >> IOVP_SHIFT));
+#if DELAYED_RESOURCE_CNT > 0
+	/* Delaying when we re-use a IO Pdir entry reduces the number
+	 * of MMIO reads needed to flush writes to the PCOM register.
+	 */
+	d = &(ioc->saved[ioc->saved_cnt]);
+	d->iova = iova;
+	d->size = size;
+	if (++(ioc->saved_cnt) >= DELAYED_RESOURCE_CNT) {
+		int cnt = ioc->saved_cnt;
+		while (cnt--) {
+			ccio_free_range(ioc, d->iova, d->size);
+			d--;
+		}
+		ioc->saved_cnt = 0;
+	}
+#else /* DELAYED_RESOURCE_CNT == 0 */
+
+	ccio_free_range(ioc, iova, size);
+
+	/* force fdc's to be visible now */
+	asm volatile("sync" :: );
+
+#endif /* DELAYED_RESOURCE_CNT == 0 */
+
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
 }
 
@@ -952,6 +1044,9 @@
 	*/
 	filled = iommu_fill_pdir(ioc, sglist, nents, hint, ccio_io_pdir_entry);
 
+	/* force FDC ops in io_pdir_entry() to be visible to IOMMU */
+	asm volatile("sync" :: );
+
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
 
 	BUG_ON(coalesced != filled);
@@ -993,11 +1088,12 @@
 
 	while(sg_dma_len(sglist) && nents--) {
 
-#ifdef CCIO_MAP_STATS
-		ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT;
-#endif
 		ccio_unmap_single(dev, sg_dma_address(sglist),
 				  sg_dma_len(sglist), direction);
+#ifdef CCIO_MAP_STATS
+		ioc->usg_pages += sg_dma_len(sglist) >> IOVP_SHIFT;
+		ioc->usingle_calls--;   /* kluge since call is unmap_sg() */
+#endif
 		++sglist;
 	}
 
@@ -1025,16 +1121,12 @@
 	int len = 0;
 	struct ioc *ioc = ioc_list;
 
-	while (ioc != NULL) {
+	while (ioc) {
 		unsigned int total_pages = ioc->res_size << 3;
-		unsigned long avg = 0, min, max;
-		int j;
 
-		len += seq_printf(m, "%s\n", ioc->name);
-		
-		len += seq_printf(m, "Cujo 2.0 bug    : %s\n",
-				  (ioc->cujo20_bug ? "yes" : "no"));
-		
+		len += seq_printf(m, "%s%s\n", ioc->name,
+			(ioc->cujo20_bug ? " (Cujo 2.0 bug)" : ""));
+
 		len += seq_printf(m, "IO PDIR size    : %d bytes (%d entries)\n",
 			       total_pages * 8, total_pages);
 
@@ -1048,6 +1140,8 @@
 				  ioc->res_size, total_pages);
 
 #ifdef CCIO_SEARCH_TIME
+		unsigned long avg = 0, min, max;
+		int j;
 		min = max = ioc->avg_search[0];
 		for(j = 0; j < CCIO_SEARCH_SAMPLE; ++j) {
 			avg += ioc->avg_search[j];
@@ -1104,7 +1198,7 @@
 	int len = 0;
 	struct ioc *ioc = ioc_list;
 
-	while (ioc != NULL) {
+	while (ioc) {
 		u32 *res_ptr = (u32 *)ioc->res_map;
 		int j;
 
@@ -1252,9 +1346,12 @@
 static void
 ccio_ioc_init(struct ioc *ioc)
 {
-	int i;
-	unsigned int iov_order;
-	u32 iova_space_size;
+	int		i;
+	uint32_t	iov_order,
+			num_iommu_pages,
+			iova_space_size;
+
+	uint32_t	IO_ChainIdMask;
 
 	/*
 	** Determine IOVA Space size from memory size.
@@ -1267,16 +1364,15 @@
 	** Hot-Plug/Removal of PCI cards. (aka PCI OLARD).
 	*/
 
-	iova_space_size = (u32) (num_physpages / count_parisc_driver(&ccio_driver));
+	unsigned long phys_mem = num_physpages << PAGE_SHIFT;
+	iova_space_size = (u_int32_t) (phys_mem  / count_parisc_driver(&ccio_driver));
 
 	/* limit IOVA space size to 1MB-1GB */
 
-	if (iova_space_size < (1 << (20 - PAGE_SHIFT))) {
-		iova_space_size =  1 << (20 - PAGE_SHIFT);
-#ifdef __LP64__
-	} else if (iova_space_size > (1 << (30 - PAGE_SHIFT))) {
-		iova_space_size =  1 << (30 - PAGE_SHIFT);
-#endif
+	if (iova_space_size < (1 << 20)) {
+		iova_space_size =  1 << 20;
+	} else if (iova_space_size > (1 << 30)) {
+		iova_space_size =  1 << 30;
 	}
 
 	/*
@@ -1292,27 +1388,27 @@
 	**   this is the case under linux."
 	*/
 
-	iov_order = get_order(iova_space_size << PAGE_SHIFT);
+	iov_order = get_iovp_order(iova_space_size);
 
-	/* iova_space_size is now bytes, not pages */
-	iova_space_size = 1 << (iov_order + PAGE_SHIFT);
+	iova_space_size = 1 << (iov_order + IOVP_SHIFT);
 
-	ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64);
+	num_iommu_pages = iova_space_size >> IOVP_SHIFT;
+	ioc->pdir_size = num_iommu_pages * PDIR_ENTRY_SIZE;
+
+	DBG_INIT("%s() hpa 0x%p mem %luMb IOV %uMb (%d bits)\n",
+			__FUNCTION__, ioc->ioc_regs,
+			phys_mem >> 20,
+			iova_space_size >> 20,
+			iov_order + IOVP_SHIFT);
 
 	BUG_ON(ioc->pdir_size > 8 * 1024 * 1024);   /* max pdir size <= 8MB */
 
 	/* Verify it's a power of two */
 	BUG_ON((1 << get_order(ioc->pdir_size)) != (ioc->pdir_size >> PAGE_SHIFT));
 
-	DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits)\n",
-			__FUNCTION__, ioc->ioc_regs,
-			(unsigned long) num_physpages >> (20 - PAGE_SHIFT),
-			iova_space_size>>20,
-			iov_order + PAGE_SHIFT);
-
 	ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL,
 						 get_order(ioc->pdir_size));
-	if(NULL == ioc->pdir_base) {
+	if(!(ioc->pdir_base)) {
 		panic("%s() could not allocate I/O Page Table\n", __FUNCTION__);
 	}
 	memset(ioc->pdir_base, 0, ioc->pdir_size);
@@ -1321,27 +1417,31 @@
 	DBG_INIT(" base %p\n", ioc->pdir_base);
 
 	/* resource map size dictated by pdir_size */
- 	ioc->res_size = (ioc->pdir_size / sizeof(u64)) >> 3;
+ 	ioc->res_size = num_iommu_pages >> 3;
 	DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, ioc->res_size);
 	
 	ioc->res_map = (u8 *)__get_free_pages(GFP_KERNEL,
 					      get_order(ioc->res_size));
-	if(NULL == ioc->res_map) {
+	if(!(ioc->res_map)) {
 		panic("%s() could not allocate resource map\n", __FUNCTION__);
 	}
 	memset(ioc->res_map, 0, ioc->res_size);
 
-	/* Initialize the res_hint to 16 */
-	ioc->res_hint = 16;
+	/* next available IOVP - circular search */
+	ioc->res_hint = (unsigned long *)
+		&(ioc->res_map[L1_CACHE_BYTES]);
 
 	/* Initialize the spinlock */
 	spin_lock_init(&ioc->res_lock);
 
+	IO_ChainIdMask = READ_U32(&ioc->ioc_regs->io_chain_id_mask);
+	DBG_INIT(" Default io_chain_id_mask 0x%x\n", IO_ChainIdMask);
+
 	/*
 	** Chainid is the upper most bits of an IOVP used to determine
 	** which TLB entry an IOVP will use.
 	*/
-	ioc->chainid_shift = get_order(iova_space_size) + PAGE_SHIFT - CCIO_CHAINID_SHIFT;
+	ioc->chainid_shift = iov_order + IOVP_SHIFT - CCIO_CHAINID_SHIFT;
 	DBG_INIT(" chainid_shift 0x%x\n", ioc->chainid_shift);
 
 	/*
@@ -1485,15 +1585,15 @@
 		return 0;
 
 	if (!expand_ioc_area(parent, size, min, max, align)) {
-		__raw_writel(((parent->start)>>16) | 0xffff0000,
+		WRITE_U32(((parent->start)>>16) | 0xffff0000,
 			     &ioc->ioc_regs->io_io_low);
-		__raw_writel(((parent->end)>>16) | 0xffff0000,
+		WRITE_U32(((parent->end)>>16) | 0xffff0000,
 			     &ioc->ioc_regs->io_io_high);
 	} else if (!expand_ioc_area(parent + 1, size, min, max, align)) {
 		parent++;
-		__raw_writel(((parent->start)>>16) | 0xffff0000,
+		WRITE_U32(((parent->start)>>16) | 0xffff0000,
 			     &ioc->ioc_regs->io_io_low_hv);
-		__raw_writel(((parent->end)>>16) | 0xffff0000,
+		WRITE_U32(((parent->end)>>16) | 0xffff0000,
 			     &ioc->ioc_regs->io_io_high_hv);
 	} else {
 		return -EBUSY;
@@ -1543,8 +1643,8 @@
 	struct ioc *ioc, **ioc_p = &ioc_list;
 	struct proc_dir_entry *info_entry, *bitmap_entry;
 	
-	ioc = kzalloc(sizeof(struct ioc), GFP_KERNEL);
-	if (ioc == NULL) {
+	ioc = kzalloc(sizeof(*ioc), GFP_KERNEL);
+	if (!ioc) {
 		printk(KERN_ERR MODULE_NAME ": memory allocation failure\n");
 		return 1;
 	}
@@ -1566,7 +1666,7 @@
 	dev->dev.platform_data = kzalloc(sizeof(struct pci_hba_data), GFP_KERNEL);
 
 	/* if this fails, no I/O cards will work, so may as well bug */
-	BUG_ON(dev->dev.platform_data == NULL);
+	BUG_ON(!(dev->dev.platform_data));
 	HBA_DATA(dev->dev.platform_data)->iommu = ioc;
 	
 	if (ioc_count == 0) {

[-- Attachment #3: Type: text/plain, Size: 169 bytes --]

_______________________________________________
parisc-linux mailing list
parisc-linux@lists.parisc-linux.org
http://lists.parisc-linux.org/mailman/listinfo/parisc-linux

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2007-11-29 18:50 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <JQIT2V$FB9C8381616CCA32E9FC6CC809E8D81D@scarlet.be>
     [not found] ` <20071028064158.GB29233@colo.lackof.org>
     [not found]   ` <4724A084.5090709@scarlet.be>
2007-10-28 15:44     ` [parisc-linux] [patch 2/2] backport of sba sg list management to ccio-dma Joel Soete
2007-10-29  5:30     ` Grant Grundler
     [not found]     ` <20071029053015.GA14763@colo.lackof.org>
2007-11-01 17:17       ` Joel Soete
     [not found]       ` <472A0A3F.5040007@scarlet.be>
2007-11-02 18:00         ` Joel Soete
2007-11-24 20:36       ` Joel Soete
2007-11-26  3:26         ` Grant Grundler
2007-11-28  8:25 Joel Soete
2007-11-29 18:50 ` Grant Grundler
  -- strict thread matches above, loose matches on Subject: below --
2007-11-27 12:48 Joel Soete
2007-11-27 21:47 ` Grant Grundler
2007-11-26  8:48 Joel Soete
2007-11-26 23:27 ` Grant Grundler
2007-10-23 16:15 Joel Soete
     [not found] <4714E800.50709@scarlet.be>
2007-10-17 18:44 ` Kyle McMartin
     [not found] ` <20071017184416.GB11502@fattire.cabal.ca>
2007-10-20 17:21   ` Joel Soete
     [not found]   ` <471A3928.8040603@scarlet.be>
2007-10-20 17:23     ` Kyle McMartin
     [not found]     ` <20071020172328.GI10429@fattire.cabal.ca>
2007-10-22  4:39       ` Grant Grundler
     [not found]       ` <20071022043909.GC11869@colo.lackof.org>
2007-11-01 17:18         ` Joel Soete
     [not found]         ` <472A0A49.8010201@scarlet.be>
2007-11-01 21:21           ` Grant Grundler
2007-10-16 16:34 Joel Soete

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.