svn commit: r248080 - in user/attilio/vmobj-rwlock: . sbin/geom/class/raid sys/arm/arm sys/dev/drm2 sys/dev/drm2/ttm sys/dev/oce sys/geom/label sys/geom/raid sys/kern sys/modules/ath sys/net sys/ne...

Attilio Rao attilio at FreeBSD.org
Sat Mar 9 01:39:48 UTC 2013


Author: attilio
Date: Sat Mar  9 01:39:42 2013
New Revision: 248080
URL: http://svnweb.freebsd.org/changeset/base/248080

Log:
  MFC

Modified:
  user/attilio/vmobj-rwlock/UPDATING
  user/attilio/vmobj-rwlock/sbin/geom/class/raid/graid.8
  user/attilio/vmobj-rwlock/sys/arm/arm/cpufunc_asm_arm11x6.S
  user/attilio/vmobj-rwlock/sys/dev/drm2/drm_fb_helper.c
  user/attilio/vmobj-rwlock/sys/dev/drm2/drm_global.c
  user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_bo.c
  user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_memory.c
  user/attilio/vmobj-rwlock/sys/dev/oce/oce_hw.h
  user/attilio/vmobj-rwlock/sys/dev/oce/oce_sysctl.c
  user/attilio/vmobj-rwlock/sys/geom/label/g_label_ntfs.c
  user/attilio/vmobj-rwlock/sys/geom/raid/g_raid.c
  user/attilio/vmobj-rwlock/sys/kern/kern_timeout.c
  user/attilio/vmobj-rwlock/sys/kern/subr_param.c
  user/attilio/vmobj-rwlock/sys/modules/ath/Makefile
  user/attilio/vmobj-rwlock/sys/net/if.c
  user/attilio/vmobj-rwlock/sys/net/route.c
  user/attilio/vmobj-rwlock/sys/net/route.h
  user/attilio/vmobj-rwlock/sys/net80211/ieee80211.c
  user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.c
  user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.h
  user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hostap.c
  user/attilio/vmobj-rwlock/sys/net80211/ieee80211_ht.c
  user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hwmp.c
  user/attilio/vmobj-rwlock/sys/net80211/ieee80211_mesh.c
  user/attilio/vmobj-rwlock/sys/net80211/ieee80211_output.c
  user/attilio/vmobj-rwlock/sys/net80211/ieee80211_power.c
  user/attilio/vmobj-rwlock/sys/net80211/ieee80211_proto.h
  user/attilio/vmobj-rwlock/sys/net80211/ieee80211_superg.c
  user/attilio/vmobj-rwlock/sys/net80211/ieee80211_var.h
  user/attilio/vmobj-rwlock/sys/net80211/ieee80211_wds.c
  user/attilio/vmobj-rwlock/sys/sparc64/conf/GENERIC
  user/attilio/vmobj-rwlock/sys/sys/callout.h
  user/attilio/vmobj-rwlock/sys/sys/systm.h
  user/attilio/vmobj-rwlock/sys/vm/vm_init.c
  user/attilio/vmobj-rwlock/usr.sbin/pkg/pkg.c
Directory Properties:
  user/attilio/vmobj-rwlock/   (props changed)
  user/attilio/vmobj-rwlock/sbin/   (props changed)
  user/attilio/vmobj-rwlock/sys/   (props changed)

Modified: user/attilio/vmobj-rwlock/UPDATING
==============================================================================
--- user/attilio/vmobj-rwlock/UPDATING	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/UPDATING	Sat Mar  9 01:39:42 2013	(r248080)
@@ -26,6 +26,10 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10
 	disable the most expensive debugging functionality run
 	"ln -s 'abort:false,junk:false' /etc/malloc.conf".)
 
+20130308:
+	CTL_DISABLE has also been added to the sparc64 GENERIC (for further
+	information, see the respective 20130304 entry).
+
 20130304:
 	Recent commits to callout(9) changed the size of struct callout,
 	so the KBI is probably heavily disturbed. Also, some functions

Modified: user/attilio/vmobj-rwlock/sbin/geom/class/raid/graid.8
==============================================================================
--- user/attilio/vmobj-rwlock/sbin/geom/class/raid/graid.8	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sbin/geom/class/raid/graid.8	Sat Mar  9 01:39:42 2013	(r248080)
@@ -305,6 +305,9 @@ Write errors are always considered as di
 Time to wait for missing array components on startup.
 .It Va kern.geom.raid. Ns Ar X Ns Va .enable : No 1
 Enable taste for specific metadata or transformation module.
+.It Va kern.geom.raid.legacy_aliases : No 0
+Enable geom raid emulation of /dev/ar%d devices from ataraid(4)
+This should aid the upgrade of systems from legacy to modern releases.
 .El
 .Sh EXIT STATUS
 Exit status is 0 on success, and non-zero if the command fails.

Modified: user/attilio/vmobj-rwlock/sys/arm/arm/cpufunc_asm_arm11x6.S
==============================================================================
--- user/attilio/vmobj-rwlock/sys/arm/arm/cpufunc_asm_arm11x6.S	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/arm/arm/cpufunc_asm_arm11x6.S	Sat Mar  9 01:39:42 2013	(r248080)
@@ -62,6 +62,8 @@
 #include <machine/asm.h>
 __FBSDID("$FreeBSD$");
 
+	.cpu arm1136js
+
 #if 0
 #define Invalidate_I_cache(Rtmp1, Rtmp2) \
 	mcr	p15, 0, Rtmp1, c7, c5, 0	/* Invalidate Entire I cache */

Modified: user/attilio/vmobj-rwlock/sys/dev/drm2/drm_fb_helper.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/dev/drm2/drm_fb_helper.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/dev/drm2/drm_fb_helper.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -555,8 +555,11 @@ static void drm_fb_helper_crtc_free(stru
 	for (i = 0; i < helper->connector_count; i++)
 		free(helper->connector_info[i], DRM_MEM_KMS);
 	free(helper->connector_info, DRM_MEM_KMS);
-	for (i = 0; i < helper->crtc_count; i++)
+	for (i = 0; i < helper->crtc_count; i++) {
 		free(helper->crtc_info[i].mode_set.connectors, DRM_MEM_KMS);
+		if (helper->crtc_info[i].mode_set.mode)
+			drm_mode_destroy(helper->dev, helper->crtc_info[i].mode_set.mode);
+	}
 	free(helper->crtc_info, DRM_MEM_KMS);
 }
 

Modified: user/attilio/vmobj-rwlock/sys/dev/drm2/drm_global.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/dev/drm2/drm_global.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/dev/drm2/drm_global.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -104,6 +104,7 @@ void drm_global_item_unref(struct drm_gl
 	MPASS(ref->object == item->object);
 	if (--item->refcount == 0) {
 		ref->release(ref);
+		free(item->object, M_DRM_GLOBAL);
 		item->object = NULL;
 	}
 	sx_xunlock(&item->mutex);

Modified: user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_bo.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_bo.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_bo.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -1400,7 +1400,6 @@ static void ttm_bo_global_kobj_release(s
 
 	ttm_mem_unregister_shrink(glob->mem_glob, &glob->shrink);
 	vm_page_free(glob->dummy_read_page);
-	free(glob, M_DRM_GLOBAL);
 }
 
 void ttm_bo_global_release(struct drm_global_reference *ref)

Modified: user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_memory.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_memory.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/dev/drm2/ttm/ttm_memory.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -125,8 +125,6 @@ static ssize_t ttm_mem_zone_store(struct
 
 static void ttm_mem_global_kobj_release(struct ttm_mem_global *glob)
 {
-
-	free(glob, M_TTM_ZONE);
 }
 
 static bool ttm_zones_above_swap_target(struct ttm_mem_global *glob,

Modified: user/attilio/vmobj-rwlock/sys/dev/oce/oce_hw.h
==============================================================================
--- user/attilio/vmobj-rwlock/sys/dev/oce/oce_hw.h	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/dev/oce/oce_hw.h	Sat Mar  9 01:39:42 2013	(r248080)
@@ -38,8 +38,6 @@
 
 /* $FreeBSD$ */
 
-/* $FreeBSD$ */
-
 #include <sys/types.h>
 
 #undef _BIG_ENDIAN /* TODO */

Modified: user/attilio/vmobj-rwlock/sys/dev/oce/oce_sysctl.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/dev/oce/oce_sysctl.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/dev/oce/oce_sysctl.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -38,8 +38,6 @@
 
 /* $FreeBSD$ */
 
-/* $FreeBSD$ */
-
 
 #include "oce_if.h"
 

Modified: user/attilio/vmobj-rwlock/sys/geom/label/g_label_ntfs.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/geom/label/g_label_ntfs.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/geom/label/g_label_ntfs.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -115,7 +115,7 @@ g_label_ntfs_taste(struct g_consumer *cp
 
 	mftrecsz = (char)bf->bf_mftrecsz;
 	recsize = (mftrecsz > 0) ? (mftrecsz * bf->bf_bps * bf->bf_spc) : (1 << -mftrecsz);
-	if (recsize % pp->sectorsize != 0)
+	if (recsize == 0 || recsize % pp->sectorsize != 0)
 		goto done;
 
 	voloff = bf->bf_mftcn * bf->bf_spc * bf->bf_bps +

Modified: user/attilio/vmobj-rwlock/sys/geom/raid/g_raid.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/geom/raid/g_raid.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/geom/raid/g_raid.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -92,6 +92,11 @@ TUNABLE_INT("kern.geom.raid.idle_thresho
 SYSCTL_UINT(_kern_geom_raid, OID_AUTO, idle_threshold, CTLFLAG_RW,
     &g_raid_idle_threshold, 1000000,
     "Time in microseconds to consider a volume idle.");
+static u_int ar_legacy_aliases = 1;
+SYSCTL_INT(_kern_geom_raid, OID_AUTO, legacy_aliases, CTLFLAG_RW,
+           &ar_legacy_aliases, 0, "Create aliases named as the legacy ataraid style.");
+TUNABLE_INT("kern.geom_raid.legacy_aliases", &ar_legacy_aliases);
+
 
 #define	MSLEEP(rv, ident, mtx, priority, wmesg, timeout)	do {	\
 	G_RAID_DEBUG(4, "%s: Sleeping %p.", __func__, (ident));		\
@@ -1637,6 +1642,7 @@ g_raid_launch_provider(struct g_raid_vol
 	struct g_raid_softc *sc;
 	struct g_provider *pp;
 	char name[G_RAID_MAX_VOLUMENAME];
+	char   announce_buf[80], buf1[32];
 	off_t off;
 
 	sc = vol->v_softc;
@@ -1650,6 +1656,22 @@ g_raid_launch_provider(struct g_raid_vol
 		/* Otherwise use sequential volume number. */
 		snprintf(name, sizeof(name), "raid/r%d", vol->v_global_id);
 	}
+
+	/*
+	 * Create a /dev/ar%d that the old ataraid(4) stack once
+	 * created as an alias for /dev/raid/r%d if requested.
+	 * This helps going from stable/7 ataraid devices to newer
+	 * FreeBSD releases. sbruno 07 MAY 2013
+	 */
+
+        if (ar_legacy_aliases) {
+		snprintf(announce_buf, sizeof(announce_buf),
+                        "kern.devalias.%s", name);
+                snprintf(buf1, sizeof(buf1),
+                        "ar%d", vol->v_global_id);
+                setenv(announce_buf, buf1);
+        }
+
 	pp = g_new_providerf(sc->sc_geom, "%s", name);
 	pp->private = vol;
 	pp->mediasize = vol->v_mediasize;

Modified: user/attilio/vmobj-rwlock/sys/kern/kern_timeout.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/kern/kern_timeout.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/kern/kern_timeout.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/bus.h>
 #include <sys/callout.h>
+#include <sys/file.h>
 #include <sys/interrupt.h>
 #include <sys/kernel.h>
 #include <sys/ktr.h>
@@ -101,6 +102,11 @@ SYSCTL_INT(_debug, OID_AUTO, to_avg_mpca
     0, "Average number of MP direct callouts made per callout_process call. "
     "Units = 1/1000");
 #endif
+
+static int ncallout;
+SYSCTL_INT(_kern, OID_AUTO, ncallout, CTLFLAG_RDTUN, &ncallout, 0,
+    "Number of entries in callwheel and size of timeout() preallocation");
+
 /*
  * TODO:
  *	allocate more timeout table slots when table overflows.
@@ -181,6 +187,7 @@ struct callout_cpu cc_cpu;
 
 static int timeout_cpu;
 
+static void	callout_cpu_init(struct callout_cpu *cc);
 static void	softclock_call_cc(struct callout *c, struct callout_cpu *cc,
 #ifdef CALLOUT_PROFILING
 		    int *mpcalls, int *lockcalls, int *gcalls,
@@ -240,18 +247,21 @@ cc_cce_migrating(struct callout_cpu *cc,
 }
 
 /*
- * kern_timeout_callwheel_alloc() - kernel low level callwheel initialization
- *
- *	This code is called very early in the kernel initialization sequence,
- *	and may be called more then once.
+ * Kernel low level callwheel initialization
+ * called on cpu0 during kernel startup.
  */
-caddr_t
-kern_timeout_callwheel_alloc(caddr_t v)
+static void
+callout_callwheel_init(void *dummy)
 {
 	struct callout_cpu *cc;
 
-	timeout_cpu = PCPU_GET(cpuid);
-	cc = CC_CPU(timeout_cpu);
+	/*
+	 * Calculate the size of the callout wheel and the preallocated
+	 * timeout() structures.
+	 */
+	ncallout = imin(16 + maxproc + maxfiles, 18508);
+	TUNABLE_INT_FETCH("kern.ncallout", &ncallout);
+
 	/*
 	 * Calculate callout wheel size, should be next power of two higher
 	 * than 'ncallout'.
@@ -259,13 +269,23 @@ kern_timeout_callwheel_alloc(caddr_t v)
 	callwheelsize = 1 << fls(ncallout);
 	callwheelmask = callwheelsize - 1;
 
-	cc->cc_callout = (struct callout *)v;
-	v = (caddr_t)(cc->cc_callout + ncallout);
-	cc->cc_callwheel = (struct callout_list *)v;
-	v = (caddr_t)(cc->cc_callwheel + callwheelsize);
-	return(v);
+	/*
+	 * Only cpu0 handles timeout(9) and receives a preallocation.
+	 *
+	 * XXX: Once all timeout(9) consumers are converted this can
+	 * be removed.
+	 */
+	timeout_cpu = PCPU_GET(cpuid);
+	cc = CC_CPU(timeout_cpu);
+	cc->cc_callout = malloc(ncallout * sizeof(struct callout),
+	    M_CALLOUT, M_WAITOK);
+	callout_cpu_init(cc);
 }
+SYSINIT(callwheel_init, SI_SUB_CPU, SI_ORDER_ANY, callout_callwheel_init, NULL);
 
+/*
+ * Initialize the per-cpu callout structures.
+ */
 static void
 callout_cpu_init(struct callout_cpu *cc)
 {
@@ -274,13 +294,15 @@ callout_cpu_init(struct callout_cpu *cc)
 
 	mtx_init(&cc->cc_lock, "callout", NULL, MTX_SPIN | MTX_RECURSE);
 	SLIST_INIT(&cc->cc_callfree);
+	cc->cc_callwheel = malloc(sizeof(struct callout_tailq) * callwheelsize,
+	    M_CALLOUT, M_WAITOK);
 	for (i = 0; i < callwheelsize; i++)
 		LIST_INIT(&cc->cc_callwheel[i]);
 	TAILQ_INIT(&cc->cc_expireq);
 	cc->cc_firstevent = INT64_MAX;
 	for (i = 0; i < 2; i++)
 		cc_cce_cleanup(cc, i);
-	if (cc->cc_callout == NULL)
+	if (cc->cc_callout == NULL)	/* Only cpu0 handles timeout(9) */
 		return;
 	for (i = 0; i < ncallout; i++) {
 		c = &cc->cc_callout[i];
@@ -321,19 +343,6 @@ callout_cpu_switch(struct callout *c, st
 #endif
 
 /*
- * kern_timeout_callwheel_init() - initialize previously reserved callwheel
- *				   space.
- *
- *	This code is called just once, after the space reserved for the
- *	callout wheel has been finalized.
- */
-void
-kern_timeout_callwheel_init(void)
-{
-	callout_cpu_init(CC_CPU(timeout_cpu));
-}
-
-/*
  * Start standard softclock thread.
  */
 static void
@@ -353,18 +362,14 @@ start_softclock(void *dummy)
 		if (cpu == timeout_cpu)
 			continue;
 		cc = CC_CPU(cpu);
+		cc->cc_callout = NULL;	/* Only cpu0 handles timeout(9). */
+		callout_cpu_init(cc);
 		if (swi_add(NULL, "clock", softclock, cc, SWI_CLOCK,
 		    INTR_MPSAFE, &cc->cc_cookie))
 			panic("died while creating standard software ithreads");
-		cc->cc_callout = NULL;	/* Only cpu0 handles timeout(). */
-		cc->cc_callwheel = malloc(
-		    sizeof(struct callout_list) * callwheelsize, M_CALLOUT,
-		    M_WAITOK);
-		callout_cpu_init(cc);
 	}
 #endif
 }
-
 SYSINIT(start_softclock, SI_SUB_SOFTINTR, SI_ORDER_FIRST, start_softclock, NULL);
 
 #define	CC_HASH_SHIFT	8

Modified: user/attilio/vmobj-rwlock/sys/kern/subr_param.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/kern/subr_param.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/kern/subr_param.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -91,7 +91,6 @@ int	maxprocperuid;			/* max # of procs p
 int	maxfiles;			/* sys. wide open files limit */
 int	maxfilesperproc;		/* per-proc open files limit */
 int	msgbufsize;			/* size of kernel message buffer */
-int	ncallout;			/* maximum # of timer events */
 int	nbuf;
 int	ngroups_max;			/* max # groups per process */
 int	nswbuf;
@@ -109,8 +108,6 @@ u_long	sgrowsiz;			/* amount to grow sta
 
 SYSCTL_INT(_kern, OID_AUTO, hz, CTLFLAG_RDTUN, &hz, 0,
     "Number of clock ticks per second");
-SYSCTL_INT(_kern, OID_AUTO, ncallout, CTLFLAG_RDTUN, &ncallout, 0,
-    "Number of pre-allocated timer events");
 SYSCTL_INT(_kern, OID_AUTO, nbuf, CTLFLAG_RDTUN, &nbuf, 0,
     "Number of buffers in the buffer cache");
 SYSCTL_INT(_kern, OID_AUTO, nswbuf, CTLFLAG_RDTUN, &nswbuf, 0,
@@ -327,15 +324,6 @@ init_param2(long physpages)
 	TUNABLE_INT_FETCH("kern.nbuf", &nbuf);
 
 	/*
-	 * XXX: Does the callout wheel have to be so big?
-	 *
-	 * Clip callout to result of previous function of maxusers maximum
-	 * 384.  This is still huge, but acceptable.
-	 */
-	ncallout = imin(16 + maxproc + maxfiles, 18508);
-	TUNABLE_INT_FETCH("kern.ncallout", &ncallout);
-
-	/*
 	 * The default for maxpipekva is min(1/64 of the kernel address space,
 	 * max(1/64 of main memory, 512KB)).  See sys_pipe.c for more details.
 	 */

Modified: user/attilio/vmobj-rwlock/sys/modules/ath/Makefile
==============================================================================
--- user/attilio/vmobj-rwlock/sys/modules/ath/Makefile	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/modules/ath/Makefile	Sat Mar  9 01:39:42 2013	(r248080)
@@ -123,6 +123,15 @@ SRCS+=  ah_eeprom_9287.c
 .PATH:  ${.CURDIR}/../../dev/ath/ath_hal/ar9002
 SRCS+=  ar9287.c ar9287_reset.c ar9287_attach.c ar9287_cal.c ar9287_olc.c
 
+# + AR9300 HAL
+# .PATH:  ${.CURDIR}/../../dev/ath/ath_hal/ar9003
+#SRCS+= ar9300_interrupts.c ar9300_radar.c ar9300_ani.c ar9300_keycache.c
+#SRCS+= ar9300_radio.c ar9300_xmit.c ar9300_attach.c ar9300_mci.c ar9300_stub.c
+#SRCS+= ar9300_xmit_ds.c ar9300_beacon.c ar9300_misc.c ar9300_recv.c
+#SRCS+= ar9300_stub_funcs.c ar9300_eeprom.c ar9300_paprd.c ar9300_recv_ds.c
+#SRCS+= ar9300_freebsd.c ar9300_phy.c ar9300_reset.c ar9300_gpio.c
+#SRCS+= ar9300_power.c ar9300_timer.c
+
 # NB: rate control is bound to the driver by symbol names so only pick one
 .if ${ATH_RATE} == "sample"
 .PATH:	${.CURDIR}/../../dev/ath/ath_rate/sample

Modified: user/attilio/vmobj-rwlock/sys/net/if.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/net/if.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/net/if.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -1357,7 +1357,8 @@ if_rtdel(struct radix_node *rn, void *ar
 			return (0);
 
 		err = rtrequest_fib(RTM_DELETE, rt_key(rt), rt->rt_gateway,
-				rt_mask(rt), rt->rt_flags|RTF_RNH_LOCKED,
+				rt_mask(rt),
+				rt->rt_flags|RTF_RNH_LOCKED|RTF_PINNED,
 				(struct rtentry **) NULL, rt->rt_fibnum);
 		if (err) {
 			log(LOG_WARNING, "if_rtdel: error %d\n", err);

Modified: user/attilio/vmobj-rwlock/sys/net/route.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/net/route.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/net/route.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -1112,6 +1112,14 @@ rtrequest1_fib(int req, struct rt_addrin
 			error = 0;
 		}
 #endif
+		if ((flags & RTF_PINNED) == 0) {
+			/* Check if target route can be deleted */
+			rt = (struct rtentry *)rnh->rnh_lookup(dst,
+			    netmask, rnh);
+			if ((rt != NULL) && (rt->rt_flags & RTF_PINNED))
+				senderr(EADDRINUSE);
+		}
+
 		/*
 		 * Remove the item from the tree and return it.
 		 * Complain if it is not there and do no more processing.
@@ -1430,6 +1438,7 @@ rtinit1(struct ifaddr *ifa, int cmd, int
 	int didwork = 0;
 	int a_failure = 0;
 	static struct sockaddr_dl null_sdl = {sizeof(null_sdl), AF_LINK};
+	struct radix_node_head *rnh;
 
 	if (flags & RTF_HOST) {
 		dst = ifa->ifa_dstaddr;
@@ -1488,7 +1497,6 @@ rtinit1(struct ifaddr *ifa, int cmd, int
 	 */
 	for ( fibnum = startfib; fibnum <= endfib; fibnum++) {
 		if (cmd == RTM_DELETE) {
-			struct radix_node_head *rnh;
 			struct radix_node *rn;
 			/*
 			 * Look up an rtentry that is in the routing tree and
@@ -1538,7 +1546,8 @@ rtinit1(struct ifaddr *ifa, int cmd, int
 		 */
 		bzero((caddr_t)&info, sizeof(info));
 		info.rti_ifa = ifa;
-		info.rti_flags = flags | (ifa->ifa_flags & ~IFA_RTSELF);
+		info.rti_flags = flags |
+		    (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED;
 		info.rti_info[RTAX_DST] = dst;
 		/* 
 		 * doing this for compatibility reasons
@@ -1550,6 +1559,33 @@ rtinit1(struct ifaddr *ifa, int cmd, int
 			info.rti_info[RTAX_GATEWAY] = ifa->ifa_addr;
 		info.rti_info[RTAX_NETMASK] = netmask;
 		error = rtrequest1_fib(cmd, &info, &rt, fibnum);
+
+		if ((error == EEXIST) && (cmd == RTM_ADD)) {
+			/*
+			 * Interface route addition failed.
+			 * Atomically delete current prefix generating
+			 * RTM_DELETE message, and retry adding
+			 * interface prefix.
+			 */
+			rnh = rt_tables_get_rnh(fibnum, dst->sa_family);
+			RADIX_NODE_HEAD_LOCK(rnh);
+
+			/* Delete old prefix */
+			info.rti_ifa = NULL;
+			info.rti_flags = RTF_RNH_LOCKED;
+
+			error = rtrequest1_fib(RTM_DELETE, &info, &rt, fibnum);
+			if (error == 0) {
+				info.rti_ifa = ifa;
+				info.rti_flags = flags | RTF_RNH_LOCKED |
+				    (ifa->ifa_flags & ~IFA_RTSELF) | RTF_PINNED;
+				error = rtrequest1_fib(cmd, &info, &rt, fibnum);
+			}
+
+			RADIX_NODE_HEAD_UNLOCK(rnh);
+		}
+
+
 		if (error == 0 && rt != NULL) {
 			/*
 			 * notify any listening routing agents of the change

Modified: user/attilio/vmobj-rwlock/sys/net/route.h
==============================================================================
--- user/attilio/vmobj-rwlock/sys/net/route.h	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/net/route.h	Sat Mar  9 01:39:42 2013	(r248080)
@@ -176,7 +176,7 @@ struct ortentry {
 /*			0x20000		   unused, was RTF_WASCLONED */
 #define RTF_PROTO3	0x40000		/* protocol specific routing flag */
 /*			0x80000		   unused */
-#define RTF_PINNED	0x100000	/* future use */
+#define RTF_PINNED	0x100000	/* route is immutable */
 #define	RTF_LOCAL	0x200000 	/* route represents a local address */
 #define	RTF_BROADCAST	0x400000	/* route represents a bcast address */
 #define	RTF_MULTICAST	0x800000	/* route represents a mcast address */

Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/net80211/ieee80211.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -278,6 +278,7 @@ ieee80211_ifattach(struct ieee80211com *
 	KASSERT(ifp->if_type == IFT_IEEE80211, ("if_type %d", ifp->if_type));
 
 	IEEE80211_LOCK_INIT(ic, ifp->if_xname);
+	IEEE80211_TX_LOCK_INIT(ic, ifp->if_xname);
 	TAILQ_INIT(&ic->ic_vaps);
 
 	/* Create a taskqueue for all state changes */
@@ -385,6 +386,7 @@ ieee80211_ifdetach(struct ieee80211com *
 	ifmedia_removeall(&ic->ic_media);
 
 	taskqueue_free(ic->ic_tq);
+	IEEE80211_TX_LOCK_DESTROY(ic);
 	IEEE80211_LOCK_DESTROY(ic);
 }
 

Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -504,6 +504,44 @@ ieee80211_process_callback(struct ieee80
 	}
 }
 
+/*
+ * Transmit a frame to the parent interface.
+ *
+ * TODO: if the transmission fails, make sure the parent node is freed
+ *   (the callers will first need modifying.)
+ */
+int
+ieee80211_parent_transmit(struct ieee80211com *ic,
+	struct mbuf *m)
+{
+	struct ifnet *parent = ic->ic_ifp;
+	/*
+	 * Assert the IC TX lock is held - this enforces the
+	 * processing -> queuing order is maintained
+	 */
+	IEEE80211_TX_LOCK_ASSERT(ic);
+
+	return (parent->if_transmit(parent, m));
+}
+
+/*
+ * Transmit a frame to the VAP interface.
+ */
+int
+ieee80211_vap_transmit(struct ieee80211vap *vap, struct mbuf *m)
+{
+	struct ifnet *ifp = vap->iv_ifp;
+
+	/*
+	 * When transmitting via the VAP, we shouldn't hold
+	 * any IC TX lock as the VAP TX path will acquire it.
+	 */
+	IEEE80211_TX_UNLOCK_ASSERT(vap->iv_ic);
+
+	return (ifp->if_transmit(ifp, m));
+
+}
+
 #include <sys/libkern.h>
 
 void

Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.h
==============================================================================
--- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.h	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_freebsd.h	Sat Mar  9 01:39:42 2013	(r248080)
@@ -57,6 +57,30 @@ typedef struct {
 	mtx_assert(IEEE80211_LOCK_OBJ(_ic), MA_NOTOWNED)
 
 /*
+ * Transmit lock.
+ *
+ * This is a (mostly) temporary lock designed to serialise all of the
+ * transmission operations throughout the stack.
+ */
+typedef struct {
+	char		name[16];		/* e.g. "ath0_com_lock" */
+	struct mtx	mtx;
+} ieee80211_tx_lock_t;
+#define	IEEE80211_TX_LOCK_INIT(_ic, _name) do {				\
+	ieee80211_tx_lock_t *cl = &(_ic)->ic_txlock;			\
+	snprintf(cl->name, sizeof(cl->name), "%s_tx_lock", _name);	\
+	mtx_init(&cl->mtx, cl->name, NULL, MTX_DEF);	\
+} while (0)
+#define	IEEE80211_TX_LOCK_OBJ(_ic)	(&(_ic)->ic_txlock.mtx)
+#define	IEEE80211_TX_LOCK_DESTROY(_ic) mtx_destroy(IEEE80211_TX_LOCK_OBJ(_ic))
+#define	IEEE80211_TX_LOCK(_ic)	   mtx_lock(IEEE80211_TX_LOCK_OBJ(_ic))
+#define	IEEE80211_TX_UNLOCK(_ic)	   mtx_unlock(IEEE80211_TX_LOCK_OBJ(_ic))
+#define	IEEE80211_TX_LOCK_ASSERT(_ic) \
+	mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_OWNED)
+#define	IEEE80211_TX_UNLOCK_ASSERT(_ic) \
+	mtx_assert(IEEE80211_TX_LOCK_OBJ(_ic), MA_NOTOWNED)
+
+/*
  * Node locking definitions.
  */
 typedef struct {
@@ -272,9 +296,11 @@ int	ieee80211_add_callback(struct mbuf *
 		void (*func)(struct ieee80211_node *, void *, int), void *arg);
 void	ieee80211_process_callback(struct ieee80211_node *, struct mbuf *, int);
 
-void	get_random_bytes(void *, size_t);
-
 struct ieee80211com;
+int	ieee80211_parent_transmit(struct ieee80211com *, struct mbuf *);
+int	ieee80211_vap_transmit(struct ieee80211vap *, struct mbuf *);
+
+void	get_random_bytes(void *, size_t);
 
 void	ieee80211_sysctl_attach(struct ieee80211com *);
 void	ieee80211_sysctl_detach(struct ieee80211com *);

Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hostap.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hostap.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hostap.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -412,7 +412,7 @@ hostap_deliver_data(struct ieee80211vap 
 		if (mcopy != NULL) {
 			int len, err;
 			len = mcopy->m_pkthdr.len;
-			err = ifp->if_transmit(ifp, mcopy);
+			err = ieee80211_vap_transmit(vap, mcopy);
 			if (err) {
 				/* NB: IFQ_HANDOFF reclaims mcopy */
 			} else {
@@ -2255,8 +2255,8 @@ void
 ieee80211_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m0)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
+	struct ieee80211com *ic = vap->iv_ic;
 	struct ieee80211_frame_min *wh;
-	struct ifnet *ifp;
 	struct mbuf *m;
 	uint16_t aid;
 	int qlen;
@@ -2320,23 +2320,15 @@ ieee80211_recv_pspoll(struct ieee80211_n
 	}
 	m->m_flags |= M_PWR_SAV;		/* bypass PS handling */
 
-	if (m->m_flags & M_ENCAP)
-		ifp = vap->iv_ic->ic_ifp;
-	else
-		ifp = vap->iv_ifp;
-
 	/*
-	 * Free any node ref which this mbuf may have.
-	 *
-	 * Much like psq_mfree(), we assume that M_ENCAP nodes have
-	 * node references.
+	 * Do the right thing; if it's an encap'ed frame then
+	 * call ieee80211_parent_transmit() (and free the ref) else
+	 * call ieee80211_vap_transmit().
 	 */
-	if (ifp->if_transmit(ifp, m) != 0) {
-		/*
-		 * XXX m is invalid (freed) at this point, determine M_ENCAP
-		 * an alternate way.
-		 */
-		if (ifp == vap->iv_ic->ic_ifp)
+	if (m->m_flags & M_ENCAP) {
+		if (ieee80211_parent_transmit(ic, m) != 0)
 			ieee80211_free_node(ni);
+	} else {
+		(void) ieee80211_vap_transmit(vap, m);
 	}
 }

Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_ht.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_ht.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_ht.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -2392,7 +2392,9 @@ ieee80211_send_bar(struct ieee80211_node
 	 * ic_raw_xmit will free the node reference
 	 * regardless of queue/TX success or failure.
 	 */
-	ret = ic->ic_raw_xmit(ni, m, NULL);
+	IEEE80211_TX_LOCK(ic);
+	ret = ieee80211_raw_output(vap, ni, m, NULL);
+	IEEE80211_TX_UNLOCK(ic);
 	if (ret != 0) {
 		IEEE80211_NOTE(vap, IEEE80211_MSG_DEBUG | IEEE80211_MSG_11N,
 		    ni, "send BAR: failed: (ret = %d)\n",

Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hwmp.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hwmp.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_hwmp.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -592,6 +592,7 @@ hwmp_send_action(struct ieee80211vap *va
 	struct ieee80211_bpf_params params;
 	struct mbuf *m;
 	uint8_t *frm;
+	int ret;
 
 	if (IEEE80211_IS_MULTICAST(da)) {
 		ni = ieee80211_ref_node(vap->iv_bss);
@@ -654,6 +655,9 @@ hwmp_send_action(struct ieee80211vap *va
 		vap->iv_stats.is_tx_nobuf++;
 		return ENOMEM;
 	}
+
+	IEEE80211_TX_LOCK(ic);
+
 	ieee80211_send_setup(ni, m,
 	    IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION,
 	    IEEE80211_NONQOS_TID, vap->iv_myaddr, da, vap->iv_myaddr);
@@ -669,7 +673,9 @@ hwmp_send_action(struct ieee80211vap *va
 	else
 		params.ibp_try0 = ni->ni_txparms->maxretry;
 	params.ibp_power = ni->ni_txpower;
-	return ic->ic_raw_xmit(ni, m, &params);
+	ret = ieee80211_raw_output(vap, ni, m, &params);
+	IEEE80211_TX_UNLOCK(ic);
+	return (ret);
 }
 
 #define ADDSHORT(frm, v) do {		\
@@ -1271,12 +1277,9 @@ hwmp_recv_prep(struct ieee80211vap *vap,
 	struct ieee80211_mesh_route *rtext = NULL;
 	struct ieee80211_hwmp_route *hr;
 	struct ieee80211com *ic = vap->iv_ic;
-	struct ifnet *ifp = vap->iv_ifp;
 	struct mbuf *m, *next;
 	uint32_t metric = 0;
 	const uint8_t *addr;
-	int is_encap;
-	struct ieee80211_node *ni_encap;
 
 	IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
 	    "received PREP, orig %6D, targ %6D", prep->prep_origaddr, ":",
@@ -1450,22 +1453,21 @@ hwmp_recv_prep(struct ieee80211vap *vap,
 	m = ieee80211_ageq_remove(&ic->ic_stageq,
 	    (struct ieee80211_node *)(uintptr_t)
 	    ieee80211_mac_hash(ic, addr)); /* either dest or ext_dest */
+
+	/*
+	 * All frames in the stageq here should be non-M_ENCAP; or things
+	 * will get very unhappy.
+	 */
 	for (; m != NULL; m = next) {
-		is_encap = !! (m->m_flags & M_ENCAP);
-		ni_encap = (struct ieee80211_node *) m->m_pkthdr.rcvif;
 		next = m->m_nextpkt;
 		m->m_nextpkt = NULL;
 		IEEE80211_NOTE(vap, IEEE80211_MSG_HWMP, ni,
 		    "flush queued frame %p len %d", m, m->m_pkthdr.len);
-
 		/*
 		 * If the mbuf has M_ENCAP set, ensure we free it.
 		 * Note that after if_transmit() is called, m is invalid.
 		 */
-		if (ifp->if_transmit(ifp, m) != 0) {
-			if (is_encap)
-				ieee80211_free_node(ni_encap);
-		}
+		(void) ieee80211_vap_transmit(vap, m);
 	}
 #undef	IS_PROXY
 #undef	PROXIED_BY_US

Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_mesh.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_mesh.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_mesh.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -1041,11 +1041,12 @@ mesh_transmit_to_gate(struct ieee80211va
 {
 	struct ifnet *ifp = vap->iv_ifp;
 	struct ieee80211com *ic = vap->iv_ic;
-	struct ifnet *parent = ic->ic_ifp;
 	struct ieee80211_node *ni;
 	struct ether_header *eh;
 	int error;
 
+	IEEE80211_TX_UNLOCK_ASSERT(ic);
+
 	eh = mtod(m, struct ether_header *);
 	ni = ieee80211_mesh_find_txnode(vap, rt_gate->rt_dest);
 	if (ni == NULL) {
@@ -1132,6 +1133,8 @@ mesh_transmit_to_gate(struct ieee80211va
 		}
 	}
 #endif /* IEEE80211_SUPPORT_SUPERG */
+
+	IEEE80211_TX_LOCK(ic);
 	if (__predict_true((vap->iv_caps & IEEE80211_C_8023ENCAP) == 0)) {
 		/*
 		 * Encapsulate the packet in prep for transmission.
@@ -1143,9 +1146,9 @@ mesh_transmit_to_gate(struct ieee80211va
 			return;
 		}
 	}
-	error = parent->if_transmit(parent, m);
+	error = ieee80211_parent_transmit(ic, m);
+	IEEE80211_TX_UNLOCK(ic);
 	if (error != 0) {
-		m_freem(m);
 		ieee80211_free_node(ni);
 	} else {
 		ifp->if_opackets++;
@@ -1171,6 +1174,8 @@ ieee80211_mesh_forward_to_gates(struct i
 	struct ieee80211_mesh_gate_route *gr = NULL, *gr_next;
 	struct mbuf *m, *mcopy, *next;
 
+	IEEE80211_TX_UNLOCK_ASSERT(ic);
+
 	KASSERT( rt_dest->rt_flags == IEEE80211_MESHRT_FLAGS_DISCOVER,
 	    ("Route is not marked with IEEE80211_MESHRT_FLAGS_DISCOVER"));
 
@@ -1240,7 +1245,6 @@ mesh_forward(struct ieee80211vap *vap, s
 	struct ieee80211com *ic = vap->iv_ic;
 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 	struct ifnet *ifp = vap->iv_ifp;
-	struct ifnet *parent = ic->ic_ifp;
 	const struct ieee80211_frame *wh =
 	    mtod(m, const struct ieee80211_frame *);
 	struct mbuf *mcopy;
@@ -1249,6 +1253,9 @@ mesh_forward(struct ieee80211vap *vap, s
 	struct ieee80211_node *ni;
 	int err;
 
+	/* This is called from the RX path - don't hold this lock */
+	IEEE80211_TX_UNLOCK_ASSERT(ic);
+
 	/*
 	 * mesh ttl of 1 means we are the last one receving it,
 	 * according to amendment we decrement and then check if
@@ -1320,7 +1327,20 @@ mesh_forward(struct ieee80211vap *vap, s
 
 	/* XXX do we know m_nextpkt is NULL? */
 	mcopy->m_pkthdr.rcvif = (void *) ni;
-	err = parent->if_transmit(parent, mcopy);
+
+	/*
+	 * XXX this bypasses all of the VAP TX handling; it passes frames
+	 * directly to the parent interface.
+	 *
+	 * Because of this, there's no TX lock being held as there's no
+	 * encaps state being used.
+	 *
+	 * Doing a direct parent transmit may not be the correct thing
+	 * to do here; we'll have to re-think this soon.
+	 */
+	IEEE80211_TX_LOCK(ic);
+	err = ieee80211_parent_transmit(ic, mcopy);
+	IEEE80211_TX_UNLOCK(ic);
 	if (err != 0) {
 		/* NB: IFQ_HANDOFF reclaims mbuf */
 		ieee80211_free_node(ni);
@@ -1457,6 +1477,10 @@ mesh_recv_indiv_data_to_fwrd(struct ieee
 	struct ieee80211_qosframe_addr4 *qwh;
 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 	struct ieee80211_mesh_route *rt_meshda, *rt_meshsa;
+	struct ieee80211com *ic = vap->iv_ic;
+
+	/* This is called from the RX path - don't hold this lock */
+	IEEE80211_TX_UNLOCK_ASSERT(ic);
 
 	qwh = (struct ieee80211_qosframe_addr4 *)wh;
 
@@ -1512,8 +1536,12 @@ mesh_recv_indiv_data_to_me(struct ieee80
 	const struct ieee80211_meshcntl_ae10 *mc10;
 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
 	struct ieee80211_mesh_route *rt;
+	struct ieee80211com *ic = vap->iv_ic;
 	int ae;
 
+	/* This is called from the RX path - don't hold this lock */
+	IEEE80211_TX_UNLOCK_ASSERT(ic);
+
 	qwh = (struct ieee80211_qosframe_addr4 *)wh;
 	mc10 = (const struct ieee80211_meshcntl_ae10 *)mc;
 
@@ -1575,6 +1603,10 @@ mesh_recv_group_data(struct ieee80211vap
 {
 #define	MC01(mc)	((const struct ieee80211_meshcntl_ae01 *)mc)
 	struct ieee80211_mesh_state *ms = vap->iv_mesh;
+	struct ieee80211com *ic = vap->iv_ic;
+
+	/* This is called from the RX path - don't hold this lock */
+	IEEE80211_TX_UNLOCK_ASSERT(ic);
 
 	mesh_forward(vap, m, mc);
 
@@ -1621,6 +1653,9 @@ mesh_input(struct ieee80211_node *ni, st
 	need_tap = 1;			/* mbuf need to be tapped. */
 	type = -1;			/* undefined */
 
+	/* This is called from the RX path - don't hold this lock */
+	IEEE80211_TX_UNLOCK_ASSERT(ic);
+
 	if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) {
 		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY,
 		    ni->ni_macaddr, NULL,
@@ -2743,6 +2778,7 @@ mesh_send_action(struct ieee80211_node *
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ieee80211_bpf_params params;
 	struct ieee80211_frame *wh;
+	int ret;
 
 	KASSERT(ni != NULL, ("null node"));
 
@@ -2761,6 +2797,7 @@ mesh_send_action(struct ieee80211_node *
 		return ENOMEM;
 	}
 
+	IEEE80211_TX_LOCK(ic);
 	wh = mtod(m, struct ieee80211_frame *);
 	ieee80211_send_setup(ni, m,
 	     IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ACTION,
@@ -2778,7 +2815,9 @@ mesh_send_action(struct ieee80211_node *
 
 	IEEE80211_NODE_STAT(ni, tx_mgmt);
 
-	return ic->ic_raw_xmit(ni, m, &params);
+	ret = ieee80211_raw_output(vap, ni, m, &params);
+	IEEE80211_TX_UNLOCK(ic);
+	return (ret);
 }
 
 #define	ADDSHORT(frm, v) do {			\

Modified: user/attilio/vmobj-rwlock/sys/net80211/ieee80211_output.c
==============================================================================
--- user/attilio/vmobj-rwlock/sys/net80211/ieee80211_output.c	Sat Mar  9 01:05:36 2013	(r248079)
+++ user/attilio/vmobj-rwlock/sys/net80211/ieee80211_output.c	Sat Mar  9 01:39:42 2013	(r248080)
@@ -110,6 +110,255 @@ doprint(struct ieee80211vap *vap, int su
 #endif
 
 /*
+ * Send the given mbuf through the given vap.
+ *
+ * This consumes the mbuf regardless of whether the transmit
+ * was successful or not.
+ *
+ * This does none of the initial checks that ieee80211_start()
+ * does (eg CAC timeout, interface wakeup) - the caller must
+ * do this first.
+ */
+static int
+ieee80211_start_pkt(struct ieee80211vap *vap, struct mbuf *m)
+{
+#define	IS_DWDS(vap) \
+	(vap->iv_opmode == IEEE80211_M_WDS && \
+	 (vap->iv_flags_ext & IEEE80211_FEXT_WDSLEGACY) == 0)
+	struct ieee80211com *ic = vap->iv_ic;
+	struct ifnet *ifp = vap->iv_ifp;
+	struct ieee80211_node *ni;
+	struct ether_header *eh;
+	int error;
+
+	/*
+	 * Cancel any background scan.
+	 */
+	if (ic->ic_flags & IEEE80211_F_SCAN)
+		ieee80211_cancel_anyscan(vap);
+	/* 
+	 * Find the node for the destination so we can do
+	 * things like power save and fast frames aggregation.
+	 *
+	 * NB: past this point various code assumes the first
+	 *     mbuf has the 802.3 header present (and contiguous).
+	 */
+	ni = NULL;
+	if (m->m_len < sizeof(struct ether_header) &&
+	   (m = m_pullup(m, sizeof(struct ether_header))) == NULL) {
+		IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+		    "discard frame, %s\n", "m_pullup failed");
+		vap->iv_stats.is_tx_nobuf++;	/* XXX */
+		ifp->if_oerrors++;
+		return (ENOBUFS);
+	}
+	eh = mtod(m, struct ether_header *);
+	if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
+		if (IS_DWDS(vap)) {
+			/*
+			 * Only unicast frames from the above go out
+			 * DWDS vaps; multicast frames are handled by
+			 * dispatching the frame as it comes through
+			 * the AP vap (see below).
+			 */
+			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_WDS,
+			    eh->ether_dhost, "mcast", "%s", "on DWDS");
+			vap->iv_stats.is_dwds_mcast++;
+			m_freem(m);
+			/* XXX better status? */
+			return (ENOBUFS);
+		}
+		if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
+			/*
+			 * Spam DWDS vap's w/ multicast traffic.
+			 */
+			/* XXX only if dwds in use? */
+			ieee80211_dwds_mcast(vap, m);
+		}
+	}
+#ifdef IEEE80211_SUPPORT_MESH
+	if (vap->iv_opmode != IEEE80211_M_MBSS) {
+#endif
+		ni = ieee80211_find_txnode(vap, eh->ether_dhost);
+		if (ni == NULL) {
+			/* NB: ieee80211_find_txnode does stat+msg */
+			ifp->if_oerrors++;
+			m_freem(m);
+			/* XXX better status? */
+			return (ENOBUFS);
+		}
+		if (ni->ni_associd == 0 &&
+		    (ni->ni_flags & IEEE80211_NODE_ASSOCID)) {
+			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_OUTPUT,
+			    eh->ether_dhost, NULL,
+			    "sta not associated (type 0x%04x)",
+			    htons(eh->ether_type));
+			vap->iv_stats.is_tx_notassoc++;
+			ifp->if_oerrors++;
+			m_freem(m);
+			ieee80211_free_node(ni);
+			/* XXX better status? */
+			return (ENOBUFS);
+		}
+#ifdef IEEE80211_SUPPORT_MESH
+	} else {
+		if (!IEEE80211_ADDR_EQ(eh->ether_shost, vap->iv_myaddr)) {
+			/*
+			 * Proxy station only if configured.
+			 */
+			if (!ieee80211_mesh_isproxyena(vap)) {
+				IEEE80211_DISCARD_MAC(vap,
+				    IEEE80211_MSG_OUTPUT |
+				    IEEE80211_MSG_MESH,
+				    eh->ether_dhost, NULL,
+				    "%s", "proxy not enabled");
+				vap->iv_stats.is_mesh_notproxy++;
+				ifp->if_oerrors++;
+				m_freem(m);
+				/* XXX better status? */
+				return (ENOBUFS);
+			}
+			IEEE80211_DPRINTF(vap, IEEE80211_MSG_OUTPUT,
+			    "forward frame from DS SA(%6D), DA(%6D)\n",
+			    eh->ether_shost, ":",
+			    eh->ether_dhost, ":");
+			ieee80211_mesh_proxy_check(vap, eh->ether_shost);
+		}
+		ni = ieee80211_mesh_discover(vap, eh->ether_dhost, m);
+		if (ni == NULL) {
+			/*
+			 * NB: ieee80211_mesh_discover holds/disposes
+			 * frame (e.g. queueing on path discovery).
+			 */
+			ifp->if_oerrors++;
+			/* XXX better status? */
+			return (ENOBUFS);
+		}
+	}
+#endif

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-user mailing list