From owner-freebsd-amd64@FreeBSD.ORG Tue Sep 19 05:40:25 2006 Return-Path: X-Original-To: freebsd-amd64@hub.freebsd.org Delivered-To: freebsd-amd64@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 7E33B16A40F for ; Tue, 19 Sep 2006 05:40:25 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 3911643D4C for ; Tue, 19 Sep 2006 05:40:25 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.4/8.13.4) with ESMTP id k8J5eP7N056889 for ; Tue, 19 Sep 2006 05:40:25 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.4/8.13.4/Submit) id k8J5ePux056888; Tue, 19 Sep 2006 05:40:25 GMT (envelope-from gnats) Date: Tue, 19 Sep 2006 05:40:25 GMT Message-Id: <200609190540.k8J5ePux056888@freefall.freebsd.org> To: freebsd-amd64@FreeBSD.org From: "Jan Mikkelsen" Cc: Subject: Re: amd64/89550: [amd64] sym0: VTOBUS failed (6.0 Release) X-BeenThere: freebsd-amd64@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Jan Mikkelsen List-Id: Porting FreeBSD to the AMD64 platform List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Sep 2006 05:40:25 -0000 The following reply was made to PR amd64/89550; it has been noted by GNATS. From: "Jan Mikkelsen" To: , 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