amd64/89550: [amd64] sym0: VTOBUS failed (6.0 Release)
Jan Mikkelsen
janm at transactionware.com
Mon Sep 18 22:40:25 PDT 2006
The following reply was made to PR amd64/89550; it has been noted by GNATS.
From: "Jan Mikkelsen" <janm at transactionware.com>
To: <bug-followup at FreeBSD.org>,
<awallac3 at uiuc.edu>
Cc:
Subject: Re: amd64/89550: [amd64] sym0: VTOBUS failed (6.0 Release)
Date: Tue, 19 Sep 2006 15:39:32 +1000
I've just been looking at this.
The problem seems to be caused by the sym driver assuming that the =
virtual
address of the memory allocated by bus_dmamem_alloc will be aligned to =
an
address 2*PAGE_SIZE. The physical address is aligned like that, but the
virtual address isn't. This also breaks the buddy algorithm.
Here are the changes I have made to make it work on my system. Summary:
Allocate additional pages and adjust the virtual address if necessary to =
get
memory with the right alignment.
Other changes (possibly incorrect):
- Adjusted the contigmalloc call because the boundary argument didn't =
make
sense to me compared to the man page.
- Adjusted the highaddr argument in the bus_dma_tag_create() call, =
again,
the usage didn't really match what I expected from the man page.
Little testing; I have used it to boot and dd over an old 4GB drive. =
With
the original version it never made it past sym_pci_attach.
*** FreeBSD/src/sys/dev/sym/sym_hipd.c Tue Aug 8 00:43:31 2006
--- /home/janm/sym_hipd.c Tue Sep 19 15:27:55 2006
***************
*** 439,445 ****
#define free_pages(p) free((p), M_DEVBUF)
#else
#define get_pages() contigmalloc(MEMO_CLUSTER_SIZE, M_DEVBUF, \
! 0, 0, 1LL << 32, PAGE_SIZE, 1LL << 32)
#define free_pages(p) contigfree((p), MEMO_CLUSTER_SIZE, M_DEVBUF)
#endif
=20
--- 439,446 ----
#define free_pages(p) free((p), M_DEVBUF)
#else
#define get_pages() contigmalloc(MEMO_CLUSTER_SIZE, M_DEVBUF, \
! 0, 0, 1LL << 32, PAGE_SIZE, \
! MEMO_CLUSTER_SIZE)
#define free_pages(p) contigfree((p), MEMO_CLUSTER_SIZE, M_DEVBUF)
#endif
=20
***************
*** 453,458 ****
--- 454,462 ----
struct m_vtob *next;
bus_dmamap_t dmamap; /* Map for this chunk */
m_addr_t vaddr; /* Virtual address */
+ #if PAGE_SIZE < MEMO_CLUSTER_SIZE
+ m_addr_t adjusted_vaddr; /* Virtual address adjusted for
buddy */
+ #endif
m_addr_t baddr; /* Bus physical address */
} m_vtob_s;
/* Hash this stuff a bit to speed up translations */
***************
*** 674,685 ****
if (bus_dmamem_alloc(mp->dmat, &vaddr,
BUS_DMA_NOWAIT, &vbp->dmamap))
goto out_err;
bus_dmamap_load(mp->dmat, vbp->dmamap, vaddr,
MEMO_CLUSTER_SIZE, getbaddrcb, &baddr, 0);
if (baddr) {
! int hc =3D VTOB_HASH_CODE(vaddr);
vbp->vaddr =3D (m_addr_t) vaddr;
vbp->baddr =3D (m_addr_t) baddr;
vbp->next =3D mp->vtob[hc];
mp->vtob[hc] =3D vbp;
++mp->nump;
--- 678,711 ----
if (bus_dmamem_alloc(mp->dmat, &vaddr,
BUS_DMA_NOWAIT, &vbp->dmamap))
goto out_err;
+ #if PAGE_SIZE < MEMO_CLUSTER_SIZE
+ bus_dmamap_load(mp->dmat, vbp->dmamap, vaddr,
+ MEMO_CLUSTER_SIZE * 2, getbaddrcb, &baddr, 0);
+ #else
bus_dmamap_load(mp->dmat, vbp->dmamap, vaddr,
MEMO_CLUSTER_SIZE, getbaddrcb, &baddr, 0);
+ #endif
if (baddr) {
! int hc;
!=20
vbp->vaddr =3D (m_addr_t) vaddr;
vbp->baddr =3D (m_addr_t) baddr;
+ #if PAGE_SIZE < MEMO_CLUSTER_SIZE
+ /*
+ * Adjusting vaddr is OK here because we do not error out.
+ * If that changes, the bus_dmamem_free() call below would
+ * need to be fixed.
+ *
+ * This code assumes that we will be at most one page away
+ * from having things aligned the way we want.
+ */
+=20
+ if (((m_addr_t) vaddr & ~MEMO_CLUSTER_MASK) !=3D (m_addr_t)
vaddr)
+ vaddr =3D (void*) ((m_addr_t) vaddr + PAGE_SIZE);
+=20
+ vbp->adjusted_vaddr =3D (m_addr_t) vaddr;
+ #endif
+ hc =3D VTOB_HASH_CODE(vaddr);
vbp->next =3D mp->vtob[hc];
mp->vtob[hc] =3D vbp;
++mp->nump;
***************
*** 733,744 ****
mp =3D __sym_calloc(&mp0, sizeof(*mp), "MPOOL");
if (mp) {
mp->dev_dmat =3D dev_dmat;
! if (!bus_dma_tag_create(dev_dmat, 1, MEMO_CLUSTER_SIZE,
BUS_SPACE_MAXADDR_32BIT,
BUS_SPACE_MAXADDR_32BIT,
NULL, NULL, MEMO_CLUSTER_SIZE, 1,
MEMO_CLUSTER_SIZE, 0,
busdma_lock_mutex, &Giant, &mp->dmat)) {
mp->getp =3D ___dma_getp;
#ifdef MEMO_FREE_UNUSED
mp->freep =3D ___dma_freep;
--- 759,779 ----
mp =3D __sym_calloc(&mp0, sizeof(*mp), "MPOOL");
if (mp) {
mp->dev_dmat =3D dev_dmat;
! #if PAGE_SIZE < MEMO_CLUSTER_SIZE
! if (!bus_dma_tag_create(dev_dmat, 1, MEMO_CLUSTER_SIZE * 2,
BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
+ NULL, NULL, MEMO_CLUSTER_SIZE * 2, 1,
+ MEMO_CLUSTER_SIZE * 2, 0,
+ busdma_lock_mutex, &Giant, &mp->dmat)) {
+ #else
+ if (!bus_dma_tag_create(dev_dmat, 1, MEMO_CLUSTER_SIZE,
BUS_SPACE_MAXADDR_32BIT,
+ BUS_SPACE_MAXADDR,
NULL, NULL, MEMO_CLUSTER_SIZE, 1,
MEMO_CLUSTER_SIZE, 0,
busdma_lock_mutex, &Giant, &mp->dmat)) {
+ #endif
mp->getp =3D ___dma_getp;
#ifdef MEMO_FREE_UNUSED
mp->freep =3D ___dma_freep;
***************
*** 815,827 ****
mp =3D ___get_dma_pool(dev_dmat);
if (mp) {
vp =3D mp->vtob[hc];
while (vp && (m_addr_t) vp->vaddr !=3D a)
vp =3D vp->next;
}
/* Unlock */
if (!vp)
panic("sym: VTOBUS FAILED!\n");
! return vp ? vp->baddr + (((m_addr_t) m) - a) : 0;
}
=20
=20
--- 850,872 ----
mp =3D ___get_dma_pool(dev_dmat);
if (mp) {
vp =3D mp->vtob[hc];
+ #if (PAGE_SIZE < MEMO_CLUSTER_SIZE)
+ while (vp && (m_addr_t) vp->adjusted_vaddr !=3D a)
+ #else
while (vp && (m_addr_t) vp->vaddr !=3D a)
+ #endif
vp =3D vp->next;
}
+=20
/* Unlock */
if (!vp)
panic("sym: VTOBUS FAILED!\n");
! #if (PAGE_SIZE < MEMO_CLUSTER_SIZE)
! return vp->baddr + (((m_addr_t) m) - a) +
! (vp->adjusted_vaddr - vp->vaddr);
! #else
! return vp->baddr + (((m_addr_t) m) - a);
! #endif
}
=20
=20
More information about the freebsd-amd64
mailing list