Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Jan 2003 16:40:56 +0100 (CET)
From:      Harti Brandt <brandt@fokus.gmd.de>
To:        Thomas Moestl <tmm@freebsd.org>
Cc:        Harti Brandt <brandt@fokus.gmd.de>, "" <sparc@freebsd.org>
Subject:   Re: Problem with iommu_dvmamap_create
Message-ID:  <20030120161832.K45050@beagle.fokus.gmd.de>
In-Reply-To: <20030120151712.GA240@crow.dom2ip.de>
References:  <20030117151958.U715@beagle.fokus.gmd.de> <20030117160857.GB304@crow.dom2ip.de> <20030117171317.F44530@beagle.fokus.gmd.de> <20030117171111.GC304@crow.dom2ip.de> <20030117181111.R45050@beagle.fokus.gmd.de> <20030117173303.GD304@crow.dom2ip.de> <20030120103814.X45050@beagle.fokus.gmd.de> <20030120151712.GA240@crow.dom2ip.de>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 20 Jan 2003, Thomas Moestl wrote:

TM>On Mon, 2003/01/20 at 10:52:11 +0100, Harti Brandt wrote:
TM>> On Fri, 17 Jan 2003, Thomas Moestl wrote:
TM>>
TM>> Just while I could not sleep last night, it occured to me, that the code
TM>> should work without even this change when the kernel is compiled with gcc.
TM>> The code in iommu.c and bus_machdep.c use #ifdef __GNUC__ to use dynamic
TM>> arrays on stack that have size ddmat->dt_nsegements size. So if I create a
TM>> tag with a number of segments large enough, the arrays should be large
TM>> enough. The only problem should be, that the size check around line 823 in
TM>> iommu.c should also be conditionalized (for __GCC__ BUS_DMAMAP_NSEGS
TM>> should not be checked.) Well, for some reason, that seems not to work.
TM>
TM>Hmmm, how does it fail?

Trying to send a 60000 byte PDU gives me the following:

hatm0: <FORE HE> mem 0x100000-0x1fffff irq 20 at device 2.0 on pci1
hatm: hw.hatm0.rbps0.size=32
hatm: hw.hatm0.rbps0.thresh=8
hatm: hw.hatm0.rbpl0.size=32
hatm: hw.hatm0.rbpl0.thresh=8
hatm: hw.hatm0.rbps1.size=32
hatm: hw.hatm0.rbps1.thresh=8
hatm0: ForeRunnerHE 155, Rev. B, S/N 5705534, MAC=00:20:48:57:0f:3e
iommu_dvmamap_load_buffer: too many segments.
iommu_dvmamap_load_buffer: too many segments.
iommu_dvmamap_load_buffer: too many segments.
iommu_dvmamap_load_buffer: too many segments.
iommu_dvmamap_load_buffer: too many segments.
iommu_dvmamap_load_buffer: too many segments.
iommu_dvmamap_load_buffer: too many segments.
iommu_dvmamap_load_buffer: too many segments.
iommu_dvmamap_load_buffer: too many segments.
iommu_dvmamap_load_buffer: too many segments.
iommu_dvmamap_load_buffer: too many segments.
iommu_dvmamap_load_buffer: too many segments.
iommu_dvmamap_load_buffer: too many segments.
seg[0]=tpd[1,0]=c02d8800/2048
seg[1]=tpd[1,1]=c02da800/2048
seg[2]=tpd[1,2]=c02dd000/2048
seg[3]=tpd[2,0]=c02de800/2048
seg[4]=tpd[2,1]=c02e0000/2048
seg[5]=tpd[2,2]=c02e3800/2048
seg[6]=tpd[3,0]=c02e5000/2048
seg[7]=tpd[3,1]=c02e6800/2048
seg[8]=tpd[3,2]=c02e8000/2048
seg[9]=tpd[4,0]=c02eb800/2048
seg[10]=tpd[4,1]=c02ed000/2048
seg[11]=tpd[4,2]=c02ee800/2048
seg[12]=tpd[5,0]=c02f0000/2048
seg[13]=tpd[5,1]=c0c67800/2048
seg[14]=tpd[5,2]=c0c69000/2048
seg[15]=tpd[6,0]=c0c6a800/2048
seg[16]=tpd[6,1]=c0c6c000/2048
seg[17]=tpd[6,2]=17f02cc0/1077936128
seg[18]=tpd[7,0]=1/3438465064
seg[19]=tpd[7,1]=ccf2d010/3438465048
seg[20]=tpd[7,2]=ccf2c711/3222760340
seg[21]=tpd[8,0]=f/0
seg[22]=tpd[8,1]=432a330/324612608
seg[23]=tpd[8,2]=1390b550/77178368
seg[24]=tpd[9,0]=16d20570/0
seg[25]=tpd[9,1]=ccf2da80/3223451912
seg[26]=tpd[9,2]=7def510/132025856
seg[27]=tpd[10,0]=0/0
seg[28]=tpd[10,1]=17f178c0/0
seg[29]=tpd[10,2]=0/1077936128

Starting at seg[17] the segments are simply wrong. The number of segments
in the tag is 39 so this should work. (The numbers are the phys address
and segment length).

TM>>From a quick inspection, I can see one class of problems (which might
TM>or might not be the cause for this specific behaviour, but will cause
TM>trouble in any case): you need to do endiannes conversions for memory
TM>that is accessed by DMA and interpreted or written by the
TM>adapter. Since it is a PCI card, it operates on little-endian
TM>data. While the bus_space_* functions know the access size and will
[...]

The card is desgined for operation in LE and BE systems. It has a register
where you set bits which tell the card to swap the data during DMA. There
is a function hatm_init_endianess, which sets the right bits.

TM>This would e.g. explain a bogus interrupt status word: since it is
TM>written by the adapter, it needs to be converted to host byte order
TM>before it is interpreted; the following:
TM>
TM>	while (q->head != tail) {
TM>		status = q->irq[q->head];
TM>		q->irq[q->head] = HE_REGM_ITYPE_INVALID;
TM>
TM>would become:
TM>
TM>	while (q->head != tail) {
TM>		status = le32toh(q->irq[q->head]);
TM>		q->irq[q->head] = htole32(HE_REGM_ITYPE_INVALID);

This is really not the problem. When I create tx_tag with a maximum of 1
segment, the receive function of the card works (that means interrupt
status is correctly processed, receive queues and buffers are correctly
red and written). When I create tx_tag with a number of segments > 1 than
only creating a couple of DMA maps with this tag (not using them at all)
entirly confuses operation.

But as I said already - with your patch applied it seems to work (albeit
not very stable, but this may be my fault).

harti
-- 
harti brandt, http://www.fokus.gmd.de/research/cc/cats/employees/hartmut.brandt/private
              brandt@fokus.gmd.de, brandt@fokus.fhg.de

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-sparc" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030120161832.K45050>