Date: Fri, 22 Sep 2006 07:46:58 +1000 From: "Jan Mikkelsen" <janm@transactionware.com> To: <freebsd-stable@freebsd.org> Subject: Patch: sym(4) "VTOBUS FAILED" panics on amd64, amd64/89550 Message-ID: <002d01c6ddc7$76d10cc0$0202a8c0@transactzbkv04>
index | next in thread | raw e-mail
[-- Attachment #1 --]
Hi,
I posted this to freebsd-amd64, but I've had no replies.
This fixes the sym "VTOBUS FAILED" panics that I got consistently on
6.1-RELEASE/amd64; see the PR amd64/89550 for dmesg, other reports, etc.
Quick summary: sym(4) assumes on amd64 that virtual addresses provided by
bus_dmamem_alloc() have the same alignment as the physical addresses (in
this case, 2*PAGE_SIZE). They don't, and stuff breaks. This patch works
around that.
I'm looking for someone to take a quick look at it and make sure that the
approach is reasonable. I would be nice if a fix was committed (not
necessarily mine).
sym(4) is listed as supported in the 6.1/amd64 hardware guide, but it
doesn't seem to be working at all. For 6.2, I either suggest putting in a
fix so that it is supported, or having a note in the hardware guide.
Sorry about coming along so late in the release cycle, but I first
encountered the problem on Monday.
Thanks,
Jan Mikkelsen
[-- Attachment #2 --]
*** 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
--- 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
***************
*** 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 = VTOB_HASH_CODE(vaddr);
vbp->vaddr = (m_addr_t) vaddr;
vbp->baddr = (m_addr_t) baddr;
vbp->next = mp->vtob[hc];
mp->vtob[hc] = 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;
!
vbp->vaddr = (m_addr_t) vaddr;
vbp->baddr = (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.
+ */
+
+ if (((m_addr_t) vaddr & ~MEMO_CLUSTER_MASK) != (m_addr_t) vaddr)
+ vaddr = (void*) ((m_addr_t) vaddr + PAGE_SIZE);
+
+ vbp->adjusted_vaddr = (m_addr_t) vaddr;
+ #endif
+ hc = VTOB_HASH_CODE(vaddr);
vbp->next = mp->vtob[hc];
mp->vtob[hc] = vbp;
++mp->nump;
***************
*** 733,744 ****
mp = __sym_calloc(&mp0, sizeof(*mp), "MPOOL");
if (mp) {
mp->dev_dmat = 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 = ___dma_getp;
#ifdef MEMO_FREE_UNUSED
mp->freep = ___dma_freep;
--- 759,779 ----
mp = __sym_calloc(&mp0, sizeof(*mp), "MPOOL");
if (mp) {
mp->dev_dmat = 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 = ___dma_getp;
#ifdef MEMO_FREE_UNUSED
mp->freep = ___dma_freep;
***************
*** 815,827 ****
mp = ___get_dma_pool(dev_dmat);
if (mp) {
vp = mp->vtob[hc];
while (vp && (m_addr_t) vp->vaddr != a)
vp = vp->next;
}
/* Unlock */
if (!vp)
panic("sym: VTOBUS FAILED!\n");
! return vp ? vp->baddr + (((m_addr_t) m) - a) : 0;
}
--- 850,872 ----
mp = ___get_dma_pool(dev_dmat);
if (mp) {
vp = mp->vtob[hc];
+ #if (PAGE_SIZE < MEMO_CLUSTER_SIZE)
+ while (vp && (m_addr_t) vp->adjusted_vaddr != a)
+ #else
while (vp && (m_addr_t) vp->vaddr != a)
+ #endif
vp = vp->next;
}
+
/* 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
}
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?002d01c6ddc7$76d10cc0$0202a8c0>
