PERFORCE change 113311 for review
Marko Zec
zec at FreeBSD.org
Mon Jan 22 13:58:44 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=113311
Change 113311 by zec at zec_tca51 on 2007/01/22 13:58:22
IFC @ 113308
Affected files ...
.. //depot/projects/vimage/src/sys/amd64/include/md_var.h#2 integrate
.. //depot/projects/vimage/src/sys/amd64/linux32/linux32_machdep.c#5 integrate
.. //depot/projects/vimage/src/sys/arm/arm/busdma_machdep.c#2 integrate
.. //depot/projects/vimage/src/sys/arm/arm/vm_machdep.c#2 integrate
.. //depot/projects/vimage/src/sys/arm/at91/uart_dev_at91usart.c#3 integrate
.. //depot/projects/vimage/src/sys/arm/include/bus_dma.h#2 integrate
.. //depot/projects/vimage/src/sys/arm/include/md_var.h#2 integrate
.. //depot/projects/vimage/src/sys/arm/include/pmap.h#2 integrate
.. //depot/projects/vimage/src/sys/arm/sa11x0/uart_dev_sa1110.c#2 integrate
.. //depot/projects/vimage/src/sys/arm/xscale/ixp425/if_npe.c#2 integrate
.. //depot/projects/vimage/src/sys/arm/xscale/ixp425/ixp425.c#2 integrate
.. //depot/projects/vimage/src/sys/arm/xscale/ixp425/ixp425_pci.c#2 integrate
.. //depot/projects/vimage/src/sys/arm/xscale/ixp425/ixp425var.h#2 integrate
.. //depot/projects/vimage/src/sys/cam/scsi/scsi_da.c#3 integrate
.. //depot/projects/vimage/src/sys/compat/linprocfs/linprocfs.c#3 integrate
.. //depot/projects/vimage/src/sys/compat/linux/linux_emul.c#4 integrate
.. //depot/projects/vimage/src/sys/compat/linux/linux_file.c#2 integrate
.. //depot/projects/vimage/src/sys/conf/files.sparc64#3 integrate
.. //depot/projects/vimage/src/sys/conf/options#7 integrate
.. //depot/projects/vimage/src/sys/conf/options.sun4v#2 integrate
.. //depot/projects/vimage/src/sys/ddb/db_command.c#2 integrate
.. //depot/projects/vimage/src/sys/ddb/db_thread.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/aic7xxx/aic79xx.h#2 integrate
.. //depot/projects/vimage/src/sys/dev/aic7xxx/aic79xx_pci.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/ath/if_ath.c#5 integrate
.. //depot/projects/vimage/src/sys/dev/ath/if_ath_pci.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/bce/if_bce.c#4 integrate
.. //depot/projects/vimage/src/sys/dev/cardbus/cardbus.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/dpt/dpt.h#2 integrate
.. //depot/projects/vimage/src/sys/dev/dpt/dpt_eisa.c#3 integrate
.. //depot/projects/vimage/src/sys/dev/dpt/dpt_scsi.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/esp/esp_sbus.c#3 integrate
.. //depot/projects/vimage/src/sys/dev/fb/creator.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/fb/creatorreg.h#2 integrate
.. //depot/projects/vimage/src/sys/dev/fb/fbreg.h#2 integrate
.. //depot/projects/vimage/src/sys/dev/firewire/fwohci_pci.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/fxp/if_fxp.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/isp/isp.c#5 integrate
.. //depot/projects/vimage/src/sys/dev/isp/isp_freebsd.c#4 integrate
.. //depot/projects/vimage/src/sys/dev/isp/isp_freebsd.h#3 integrate
.. //depot/projects/vimage/src/sys/dev/isp/isp_sbus.c#4 integrate
.. //depot/projects/vimage/src/sys/dev/isp/isp_target.c#3 integrate
.. //depot/projects/vimage/src/sys/dev/isp/isp_target.h#2 integrate
.. //depot/projects/vimage/src/sys/dev/isp/isp_tpublic.h#2 integrate
.. //depot/projects/vimage/src/sys/dev/isp/ispvar.h#3 integrate
.. //depot/projects/vimage/src/sys/dev/le/if_le_cbus.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/le/if_le_isa.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/le/if_le_lebuffer.c#1 branch
.. //depot/projects/vimage/src/sys/dev/le/if_le_ledma.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/le/if_le_pci.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/le/lance.c#3 integrate
.. //depot/projects/vimage/src/sys/dev/le/lebuffer_sbus.c#1 branch
.. //depot/projects/vimage/src/sys/dev/mc146818/mc146818reg.h#2 integrate
.. //depot/projects/vimage/src/sys/dev/mfi/mfi_pci.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/mii/brgphy.c#5 integrate
.. //depot/projects/vimage/src/sys/dev/mii/mii.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/mii/rlphy.c#4 integrate
.. //depot/projects/vimage/src/sys/dev/mii/ukphy.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/pci/pci.c#5 integrate
.. //depot/projects/vimage/src/sys/dev/pci/pcireg.h#3 integrate
.. //depot/projects/vimage/src/sys/dev/re/if_re.c#4 integrate
.. //depot/projects/vimage/src/sys/dev/si/si.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/sk/if_sk.c#3 integrate
.. //depot/projects/vimage/src/sys/dev/sound/pci/es137x.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/sound/pci/hda/hdac_private.h#2 integrate
.. //depot/projects/vimage/src/sys/dev/sound/sbus/cs4231.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/stge/if_stge.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/sym/sym_hipd.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/ti/if_ti.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/uart/uart_cpu.h#2 integrate
.. //depot/projects/vimage/src/sys/dev/uart/uart_dev_ns8250.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/uart/uart_dev_sab82532.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/uart/uart_dev_z8530.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/uart/uart_kbd_sun.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/usb/ehci_pci.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/usb/uhci_pci.c#2 integrate
.. //depot/projects/vimage/src/sys/dev/usb/ums.c#2 integrate
.. //depot/projects/vimage/src/sys/fs/deadfs/dead_vnops.c#2 integrate
.. //depot/projects/vimage/src/sys/fs/msdosfs/denode.h#2 integrate
.. //depot/projects/vimage/src/sys/fs/msdosfs/msdosfs_fat.c#2 integrate
.. //depot/projects/vimage/src/sys/i386/i386/pmap.c#2 integrate
.. //depot/projects/vimage/src/sys/i386/ibcs2/ibcs2_sysvec.c#2 integrate
.. //depot/projects/vimage/src/sys/i386/linux/linux_machdep.c#3 integrate
.. //depot/projects/vimage/src/sys/kern/imgact_elf.c#2 integrate
.. //depot/projects/vimage/src/sys/kern/init_main.c#5 integrate
.. //depot/projects/vimage/src/sys/kern/kern_descrip.c#3 integrate
.. //depot/projects/vimage/src/sys/kern/kern_ktrace.c#3 integrate
.. //depot/projects/vimage/src/sys/kern/kern_resource.c#3 integrate
.. //depot/projects/vimage/src/sys/kern/kern_sig.c#3 integrate
.. //depot/projects/vimage/src/sys/kern/kern_subr.c#4 integrate
.. //depot/projects/vimage/src/sys/kern/sched_ule.c#4 integrate
.. //depot/projects/vimage/src/sys/kern/subr_turnstile.c#3 integrate
.. //depot/projects/vimage/src/sys/kern/subr_witness.c#2 integrate
.. //depot/projects/vimage/src/sys/kern/vfs_lookup.c#2 integrate
.. //depot/projects/vimage/src/sys/modules/le/Makefile#2 integrate
.. //depot/projects/vimage/src/sys/net/bridgestp.c#3 integrate
.. //depot/projects/vimage/src/sys/netgraph/ng_ppp.c#3 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_asconf.c#5 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_asconf.h#3 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_auth.c#3 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_bsd_addr.c#3 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_bsd_addr.h#2 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_constants.h#4 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_crc32.h#2 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_indata.c#5 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_indata.h#3 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_input.c#5 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_input.h#2 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_os.h#3 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_os_bsd.h#5 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_output.c#5 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_output.h#2 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_pcb.c#5 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_pcb.h#5 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_peeloff.c#3 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_peeloff.h#2 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_structs.h#5 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_timer.c#4 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_timer.h#2 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_usrreq.c#5 integrate
.. //depot/projects/vimage/src/sys/netinet/sctp_var.h#4 integrate
.. //depot/projects/vimage/src/sys/netinet/sctputil.c#5 integrate
.. //depot/projects/vimage/src/sys/netinet/sctputil.h#4 integrate
.. //depot/projects/vimage/src/sys/netinet6/icmp6.c#5 integrate
.. //depot/projects/vimage/src/sys/netinet6/sctp6_usrreq.c#5 integrate
.. //depot/projects/vimage/src/sys/netinet6/sctp6_var.h#2 integrate
.. //depot/projects/vimage/src/sys/pci/if_rl.c#4 integrate
.. //depot/projects/vimage/src/sys/pci/if_rlreg.h#3 integrate
.. //depot/projects/vimage/src/sys/pci/intpm.c#3 integrate
.. //depot/projects/vimage/src/sys/sparc64/creator/creator.h#2 delete
.. //depot/projects/vimage/src/sys/sparc64/creator/creator_upa.c#2 delete
.. //depot/projects/vimage/src/sys/sparc64/include/bus.h#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/include/cache.h#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/include/frame.h#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/include/fsr.h#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/include/intr_machdep.h#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/include/pcb.h#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/include/tsb.h#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/isa/isa.c#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/pci/ofw_pci_if.m#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/pci/psycho.c#3 integrate
.. //depot/projects/vimage/src/sys/sparc64/sbus/dma_sbus.c#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/sparc64/bus_machdep.c#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/sparc64/exception.S#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/sparc64/genassym.c#3 integrate
.. //depot/projects/vimage/src/sys/sparc64/sparc64/interrupt.S#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/sparc64/mp_exception.S#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/sparc64/mp_locore.S#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/sparc64/ofw_machdep.c#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/sparc64/support.S#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/sparc64/swtch.S#2 integrate
.. //depot/projects/vimage/src/sys/sparc64/sparc64/upa.c#1 branch
.. //depot/projects/vimage/src/sys/sun4v/include/bus.h#2 integrate
.. //depot/projects/vimage/src/sys/sun4v/include/frame.h#2 integrate
.. //depot/projects/vimage/src/sys/sun4v/include/fsr.h#2 integrate
.. //depot/projects/vimage/src/sys/sun4v/include/intr_machdep.h#2 integrate
.. //depot/projects/vimage/src/sys/sun4v/include/pcb.h#2 integrate
.. //depot/projects/vimage/src/sys/sun4v/include/utrap.h#2 integrate
.. //depot/projects/vimage/src/sys/sun4v/sun4v/bus_machdep.c#2 integrate
.. //depot/projects/vimage/src/sys/sun4v/sun4v/exception.S#3 integrate
.. //depot/projects/vimage/src/sys/sun4v/sun4v/hv_pci.c#2 integrate
.. //depot/projects/vimage/src/sys/sun4v/sun4v/interrupt.S#3 integrate
.. //depot/projects/vimage/src/sys/sun4v/sun4v/mp_locore.S#2 integrate
.. //depot/projects/vimage/src/sys/sun4v/sun4v/support.S#2 integrate
.. //depot/projects/vimage/src/sys/sun4v/sun4v/swtch.S#2 integrate
.. //depot/projects/vimage/src/sys/sun4v/sun4v/wbuf.S#3 integrate
.. //depot/projects/vimage/src/sys/ufs/ffs/ffs_alloc.c#2 integrate
.. //depot/projects/vimage/src/sys/ufs/ffs/ffs_snapshot.c#2 integrate
.. //depot/projects/vimage/src/sys/ufs/ufs/quota.h#2 integrate
.. //depot/projects/vimage/src/sys/ufs/ufs/ufs_quota.c#2 integrate
.. //depot/projects/vimage/src/sys/ufs/ufs/ufs_vnops.c#2 integrate
.. //depot/projects/vimage/src/sys/vm/vm_object.c#3 integrate
.. //depot/projects/vimage/src/sys/vm/vm_pageout.c#2 integrate
Differences ...
==== //depot/projects/vimage/src/sys/amd64/include/md_var.h#2 (text+ko) ====
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/amd64/include/md_var.h,v 1.78 2006/06/19 22:36:01 davidxu Exp $
+ * $FreeBSD: src/sys/amd64/include/md_var.h,v 1.80 2007/01/18 05:46:32 rodrigc Exp $
*/
#ifndef _MACHINE_MD_VAR_H_
==== //depot/projects/vimage/src/sys/amd64/linux32/linux32_machdep.c#5 (text+ko) ====
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/amd64/linux32/linux32_machdep.c,v 1.26 2007/01/14 16:20:37 netchild Exp $");
+__FBSDID("$FreeBSD: src/sys/amd64/linux32/linux32_machdep.c,v 1.27 2007/01/20 14:58:59 netchild Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -453,14 +453,21 @@
linux_fork(struct thread *td, struct linux_fork_args *args)
{
int error;
+ struct proc *p2;
+ struct thread *td2;
#ifdef DEBUG
if (ldebug(fork))
printf(ARGS(fork, ""));
#endif
- if ((error = fork(td, (struct fork_args *)args)) != 0)
+ if ((error = fork1(td, RFFDG | RFPROC | RFSTOPPED, 0, &p2)) != 0)
return (error);
+
+ if (error == 0) {
+ td->td_retval[0] = p2->p_pid;
+ td->td_retval[1] = 0;
+ }
if (td->td_retval[1] == 1)
td->td_retval[0] = 0;
@@ -468,6 +475,14 @@
if (error)
return (error);
+ td2 = FIRST_THREAD_IN_PROC(p2);
+
+ /* make it run */
+ mtx_lock_spin(&sched_lock);
+ TD_SET_CAN_RUN(td2);
+ setrunqueue(td2, SRQ_BORING);
+ mtx_unlock_spin(&sched_lock);
+
return (0);
}
@@ -476,6 +491,7 @@
{
int error;
struct proc *p2;
+ struct thread *td2;
#ifdef DEBUG
if (ldebug(vfork))
@@ -483,7 +499,7 @@
#endif
/* exclude RFPPWAIT */
- if ((error = fork1(td, RFFDG | RFPROC | RFMEM, 0, &p2)) != 0)
+ if ((error = fork1(td, RFFDG | RFPROC | RFMEM | RFSTOPPED, 0, &p2)) != 0)
return (error);
if (error == 0) {
td->td_retval[0] = p2->p_pid;
@@ -495,12 +511,25 @@
error = linux_proc_init(td, td->td_retval[0], 0);
if (error)
return (error);
+
+ PROC_LOCK(p2);
+ p2->p_flag |= P_PPWAIT;
+ PROC_UNLOCK(p2);
+
+ td2 = FIRST_THREAD_IN_PROC(p2);
+
+ /* make it run */
+ mtx_lock_spin(&sched_lock);
+ TD_SET_CAN_RUN(td2);
+ setrunqueue(td2, SRQ_BORING);
+ mtx_unlock_spin(&sched_lock);
+
/* wait for the children to exit, ie. emulate vfork */
PROC_LOCK(p2);
- p2->p_flag |= P_PPWAIT;
while (p2->p_flag & P_PPWAIT)
msleep(td->td_proc, &p2->p_mtx, PWAIT, "ppwait", 0);
PROC_UNLOCK(p2);
+
return (0);
}
@@ -632,6 +661,11 @@
printf(LMSG("clone: successful rfork to %ld, stack %p sig = %d"),
(long)p2->p_pid, args->stack, exit_signal);
#endif
+ if (args->flags & CLONE_VFORK) {
+ PROC_LOCK(p2);
+ p2->p_flag |= P_PPWAIT;
+ PROC_UNLOCK(p2);
+ }
/*
* Make this runnable after we are finished with it.
@@ -647,7 +681,6 @@
if (args->flags & CLONE_VFORK) {
/* wait for the children to exit, ie. emulate vfork */
PROC_LOCK(p2);
- p2->p_flag |= P_PPWAIT;
while (p2->p_flag & P_PPWAIT)
msleep(td->td_proc, &p2->p_mtx, PWAIT, "ppwait", 0);
PROC_UNLOCK(p2);
==== //depot/projects/vimage/src/sys/arm/arm/busdma_machdep.c#2 (text+ko) ====
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/arm/arm/busdma_machdep.c,v 1.27 2006/08/25 15:10:45 cognet Exp $");
+__FBSDID("$FreeBSD: src/sys/arm/arm/busdma_machdep.c,v 1.28 2007/01/17 00:53:05 cognet Exp $");
/*
* MacPPC bus dma support routines
@@ -48,6 +48,7 @@
#include <sys/uio.h>
#include <sys/ktr.h>
#include <sys/kernel.h>
+#include <sys/sysctl.h>
#include <vm/vm.h>
#include <vm/vm_page.h>
@@ -56,7 +57,14 @@
#include <machine/atomic.h>
#include <machine/bus.h>
#include <machine/cpufunc.h>
+#include <machine/md_var.h>
+#define MAX_BPAGES 64
+#define BUS_DMA_COULD_BOUNCE BUS_DMA_BUS3
+#define BUS_DMA_MIN_ALLOC_COMP BUS_DMA_BUS4
+
+struct bounce_zone;
+
struct bus_dma_tag {
bus_dma_tag_t parent;
bus_size_t alignment;
@@ -81,8 +89,47 @@
*/
struct arm32_dma_range *ranges;
int _nranges;
+ struct bounce_zone *bounce_zone;
};
+struct bounce_page {
+ vm_offset_t vaddr; /* kva of bounce buffer */
+ vm_offset_t vaddr_nocache; /* kva of bounce buffer uncached */
+ bus_addr_t busaddr; /* Physical address */
+ vm_offset_t datavaddr; /* kva of client data */
+ bus_size_t datacount; /* client data count */
+ STAILQ_ENTRY(bounce_page) links;
+};
+
+int busdma_swi_pending;
+
+struct bounce_zone {
+ STAILQ_ENTRY(bounce_zone) links;
+ STAILQ_HEAD(bp_list, bounce_page) bounce_page_list;
+ int total_bpages;
+ int free_bpages;
+ int reserved_bpages;
+ int active_bpages;
+ int total_bounced;
+ int total_deferred;
+ bus_size_t alignment;
+ bus_size_t boundary;
+ bus_addr_t lowaddr;
+ char zoneid[8];
+ char lowaddrid[20];
+ struct sysctl_ctx_list sysctl_tree;
+ struct sysctl_oid *sysctl_tree_top;
+};
+
+static struct mtx bounce_lock;
+static int total_bpages;
+static int busdma_zonecount;
+static STAILQ_HEAD(, bounce_zone) bounce_zone_list;
+
+SYSCTL_NODE(_hw, OID_AUTO, busdma, CTLFLAG_RD, 0, "Busdma parameters");
+SYSCTL_INT(_hw_busdma, OID_AUTO, total_bpages, CTLFLAG_RD, &total_bpages, 0,
+ "Total bounce pages");
+
#define DMAMAP_LINEAR 0x1
#define DMAMAP_MBUF 0x2
#define DMAMAP_UIO 0x4
@@ -90,6 +137,9 @@
#define DMAMAP_TYPE_MASK (DMAMAP_LINEAR|DMAMAP_MBUF|DMAMAP_UIO)
#define DMAMAP_COHERENT 0x8
struct bus_dmamap {
+ struct bp_list bpages;
+ int pagesneeded;
+ int pagesreserved;
bus_dma_tag_t dmat;
int flags;
void *buffer;
@@ -97,8 +147,15 @@
void *allocbuffer;
TAILQ_ENTRY(bus_dmamap) freelist;
int len;
+ STAILQ_ENTRY(bus_dmamap) links;
+ bus_dmamap_callback_t *callback;
+ void *callback_arg;
+
};
+static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
+static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist;
+
static TAILQ_HEAD(,bus_dmamap) dmamap_freelist =
TAILQ_HEAD_INITIALIZER(dmamap_freelist);
@@ -109,6 +166,45 @@
MTX_SYSINIT(busdma_mtx, &busdma_mtx, "busdma lock", MTX_DEF);
+static void init_bounce_pages(void *dummy);
+static int alloc_bounce_zone(bus_dma_tag_t dmat);
+static int alloc_bounce_pages(bus_dma_tag_t dmat, u_int numpages);
+static int reserve_bounce_pages(bus_dma_tag_t dmat, bus_dmamap_t map,
+ int commit);
+static bus_addr_t add_bounce_page(bus_dma_tag_t dmat, bus_dmamap_t map,
+ vm_offset_t vaddr, bus_size_t size);
+static void free_bounce_page(bus_dma_tag_t dmat, struct bounce_page *bpage);
+
+/* Default tag, as most drivers provide no parent tag. */
+bus_dma_tag_t arm_root_dma_tag;
+
+/*
+ * Return true if a match is made.
+ *
+ * To find a match walk the chain of bus_dma_tag_t's looking for 'paddr'.
+ *
+ * If paddr is within the bounds of the dma tag then call the filter callback
+ * to check for a match, if there is no filter callback then assume a match.
+ */
+static int
+run_filter(bus_dma_tag_t dmat, bus_addr_t paddr)
+{
+ int retval;
+
+ retval = 0;
+
+ do {
+ if (((paddr > dmat->lowaddr && paddr <= dmat->highaddr)
+ || ((paddr & (dmat->alignment - 1)) != 0))
+ && (dmat->filter == NULL
+ || (*dmat->filter)(dmat->filterarg, paddr) != 0))
+ retval = 1;
+
+ dmat = dmat->parent;
+ } while (retval == 0 && dmat != NULL);
+ return (retval);
+}
+
static void
arm_dmamap_freelist_init(void *dummy)
{
@@ -129,6 +225,19 @@
bus_dmamap_t map, void *buf, bus_size_t buflen, struct pmap *pmap,
int flags, vm_offset_t *lastaddrp, int *segp);
+static __inline int
+_bus_dma_can_bounce(vm_offset_t lowaddr, vm_offset_t highaddr)
+{
+ int i;
+ for (i = 0; phys_avail[i] && phys_avail[i + 1]; i += 2) {
+ if ((lowaddr >= phys_avail[i] && lowaddr <= phys_avail[i + 1])
+ || (lowaddr < phys_avail[i] &&
+ highaddr > phys_avail[i]))
+ return (1);
+ }
+ return (0);
+}
+
static __inline struct arm32_dma_range *
_bus_dma_inrange(struct arm32_dma_range *ranges, int nranges,
bus_addr_t curaddr)
@@ -195,11 +304,12 @@
TAILQ_REMOVE(&dmamap_freelist, map, freelist);
mtx_unlock(&busdma_mtx);
if (!map) {
- map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT);
+ map = malloc(sizeof(*map), M_DEVBUF, M_NOWAIT | M_ZERO);
if (map)
map->flags = DMAMAP_ALLOCATED;
} else
map->flags = 0;
+ STAILQ_INIT(&map->bpages);
return (map);
}
@@ -232,6 +342,8 @@
int error = 0;
/* Return a NULL tag on failure */
*dmat = NULL;
+ if (!parent)
+ parent = arm_root_dma_tag;
newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, M_NOWAIT);
if (newtag == NULL) {
@@ -273,6 +385,9 @@
else if (parent->boundary != 0)
newtag->boundary = min(parent->boundary,
newtag->boundary);
+ if ((newtag->filter != NULL) ||
+ ((parent->flags & BUS_DMA_COULD_BOUNCE) != 0))
+ newtag->flags |= BUS_DMA_COULD_BOUNCE;
if (newtag->filter == NULL) {
/*
* Short circuit looking at our parent directly
@@ -285,8 +400,38 @@
if (newtag->parent != NULL)
atomic_add_int(&parent->ref_count, 1);
}
+ if (_bus_dma_can_bounce(newtag->lowaddr, newtag->highaddr)
+ || newtag->alignment > 1)
+ newtag->flags |= BUS_DMA_COULD_BOUNCE;
+
+ if (((newtag->flags & BUS_DMA_COULD_BOUNCE) != 0) &&
+ (flags & BUS_DMA_ALLOCNOW) != 0) {
+ struct bounce_zone *bz;
+
+ /* Must bounce */
+
+ if ((error = alloc_bounce_zone(newtag)) != 0) {
+ free(newtag, M_DEVBUF);
+ return (error);
+ }
+ bz = newtag->bounce_zone;
- *dmat = newtag;
+ if (ptoa(bz->total_bpages) < maxsize) {
+ int pages;
+
+ pages = atop(maxsize) - bz->total_bpages;
+
+ /* Add pages to our bounce pool */
+ if (alloc_bounce_pages(newtag, pages) < pages)
+ error = ENOMEM;
+ }
+ /* Performed initial allocation */
+ newtag->flags |= BUS_DMA_MIN_ALLOC_COMP;
+ }
+ if (error != 0)
+ free(newtag, M_DEVBUF);
+ else
+ *dmat = newtag;
CTR4(KTR_BUSDMA, "%s returned tag %p tag flags 0x%x error %d",
__func__, newtag, (newtag != NULL ? newtag->flags : 0), error);
@@ -327,6 +472,7 @@
return (0);
}
+#include <sys/kdb.h>
/*
* Allocate a handle for mapping from kva/uva/physical
* address space into bus device space.
@@ -335,9 +481,7 @@
bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)
{
bus_dmamap_t newmap;
-#ifdef KTR
int error = 0;
-#endif
newmap = _busdma_alloc_dmamap();
if (newmap == NULL) {
@@ -349,6 +493,52 @@
newmap->allocbuffer = NULL;
dmat->map_count++;
+ /*
+ * Bouncing might be required if the driver asks for an active
+ * exclusion region, a data alignment that is stricter than 1, and/or
+ * an active address boundary.
+ */
+ if (dmat->flags & BUS_DMA_COULD_BOUNCE) {
+
+ /* Must bounce */
+ struct bounce_zone *bz;
+ int maxpages;
+
+ if (dmat->bounce_zone == NULL) {
+ if ((error = alloc_bounce_zone(dmat)) != 0) {
+ _busdma_free_dmamap(newmap);
+ *mapp = NULL;
+ return (error);
+ }
+ }
+ bz = dmat->bounce_zone;
+
+ /* Initialize the new map */
+ STAILQ_INIT(&((*mapp)->bpages));
+
+ /*
+ * Attempt to add pages to our pool on a per-instance
+ * basis up to a sane limit.
+ */
+ maxpages = MAX_BPAGES;
+ if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0
+ || (dmat->map_count > 0 && bz->total_bpages < maxpages)) {
+ int pages;
+
+ pages = MAX(atop(dmat->maxsize), 1);
+ pages = MIN(maxpages - bz->total_bpages, pages);
+ pages = MAX(pages, 1);
+ if (alloc_bounce_pages(dmat, pages) < pages)
+ error = ENOMEM;
+
+ if ((dmat->flags & BUS_DMA_MIN_ALLOC_COMP) == 0) {
+ if (error == 0)
+ dmat->flags |= BUS_DMA_MIN_ALLOC_COMP;
+ } else {
+ error = 0;
+ }
+ }
+ }
CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
__func__, dmat, dmat->flags, error);
@@ -364,6 +554,11 @@
{
_busdma_free_dmamap(map);
+ if (STAILQ_FIRST(&map->bpages) != NULL) {
+ CTR3(KTR_BUSDMA, "%s: tag %p error %d",
+ __func__, dmat, EBUSY);
+ return (EBUSY);
+ }
dmat->map_count--;
CTR2(KTR_BUSDMA, "%s: tag %p error 0", __func__, dmat);
return (0);
@@ -399,7 +594,9 @@
*mapp = newmap;
newmap->dmat = dmat;
- if (dmat->maxsize <= PAGE_SIZE) {
+ if (dmat->maxsize <= PAGE_SIZE &&
+ (dmat->alignment < dmat->maxsize) &&
+ !_bus_dma_can_bounce(dmat->lowaddr, dmat->highaddr)) {
*vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);
} else {
/*
@@ -452,7 +649,9 @@
vaddr = map->origbuffer;
arm_unmap_nocache(map->allocbuffer, dmat->maxsize);
}
- if (dmat->maxsize <= PAGE_SIZE)
+ if (dmat->maxsize <= PAGE_SIZE &&
+ dmat->alignment < dmat->maxsize &&
+ !_bus_dma_can_bounce(dmat->lowaddr, dmat->highaddr))
free(vaddr, M_DEVBUF);
else {
contigfree(vaddr, dmat->maxsize, M_DEVBUF);
@@ -462,6 +661,64 @@
CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
}
+static int
+_bus_dmamap_count_pages(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf,
+ bus_size_t buflen, int flags, int *nb)
+{
+ vm_offset_t vaddr;
+ vm_offset_t vendaddr;
+ bus_addr_t paddr;
+ int needbounce = *nb;
+
+ if ((map->pagesneeded == 0)) {
+ CTR4(KTR_BUSDMA, "lowaddr= %d Maxmem= %d, boundary= %d, "
+ "alignment= %d", dmat->lowaddr, ptoa((vm_paddr_t)Maxmem),
+ dmat->boundary, dmat->alignment);
+ CTR3(KTR_BUSDMA, "map= %p, nobouncemap= %p, pagesneeded= %d",
+ map, &nobounce_dmamap, map->pagesneeded);
+ /*
+ * Count the number of bounce pages
+ * needed in order to complete this transfer
+ */
+ vaddr = trunc_page((vm_offset_t)buf);
+ vendaddr = (vm_offset_t)buf + buflen;
+
+ while (vaddr < vendaddr) {
+ paddr = pmap_kextract(vaddr);
+ if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) &&
+ run_filter(dmat, paddr) != 0) {
+ needbounce = 1;
+ map->pagesneeded++;
+ }
+ vaddr += PAGE_SIZE;
+ }
+ CTR1(KTR_BUSDMA, "pagesneeded= %d\n", map->pagesneeded);
+ }
+
+ /* Reserve Necessary Bounce Pages */
+ if (map->pagesneeded != 0) {
+ mtx_lock(&bounce_lock);
+ if (flags & BUS_DMA_NOWAIT) {
+ if (reserve_bounce_pages(dmat, map, 0) != 0) {
+ mtx_unlock(&bounce_lock);
+ return (ENOMEM);
+ }
+ } else {
+ if (reserve_bounce_pages(dmat, map, 1) != 0) {
+ /* Queue us for resources */
+ STAILQ_INSERT_TAIL(&bounce_map_waitinglist,
+ map, links);
+ mtx_unlock(&bounce_lock);
+ return (EINPROGRESS);
+ }
+ }
+ mtx_unlock(&bounce_lock);
+ }
+
+ *nb = needbounce;
+ return (0);
+}
+
/*
* Utility function to load a linear buffer. lastaddrp holds state
* between invocations (for multiple-buffer loads). segp contains
@@ -481,10 +738,17 @@
pd_entry_t *pde;
pt_entry_t pte;
pt_entry_t *ptep;
+ int needbounce = 0;
lastaddr = *lastaddrp;
bmask = ~(dmat->boundary - 1);
+ if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
+ error = _bus_dmamap_count_pages(dmat, map, buf, buflen, flags,
+ &needbounce);
+ if (error)
+ return (error);
+ }
CTR3(KTR_BUSDMA, "lowaddr= %d boundary= %d, "
"alignment= %d", dmat->lowaddr, dmat->boundary, dmat->alignment);
@@ -531,20 +795,6 @@
map->flags &= ~DMAMAP_COHERENT;
}
- if (dmat->ranges) {
- struct arm32_dma_range *dr;
-
- dr = _bus_dma_inrange(dmat->ranges, dmat->_nranges,
- curaddr);
- if (dr == NULL)
- return (EINVAL);
- /*
- * In a valid DMA range. Translate the physical
- * memory address to an address in the DMA window.
- */
- curaddr = (curaddr - dr->dr_sysbase) + dr->dr_busbase;
-
- }
/*
* Compute the segment size, and adjust counts.
*/
@@ -560,12 +810,30 @@
if (sgsize > (baddr - curaddr))
sgsize = (baddr - curaddr);
}
+ if (((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) &&
+ map->pagesneeded != 0 && run_filter(dmat, curaddr))
+ curaddr = add_bounce_page(dmat, map, vaddr, sgsize);
+
+ if (dmat->ranges) {
+ struct arm32_dma_range *dr;
+ dr = _bus_dma_inrange(dmat->ranges, dmat->_nranges,
+ curaddr);
+ if (dr == NULL)
+ return (EINVAL);
+ /*
+ * In a valid DMA range. Translate the physical
+ * memory address to an address in the DMA window.
+ */
+ curaddr = (curaddr - dr->dr_sysbase) + dr->dr_busbase;
+
+ }
+
/*
* Insert chunk into a segment, coalescing with
* the previous segment if possible.
*/
- if (seg >= 0 && curaddr == lastaddr &&
+ if (needbounce == 0 && seg >= 0 && curaddr == lastaddr &&
(segs[seg].ds_len + sgsize) <= dmat->maxsegsz &&
(dmat->boundary == 0 ||
(segs[seg].ds_addr & bmask) ==
@@ -615,6 +883,8 @@
KASSERT(dmat != NULL, ("dmatag is NULL"));
KASSERT(map != NULL, ("dmamap is NULL"));
+ map->callback = callback;
+ map->callback_arg = callback_arg;
map->flags &= ~DMAMAP_TYPE_MASK;
map->flags |= DMAMAP_LINEAR|DMAMAP_COHERENT;
map->buffer = buf;
@@ -622,6 +892,8 @@
error = bus_dmamap_load_buffer(dmat,
dm_segments, map, buf, buflen, kernel_pmap,
flags, &lastaddr, &nsegs);
+ if (error == EINPROGRESS)
+ return (error);
if (error)
(*callback)(callback_arg, NULL, 0, error);
else
@@ -797,26 +1069,93 @@
void
_bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)
{
+ struct bounce_page *bpage;
+
map->flags &= ~DMAMAP_TYPE_MASK;
+ while ((bpage = STAILQ_FIRST(&map->bpages)) != NULL) {
+ STAILQ_REMOVE_HEAD(&map->bpages, links);
+ free_bounce_page(dmat, bpage);
+ }
return;
}
static __inline void
bus_dmamap_sync_buf(void *buf, int len, bus_dmasync_op_t op)
{
+ char _tmp_cl[arm_dcache_align], _tmp_clend[arm_dcache_align];
if (op & BUS_DMASYNC_PREWRITE)
cpu_dcache_wb_range((vm_offset_t)buf, len);
- if (op & BUS_DMASYNC_PREREAD) {
+ if (op & BUS_DMASYNC_POSTREAD) {
+ if ((vm_offset_t)buf & arm_dcache_align_mask)
+ memcpy(_tmp_cl, (void *)((vm_offset_t)buf & ~
+ arm_dcache_align_mask),
+ (vm_offset_t)buf - ((vm_offset_t)buf &~
+ arm_dcache_align_mask));
+ if (((vm_offset_t)buf + len) & arm_dcache_align_mask)
+ memcpy(_tmp_cl, (void *)((vm_offset_t)buf & ~
+ arm_dcache_align_mask),
+ (vm_offset_t)buf - ((vm_offset_t)buf &~
+ arm_dcache_align_mask));
+ if (((vm_offset_t)buf + len) & arm_dcache_align_mask)
+ memcpy(_tmp_clend, (void *)(((vm_offset_t)buf + len) & ~
+ arm_dcache_align_mask),
+ (vm_offset_t)buf +len - (((vm_offset_t)buf + len) &~
+ arm_dcache_align_mask));
+ cpu_dcache_inv_range((vm_offset_t)buf, len);
if ((vm_offset_t)buf & arm_dcache_align_mask)
- cpu_dcache_wbinv_range((vm_offset_t)buf &
- ~arm_dcache_align_mask, arm_dcache_align);
+ memcpy((void *)((vm_offset_t)buf &
+ ~arm_dcache_align_mask),
+ _tmp_cl,
+ (vm_offset_t)buf - ((vm_offset_t)buf &~
+ arm_dcache_align_mask));
if (((vm_offset_t)buf + len) & arm_dcache_align_mask)
- cpu_dcache_wbinv_range(((vm_offset_t)buf + len) &
- ~arm_dcache_align_mask, arm_dcache_align);
+ memcpy((void *)(((vm_offset_t)buf + len) & ~
+ arm_dcache_align_mask), _tmp_clend,
+ (vm_offset_t)buf +len - (((vm_offset_t)buf + len) &~
+ arm_dcache_align_mask));
+ }
+}
+
+static void
+_bus_dmamap_sync_bp(bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)
+{
+ struct bounce_page *bpage;
+
+ STAILQ_FOREACH(bpage, &map->bpages, links) {
+ if (op & BUS_DMASYNC_PREWRITE) {
+ bcopy((void *)bpage->datavaddr,
+ (void *)(bpage->vaddr_nocache != 0 ?
+ bpage->vaddr_nocache : bpage->vaddr),
+ bpage->datacount);
+ if (bpage->vaddr_nocache == 0)
+ cpu_dcache_wb_range(bpage->vaddr,
+ bpage->datacount);
+ }
+ if (op & BUS_DMASYNC_POSTREAD) {
+ if (bpage->vaddr_nocache == 0)
+ cpu_dcache_inv_range(bpage->vaddr,
+ bpage->datacount);
+ bcopy((void *)(bpage->vaddr_nocache != 0 ?
+ bpage->vaddr_nocache : bpage->vaddr),
+ (void *)bpage->datavaddr, bpage->datacount);
+ }
+ }
+}
+
+static __inline int
+_bus_dma_buf_is_in_bp(bus_dmamap_t map, void *buf, int len)
+{
+ struct bounce_page *bpage;
+
+ STAILQ_FOREACH(bpage, &map->bpages, links) {
+ if ((vm_offset_t)buf >= bpage->datavaddr &&
+ (vm_offset_t)buf + len < bpage->datavaddr +
+ bpage->datacount)
+ return (1);
}
- if (op & BUS_DMASYNC_POSTREAD)
- cpu_dcache_inv_range((vm_offset_t)buf, len);
+ return (0);
+
}
void
@@ -829,6 +1168,8 @@
if (op == BUS_DMASYNC_POSTWRITE)
return;
+ if (STAILQ_FIRST(&map->bpages))
+ _bus_dmamap_sync_bp(dmat, map, op);
if (map->flags & DMAMAP_COHERENT)
return;
if ((op && BUS_DMASYNC_POSTREAD) && (map->len >= 2 * PAGE_SIZE)) {
@@ -838,12 +1179,14 @@
CTR3(KTR_BUSDMA, "%s: op %x flags %x", __func__, op, map->flags);
switch(map->flags & DMAMAP_TYPE_MASK) {
case DMAMAP_LINEAR:
- bus_dmamap_sync_buf(map->buffer, map->len, op);
+ if (!(_bus_dma_buf_is_in_bp(map, map->buffer, map->len)))
+ bus_dmamap_sync_buf(map->buffer, map->len, op);
break;
case DMAMAP_MBUF:
m = map->buffer;
while (m) {
- if (m->m_len > 0)
+ if (m->m_len > 0 &&
+ !(_bus_dma_buf_is_in_bp(map, m->m_data, m->m_len)))
bus_dmamap_sync_buf(m->m_data, m->m_len, op);
m = m->m_next;
}
@@ -856,8 +1199,10 @@
bus_size_t minlen = resid < iov[i].iov_len ? resid :
iov[i].iov_len;
if (minlen > 0) {
- bus_dmamap_sync_buf(iov[i].iov_base, minlen,
- op);
+ if (!_bus_dma_buf_is_in_bp(map, iov[i].iov_base,
+ minlen))
+ bus_dmamap_sync_buf(iov[i].iov_base,
+ minlen, op);
resid -= minlen;
}
}
@@ -867,3 +1212,247 @@
}
cpu_drain_writebuf();
}
+
+static void
+init_bounce_pages(void *dummy __unused)
+{
+
+ total_bpages = 0;
+ STAILQ_INIT(&bounce_zone_list);
+ STAILQ_INIT(&bounce_map_waitinglist);
+ STAILQ_INIT(&bounce_map_callbacklist);
+ mtx_init(&bounce_lock, "bounce pages lock", NULL, MTX_DEF);
+}
+SYSINIT(bpages, SI_SUB_LOCK, SI_ORDER_ANY, init_bounce_pages, NULL);
+
+static struct sysctl_ctx_list *
+busdma_sysctl_tree(struct bounce_zone *bz)
+{
+ return (&bz->sysctl_tree);
+}
+
+static struct sysctl_oid *
+busdma_sysctl_tree_top(struct bounce_zone *bz)
+{
+ return (bz->sysctl_tree_top);
+}
+
+static int
+alloc_bounce_zone(bus_dma_tag_t dmat)
+{
+ struct bounce_zone *bz;
+
+ /* Check to see if we already have a suitable zone */
+ STAILQ_FOREACH(bz, &bounce_zone_list, links) {
+ if ((dmat->alignment <= bz->alignment)
+ && (dmat->boundary <= bz->boundary)
+ && (dmat->lowaddr >= bz->lowaddr)) {
+ dmat->bounce_zone = bz;
+ return (0);
+ }
+ }
+
+ if ((bz = (struct bounce_zone *)malloc(sizeof(*bz), M_DEVBUF,
+ M_NOWAIT | M_ZERO)) == NULL)
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list