svn commit: r239014 - in user/mjacob/sys: conf dev/esp dev/isp geom/multipath kern netgraph powerpc/powerpc x86/x86

Matt Jacob mjacob at FreeBSD.org
Fri Aug 3 15:29:20 UTC 2012


Author: mjacob
Date: Fri Aug  3 15:29:19 2012
New Revision: 239014
URL: http://svn.freebsd.org/changeset/base/239014

Log:
  MFC at 239013

Modified:
  user/mjacob/sys/conf/files
  user/mjacob/sys/dev/esp/ncr53c9x.c
  user/mjacob/sys/dev/isp/isp_pci.c
  user/mjacob/sys/geom/multipath/g_multipath.c
  user/mjacob/sys/kern/kern_clocksource.c
  user/mjacob/sys/netgraph/ng_pptpgre.c
  user/mjacob/sys/powerpc/powerpc/busdma_machdep.c
  user/mjacob/sys/x86/x86/busdma_machdep.c
  user/mjacob/sys/x86/x86/local_apic.c
Directory Properties:
  user/mjacob/sys/   (props changed)
  user/mjacob/sys/conf/   (props changed)

Modified: user/mjacob/sys/conf/files
==============================================================================
--- user/mjacob/sys/conf/files	Fri Aug  3 15:19:59 2012	(r239013)
+++ user/mjacob/sys/conf/files	Fri Aug  3 15:29:19 2012	(r239014)
@@ -2213,6 +2213,16 @@ dev/utopia/idtphy.c		optional utopia
 dev/utopia/suni.c		optional utopia
 dev/utopia/utopia.c		optional utopia
 dev/vge/if_vge.c		optional vge
+#
+# virtio support
+#
+dev/virtio/pci/virtio_pci.c    optional vtnet
+dev/virtio/virtio.c            optional vtnet
+dev/virtio/virtqueue.c         optional vtnet
+dev/virtio/network/if_vtnet.c  optional vtnet
+dev/virtio/virtio_bus_if.m     optional vtnet
+dev/virtio/virtio_if.m         optional vtnet
+
 dev/vkbd/vkbd.c			optional vkbd
 dev/vr/if_vr.c			optional vr pci
 dev/vte/if_vte.c		optional vte pci

Modified: user/mjacob/sys/dev/esp/ncr53c9x.c
==============================================================================
--- user/mjacob/sys/dev/esp/ncr53c9x.c	Fri Aug  3 15:19:59 2012	(r239013)
+++ user/mjacob/sys/dev/esp/ncr53c9x.c	Fri Aug  3 15:29:19 2012	(r239014)
@@ -2038,6 +2038,10 @@ gotit:
 			}
 			break;
 
+        case MSG_IGN_WIDE_RESIDUE:
+            NCR_MSGS(("ignore_wide_residue "));
+            break;
+
 		default:
 			NCR_MSGS(("ident "));
 			xpt_print_path(ecb->ccb->ccb_h.path);

Modified: user/mjacob/sys/dev/isp/isp_pci.c
==============================================================================
--- user/mjacob/sys/dev/isp/isp_pci.c	Fri Aug  3 15:19:59 2012	(r239013)
+++ user/mjacob/sys/dev/isp/isp_pci.c	Fri Aug  3 15:29:19 2012	(r239014)
@@ -1482,16 +1482,18 @@ imc(void *arg, bus_dma_segment_t *segs, 
 	segs->ds_addr += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp));
 	imushp->vbase += ISP_QUEUE_SIZE(RESULT_QUEUE_LEN(imushp->isp));
 
-	imushp->isp->isp_osinfo.ecmd_dma = segs->ds_addr;
-	imushp->isp->isp_osinfo.ecmd_free = (isp_ecmd_t *)imushp->vbase;
-	imushp->isp->isp_osinfo.ecmd_base = imushp->isp->isp_osinfo.ecmd_free;
-	for (ecmd = imushp->isp->isp_osinfo.ecmd_free; ecmd < &imushp->isp->isp_osinfo.ecmd_free[N_XCMDS]; ecmd++) {
-		if (ecmd == &imushp->isp->isp_osinfo.ecmd_free[N_XCMDS - 1]) {
-			ecmd->next = NULL;
-		} else {
-			ecmd->next = ecmd + 1;
-		}
-	}
+	if (imushp->isp->isp_type >= ISP_HA_FC_2300) {
+        imushp->isp->isp_osinfo.ecmd_dma = segs->ds_addr;
+        imushp->isp->isp_osinfo.ecmd_free = (isp_ecmd_t *)imushp->vbase;
+        imushp->isp->isp_osinfo.ecmd_base = imushp->isp->isp_osinfo.ecmd_free;
+        for (ecmd = imushp->isp->isp_osinfo.ecmd_free; ecmd < &imushp->isp->isp_osinfo.ecmd_free[N_XCMDS]; ecmd++) {
+            if (ecmd == &imushp->isp->isp_osinfo.ecmd_free[N_XCMDS - 1]) {
+                ecmd->next = NULL;
+            } else {
+                ecmd->next = ecmd + 1;
+            }
+        }
+    }
 #ifdef	ISP_TARGET_MODE
 	segs->ds_addr += (N_XCMDS * XCMD_SIZE);
 	imushp->vbase += (N_XCMDS * XCMD_SIZE);

Modified: user/mjacob/sys/geom/multipath/g_multipath.c
==============================================================================
--- user/mjacob/sys/geom/multipath/g_multipath.c	Fri Aug  3 15:19:59 2012	(r239013)
+++ user/mjacob/sys/geom/multipath/g_multipath.c	Fri Aug  3 15:29:19 2012	(r239014)
@@ -849,6 +849,78 @@ g_multipath_ctl_add_name(struct gctl_req
 }
 
 static void
+g_multipath_ctl_prefer(struct gctl_req *req, struct g_class *mp)
+{
+	struct g_geom *gp;
+	struct g_multipath_softc *sc;
+	struct g_consumer *cp;
+	const char *name, *mpname;
+	static const char devpf[6] = "/dev/";
+	int *nargs;
+
+	g_topology_assert();
+
+	mpname = gctl_get_asciiparam(req, "arg0");
+        if (mpname == NULL) {
+                gctl_error(req, "No 'arg0' argument");
+                return;
+        }
+	gp = g_multipath_find_geom(mp, mpname);
+	if (gp == NULL) {
+		gctl_error(req, "Device %s is invalid", mpname);
+		return;
+	}
+	sc = gp->softc;
+
+	nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs));
+	if (nargs == NULL) {
+		gctl_error(req, "No 'nargs' argument");
+		return;
+	}
+	if (*nargs != 2) {
+		gctl_error(req, "missing device");
+		return;
+	}
+
+	name = gctl_get_asciiparam(req, "arg1");
+	if (name == NULL) {
+		gctl_error(req, "No 'arg1' argument");
+		return;
+	}
+	if (strncmp(name, devpf, 5) == 0) {
+		name += 5;
+	}
+
+	LIST_FOREACH(cp, &gp->consumer, consumer) {
+		if (cp->provider != NULL
+                      && strcmp(cp->provider->name, name) == 0)
+		    break;
+	}
+
+	if (cp == NULL) {
+		gctl_error(req, "Provider %s not found", name);
+		return;
+	}
+
+	mtx_lock(&sc->sc_mtx);
+
+	if (cp->index & MP_BAD) {
+		gctl_error(req, "Consumer %s is invalid", name);
+		mtx_unlock(&sc->sc_mtx);
+		return;
+	}
+
+	/* Here when the consumer is present and in good shape */
+
+	sc->sc_active = cp;
+	if (!sc->sc_active_active)
+	    printf("GEOM_MULTIPATH: %s now active path in %s\n",
+		sc->sc_active->provider->name, sc->sc_name);
+
+	mtx_unlock(&sc->sc_mtx);
+}
+
+static void
 g_multipath_ctl_add(struct gctl_req *req, struct g_class *mp)
 {
 	struct g_multipath_softc *sc;
@@ -1278,6 +1350,8 @@ g_multipath_config(struct gctl_req *req,
 		gctl_error(req, "Userland and kernel parts are out of sync");
 	} else if (strcmp(verb, "add") == 0) {
 		g_multipath_ctl_add(req, mp);
+	} else if (strcmp(verb, "prefer") == 0) {
+		g_multipath_ctl_prefer(req, mp);
 	} else if (strcmp(verb, "create") == 0) {
 		g_multipath_ctl_create(req, mp);
 	} else if (strcmp(verb, "configure") == 0) {

Modified: user/mjacob/sys/kern/kern_clocksource.c
==============================================================================
--- user/mjacob/sys/kern/kern_clocksource.c	Fri Aug  3 15:19:59 2012	(r239013)
+++ user/mjacob/sys/kern/kern_clocksource.c	Fri Aug  3 15:29:19 2012	(r239014)
@@ -205,19 +205,21 @@ handleevents(struct bintime *now, int fa
 
 	runs = 0;
 	while (bintime_cmp(now, &state->nexthard, >=)) {
-		bintime_add(&state->nexthard, &hardperiod);
+		bintime_addx(&state->nexthard, hardperiod.frac);
 		runs++;
 	}
-	if ((timer->et_flags & ET_FLAGS_PERCPU) == 0 &&
-	    bintime_cmp(&state->nexthard, &nexthard, >))
-		nexthard = state->nexthard;
-	if (runs && fake < 2) {
-		hardclock_cnt(runs, usermode);
-		done = 1;
+	if (runs) {
+		if ((timer->et_flags & ET_FLAGS_PERCPU) == 0 &&
+		    bintime_cmp(&state->nexthard, &nexthard, >))
+			nexthard = state->nexthard;
+		if (fake < 2) {
+			hardclock_cnt(runs, usermode);
+			done = 1;
+		}
 	}
 	runs = 0;
 	while (bintime_cmp(now, &state->nextstat, >=)) {
-		bintime_add(&state->nextstat, &statperiod);
+		bintime_addx(&state->nextstat, statperiod.frac);
 		runs++;
 	}
 	if (runs && fake < 2) {
@@ -227,7 +229,7 @@ handleevents(struct bintime *now, int fa
 	if (profiling) {
 		runs = 0;
 		while (bintime_cmp(now, &state->nextprof, >=)) {
-			bintime_add(&state->nextprof, &profperiod);
+			bintime_addx(&state->nextprof, profperiod.frac);
 			runs++;
 		}
 		if (runs && !fake) {
@@ -356,7 +358,7 @@ timercb(struct eventtimer *et, void *arg
 		next = &nexttick;
 	if (periodic) {
 		now = *next;	/* Ex-next tick time becomes present time. */
-		bintime_add(next, &timerperiod); /* Next tick in 1 period. */
+		bintime_addx(next, timerperiod.frac); /* Next tick in 1 period. */
 	} else {
 		binuptime(&now);	/* Get present time from hardware. */
 		next->sec = -1;		/* Next tick is not scheduled yet. */
@@ -433,7 +435,7 @@ loadtimer(struct bintime *now, int start
 			new.sec = 0;
 			new.frac = timerperiod.frac - tmp;
 			if (new.frac < tmp)	/* Left less then passed. */
-				bintime_add(&new, &timerperiod);
+				bintime_addx(&new, timerperiod.frac);
 			CTR5(KTR_SPARE2, "load p at %d:   now %d.%08x first in %d.%08x",
 			    curcpu, now->sec, (unsigned int)(now->frac >> 32),
 			    new.sec, (unsigned int)(new.frac >> 32));
@@ -531,7 +533,7 @@ configtimer(int start)
 	if (start) {
 		/* Initialize time machine parameters. */
 		next = now;
-		bintime_add(&next, &timerperiod);
+		bintime_addx(&next, timerperiod.frac);
 		if (periodic)
 			nexttick = next;
 		else

Modified: user/mjacob/sys/netgraph/ng_pptpgre.c
==============================================================================
--- user/mjacob/sys/netgraph/ng_pptpgre.c	Fri Aug  3 15:19:59 2012	(r239013)
+++ user/mjacob/sys/netgraph/ng_pptpgre.c	Fri Aug  3 15:29:19 2012	(r239014)
@@ -562,7 +562,7 @@ ng_pptpgre_xmit(hpriv_p hpriv, item_p it
 		}
 
 		/* Sanity check frame length */
-		if (m != NULL && m->m_pkthdr.len > PPTP_MAX_PAYLOAD) {
+		if (m->m_pkthdr.len > PPTP_MAX_PAYLOAD) {
 			priv->stats.xmitTooBig++;
 			ERROUT(EMSGSIZE);
 		}

Modified: user/mjacob/sys/powerpc/powerpc/busdma_machdep.c
==============================================================================
--- user/mjacob/sys/powerpc/powerpc/busdma_machdep.c	Fri Aug  3 15:19:59 2012	(r239013)
+++ user/mjacob/sys/powerpc/powerpc/busdma_machdep.c	Fri Aug  3 15:29:19 2012	(r239014)
@@ -46,6 +46,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysctl.h>
 
 #include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
 #include <vm/vm_page.h>
 #include <vm/vm_map.h>
 
@@ -130,6 +132,7 @@ struct bus_dmamap {
 	bus_dmamap_callback_t *callback;
 	void		      *callback_arg;
 	STAILQ_ENTRY(bus_dmamap) links;
+	int		       contigalloc;
 };
 
 static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
@@ -489,6 +492,7 @@ int
 bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
 		 bus_dmamap_t *mapp)
 {
+	vm_memattr_t attr;
 	int mflags;
 
 	if (flags & BUS_DMA_NOWAIT)
@@ -500,6 +504,12 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
 
 	if (flags & BUS_DMA_ZERO)
 		mflags |= M_ZERO;
+#ifdef NOTYET
+	if (flags & BUS_DMA_NOCACHE)
+		attr = VM_MEMATTR_UNCACHEABLE;
+	else
+#endif
+		attr = VM_MEMATTR_DEFAULT;
 
 	/* 
 	 * XXX:
@@ -511,7 +521,8 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
 	 */
 	if ((dmat->maxsize <= PAGE_SIZE) &&
 	   (dmat->alignment < dmat->maxsize) &&
-	    dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) {
+	    dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem) &&
+	    attr == VM_MEMATTR_DEFAULT) {
 		*vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);
 	} else {
 		/*
@@ -520,9 +531,10 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
 		 *     multi-seg allocations yet though.
 		 * XXX Certain AGP hardware does.
 		 */
-		*vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags,
-		    0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul,
-		    dmat->boundary);
+		*vaddr = (void *)kmem_alloc_contig(kernel_map, dmat->maxsize,
+		    mflags, 0ul, dmat->lowaddr, dmat->alignment ?
+		    dmat->alignment : 1ul, dmat->boundary, attr);
+		(*mapp)->contigalloc = 1;
 	}
 	if (*vaddr == NULL) {
 		CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
@@ -531,11 +543,6 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
 	} else if (vtophys(*vaddr) & (dmat->alignment - 1)) {
 		printf("bus_dmamem_alloc failed to align memory properly.\n");
 	}
-#ifdef NOTYET
-	if (flags & BUS_DMA_NOCACHE)
-		pmap_change_attr((vm_offset_t)*vaddr, dmat->maxsize,
-		    VM_MEMATTR_UNCACHEABLE);
-#endif
 	CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
 	    __func__, dmat, dmat->flags, 0);
 	return (0);
@@ -548,18 +555,12 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
 void
 bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)
 {
-	bus_dmamap_destroy(dmat, map);
 
-#ifdef NOTYET
-	pmap_change_attr((vm_offset_t)vaddr, dmat->maxsize, VM_MEMATTR_DEFAULT);
-#endif
-	if ((dmat->maxsize <= PAGE_SIZE) &&
-	   (dmat->alignment < dmat->maxsize) &&
-	    dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem))
+	if (!map->contigalloc)
 		free(vaddr, M_DEVBUF);
-	else {
-		contigfree(vaddr, dmat->maxsize, M_DEVBUF);
-	}
+	else
+		kmem_free(kernel_map, (vm_offset_t)vaddr, dmat->maxsize);
+	bus_dmamap_destroy(dmat, map);
 	CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
 }
 

Modified: user/mjacob/sys/x86/x86/busdma_machdep.c
==============================================================================
--- user/mjacob/sys/x86/x86/busdma_machdep.c	Fri Aug  3 15:19:59 2012	(r239013)
+++ user/mjacob/sys/x86/x86/busdma_machdep.c	Fri Aug  3 15:29:19 2012	(r239014)
@@ -42,6 +42,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/sysctl.h>
 
 #include <vm/vm.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_kern.h>
 #include <vm/vm_page.h>
 #include <vm/vm_map.h>
 
@@ -131,7 +133,7 @@ struct bus_dmamap {
 
 static STAILQ_HEAD(, bus_dmamap) bounce_map_waitinglist;
 static STAILQ_HEAD(, bus_dmamap) bounce_map_callbacklist;
-static struct bus_dmamap nobounce_dmamap;
+static struct bus_dmamap nobounce_dmamap, contig_dmamap;
 
 static void init_bounce_pages(void *dummy);
 static int alloc_bounce_zone(bus_dma_tag_t dmat);
@@ -465,7 +467,7 @@ bus_dmamap_create(bus_dma_tag_t dmat, in
 int
 bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)
 {
-	if (map != NULL && map != &nobounce_dmamap) {
+	if (map != NULL && map != &nobounce_dmamap && map != &contig_dmamap) {
 		if (STAILQ_FIRST(&map->bpages) != NULL) {
 			CTR3(KTR_BUSDMA, "%s: tag %p error %d",
 			    __func__, dmat, EBUSY);
@@ -490,6 +492,7 @@ int
 bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
 		 bus_dmamap_t *mapp)
 {
+	vm_memattr_t attr;
 	int mflags;
 
 	if (flags & BUS_DMA_NOWAIT)
@@ -512,6 +515,10 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
 	}
 	if (flags & BUS_DMA_ZERO)
 		mflags |= M_ZERO;
+	if (flags & BUS_DMA_NOCACHE)
+		attr = VM_MEMATTR_UNCACHEABLE;
+	else
+		attr = VM_MEMATTR_DEFAULT;
 
 	/* 
 	 * XXX:
@@ -523,7 +530,8 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
 	 */
 	if ((dmat->maxsize <= PAGE_SIZE) &&
 	   (dmat->alignment < dmat->maxsize) &&
-	    dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem)) {
+	    dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem) &&
+	    attr == VM_MEMATTR_DEFAULT) {
 		*vaddr = malloc(dmat->maxsize, M_DEVBUF, mflags);
 	} else {
 		/*
@@ -532,9 +540,10 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
 		 *     multi-seg allocations yet though.
 		 * XXX Certain AGP hardware does.
 		 */
-		*vaddr = contigmalloc(dmat->maxsize, M_DEVBUF, mflags,
-		    0ul, dmat->lowaddr, dmat->alignment? dmat->alignment : 1ul,
-		    dmat->boundary);
+		*vaddr = (void *)kmem_alloc_contig(kernel_map, dmat->maxsize,
+		    mflags, 0ul, dmat->lowaddr, dmat->alignment ?
+		    dmat->alignment : 1ul, dmat->boundary, attr);
+		*mapp = &contig_dmamap;
 	}
 	if (*vaddr == NULL) {
 		CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
@@ -543,9 +552,6 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, voi
 	} else if (vtophys(*vaddr) & (dmat->alignment - 1)) {
 		printf("bus_dmamem_alloc failed to align memory properly.\n");
 	}
-	if (flags & BUS_DMA_NOCACHE)
-		pmap_change_attr((vm_offset_t)*vaddr, dmat->maxsize,
-		    PAT_UNCACHEABLE);
 	CTR4(KTR_BUSDMA, "%s: tag %p tag flags 0x%x error %d",
 	    __func__, dmat, dmat->flags, 0);
 	return (0);
@@ -560,18 +566,15 @@ bus_dmamem_free(bus_dma_tag_t dmat, void
 {
 	/*
 	 * dmamem does not need to be bounced, so the map should be
-	 * NULL
+	 * NULL if malloc() was used and contig_dmamap if
+	 * contigmalloc() was used.
 	 */
-	if (map != NULL)
+	if (!(map == NULL || map == &contig_dmamap))
 		panic("bus_dmamem_free: Invalid map freed\n");
-	pmap_change_attr((vm_offset_t)vaddr, dmat->maxsize, PAT_WRITE_BACK);
-	if ((dmat->maxsize <= PAGE_SIZE) &&
-	   (dmat->alignment < dmat->maxsize) &&
-	    dmat->lowaddr >= ptoa((vm_paddr_t)Maxmem))
+	if (map == NULL)
 		free(vaddr, M_DEVBUF);
-	else {
-		contigfree(vaddr, dmat->maxsize, M_DEVBUF);
-	}
+	else
+		kmem_free(kernel_map, (vm_offset_t)vaddr, dmat->maxsize);
 	CTR3(KTR_BUSDMA, "%s: tag %p flags 0x%x", __func__, dmat, dmat->flags);
 }
 
@@ -662,7 +665,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t dm
 	vm_offset_t vaddr;
 	int seg, error;
 
-	if (map == NULL)
+	if (map == NULL || map == &contig_dmamap)
 		map = &nobounce_dmamap;
 
 	if ((dmat->flags & BUS_DMA_COULD_BOUNCE) != 0) {
@@ -1139,7 +1142,7 @@ add_bounce_page(bus_dma_tag_t dmat, bus_
 	struct bounce_page *bpage;
 
 	KASSERT(dmat->bounce_zone != NULL, ("no bounce zone in dma tag"));
-	KASSERT(map != NULL && map != &nobounce_dmamap,
+	KASSERT(map != NULL && map != &nobounce_dmamap && map != &contig_dmamap,
 	    ("add_bounce_page: bad map %p", map));
 
 	bz = dmat->bounce_zone;

Modified: user/mjacob/sys/x86/x86/local_apic.c
==============================================================================
--- user/mjacob/sys/x86/x86/local_apic.c	Fri Aug  3 15:19:59 2012	(r239013)
+++ user/mjacob/sys/x86/x86/local_apic.c	Fri Aug  3 15:29:19 2012	(r239014)
@@ -119,6 +119,7 @@ struct lapic {
 	u_long *la_timer_count;
 	u_long la_timer_period;
 	u_int la_timer_mode;
+	uint32_t lvt_timer_cache;
 	/* Include IDT_SYSCALL to make indexing easier. */
 	int la_ioint_irqs[APIC_NUM_IOINTS + 1];
 } static lapics[MAX_APIC_ID + 1];
@@ -160,9 +161,11 @@ static struct eventtimer lapic_et;
 
 static void	lapic_enable(void);
 static void	lapic_resume(struct pic *pic);
-static void	lapic_timer_oneshot(u_int count, int enable_int);
-static void	lapic_timer_periodic(u_int count, int enable_int);
-static void	lapic_timer_stop(void);
+static void	lapic_timer_oneshot(struct lapic *,
+		    u_int count, int enable_int);
+static void	lapic_timer_periodic(struct lapic *,
+		    u_int count, int enable_int);
+static void	lapic_timer_stop(struct lapic *);
 static void	lapic_timer_set_divisor(u_int divisor);
 static uint32_t	lvt_mode(struct lapic *la, u_int pin, uint32_t value);
 static int	lapic_et_start(struct eventtimer *et,
@@ -370,7 +373,8 @@ lapic_setup(int boot)
 		lapic->lvt_pcint = lvt_mode(la, LVT_PMC, lapic->lvt_pcint);
 
 	/* Program timer LVT and setup handler. */
-	lapic->lvt_timer = lvt_mode(la, LVT_TIMER, lapic->lvt_timer);
+	la->lvt_timer_cache = lapic->lvt_timer =
+	    lvt_mode(la, LVT_TIMER, lapic->lvt_timer);
 	if (boot) {
 		snprintf(buf, sizeof(buf), "cpu%d:timer", PCPU_GET(cpuid));
 		intrcnt_add(buf, &la->la_timer_count);
@@ -382,9 +386,9 @@ lapic_setup(int boot)
 		    lapic_id()));
 		lapic_timer_set_divisor(lapic_timer_divisor);
 		if (la->la_timer_mode == 1)
-			lapic_timer_periodic(la->la_timer_period, 1);
+			lapic_timer_periodic(la, la->la_timer_period, 1);
 		else
-			lapic_timer_oneshot(la->la_timer_period, 1);
+			lapic_timer_oneshot(la, la->la_timer_period, 1);
 	}
 
 	/* Program error LVT and clear any existing errors. */
@@ -489,13 +493,14 @@ lapic_et_start(struct eventtimer *et,
 	struct lapic *la;
 	u_long value;
 
+	la = &lapics[PCPU_GET(apic_id)];
 	if (et->et_frequency == 0) {
 		/* Start off with a divisor of 2 (power on reset default). */
 		lapic_timer_divisor = 2;
 		/* Try to calibrate the local APIC timer. */
 		do {
 			lapic_timer_set_divisor(lapic_timer_divisor);
-			lapic_timer_oneshot(APIC_TIMER_MAX_COUNT, 0);
+			lapic_timer_oneshot(la, APIC_TIMER_MAX_COUNT, 0);
 			DELAY(1000000);
 			value = APIC_TIMER_MAX_COUNT - lapic->ccr_timer;
 			if (value != APIC_TIMER_MAX_COUNT)
@@ -515,22 +520,22 @@ lapic_et_start(struct eventtimer *et,
 		et->et_max_period.frac =
 		    ((0xfffffffeLLU << 32) / et->et_frequency) << 32;
 	}
-	lapic_timer_set_divisor(lapic_timer_divisor);
-	la = &lapics[lapic_id()];
+	if (la->la_timer_mode == 0)
+		lapic_timer_set_divisor(lapic_timer_divisor);
 	if (period != NULL) {
 		la->la_timer_mode = 1;
 		la->la_timer_period =
 		    (et->et_frequency * (period->frac >> 32)) >> 32;
 		if (period->sec != 0)
 			la->la_timer_period += et->et_frequency * period->sec;
-		lapic_timer_periodic(la->la_timer_period, 1);
+		lapic_timer_periodic(la, la->la_timer_period, 1);
 	} else {
 		la->la_timer_mode = 2;
 		la->la_timer_period =
 		    (et->et_frequency * (first->frac >> 32)) >> 32;
 		if (first->sec != 0)
 			la->la_timer_period += et->et_frequency * first->sec;
-		lapic_timer_oneshot(la->la_timer_period, 1);
+		lapic_timer_oneshot(la, la->la_timer_period, 1);
 	}
 	return (0);
 }
@@ -538,10 +543,10 @@ lapic_et_start(struct eventtimer *et,
 static int
 lapic_et_stop(struct eventtimer *et)
 {
-	struct lapic *la = &lapics[lapic_id()];
+	struct lapic *la = &lapics[PCPU_GET(apic_id)];
 
 	la->la_timer_mode = 0;
-	lapic_timer_stop();
+	lapic_timer_stop(la);
 	return (0);
 }
 
@@ -835,11 +840,11 @@ lapic_timer_set_divisor(u_int divisor)
 }
 
 static void
-lapic_timer_oneshot(u_int count, int enable_int)
+lapic_timer_oneshot(struct lapic *la, u_int count, int enable_int)
 {
 	u_int32_t value;
 
-	value = lapic->lvt_timer;
+	value = la->lvt_timer_cache;
 	value &= ~APIC_LVTT_TM;
 	value |= APIC_LVTT_TM_ONE_SHOT;
 	if (enable_int)
@@ -849,11 +854,11 @@ lapic_timer_oneshot(u_int count, int ena
 }
 
 static void
-lapic_timer_periodic(u_int count, int enable_int)
+lapic_timer_periodic(struct lapic *la, u_int count, int enable_int)
 {
 	u_int32_t value;
 
-	value = lapic->lvt_timer;
+	value = la->lvt_timer_cache;
 	value &= ~APIC_LVTT_TM;
 	value |= APIC_LVTT_TM_PERIODIC;
 	if (enable_int)
@@ -863,11 +868,11 @@ lapic_timer_periodic(u_int count, int en
 }
 
 static void
-lapic_timer_stop(void)
+lapic_timer_stop(struct lapic *la)
 {
 	u_int32_t value;
 
-	value = lapic->lvt_timer;
+	value = la->lvt_timer_cache;
 	value &= ~APIC_LVTT_TM;
 	value |= APIC_LVT_M;
 	lapic->lvt_timer = value;


More information about the svn-src-user mailing list