summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorngie <ngie@FreeBSD.org>2015-10-05 00:11:49 +0000
committerngie <ngie@FreeBSD.org>2015-10-05 00:11:49 +0000
commite3bac3a30a41f56ac36f4791a7df260f2155c8db (patch)
treeac20948d4aa368300bc16ece67336a1bed25e992 /sys
parentca6cf0ba737487849f2ee102afce74545600850c (diff)
parent85fa330dc74592563cea8d7cf0e628fd30683993 (diff)
downloadFreeBSD-src-e3bac3a30a41f56ac36f4791a7df260f2155c8db.zip
FreeBSD-src-e3bac3a30a41f56ac36f4791a7df260f2155c8db.tar.gz
MFhead @ r281414
Diffstat (limited to 'sys')
-rw-r--r--sys/arm/arm/bcopy_page.S4
-rw-r--r--sys/arm/arm/bcopyinout.S3
-rw-r--r--sys/arm/arm/machdep.c2
-rw-r--r--sys/arm/arm/vm_machdep.c2
-rw-r--r--sys/arm/include/asm.h2
-rw-r--r--sys/arm/include/atomic-v4.h33
-rw-r--r--sys/arm/include/atomic-v6.h28
-rw-r--r--sys/arm/include/atomic.h28
-rw-r--r--sys/arm64/arm64/trap.c7
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c2
-rw-r--r--sys/dev/ath/if_ath_beacon.c6
-rw-r--r--sys/dev/ath/if_ath_keycache.c3
-rw-r--r--sys/dev/ath/if_ath_keycache.h3
-rw-r--r--sys/dev/drm2/drmP.h6
-rw-r--r--sys/dev/drm2/drm_crtc.c20
-rw-r--r--sys/dev/drm2/drm_fops.c2
-rw-r--r--sys/dev/drm2/drm_pci.c2
-rw-r--r--sys/dev/drm2/drm_stub.c6
-rw-r--r--sys/dev/drm2/i915/i915_dma.c2
-rw-r--r--sys/dev/drm2/i915/i915_drv.c1
-rw-r--r--sys/dev/drm2/i915/intel_opregion.c4
-rw-r--r--sys/dev/if_ndis/if_ndis.c5
-rw-r--r--sys/dev/mwl/if_mwl.c21
-rw-r--r--sys/dev/ral/rt2560.c5
-rw-r--r--sys/dev/ral/rt2661.c4
-rw-r--r--sys/dev/ral/rt2860.c3
-rw-r--r--sys/dev/usb/wlan/if_rum.c1223
-rw-r--r--sys/dev/usb/wlan/if_rumreg.h81
-rw-r--r--sys/dev/usb/wlan/if_rumvar.h64
-rw-r--r--sys/dev/usb/wlan/if_run.c117
-rw-r--r--sys/dev/usb/wlan/if_runreg.h1
-rw-r--r--sys/dev/usb/wlan/if_runvar.h4
-rw-r--r--sys/dev/usb/wlan/if_upgt.c5
-rw-r--r--sys/dev/usb/wlan/if_ural.c27
-rw-r--r--sys/dev/usb/wlan/if_urtwn.c6
-rw-r--r--sys/dev/usb/wlan/if_zyd.c22
-rw-r--r--sys/dev/wpi/if_wpi.c13
-rw-r--r--sys/dev/wtap/if_wtap.c4
-rw-r--r--sys/kern/subr_sbuf.c4
-rw-r--r--sys/kern/vfs_bio.c6
-rw-r--r--sys/mips/conf/WZR-300HP12
-rw-r--r--sys/mips/conf/WZR-300HP.hints12
-rw-r--r--sys/net/if_gif.c10
-rw-r--r--sys/net/if_gre.c9
-rw-r--r--sys/net/if_lagg.c9
-rw-r--r--sys/net/if_lagg.h2
-rw-r--r--sys/net/if_me.c7
-rw-r--r--sys/net80211/ieee80211_crypto.c50
-rw-r--r--sys/net80211/ieee80211_crypto.h8
-rw-r--r--sys/net80211/ieee80211_crypto_ccmp.c36
-rw-r--r--sys/net80211/ieee80211_crypto_none.c16
-rw-r--r--sys/net80211/ieee80211_crypto_tkip.c52
-rw-r--r--sys/net80211/ieee80211_crypto_wep.c56
-rw-r--r--sys/net80211/ieee80211_ioctl.c52
-rw-r--r--sys/net80211/ieee80211_output.c14
-rw-r--r--sys/net80211/ieee80211_proto.h5
-rw-r--r--sys/net80211/ieee80211_var.h3
-rw-r--r--sys/netinet6/nd6.c87
-rw-r--r--sys/netinet6/nd6.h2
-rw-r--r--sys/netinet6/nd6_nbr.c40
-rw-r--r--sys/netpfil/ipfw/ip_fw_sockopt.c2
-rw-r--r--sys/vm/vm_page.c2
-rw-r--r--sys/vm/vm_pageout.c1
-rw-r--r--sys/vm/vm_pageout.h1
64 files changed, 1626 insertions, 643 deletions
diff --git a/sys/arm/arm/bcopy_page.S b/sys/arm/arm/bcopy_page.S
index 92e38cc..0d787b2 100644
--- a/sys/arm/arm/bcopy_page.S
+++ b/sys/arm/arm/bcopy_page.S
@@ -75,7 +75,7 @@ __FBSDID("$FreeBSD$");
#endif /* ! COPY_CHUNK */
#ifndef SAVE_REGS
-#define SAVE_REGS stmfd sp!, {r4-r8, lr}
+#define SAVE_REGS stmfd sp!, {r4-r8, lr}; _SAVE({r4-r8, lr})
#define RESTORE_REGS ldmfd sp!, {r4-r8, pc}
#endif
@@ -134,6 +134,7 @@ END(bcopy_page)
ENTRY(bzero_page)
stmfd sp!, {r4-r8, lr}
+ _SAVE({r4-r8, lr})
#ifdef BIG_LOOPS
mov r2, #(PAGE_SIZE >> 9)
#else
@@ -189,6 +190,7 @@ END(bzero_page)
ENTRY(bcopy_page)
pld [r0]
stmfd sp!, {r4, r5}
+ _SAVE({r4, r5})
mov ip, #32
ldr r2, [r0], #0x04 /* 0x00 */
ldr r3, [r0], #0x04 /* 0x04 */
diff --git a/sys/arm/arm/bcopyinout.S b/sys/arm/arm/bcopyinout.S
index c030e24..df0484e 100644
--- a/sys/arm/arm/bcopyinout.S
+++ b/sys/arm/arm/bcopyinout.S
@@ -68,7 +68,7 @@ __FBSDID("$FreeBSD$");
#endif
-#define SAVE_REGS stmfd sp!, {r4-r11}
+#define SAVE_REGS stmfd sp!, {r4-r11}; _SAVE({r4-r11})
#define RESTORE_REGS ldmfd sp!, {r4-r11}
#if defined(_ARM_ARCH_5E)
@@ -341,6 +341,7 @@ ENTRY(copyout)
cmp r2, r3
blt .Lnormale
stmfd sp!, {r0-r2, r4, lr}
+ _SAVE({r0-r2, r4, lr})
mov r3, r0
mov r0, r1
mov r1, r3
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index 32bbbc6..1c422f3 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -1069,7 +1069,7 @@ init_proc0(vm_offset_t kstack)
(thread0.td_kstack + kstack_pages * PAGE_SIZE) - 1;
thread0.td_pcb->pcb_flags = 0;
thread0.td_pcb->pcb_vfpcpu = -1;
- thread0.td_pcb->pcb_vfpstate.fpscr = VFPSCR_DN | VFPSCR_FZ;
+ thread0.td_pcb->pcb_vfpstate.fpscr = VFPSCR_DN;
thread0.td_frame = &proc0_tf;
pcpup->pc_curpcb = thread0.td_pcb;
}
diff --git a/sys/arm/arm/vm_machdep.c b/sys/arm/arm/vm_machdep.c
index 223ad96..895a14c 100644
--- a/sys/arm/arm/vm_machdep.c
+++ b/sys/arm/arm/vm_machdep.c
@@ -134,7 +134,7 @@ cpu_fork(register struct thread *td1, register struct proc *p2,
pcb2->pcb_regs.sf_sp = STACKALIGN(td2->td_frame);
pcb2->pcb_vfpcpu = -1;
- pcb2->pcb_vfpstate.fpscr = VFPSCR_DN | VFPSCR_FZ;
+ pcb2->pcb_vfpstate.fpscr = VFPSCR_DN;
tf = td2->td_frame;
tf->tf_spsr &= ~PSR_C;
diff --git a/sys/arm/include/asm.h b/sys/arm/include/asm.h
index 2f64c37..5958ea3 100644
--- a/sys/arm/include/asm.h
+++ b/sys/arm/include/asm.h
@@ -53,10 +53,12 @@
#define STOP_UNWINDING .cantunwind
#define _FNSTART .fnstart
#define _FNEND .fnend
+#define _SAVE(...) .save __VA_ARGS__
#else
#define STOP_UNWINDING
#define _FNSTART
#define _FNEND
+#define _SAVE(...)
#endif
/*
diff --git a/sys/arm/include/atomic-v4.h b/sys/arm/include/atomic-v4.h
index 7048178..2854655 100644
--- a/sys/arm/include/atomic-v4.h
+++ b/sys/arm/include/atomic-v4.h
@@ -439,4 +439,37 @@ atomic_subtract_long(volatile u_long *p, u_long v)
atomic_subtract_32((volatile uint32_t *)p, v);
}
+/*
+ * ARMv5 does not support SMP. For both kernel and user modes, only a
+ * compiler barrier is needed for fences, since CPU is always
+ * self-consistent.
+ */
+static __inline void
+atomic_thread_fence_acq(void)
+{
+
+ __compiler_membar();
+}
+
+static __inline void
+atomic_thread_fence_rel(void)
+{
+
+ __compiler_membar();
+}
+
+static __inline void
+atomic_thread_fence_acq_rel(void)
+{
+
+ __compiler_membar();
+}
+
+static __inline void
+atomic_thread_fence_seq_cst(void)
+{
+
+ __compiler_membar();
+}
+
#endif /* _MACHINE_ATOMIC_H_ */
diff --git a/sys/arm/include/atomic-v6.h b/sys/arm/include/atomic-v6.h
index 06d8880..d22f7e1 100644
--- a/sys/arm/include/atomic-v6.h
+++ b/sys/arm/include/atomic-v6.h
@@ -596,4 +596,32 @@ atomic_store_rel_long(volatile u_long *p, u_long v)
#undef ATOMIC_ACQ_REL
#undef ATOMIC_ACQ_REL_LONG
+static __inline void
+atomic_thread_fence_acq(void)
+{
+
+ dmb();
+}
+
+static __inline void
+atomic_thread_fence_rel(void)
+{
+
+ dmb();
+}
+
+static __inline void
+atomic_thread_fence_acq_rel(void)
+{
+
+ dmb();
+}
+
+static __inline void
+atomic_thread_fence_seq_cst(void)
+{
+
+ dmb();
+}
+
#endif /* _MACHINE_ATOMIC_V6_H_ */
diff --git a/sys/arm/include/atomic.h b/sys/arm/include/atomic.h
index 5379030..039af34 100644
--- a/sys/arm/include/atomic.h
+++ b/sys/arm/include/atomic.h
@@ -82,34 +82,6 @@ atomic_store_long(volatile u_long *dst, u_long src)
*dst = src;
}
-static __inline void
-atomic_thread_fence_acq(void)
-{
-
- dmb();
-}
-
-static __inline void
-atomic_thread_fence_rel(void)
-{
-
- dmb();
-}
-
-static __inline void
-atomic_thread_fence_acq_rel(void)
-{
-
- dmb();
-}
-
-static __inline void
-atomic_thread_fence_seq_cst(void)
-{
-
- dmb();
-}
-
#define atomic_clear_ptr atomic_clear_32
#define atomic_set_ptr atomic_set_32
#define atomic_cmpset_ptr atomic_cmpset_32
diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c
index e54c20e..a29f915 100644
--- a/sys/arm64/arm64/trap.c
+++ b/sys/arm64/arm64/trap.c
@@ -275,7 +275,7 @@ do_el1h_sync(struct trapframe *frame)
*/
KASSERT((esr & ESR_ELx_IL) == ESR_ELx_IL ||
(exception == EXCP_DATA_ABORT && ((esr & ISS_DATA_ISV) == 0)),
- ("Invalid instruction length in exception"));
+ ("Invalid instruction length in exception, esr %lx", esr));
CTR4(KTR_TRAP,
"do_el1_sync: curthread: %p, esr %lx, elr: %lx, frame: %p",
@@ -377,6 +377,11 @@ do_el0_sync(struct trapframe *frame)
case EXCP_UNKNOWN:
el0_excp_unknown(frame);
break;
+ case EXCP_PC_ALIGN:
+ td = curthread;
+ call_trapsignal(td, SIGBUS, BUS_ADRALN, (void *)frame->tf_elr);
+ userret(td, frame);
+ break;
case EXCP_BRK:
td = curthread;
call_trapsignal(td, SIGTRAP, TRAP_BRKPT, (void *)frame->tf_elr);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
index 326b03e..4ed3f52 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c
@@ -449,7 +449,7 @@ dmu_buf_hold_array_by_dnode(dnode_t *dn, uint64_t offset, uint64_t length,
}
if ((flags & DMU_READ_NO_PREFETCH) == 0 && read &&
- length < zfetch_array_rd_sz) {
+ length <= zfetch_array_rd_sz) {
dmu_zfetch(&dn->dn_zfetch, blkid, nblks);
}
rw_exit(&dn->dn_struct_rwlock);
diff --git a/sys/dev/ath/if_ath_beacon.c b/sys/dev/ath/if_ath_beacon.c
index 1ef3d58..5db0ba4 100644
--- a/sys/dev/ath/if_ath_beacon.c
+++ b/sys/dev/ath/if_ath_beacon.c
@@ -199,7 +199,7 @@ ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni)
* we assume the mbuf routines will return us something
* with this alignment (perhaps should assert).
*/
- m = ieee80211_beacon_alloc(ni, &vap->iv_bcn_off);
+ m = ieee80211_beacon_alloc(ni);
if (m == NULL) {
device_printf(sc->sc_dev, "%s: cannot get mbuf\n", __func__);
sc->sc_stats.ast_be_nombuf++;
@@ -713,7 +713,7 @@ ath_beacon_generate(struct ath_softc *sc, struct ieee80211vap *vap)
/* XXX lock mcastq? */
nmcastq = avp->av_mcastq.axq_depth;
- if (ieee80211_beacon_update(bf->bf_node, &vap->iv_bcn_off, m, nmcastq)) {
+ if (ieee80211_beacon_update(bf->bf_node, m, nmcastq)) {
/* XXX too conservative? */
bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m,
@@ -829,7 +829,7 @@ ath_beacon_start_adhoc(struct ath_softc *sc, struct ieee80211vap *vap)
*/
bf = avp->av_bcbuf;
m = bf->bf_m;
- if (ieee80211_beacon_update(bf->bf_node, &vap->iv_bcn_off, m, 0)) {
+ if (ieee80211_beacon_update(bf->bf_node, m, 0)) {
/* XXX too conservative? */
bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
error = bus_dmamap_load_mbuf_sg(sc->sc_dmat, bf->bf_dmamap, m,
diff --git a/sys/dev/ath/if_ath_keycache.c b/sys/dev/ath/if_ath_keycache.c
index f81785f..ff1df84 100644
--- a/sys/dev/ath/if_ath_keycache.c
+++ b/sys/dev/ath/if_ath_keycache.c
@@ -527,8 +527,7 @@ ath_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
* slot(s) must already have been allocated by ath_key_alloc.
*/
int
-ath_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
- const u_int8_t mac[IEEE80211_ADDR_LEN])
+ath_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
{
struct ath_softc *sc = vap->iv_ic->ic_softc;
diff --git a/sys/dev/ath/if_ath_keycache.h b/sys/dev/ath/if_ath_keycache.h
index 0b79e6f..c67e555 100644
--- a/sys/dev/ath/if_ath_keycache.h
+++ b/sys/dev/ath/if_ath_keycache.h
@@ -35,8 +35,7 @@
extern int ath_key_alloc(struct ieee80211vap *, struct ieee80211_key *,
ieee80211_keyix *, ieee80211_keyix *);
extern int ath_key_delete(struct ieee80211vap *, const struct ieee80211_key *);
-extern int ath_key_set(struct ieee80211vap *, const struct ieee80211_key *,
- const u_int8_t mac[IEEE80211_ADDR_LEN]);
+extern int ath_key_set(struct ieee80211vap *, const struct ieee80211_key *);
extern int ath_keyset(struct ath_softc *sc, struct ieee80211vap *vap,
const struct ieee80211_key *k, struct ieee80211_node *bss);
diff --git a/sys/dev/drm2/drmP.h b/sys/dev/drm2/drmP.h
index 32c3fcd..b3633c3 100644
--- a/sys/dev/drm2/drmP.h
+++ b/sys/dev/drm2/drmP.h
@@ -1782,12 +1782,6 @@ void drm_driver_irq_preinstall(struct drm_device *dev);
void drm_driver_irq_postinstall(struct drm_device *dev);
void drm_driver_irq_uninstall(struct drm_device *dev);
-/* AGP/PCI Express/GART support (drm_agpsupport.c) */
-void *drm_agp_allocate_memory(size_t pages, u32 type);
-int drm_agp_free_memory(void *handle);
-int drm_agp_bind_memory(void *handle, off_t start);
-int drm_agp_unbind_memory(void *handle);
-
/* sysctl support (drm_sysctl.h) */
extern int drm_sysctl_init(struct drm_device *dev);
extern int drm_sysctl_cleanup(struct drm_device *dev);
diff --git a/sys/dev/drm2/drm_crtc.c b/sys/dev/drm2/drm_crtc.c
index 318a764..79f66aa 100644
--- a/sys/dev/drm2/drm_crtc.c
+++ b/sys/dev/drm2/drm_crtc.c
@@ -663,7 +663,7 @@ int drm_plane_init(struct drm_device *dev, struct drm_plane *plane,
plane->dev = dev;
plane->funcs = funcs;
plane->format_types = malloc(sizeof(uint32_t) * format_count,
- DRM_MEM_KMS, M_WAITOK);
+ DRM_MEM_KMS, M_NOWAIT);
if (!plane->format_types) {
DRM_DEBUG_KMS("out of memory when allocating plane\n");
drm_mode_object_put(dev, &plane->base);
@@ -1010,7 +1010,7 @@ int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
total_objects += dev->mode_config.num_encoder;
group->id_list = malloc(total_objects * sizeof(uint32_t),
- DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ DRM_MEM_KMS, M_NOWAIT | M_ZERO);
if (!group->id_list)
return -ENOMEM;
@@ -1998,7 +1998,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
connector_set = malloc(crtc_req->count_connectors *
sizeof(struct drm_connector *),
- DRM_MEM_KMS, M_WAITOK);
+ DRM_MEM_KMS, M_NOWAIT);
if (!connector_set) {
ret = -ENOMEM;
goto out;
@@ -2523,7 +2523,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
goto out_err1;
}
clips = malloc(num_clips * sizeof(*clips), DRM_MEM_KMS,
- M_WAITOK | M_ZERO);
+ M_NOWAIT | M_ZERO);
if (!clips) {
ret = -ENOMEM;
goto out_err1;
@@ -2774,13 +2774,13 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
int ret;
property = malloc(sizeof(struct drm_property), DRM_MEM_KMS,
- M_WAITOK | M_ZERO);
+ M_NOWAIT | M_ZERO);
if (!property)
return NULL;
if (num_values) {
property->values = malloc(sizeof(uint64_t)*num_values, DRM_MEM_KMS,
- M_WAITOK | M_ZERO);
+ M_NOWAIT | M_ZERO);
if (!property->values)
goto fail;
}
@@ -2908,7 +2908,7 @@ int drm_property_add_enum(struct drm_property *property, int index,
}
prop_enum = malloc(sizeof(struct drm_property_enum), DRM_MEM_KMS,
- M_WAITOK | M_ZERO);
+ M_NOWAIT | M_ZERO);
if (!prop_enum)
return -ENOMEM;
@@ -3104,7 +3104,7 @@ static struct drm_property_blob *drm_property_create_blob(struct drm_device *dev
return NULL;
blob = malloc(sizeof(struct drm_property_blob)+length, DRM_MEM_KMS,
- M_WAITOK | M_ZERO);
+ M_NOWAIT | M_ZERO);
if (!blob)
return NULL;
@@ -3434,7 +3434,7 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
crtc->gamma_size = gamma_size;
crtc->gamma_store = malloc(gamma_size * sizeof(uint16_t) * 3,
- DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ DRM_MEM_KMS, M_NOWAIT | M_ZERO);
if (!crtc->gamma_store) {
crtc->gamma_size = 0;
return -ENOMEM;
@@ -3632,7 +3632,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
file_priv->event_space -= sizeof e->event;
mtx_unlock(&dev->event_lock);
- e = malloc(sizeof *e, DRM_MEM_KMS, M_WAITOK | M_ZERO);
+ e = malloc(sizeof *e, DRM_MEM_KMS, M_NOWAIT | M_ZERO);
if (e == NULL) {
mtx_lock(&dev->event_lock);
file_priv->event_space += sizeof e->event;
diff --git a/sys/dev/drm2/drm_fops.c b/sys/dev/drm2/drm_fops.c
index b73cec6..3b3be06 100644
--- a/sys/dev/drm2/drm_fops.c
+++ b/sys/dev/drm2/drm_fops.c
@@ -136,7 +136,7 @@ int drm_open(struct cdev *kdev, int flags, int fmt, DRM_STRUCTPROC *p)
sx_xlock(&drm_global_mutex);
/*
- * FIXME Linux<->FreeBSD: On Linux, counter updated outisde
+ * FIXME Linux<->FreeBSD: On Linux, counter updated outside
* global mutex.
*/
if (!dev->open_count++)
diff --git a/sys/dev/drm2/drm_pci.c b/sys/dev/drm2/drm_pci.c
index f2c5bbd..ecbfcb7 100644
--- a/sys/dev/drm2/drm_pci.c
+++ b/sys/dev/drm2/drm_pci.c
@@ -225,7 +225,7 @@ int drm_pci_set_unique(struct drm_device *dev,
master->unique_len = u->unique_len;
master->unique_size = u->unique_len + 1;
- master->unique = malloc(master->unique_size, DRM_MEM_DRIVER, M_WAITOK);
+ master->unique = malloc(master->unique_size, DRM_MEM_DRIVER, M_NOWAIT);
if (!master->unique) {
ret = -ENOMEM;
goto err;
diff --git a/sys/dev/drm2/drm_stub.c b/sys/dev/drm2/drm_stub.c
index d7ec6cb..06663ac 100644
--- a/sys/dev/drm2/drm_stub.c
+++ b/sys/dev/drm2/drm_stub.c
@@ -94,9 +94,9 @@ static int drm_minor_get_id(struct drm_device *dev, int type)
if (type == DRM_MINOR_CONTROL) {
new_id += 64;
- } else if (type == DRM_MINOR_RENDER) {
- new_id += 128;
- }
+ } else if (type == DRM_MINOR_RENDER) {
+ new_id += 128;
+ }
return new_id;
}
diff --git a/sys/dev/drm2/i915/i915_dma.c b/sys/dev/drm2/i915/i915_dma.c
index 2265ac0..dddc03e 100644
--- a/sys/dev/drm2/i915/i915_dma.c
+++ b/sys/dev/drm2/i915/i915_dma.c
@@ -1452,6 +1452,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
}
}
+ pci_enable_busmaster(dev->dev);
+
intel_opregion_init(dev);
callout_init(&dev_priv->hangcheck_timer, 1);
diff --git a/sys/dev/drm2/i915/i915_drv.c b/sys/dev/drm2/i915/i915_drv.c
index 3109827..e9cf3a4 100644
--- a/sys/dev/drm2/i915/i915_drv.c
+++ b/sys/dev/drm2/i915/i915_drv.c
@@ -894,6 +894,7 @@ int intel_gpu_reset(struct drm_device *dev)
case 4:
ret = i965_do_reset(dev);
break;
+ case 3:
case 2:
ret = i8xx_do_reset(dev);
break;
diff --git a/sys/dev/drm2/i915/intel_opregion.c b/sys/dev/drm2/i915/intel_opregion.c
index 411e530..397c559 100644
--- a/sys/dev/drm2/i915/intel_opregion.c
+++ b/sys/dev/drm2/i915/intel_opregion.c
@@ -533,11 +533,9 @@ void intel_opregion_fini(struct drm_device *dev)
opregion->vbt = NULL;
}
#else
-int
+void
intel_opregion_init(struct drm_device *dev)
{
-
- return (0);
}
void
diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c
index c30f31c..bb1f19e 100644
--- a/sys/dev/if_ndis/if_ndis.c
+++ b/sys/dev/if_ndis/if_ndis.c
@@ -194,7 +194,7 @@ static void ndis_media_status (struct ifnet *, struct ifmediareq *);
static int ndis_set_cipher (struct ndis_softc *, int);
static int ndis_set_wpa (struct ndis_softc *, void *, int);
static int ndis_add_key (struct ieee80211vap *,
- const struct ieee80211_key *, const u_int8_t []);
+ const struct ieee80211_key *);
static int ndis_del_key (struct ieee80211vap *,
const struct ieee80211_key *);
static void ndis_setmulti (struct ndis_softc *);
@@ -3070,8 +3070,7 @@ ndis_del_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
* set after initial authentication with the AP.
*/
static int
-ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key,
- const uint8_t mac[IEEE80211_ADDR_LEN])
+ndis_add_key(struct ieee80211vap *vap, const struct ieee80211_key *key)
{
struct ndis_softc *sc = vap->iv_ic->ic_softc;
ndis_80211_key rkey;
diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c
index 463b5c9..7f9d8e0 100644
--- a/sys/dev/mwl/if_mwl.c
+++ b/sys/dev/mwl/if_mwl.c
@@ -111,7 +111,10 @@ static int mwl_key_alloc(struct ieee80211vap *,
ieee80211_keyix *, ieee80211_keyix *);
static int mwl_key_delete(struct ieee80211vap *,
const struct ieee80211_key *);
-static int mwl_key_set(struct ieee80211vap *, const struct ieee80211_key *,
+static int mwl_key_set(struct ieee80211vap *,
+ const struct ieee80211_key *);
+static int _mwl_key_set(struct ieee80211vap *,
+ const struct ieee80211_key *,
const uint8_t mac[IEEE80211_ADDR_LEN]);
static int mwl_mode_init(struct mwl_softc *);
static void mwl_update_mcast(struct ieee80211com *);
@@ -1604,7 +1607,13 @@ addgroupflags(MWL_HAL_KEYVAL *hk, const struct ieee80211_key *k)
* slot(s) must already have been allocated by mwl_key_alloc.
*/
static int
-mwl_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
+mwl_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
+{
+ return (_mwl_key_set(vap, k, k->wk_macaddr));
+}
+
+static int
+_mwl_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
const uint8_t mac[IEEE80211_ADDR_LEN])
{
#define GRPXMIT (IEEE80211_KEY_XMIT | IEEE80211_KEY_GROUP)
@@ -1834,10 +1843,9 @@ mwl_beacon_setup(struct ieee80211vap *vap)
{
struct mwl_hal_vap *hvap = MWL_VAP(vap)->mv_hvap;
struct ieee80211_node *ni = vap->iv_bss;
- struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off;
struct mbuf *m;
- m = ieee80211_beacon_alloc(ni, bo);
+ m = ieee80211_beacon_alloc(ni);
if (m == NULL)
return ENOBUFS;
mwl_hal_setbeacon(hvap, mtod(m, const void *), m->m_len);
@@ -3911,7 +3919,8 @@ mwl_setanywepkey(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]
IEEE80211_F_PRIVACY &&
vap->iv_def_txkey != IEEE80211_KEYIX_NONE &&
vap->iv_nw_keys[vap->iv_def_txkey].wk_keyix != IEEE80211_KEYIX_NONE)
- (void) mwl_key_set(vap, &vap->iv_nw_keys[vap->iv_def_txkey], mac);
+ (void) _mwl_key_set(vap, &vap->iv_nw_keys[vap->iv_def_txkey],
+ mac);
}
static int
@@ -3956,7 +3965,7 @@ mwl_setglobalkeys(struct ieee80211vap *vap)
wk = &vap->iv_nw_keys[0];
for (; wk < &vap->iv_nw_keys[IEEE80211_WEP_NKID]; wk++)
if (wk->wk_keyix != IEEE80211_KEYIX_NONE)
- (void) mwl_key_set(vap, wk, vap->iv_myaddr);
+ (void) _mwl_key_set(vap, wk, vap->iv_myaddr);
}
/*
diff --git a/sys/dev/ral/rt2560.c b/sys/dev/ral/rt2560.c
index ef5a01c..b03e8fa 100644
--- a/sys/dev/ral/rt2560.c
+++ b/sys/dev/ral/rt2560.c
@@ -768,7 +768,7 @@ rt2560_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
vap->iv_opmode == IEEE80211_M_IBSS ||
vap->iv_opmode == IEEE80211_M_MBSS) {
- m = ieee80211_beacon_alloc(ni, &vap->iv_bcn_off);
+ m = ieee80211_beacon_alloc(ni);
if (m == NULL) {
device_printf(sc->sc_dev,
"could not allocate beacon\n");
@@ -1286,7 +1286,6 @@ static void
rt2560_beacon_expire(struct rt2560_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct rt2560_tx_data *data;
if (ic->ic_opmode != IEEE80211_M_IBSS &&
@@ -1305,7 +1304,7 @@ rt2560_beacon_expire(struct rt2560_softc *sc)
bus_dmamap_unload(sc->bcnq.data_dmat, data->map);
/* XXX 1 =>'s mcast frames which means all PS sta's will wakeup! */
- ieee80211_beacon_update(data->ni, &vap->iv_bcn_off, data->m, 1);
+ ieee80211_beacon_update(data->ni, data->m, 1);
rt2560_tx_bcn(sc, data->m, data->ni);
diff --git a/sys/dev/ral/rt2661.c b/sys/dev/ral/rt2661.c
index 5c73ba0..100b5d6 100644
--- a/sys/dev/ral/rt2661.c
+++ b/sys/dev/ral/rt2661.c
@@ -2626,13 +2626,11 @@ static int
rt2661_prepare_beacon(struct rt2661_softc *sc, struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off;
struct rt2661_tx_desc desc;
struct mbuf *m0;
int rate;
- m0 = ieee80211_beacon_alloc(vap->iv_bss, bo);
- if (m0 == NULL) {
+ if ((m0 = ieee80211_beacon_alloc(vap->iv_bss))== NULL) {
device_printf(sc->sc_dev, "could not allocate beacon frame\n");
return ENOBUFS;
}
diff --git a/sys/dev/ral/rt2860.c b/sys/dev/ral/rt2860.c
index a6b1e26..9c7fa53 100644
--- a/sys/dev/ral/rt2860.c
+++ b/sys/dev/ral/rt2860.c
@@ -4268,12 +4268,11 @@ static int
rt2860_setup_beacon(struct rt2860_softc *sc, struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
- struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off;
struct rt2860_txwi txwi;
struct mbuf *m;
int ridx;
- if ((m = ieee80211_beacon_alloc(vap->iv_bss, bo)) == NULL)
+ if ((m = ieee80211_beacon_alloc(vap->iv_bss)) == NULL)
return ENOBUFS;
memset(&txwi, 0, sizeof txwi);
diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c
index 6a558f6..f1c9cdf 100644
--- a/sys/dev/usb/wlan/if_rum.c
+++ b/sys/dev/usb/wlan/if_rum.c
@@ -86,8 +86,6 @@ SYSCTL_INT(_hw_usb_rum, OID_AUTO, debug, CTLFLAG_RWTUN, &rum_debug, 0,
"Debug level");
#endif
-#define N(a) ((int)(sizeof (a) / sizeof ((a)[0])))
-
static const STRUCT_USB_HOST_ID rum_devs[] = {
#define RUM_DEV(v,p) { USB_VP(USB_VENDOR_##v, USB_PRODUCT_##v##_##p) }
RUM_DEV(ABOCOM, HWU54DM),
@@ -160,14 +158,21 @@ static struct ieee80211vap *rum_vap_create(struct ieee80211com *,
int, const uint8_t [IEEE80211_ADDR_LEN],
const uint8_t [IEEE80211_ADDR_LEN]);
static void rum_vap_delete(struct ieee80211vap *);
+static void rum_cmdq_cb(void *, int);
+static int rum_cmd_sleepable(struct rum_softc *, const void *,
+ size_t, uint8_t, CMD_FUNC_PROTO);
static void rum_tx_free(struct rum_tx_data *, int);
static void rum_setup_tx_list(struct rum_softc *);
static void rum_unsetup_tx_list(struct rum_softc *);
static int rum_newstate(struct ieee80211vap *,
enum ieee80211_state, int);
+static uint8_t rum_crypto_mode(struct rum_softc *, u_int, int);
static void rum_setup_tx_desc(struct rum_softc *,
- struct rum_tx_desc *, uint32_t, uint16_t, int,
- int);
+ struct rum_tx_desc *, struct ieee80211_key *,
+ uint32_t, uint8_t, uint8_t, int, int, int);
+static uint32_t rum_tx_crypto_flags(struct rum_softc *,
+ struct ieee80211_node *,
+ const struct ieee80211_key *);
static int rum_tx_mgt(struct rum_softc *, struct mbuf *,
struct ieee80211_node *);
static int rum_tx_raw(struct rum_softc *, struct mbuf *,
@@ -186,6 +191,11 @@ static void rum_read_multi(struct rum_softc *, uint16_t, void *,
static usb_error_t rum_write(struct rum_softc *, uint16_t, uint32_t);
static usb_error_t rum_write_multi(struct rum_softc *, uint16_t, void *,
size_t);
+static usb_error_t rum_setbits(struct rum_softc *, uint16_t, uint32_t);
+static usb_error_t rum_clrbits(struct rum_softc *, uint16_t, uint32_t);
+static usb_error_t rum_modbits(struct rum_softc *, uint16_t, uint32_t,
+ uint32_t);
+static int rum_bbp_busy(struct rum_softc *);
static void rum_bbp_write(struct rum_softc *, uint8_t, uint8_t);
static uint8_t rum_bbp_read(struct rum_softc *, uint8_t);
static void rum_rf_write(struct rum_softc *, uint8_t, uint32_t);
@@ -197,9 +207,18 @@ static void rum_select_band(struct rum_softc *,
struct ieee80211_channel *);
static void rum_set_chan(struct rum_softc *,
struct ieee80211_channel *);
-static void rum_enable_tsf_sync(struct rum_softc *);
+static void rum_set_maxretry(struct rum_softc *,
+ struct ieee80211vap *);
+static int rum_enable_tsf_sync(struct rum_softc *);
static void rum_enable_tsf(struct rum_softc *);
-static void rum_update_slot(struct rum_softc *);
+static void rum_abort_tsf_sync(struct rum_softc *);
+static void rum_get_tsf(struct rum_softc *, uint64_t *);
+static void rum_update_slot_cb(struct rum_softc *,
+ union sec_param *, uint8_t);
+static void rum_update_slot(struct ieee80211com *);
+static void rum_wme_update_cb(struct rum_softc *,
+ union sec_param *, uint8_t);
+static int rum_wme_update(struct ieee80211com *);
static void rum_set_bssid(struct rum_softc *, const uint8_t *);
static void rum_set_macaddr(struct rum_softc *, const uint8_t *);
static void rum_update_mcast(struct ieee80211com *);
@@ -207,13 +226,37 @@ static void rum_update_promisc(struct ieee80211com *);
static void rum_setpromisc(struct rum_softc *);
static const char *rum_get_rf(int);
static void rum_read_eeprom(struct rum_softc *);
+static int rum_bbp_wakeup(struct rum_softc *);
static int rum_bbp_init(struct rum_softc *);
-static void rum_init(struct rum_softc *);
+static void rum_clr_shkey_regs(struct rum_softc *);
+static int rum_init(struct rum_softc *);
static void rum_stop(struct rum_softc *);
static void rum_load_microcode(struct rum_softc *, const uint8_t *,
size_t);
-static void rum_prepare_beacon(struct rum_softc *,
+static int rum_set_beacon(struct rum_softc *,
+ struct ieee80211vap *);
+static int rum_alloc_beacon(struct rum_softc *,
struct ieee80211vap *);
+static void rum_update_beacon_cb(struct rum_softc *,
+ union sec_param *, uint8_t);
+static void rum_update_beacon(struct ieee80211vap *, int);
+static int rum_common_key_set(struct rum_softc *,
+ struct ieee80211_key *, uint16_t);
+static void rum_group_key_set_cb(struct rum_softc *,
+ union sec_param *, uint8_t);
+static void rum_group_key_del_cb(struct rum_softc *,
+ union sec_param *, uint8_t);
+static void rum_pair_key_set_cb(struct rum_softc *,
+ union sec_param *, uint8_t);
+static void rum_pair_key_del_cb(struct rum_softc *,
+ union sec_param *, uint8_t);
+static int rum_key_alloc(struct ieee80211vap *,
+ struct ieee80211_key *, ieee80211_keyix *,
+ ieee80211_keyix *);
+static int rum_key_set(struct ieee80211vap *,
+ const struct ieee80211_key *);
+static int rum_key_delete(struct ieee80211vap *,
+ const struct ieee80211_key *);
static int rum_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void rum_scan_start(struct ieee80211com *);
@@ -242,9 +285,9 @@ static const struct {
{ RT2573_MAC_CSR10, 0x00000718 },
{ RT2573_MAC_CSR12, 0x00000004 },
{ RT2573_MAC_CSR13, 0x00007f00 },
- { RT2573_SEC_CSR0, 0x00000000 },
- { RT2573_SEC_CSR1, 0x00000000 },
- { RT2573_SEC_CSR5, 0x00000000 },
+ { RT2573_SEC_CSR2, 0x00000000 },
+ { RT2573_SEC_CSR3, 0x00000000 },
+ { RT2573_SEC_CSR4, 0x00000000 },
{ RT2573_PHY_CSR1, 0x000023b0 },
{ RT2573_PHY_CSR5, 0x00040a06 },
{ RT2573_PHY_CSR6, 0x00080606 },
@@ -434,8 +477,8 @@ rum_attach(device_t self)
sc->sc_udev = uaa->device;
sc->sc_dev = self;
- mtx_init(&sc->sc_mtx, device_get_nameunit(self),
- MTX_NETWORK_LOCK, MTX_DEF);
+ RUM_LOCK_INIT(sc);
+ RUM_CMDQ_LOCK_INIT(sc);
mbufq_init(&sc->sc_snd, ifqmaxlen);
iface_index = RT2573_IFACE_INDEX;
@@ -480,13 +523,21 @@ rum_attach(device_t self)
| IEEE80211_C_IBSS /* IBSS mode supported */
| IEEE80211_C_MONITOR /* monitor mode supported */
| IEEE80211_C_HOSTAP /* HostAp mode supported */
+ | IEEE80211_C_AHDEMO /* adhoc demo mode */
| IEEE80211_C_TXPMGT /* tx power management */
| IEEE80211_C_SHPREAMBLE /* short preamble supported */
| IEEE80211_C_SHSLOT /* short slot time supported */
| IEEE80211_C_BGSCAN /* bg scanning supported */
| IEEE80211_C_WPA /* 802.11i */
+ | IEEE80211_C_WME /* 802.11e */
;
+ ic->ic_cryptocaps =
+ IEEE80211_CRYPTO_WEP |
+ IEEE80211_CRYPTO_AES_CCM |
+ IEEE80211_CRYPTO_TKIPMIC |
+ IEEE80211_CRYPTO_TKIP;
+
bands = 0;
setbit(&bands, IEEE80211_MODE_11B);
setbit(&bands, IEEE80211_MODE_11G);
@@ -504,6 +555,8 @@ rum_attach(device_t self)
ic->ic_parent = rum_parent;
ic->ic_vap_create = rum_vap_create;
ic->ic_vap_delete = rum_vap_delete;
+ ic->ic_updateslot = rum_update_slot;
+ ic->ic_wme.wme_update = rum_wme_update;
ic->ic_update_mcast = rum_update_mcast;
ieee80211_radiotap_attach(ic,
@@ -512,6 +565,8 @@ rum_attach(device_t self)
&sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
RT2573_RX_RADIOTAP_PRESENT);
+ TASK_INIT(&sc->cmdq_task, 0, rum_cmdq_cb, sc);
+
if (bootverbose)
ieee80211_announce(ic);
@@ -526,6 +581,7 @@ static int
rum_detach(device_t self)
{
struct rum_softc *sc = device_get_softc(self);
+ struct ieee80211com *ic = &sc->sc_ic;
/* Prevent further ioctls */
RUM_LOCK(sc);
@@ -540,10 +596,15 @@ rum_detach(device_t self)
rum_unsetup_tx_list(sc);
RUM_UNLOCK(sc);
- if (sc->sc_ic.ic_softc == sc)
- ieee80211_ifdetach(&sc->sc_ic);
+ if (ic->ic_softc == sc) {
+ ieee80211_draintask(ic, &sc->cmdq_task);
+ ieee80211_ifdetach(ic);
+ }
+
mbufq_drain(&sc->sc_snd);
- mtx_destroy(&sc->sc_mtx);
+ RUM_CMDQ_LOCK_DESTROY(sc);
+ RUM_LOCK_DESTROY(sc);
+
return (0);
}
@@ -594,6 +655,11 @@ rum_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* override state transition machine */
rvp->newstate = vap->iv_newstate;
vap->iv_newstate = rum_newstate;
+ vap->iv_key_alloc = rum_key_alloc;
+ vap->iv_key_set = rum_key_set;
+ vap->iv_key_delete = rum_key_delete;
+ vap->iv_update_beacon = rum_update_beacon;
+ vap->iv_max_aid = RT2573_ADDR_MAX;
usb_callout_init_mtx(&rvp->ratectl_ch, &sc->sc_mtx, 0);
TASK_INIT(&rvp->ratectl_task, 0, rum_ratectl_task, rvp);
@@ -612,6 +678,7 @@ rum_vap_delete(struct ieee80211vap *vap)
struct rum_vap *rvp = RUM_VAP(vap);
struct ieee80211com *ic = vap->iv_ic;
+ m_freem(rvp->bcn_mbuf);
usb_callout_drain(&rvp->ratectl_ch);
ieee80211_draintask(ic, &rvp->ratectl_task);
ieee80211_ratectl_deinit(vap);
@@ -620,6 +687,56 @@ rum_vap_delete(struct ieee80211vap *vap)
}
static void
+rum_cmdq_cb(void *arg, int pending)
+{
+ struct rum_softc *sc = arg;
+ struct rum_cmdq *rc;
+
+ RUM_CMDQ_LOCK(sc);
+ while (sc->cmdq[sc->cmdq_first].func != NULL) {
+ rc = &sc->cmdq[sc->cmdq_first];
+ RUM_CMDQ_UNLOCK(sc);
+
+ RUM_LOCK(sc);
+ rc->func(sc, &rc->data, rc->rvp_id);
+ RUM_UNLOCK(sc);
+
+ RUM_CMDQ_LOCK(sc);
+ memset(rc, 0, sizeof (*rc));
+ sc->cmdq_first = (sc->cmdq_first + 1) % RUM_CMDQ_SIZE;
+ }
+ RUM_CMDQ_UNLOCK(sc);
+}
+
+static int
+rum_cmd_sleepable(struct rum_softc *sc, const void *ptr, size_t len,
+ uint8_t rvp_id, CMD_FUNC_PROTO)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+
+ KASSERT(len <= sizeof(union sec_param), ("buffer overflow"));
+
+ RUM_CMDQ_LOCK(sc);
+ if (sc->cmdq[sc->cmdq_last].func != NULL) {
+ device_printf(sc->sc_dev, "%s: cmdq overflow\n", __func__);
+ RUM_CMDQ_UNLOCK(sc);
+
+ return EAGAIN;
+ }
+
+ if (ptr != NULL)
+ memcpy(&sc->cmdq[sc->cmdq_last].data, ptr, len);
+ sc->cmdq[sc->cmdq_last].rvp_id = rvp_id;
+ sc->cmdq[sc->cmdq_last].func = func;
+ sc->cmdq_last = (sc->cmdq_last + 1) % RUM_CMDQ_SIZE;
+ RUM_CMDQ_UNLOCK(sc);
+
+ ieee80211_runtask(ic, &sc->cmdq_task);
+
+ return 0;
+}
+
+static void
rum_tx_free(struct rum_tx_data *data, int txerr)
{
struct rum_softc *sc = data->sc;
@@ -687,7 +804,7 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
const struct ieee80211_txparam *tp;
enum ieee80211_state ostate;
struct ieee80211_node *ni;
- uint32_t tmp;
+ int ret;
ostate = vap->iv_state;
DPRINTF("%s -> %s\n",
@@ -700,38 +817,40 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
switch (nstate) {
case IEEE80211_S_INIT:
- if (ostate == IEEE80211_S_RUN) {
- /* abort TSF synchronization */
- tmp = rum_read(sc, RT2573_TXRX_CSR9);
- rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff);
- }
+ if (ostate == IEEE80211_S_RUN)
+ rum_abort_tsf_sync(sc);
+
break;
case IEEE80211_S_RUN:
ni = ieee80211_ref_node(vap->iv_bss);
if (vap->iv_opmode != IEEE80211_M_MONITOR) {
- if (ic->ic_bsschan == IEEE80211_CHAN_ANYC) {
- RUM_UNLOCK(sc);
- IEEE80211_LOCK(ic);
- ieee80211_free_node(ni);
- return (-1);
+ if (ic->ic_bsschan == IEEE80211_CHAN_ANYC ||
+ ni->ni_chan == IEEE80211_CHAN_ANYC) {
+ ret = EINVAL;
+ goto run_fail;
}
- rum_update_slot(sc);
+ rum_update_slot_cb(sc, NULL, 0);
rum_enable_mrr(sc);
rum_set_txpreamble(sc);
rum_set_basicrates(sc);
- IEEE80211_ADDR_COPY(ic->ic_macaddr, ni->ni_bssid);
- rum_set_bssid(sc, ic->ic_macaddr);
+ rum_set_maxretry(sc, vap);
+ IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
+ rum_set_bssid(sc, sc->sc_bssid);
}
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
- vap->iv_opmode == IEEE80211_M_IBSS)
- rum_prepare_beacon(sc, vap);
+ vap->iv_opmode == IEEE80211_M_IBSS) {
+ if ((ret = rum_alloc_beacon(sc, vap)) != 0)
+ goto run_fail;
+ }
- if (vap->iv_opmode != IEEE80211_M_MONITOR)
- rum_enable_tsf_sync(sc);
- else
+ if (vap->iv_opmode != IEEE80211_M_MONITOR &&
+ vap->iv_opmode != IEEE80211_M_AHDEMO) {
+ if ((ret = rum_enable_tsf_sync(sc)) != 0)
+ goto run_fail;
+ } else
rum_enable_tsf(sc);
/* enable automatic rate adaptation */
@@ -746,6 +865,12 @@ rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
RUM_UNLOCK(sc);
IEEE80211_LOCK(ic);
return (rvp->newstate(vap, nstate, arg));
+
+run_fail:
+ RUM_UNLOCK(sc);
+ IEEE80211_LOCK(ic);
+ ieee80211_free_node(ni);
+ return ret;
}
static void
@@ -794,6 +919,7 @@ tr_setup:
tap->wt_flags = 0;
tap->wt_rate = data->rate;
+ rum_get_tsf(sc, &tap->wt_tsf);
tap->wt_antenna = sc->tx_ant;
ieee80211_radiotap_tx(vap, m);
@@ -847,6 +973,7 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct rum_softc *sc = usbd_xfer_softc(xfer);
struct ieee80211com *ic = &sc->sc_ic;
+ struct ieee80211_frame_min *wh;
struct ieee80211_node *ni;
struct mbuf *m = NULL;
struct usb_page_cache *pc;
@@ -884,6 +1011,21 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
counter_u64_add(ic->ic_ierrors, 1);
goto tr_setup;
}
+ if ((flags & RT2573_RX_DEC_MASK) != RT2573_RX_DEC_OK) {
+ switch (flags & RT2573_RX_DEC_MASK) {
+ case RT2573_RX_IV_ERROR:
+ DPRINTFN(5, "IV/EIV error\n");
+ break;
+ case RT2573_RX_MIC_ERROR:
+ DPRINTFN(5, "MIC error\n");
+ break;
+ case RT2573_RX_KEY_ERROR:
+ DPRINTFN(5, "Key error\n");
+ break;
+ }
+ counter_u64_add(ic->ic_ierrors, 1);
+ goto tr_setup;
+ }
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
if (m == NULL) {
@@ -894,17 +1036,26 @@ rum_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
usbd_copy_out(pc, RT2573_RX_DESC_SIZE,
mtod(m, uint8_t *), len);
+ wh = mtod(m, struct ieee80211_frame_min *);
+
+ if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
+ (flags & RT2573_RX_CIP_MASK) !=
+ RT2573_RX_CIP_MODE(RT2573_MODE_NOSEC)) {
+ wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED;
+ m->m_flags |= M_WEP;
+ }
+
/* finalize mbuf */
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;
if (ieee80211_radiotap_active(ic)) {
struct rum_rx_radiotap_header *tap = &sc->sc_rxtap;
- /* XXX read tsf */
tap->wr_flags = 0;
tap->wr_rate = ieee80211_plcp2rate(sc->sc_rx_desc.rate,
(flags & RT2573_RX_OFDM) ?
IEEE80211_T_OFDM : IEEE80211_T_CCK);
+ rum_get_tsf(sc, &tap->wr_tsf);
tap->wr_antsignal = RT2573_NOISE_FLOOR + rssi;
tap->wr_antnoise = RT2573_NOISE_FLOOR;
tap->wr_antenna = sc->rx_ant;
@@ -922,8 +1073,11 @@ tr_setup:
*/
RUM_UNLOCK(sc);
if (m) {
- ni = ieee80211_find_rxnode(ic,
- mtod(m, struct ieee80211_frame_min *));
+ if (m->m_len >= sizeof(struct ieee80211_frame_min))
+ ni = ieee80211_find_rxnode(ic, wh);
+ else
+ ni = NULL;
+
if (ni != NULL) {
(void) ieee80211_input(ni, m, rssi,
RT2573_NOISE_FLOOR);
@@ -969,22 +1123,46 @@ rum_plcp_signal(int rate)
return 0xff; /* XXX unsupported/unknown rate */
}
+/*
+ * Map net80211 cipher to RT2573 security mode.
+ */
+static uint8_t
+rum_crypto_mode(struct rum_softc *sc, u_int cipher, int keylen)
+{
+ switch (cipher) {
+ case IEEE80211_CIPHER_WEP:
+ return (keylen < 8 ? RT2573_MODE_WEP40 : RT2573_MODE_WEP104);
+ case IEEE80211_CIPHER_TKIP:
+ return RT2573_MODE_TKIP;
+ case IEEE80211_CIPHER_AES_CCM:
+ return RT2573_MODE_AES_CCMP;
+ default:
+ device_printf(sc->sc_dev, "unknown cipher %d\n", cipher);
+ return 0;
+ }
+}
+
static void
rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc,
- uint32_t flags, uint16_t xflags, int len, int rate)
+ struct ieee80211_key *k, uint32_t flags, uint8_t xflags, uint8_t qid,
+ int hdrlen, int len, int rate)
{
struct ieee80211com *ic = &sc->sc_ic;
+ struct wmeParams *wmep = &sc->wme_params[qid];
uint16_t plcp_length;
int remainder;
- desc->flags = htole32(flags);
- desc->flags |= htole32(RT2573_TX_VALID);
- desc->flags |= htole32(len << 16);
+ flags |= RT2573_TX_VALID;
+ flags |= len << 16;
+
+ if (k != NULL && !(k->wk_flags & IEEE80211_KEY_SWCRYPT)) {
+ const struct ieee80211_cipher *cip = k->wk_cipher;
- desc->xflags = htole16(xflags);
+ len += cip->ic_header + cip->ic_trailer + cip->ic_miclen;
- desc->wme = htole16(RT2573_QID(0) | RT2573_AIFSN(2) |
- RT2573_LOGCWMIN(4) | RT2573_LOGCWMAX(10));
+ desc->eiv = 0; /* for WEP */
+ cip->ic_setiv(k, (uint8_t *)&desc->iv);
+ }
/* setup PLCP fields */
desc->plcp_signal = rum_plcp_signal(rate);
@@ -992,7 +1170,7 @@ rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc,
len += IEEE80211_CRC_LEN;
if (ieee80211_rate2phytype(ic->ic_rt, rate) == IEEE80211_T_OFDM) {
- desc->flags |= htole32(RT2573_TX_OFDM);
+ flags |= RT2573_TX_OFDM;
plcp_length = len & 0xfff;
desc->plcp_length_hi = plcp_length >> 6;
@@ -1012,6 +1190,15 @@ rum_setup_tx_desc(struct rum_softc *sc, struct rum_tx_desc *desc,
if (rate != 2 && (ic->ic_flags & IEEE80211_F_SHPREAMBLE))
desc->plcp_signal |= 0x08;
}
+
+ desc->flags = htole32(flags);
+ desc->hdrlen = hdrlen;
+ desc->xflags = xflags;
+
+ desc->wme = htole16(RT2573_QID(qid) |
+ RT2573_AIFSN(wmep->wmep_aifsn) |
+ RT2573_LOGCWMIN(wmep->wmep_logcwmin) |
+ RT2573_LOGCWMAX(wmep->wmep_logcwmax));
}
static int
@@ -1022,10 +1209,10 @@ rum_sendprot(struct rum_softc *sc,
const struct ieee80211_frame *wh;
struct rum_tx_data *data;
struct mbuf *mprot;
- int protrate, ackrate, pktlen, flags, isshort;
+ int protrate, pktlen, flags, isshort;
uint16_t dur;
- RUM_LOCK_ASSERT(sc, MA_OWNED);
+ RUM_LOCK_ASSERT(sc);
KASSERT(prot == IEEE80211_PROT_RTSCTS || prot == IEEE80211_PROT_CTSONLY,
("protection %d", prot));
@@ -1033,12 +1220,11 @@ rum_sendprot(struct rum_softc *sc,
pktlen = m->m_pkthdr.len + IEEE80211_CRC_LEN;
protrate = ieee80211_ctl_rate(ic->ic_rt, rate);
- ackrate = ieee80211_ack_rate(ic->ic_rt, rate);
isshort = (ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0;
dur = ieee80211_compute_duration(ic->ic_rt, pktlen, rate, isshort)
+ ieee80211_ack_duration(ic->ic_rt, rate, isshort);
- flags = RT2573_TX_MORE_FRAG;
+ flags = 0;
if (prot == IEEE80211_PROT_RTSCTS) {
/* NB: CTS is the same size as an ACK */
dur += ieee80211_ack_duration(ic->ic_rt, rate, isshort);
@@ -1058,7 +1244,8 @@ rum_sendprot(struct rum_softc *sc,
data->m = mprot;
data->ni = ieee80211_ref_node(ni);
data->rate = protrate;
- rum_setup_tx_desc(sc, &data->desc, flags, 0, mprot->m_pkthdr.len, protrate);
+ rum_setup_tx_desc(sc, &data->desc, NULL, flags, 0, 0, 0,
+ mprot->m_pkthdr.len, protrate);
STAILQ_INSERT_TAIL(&sc->tx_q, data, next);
usbd_transfer_start(sc->sc_xfer[RUM_BULK_WR]);
@@ -1066,6 +1253,40 @@ rum_sendprot(struct rum_softc *sc,
return 0;
}
+static uint32_t
+rum_tx_crypto_flags(struct rum_softc *sc, struct ieee80211_node *ni,
+ const struct ieee80211_key *k)
+{
+ struct ieee80211vap *vap = ni->ni_vap;
+ u_int cipher;
+ uint32_t flags = 0;
+ uint8_t mode, pos;
+
+ if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT)) {
+ cipher = k->wk_cipher->ic_cipher;
+ pos = k->wk_keyix;
+ mode = rum_crypto_mode(sc, cipher, k->wk_keylen);
+ if (mode == 0)
+ return 0;
+
+ flags |= RT2573_TX_CIP_MODE(mode);
+
+ /* Do not trust GROUP flag */
+ if (!(k >= &vap->iv_nw_keys[0] &&
+ k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]))
+ flags |= RT2573_TX_KEY_PAIR;
+ else
+ pos += 0 * RT2573_SKEY_MAX; /* vap id */
+
+ flags |= RT2573_TX_KEY_ID(pos);
+
+ if (cipher == IEEE80211_CIPHER_TKIP)
+ flags |= RT2573_TX_TKIPMIC;
+ }
+
+ return flags;
+}
+
static int
rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
{
@@ -1074,23 +1295,32 @@ rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
struct rum_tx_data *data;
struct ieee80211_frame *wh;
const struct ieee80211_txparam *tp;
- struct ieee80211_key *k;
+ struct ieee80211_key *k = NULL;
uint32_t flags = 0;
uint16_t dur;
+ uint8_t ac, type, xflags = 0;
+ int hdrlen;
- RUM_LOCK_ASSERT(sc, MA_OWNED);
+ RUM_LOCK_ASSERT(sc);
data = STAILQ_FIRST(&sc->tx_free);
STAILQ_REMOVE_HEAD(&sc->tx_free, next);
sc->tx_nfree--;
wh = mtod(m0, struct ieee80211_frame *);
+ type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+ hdrlen = ieee80211_anyhdrsize(wh);
+ ac = M_WME_GETAC(m0);
+
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
- k = ieee80211_crypto_encap(ni, m0);
- if (k == NULL) {
- m_freem(m0);
- return ENOBUFS;
- }
+ k = ieee80211_crypto_get_txkey(ni, m0);
+ if (k == NULL)
+ return (ENOENT);
+
+ if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
+ !k->wk_cipher->ic_encap(k, m0))
+ return (ENOBUFS);
+
wh = mtod(m0, struct ieee80211_frame *);
}
@@ -1104,17 +1334,24 @@ rum_tx_mgt(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
USETW(wh->i_dur, dur);
/* tell hardware to add timestamp for probe responses */
- if ((wh->i_fc[0] &
- (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==
- (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_RESP))
+ if (type == IEEE80211_FC0_TYPE_MGT &&
+ (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
+ IEEE80211_FC0_SUBTYPE_PROBE_RESP)
flags |= RT2573_TX_TIMESTAMP;
}
+ if (type != IEEE80211_FC0_TYPE_CTL && !IEEE80211_QOS_HAS_SEQ(wh))
+ xflags |= RT2573_TX_HWSEQ;
+
+ if (k != NULL)
+ flags |= rum_tx_crypto_flags(sc, ni, k);
+
data->m = m0;
data->ni = ni;
data->rate = tp->mgmtrate;
- rum_setup_tx_desc(sc, &data->desc, flags, 0, m0->m_pkthdr.len, tp->mgmtrate);
+ rum_setup_tx_desc(sc, &data->desc, k, flags, xflags, ac, hdrlen,
+ m0->m_pkthdr.len, tp->mgmtrate);
DPRINTFN(10, "sending mgt frame len=%d rate=%d\n",
m0->m_pkthdr.len + (int)RT2573_TX_DESC_SIZE, tp->mgmtrate);
@@ -1130,18 +1367,23 @@ rum_tx_raw(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
const struct ieee80211_bpf_params *params)
{
struct ieee80211com *ic = ni->ni_ic;
+ struct ieee80211_frame *wh;
struct rum_tx_data *data;
uint32_t flags;
+ uint8_t ac, type, xflags = 0;
int rate, error;
- RUM_LOCK_ASSERT(sc, MA_OWNED);
- KASSERT(params != NULL, ("no raw xmit params"));
+ RUM_LOCK_ASSERT(sc);
+
+ wh = mtod(m0, struct ieee80211_frame *);
+ type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+
+ ac = params->ibp_pri & 3;
rate = params->ibp_rate0;
- if (!ieee80211_isratevalid(ic->ic_rt, rate)) {
- m_freem(m0);
- return EINVAL;
- }
+ if (!ieee80211_isratevalid(ic->ic_rt, rate))
+ return (EINVAL);
+
flags = 0;
if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0)
flags |= RT2573_TX_NEED_ACK;
@@ -1150,13 +1392,15 @@ rum_tx_raw(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
params->ibp_flags & IEEE80211_BPF_RTS ?
IEEE80211_PROT_RTSCTS : IEEE80211_PROT_CTSONLY,
rate);
- if (error || sc->tx_nfree == 0) {
- m_freem(m0);
- return ENOBUFS;
- }
+ if (error || sc->tx_nfree == 0)
+ return (ENOBUFS);
+
flags |= RT2573_TX_LONG_RETRY | RT2573_TX_IFS_SIFS;
}
+ if (type != IEEE80211_FC0_TYPE_CTL && !IEEE80211_QOS_HAS_SEQ(wh))
+ xflags |= RT2573_TX_HWSEQ;
+
data = STAILQ_FIRST(&sc->tx_free);
STAILQ_REMOVE_HEAD(&sc->tx_free, next);
sc->tx_nfree--;
@@ -1166,7 +1410,8 @@ rum_tx_raw(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
data->rate = rate;
/* XXX need to setup descriptor ourself */
- rum_setup_tx_desc(sc, &data->desc, flags, 0, m0->m_pkthdr.len, rate);
+ rum_setup_tx_desc(sc, &data->desc, NULL, flags, xflags, ac, 0,
+ m0->m_pkthdr.len, rate);
DPRINTFN(10, "sending raw frame len=%u rate=%u\n",
m0->m_pkthdr.len, rate);
@@ -1185,14 +1430,23 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
struct rum_tx_data *data;
struct ieee80211_frame *wh;
const struct ieee80211_txparam *tp;
- struct ieee80211_key *k;
+ struct ieee80211_key *k = NULL;
uint32_t flags = 0;
uint16_t dur;
- int error, rate;
+ uint8_t ac, type, qos, xflags = 0;
+ int error, hdrlen, rate;
- RUM_LOCK_ASSERT(sc, MA_OWNED);
+ RUM_LOCK_ASSERT(sc);
wh = mtod(m0, struct ieee80211_frame *);
+ type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+ hdrlen = ieee80211_anyhdrsize(wh);
+
+ if (IEEE80211_QOS_HAS_SEQ(wh))
+ qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0];
+ else
+ qos = 0;
+ ac = M_WME_GETAC(m0);
tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)];
if (IEEE80211_IS_MULTICAST(wh->i_addr1))
@@ -1203,16 +1457,24 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
rate = ni->ni_txrate;
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
- k = ieee80211_crypto_encap(ni, m0);
+ k = ieee80211_crypto_get_txkey(ni, m0);
if (k == NULL) {
m_freem(m0);
- return ENOBUFS;
+ return (ENOENT);
+ }
+ if ((k->wk_flags & IEEE80211_KEY_SWCRYPT) &&
+ !k->wk_cipher->ic_encap(k, m0)) {
+ m_freem(m0);
+ return (ENOBUFS);
}
/* packet header may have moved, reset our local pointer */
wh = mtod(m0, struct ieee80211_frame *);
}
+ if (type != IEEE80211_FC0_TYPE_CTL && !IEEE80211_QOS_HAS_SEQ(wh))
+ xflags |= RT2573_TX_HWSEQ;
+
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
int prot = IEEE80211_PROT_NONE;
if (m0->m_pkthdr.len + IEEE80211_CRC_LEN > vap->iv_rtsthreshold)
@@ -1230,6 +1492,9 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
}
}
+ if (k != NULL)
+ flags |= rum_tx_crypto_flags(sc, ni, k);
+
data = STAILQ_FIRST(&sc->tx_free);
STAILQ_REMOVE_HEAD(&sc->tx_free, next);
sc->tx_nfree--;
@@ -1239,15 +1504,18 @@ rum_tx_data(struct rum_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
data->rate = rate;
if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
- flags |= RT2573_TX_NEED_ACK;
- flags |= RT2573_TX_MORE_FRAG;
+ /* Unicast frame, check if an ACK is expected. */
+ if (!qos || (qos & IEEE80211_QOS_ACKPOLICY) !=
+ IEEE80211_QOS_ACKPOLICY_NOACK)
+ flags |= RT2573_TX_NEED_ACK;
- dur = ieee80211_ack_duration(ic->ic_rt, rate,
+ dur = ieee80211_ack_duration(ic->ic_rt, rate,
ic->ic_flags & IEEE80211_F_SHPREAMBLE);
USETW(wh->i_dur, dur);
}
- rum_setup_tx_desc(sc, &data->desc, flags, 0, m0->m_pkthdr.len, rate);
+ rum_setup_tx_desc(sc, &data->desc, k, flags, xflags, ac, hdrlen,
+ m0->m_pkthdr.len, rate);
DPRINTFN(10, "sending frame len=%d rate=%d\n",
m0->m_pkthdr.len + (int)RT2573_TX_DESC_SIZE, rate);
@@ -1286,7 +1554,7 @@ rum_start(struct rum_softc *sc)
struct ieee80211_node *ni;
struct mbuf *m;
- RUM_LOCK_ASSERT(sc, MA_OWNED);
+ RUM_LOCK_ASSERT(sc);
if (!sc->sc_running)
return;
@@ -1307,24 +1575,22 @@ static void
rum_parent(struct ieee80211com *ic)
{
struct rum_softc *sc = ic->ic_softc;
- int startall = 0;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
RUM_LOCK(sc);
if (sc->sc_detached) {
RUM_UNLOCK(sc);
return;
}
+ RUM_UNLOCK(sc);
+
if (ic->ic_nrunning > 0) {
- if (!sc->sc_running) {
- rum_init(sc);
- startall = 1;
- } else
- rum_setpromisc(sc);
- } else if (sc->sc_running)
+ if (rum_init(sc) == 0)
+ ieee80211_start_all(ic);
+ else
+ ieee80211_stop(vap);
+ } else
rum_stop(sc);
- RUM_UNLOCK(sc);
- if (startall)
- ieee80211_start_all(ic);
}
static void
@@ -1412,13 +1678,28 @@ rum_write_multi(struct rum_softc *sc, uint16_t reg, void *buf, size_t len)
return (USB_ERR_NORMAL_COMPLETION);
}
-static void
-rum_bbp_write(struct rum_softc *sc, uint8_t reg, uint8_t val)
+static usb_error_t
+rum_setbits(struct rum_softc *sc, uint16_t reg, uint32_t mask)
{
- uint32_t tmp;
- int ntries;
+ return (rum_write(sc, reg, rum_read(sc, reg) | mask));
+}
- DPRINTFN(2, "reg=0x%08x\n", reg);
+static usb_error_t
+rum_clrbits(struct rum_softc *sc, uint16_t reg, uint32_t mask)
+{
+ return (rum_write(sc, reg, rum_read(sc, reg) & ~mask));
+}
+
+static usb_error_t
+rum_modbits(struct rum_softc *sc, uint16_t reg, uint32_t set, uint32_t unset)
+{
+ return (rum_write(sc, reg, (rum_read(sc, reg) & ~unset) | set));
+}
+
+static int
+rum_bbp_busy(struct rum_softc *sc)
+{
+ int ntries;
for (ntries = 0; ntries < 100; ntries++) {
if (!(rum_read(sc, RT2573_PHY_CSR3) & RT2573_BBP_BUSY))
@@ -1426,7 +1707,20 @@ rum_bbp_write(struct rum_softc *sc, uint8_t reg, uint8_t val)
if (rum_pause(sc, hz / 100))
break;
}
- if (ntries == 100) {
+ if (ntries == 100)
+ return (ETIMEDOUT);
+
+ return (0);
+}
+
+static void
+rum_bbp_write(struct rum_softc *sc, uint8_t reg, uint8_t val)
+{
+ uint32_t tmp;
+
+ DPRINTFN(2, "reg=0x%08x\n", reg);
+
+ if (rum_bbp_busy(sc) != 0) {
device_printf(sc->sc_dev, "could not write to BBP\n");
return;
}
@@ -1443,13 +1737,7 @@ rum_bbp_read(struct rum_softc *sc, uint8_t reg)
DPRINTFN(2, "reg=0x%08x\n", reg);
- for (ntries = 0; ntries < 100; ntries++) {
- if (!(rum_read(sc, RT2573_PHY_CSR3) & RT2573_BBP_BUSY))
- break;
- if (rum_pause(sc, hz / 100))
- break;
- }
- if (ntries == 100) {
+ if (rum_bbp_busy(sc) != 0) {
device_printf(sc->sc_dev, "could not read BBP\n");
return 0;
}
@@ -1525,31 +1813,25 @@ static void
rum_enable_mrr(struct rum_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
- uint32_t tmp;
- tmp = rum_read(sc, RT2573_TXRX_CSR4);
-
- tmp &= ~RT2573_MRR_CCK_FALLBACK;
- if (!IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan))
- tmp |= RT2573_MRR_CCK_FALLBACK;
- tmp |= RT2573_MRR_ENABLED;
-
- rum_write(sc, RT2573_TXRX_CSR4, tmp);
+ if (!IEEE80211_IS_CHAN_5GHZ(ic->ic_bsschan)) {
+ rum_setbits(sc, RT2573_TXRX_CSR4,
+ RT2573_MRR_ENABLED | RT2573_MRR_CCK_FALLBACK);
+ } else {
+ rum_modbits(sc, RT2573_TXRX_CSR4,
+ RT2573_MRR_ENABLED, RT2573_MRR_CCK_FALLBACK);
+ }
}
static void
rum_set_txpreamble(struct rum_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
- uint32_t tmp;
-
- tmp = rum_read(sc, RT2573_TXRX_CSR4);
- tmp &= ~RT2573_SHORT_PREAMBLE;
if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
- tmp |= RT2573_SHORT_PREAMBLE;
-
- rum_write(sc, RT2573_TXRX_CSR4, tmp);
+ rum_setbits(sc, RT2573_TXRX_CSR4, RT2573_SHORT_PREAMBLE);
+ else
+ rum_clrbits(sc, RT2573_TXRX_CSR4, RT2573_SHORT_PREAMBLE);
}
static void
@@ -1578,7 +1860,6 @@ static void
rum_select_band(struct rum_softc *sc, struct ieee80211_channel *c)
{
uint8_t bbp17, bbp35, bbp96, bbp97, bbp98, bbp104;
- uint32_t tmp;
/* update all BBP registers that depend on the band */
bbp17 = 0x20; bbp96 = 0x48; bbp104 = 0x2c;
@@ -1608,13 +1889,13 @@ rum_select_band(struct rum_softc *sc, struct ieee80211_channel *c)
rum_bbp_write(sc, 97, bbp97);
rum_bbp_write(sc, 98, bbp98);
- tmp = rum_read(sc, RT2573_PHY_CSR0);
- tmp &= ~(RT2573_PA_PE_2GHZ | RT2573_PA_PE_5GHZ);
- if (IEEE80211_IS_CHAN_2GHZ(c))
- tmp |= RT2573_PA_PE_2GHZ;
- else
- tmp |= RT2573_PA_PE_5GHZ;
- rum_write(sc, RT2573_PHY_CSR0, tmp);
+ if (IEEE80211_IS_CHAN_2GHZ(c)) {
+ rum_modbits(sc, RT2573_PHY_CSR0, RT2573_PA_PE_2GHZ,
+ RT2573_PA_PE_5GHZ);
+ } else {
+ rum_modbits(sc, RT2573_PHY_CSR0, RT2573_PA_PE_5GHZ,
+ RT2573_PA_PE_2GHZ);
+ }
}
static void
@@ -1689,11 +1970,26 @@ rum_set_chan(struct rum_softc *sc, struct ieee80211_channel *c)
rum_pause(sc, hz / 100);
}
+static void
+rum_set_maxretry(struct rum_softc *sc, struct ieee80211vap *vap)
+{
+ const struct ieee80211_txparam *tp;
+ struct ieee80211_node *ni = vap->iv_bss;
+ struct rum_vap *rvp = RUM_VAP(vap);
+
+ tp = &vap->iv_txparms[ieee80211_chan2mode(ni->ni_chan)];
+ rvp->maxretry = tp->maxretry < 0xf ? tp->maxretry : 0xf;
+
+ rum_modbits(sc, RT2573_TXRX_CSR4, RT2573_SHORT_RETRY(rvp->maxretry) |
+ RT2573_LONG_RETRY(rvp->maxretry),
+ RT2573_SHORT_RETRY_MASK | RT2573_LONG_RETRY_MASK);
+}
+
/*
* Enable TSF synchronization and tell h/w to start sending beacons for IBSS
* and HostAP operating modes.
*/
-static void
+static int
rum_enable_tsf_sync(struct rum_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
@@ -1705,85 +2001,178 @@ rum_enable_tsf_sync(struct rum_softc *sc)
* Change default 16ms TBTT adjustment to 8ms.
* Must be done before enabling beacon generation.
*/
- rum_write(sc, RT2573_TXRX_CSR10, 1 << 12 | 8);
+ if (rum_write(sc, RT2573_TXRX_CSR10, 1 << 12 | 8) != 0)
+ return EIO;
}
tmp = rum_read(sc, RT2573_TXRX_CSR9) & 0xff000000;
/* set beacon interval (in 1/16ms unit) */
tmp |= vap->iv_bss->ni_intval * 16;
+ tmp |= RT2573_TSF_TIMER_EN | RT2573_TBTT_TIMER_EN;
- tmp |= RT2573_TSF_TICKING | RT2573_ENABLE_TBTT;
- if (vap->iv_opmode == IEEE80211_M_STA)
- tmp |= RT2573_TSF_MODE(1);
- else
- tmp |= RT2573_TSF_MODE(2) | RT2573_GENERATE_BEACON;
+ switch (vap->iv_opmode) {
+ case IEEE80211_M_STA:
+ /*
+ * Local TSF is always updated with remote TSF on beacon
+ * reception.
+ */
+ tmp |= RT2573_TSF_SYNC_MODE(RT2573_TSF_SYNC_MODE_STA);
+ break;
+ case IEEE80211_M_IBSS:
+ /*
+ * Local TSF is updated with remote TSF on beacon reception
+ * only if the remote TSF is greater than local TSF.
+ */
+ tmp |= RT2573_TSF_SYNC_MODE(RT2573_TSF_SYNC_MODE_IBSS);
+ tmp |= RT2573_BCN_TX_EN;
+ break;
+ case IEEE80211_M_HOSTAP:
+ /* SYNC with nobody */
+ tmp |= RT2573_TSF_SYNC_MODE(RT2573_TSF_SYNC_MODE_HOSTAP);
+ tmp |= RT2573_BCN_TX_EN;
+ break;
+ default:
+ device_printf(sc->sc_dev,
+ "Enabling TSF failed. undefined opmode %d\n",
+ vap->iv_opmode);
+ return EINVAL;
+ }
+
+ if (rum_write(sc, RT2573_TXRX_CSR9, tmp) != 0)
+ return EIO;
- rum_write(sc, RT2573_TXRX_CSR9, tmp);
+ return 0;
}
static void
rum_enable_tsf(struct rum_softc *sc)
{
- rum_write(sc, RT2573_TXRX_CSR9,
- (rum_read(sc, RT2573_TXRX_CSR9) & 0xff000000) |
- RT2573_TSF_TICKING | RT2573_TSF_MODE(2));
+ rum_modbits(sc, RT2573_TXRX_CSR9, RT2573_TSF_TIMER_EN |
+ RT2573_TSF_SYNC_MODE(RT2573_TSF_SYNC_MODE_DIS), 0x00ffffff);
+}
+
+static void
+rum_abort_tsf_sync(struct rum_softc *sc)
+{
+ rum_clrbits(sc, RT2573_TXRX_CSR9, 0x00ffffff);
+}
+
+static void
+rum_get_tsf(struct rum_softc *sc, uint64_t *buf)
+{
+ rum_read_multi(sc, RT2573_TXRX_CSR12, buf, sizeof (*buf));
}
static void
-rum_update_slot(struct rum_softc *sc)
+rum_update_slot_cb(struct rum_softc *sc, union sec_param *data, uint8_t rvp_id)
{
struct ieee80211com *ic = &sc->sc_ic;
uint8_t slottime;
- uint32_t tmp;
slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20;
- tmp = rum_read(sc, RT2573_MAC_CSR9);
- tmp = (tmp & ~0xff) | slottime;
- rum_write(sc, RT2573_MAC_CSR9, tmp);
+ rum_modbits(sc, RT2573_MAC_CSR9, slottime, 0xff);
DPRINTF("setting slot time to %uus\n", slottime);
}
static void
-rum_set_bssid(struct rum_softc *sc, const uint8_t *bssid)
+rum_update_slot(struct ieee80211com *ic)
{
- uint32_t tmp;
+ rum_cmd_sleepable(ic->ic_softc, NULL, 0, 0, rum_update_slot_cb);
+}
- tmp = bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24;
- rum_write(sc, RT2573_MAC_CSR4, tmp);
+static void
+rum_wme_update_cb(struct rum_softc *sc, union sec_param *data, uint8_t rvp_id)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ const struct wmeParams *chanp =
+ ic->ic_wme.wme_chanParams.cap_wmeParams;
+ int error = 0;
+
+ error = rum_write(sc, RT2573_AIFSN_CSR,
+ chanp[WME_AC_VO].wmep_aifsn << 12 |
+ chanp[WME_AC_VI].wmep_aifsn << 8 |
+ chanp[WME_AC_BK].wmep_aifsn << 4 |
+ chanp[WME_AC_BE].wmep_aifsn);
+ if (error)
+ goto print_err;
+ error = rum_write(sc, RT2573_CWMIN_CSR,
+ chanp[WME_AC_VO].wmep_logcwmin << 12 |
+ chanp[WME_AC_VI].wmep_logcwmin << 8 |
+ chanp[WME_AC_BK].wmep_logcwmin << 4 |
+ chanp[WME_AC_BE].wmep_logcwmin);
+ if (error)
+ goto print_err;
+ error = rum_write(sc, RT2573_CWMAX_CSR,
+ chanp[WME_AC_VO].wmep_logcwmax << 12 |
+ chanp[WME_AC_VI].wmep_logcwmax << 8 |
+ chanp[WME_AC_BK].wmep_logcwmax << 4 |
+ chanp[WME_AC_BE].wmep_logcwmax);
+ if (error)
+ goto print_err;
+ error = rum_write(sc, RT2573_TXOP01_CSR,
+ chanp[WME_AC_BK].wmep_txopLimit << 16 |
+ chanp[WME_AC_BE].wmep_txopLimit);
+ if (error)
+ goto print_err;
+ error = rum_write(sc, RT2573_TXOP23_CSR,
+ chanp[WME_AC_VO].wmep_txopLimit << 16 |
+ chanp[WME_AC_VI].wmep_txopLimit);
+ if (error)
+ goto print_err;
+
+ memcpy(sc->wme_params, chanp, sizeof(*chanp) * WME_NUM_AC);
- tmp = bssid[4] | bssid[5] << 8 | RT2573_ONE_BSSID << 16;
- rum_write(sc, RT2573_MAC_CSR5, tmp);
+ return;
+
+print_err:
+ device_printf(sc->sc_dev, "%s: WME update failed, error %d\n",
+ __func__, error);
}
-static void
-rum_set_macaddr(struct rum_softc *sc, const uint8_t *addr)
+static int
+rum_wme_update(struct ieee80211com *ic)
{
- uint32_t tmp;
+ struct rum_softc *sc = ic->ic_softc;
- tmp = addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24;
- rum_write(sc, RT2573_MAC_CSR2, tmp);
+ rum_cmd_sleepable(sc, NULL, 0, 0, rum_wme_update_cb);
- tmp = addr[4] | addr[5] << 8 | 0xff << 16;
- rum_write(sc, RT2573_MAC_CSR3, tmp);
+ return (0);
}
static void
-rum_setpromisc(struct rum_softc *sc)
+rum_set_bssid(struct rum_softc *sc, const uint8_t *bssid)
{
- uint32_t tmp;
- tmp = rum_read(sc, RT2573_TXRX_CSR0);
+ rum_write(sc, RT2573_MAC_CSR4,
+ bssid[0] | bssid[1] << 8 | bssid[2] << 16 | bssid[3] << 24);
+ rum_write(sc, RT2573_MAC_CSR5,
+ bssid[4] | bssid[5] << 8 | RT2573_NUM_BSSID_MSK(1));
+}
- tmp &= ~RT2573_DROP_NOT_TO_ME;
- if (sc->sc_ic.ic_promisc == 0)
- tmp |= RT2573_DROP_NOT_TO_ME;
+static void
+rum_set_macaddr(struct rum_softc *sc, const uint8_t *addr)
+{
- rum_write(sc, RT2573_TXRX_CSR0, tmp);
+ rum_write(sc, RT2573_MAC_CSR2,
+ addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
+ rum_write(sc, RT2573_MAC_CSR3,
+ addr[4] | addr[5] << 8 | 0xff << 16);
+}
- DPRINTF("%s promiscuous mode\n", sc->sc_ic.ic_promisc > 0 ?
+static void
+rum_setpromisc(struct rum_softc *sc)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+
+ if (ic->ic_promisc == 0)
+ rum_setbits(sc, RT2573_TXRX_CSR0, RT2573_DROP_NOT_TO_ME);
+ else
+ rum_clrbits(sc, RT2573_TXRX_CSR0, RT2573_DROP_NOT_TO_ME);
+
+ DPRINTF("%s promiscuous mode\n", ic->ic_promisc > 0 ?
"entering" : "leaving");
}
@@ -1793,23 +2182,15 @@ rum_update_promisc(struct ieee80211com *ic)
struct rum_softc *sc = ic->ic_softc;
RUM_LOCK(sc);
- if (!sc->sc_running) {
- RUM_UNLOCK(sc);
- return;
- }
- rum_setpromisc(sc);
+ if (sc->sc_running)
+ rum_setpromisc(sc);
RUM_UNLOCK(sc);
}
static void
rum_update_mcast(struct ieee80211com *ic)
{
- static int warning_printed;
-
- if (warning_printed == 0) {
- ic_printf(ic, "need to implement %s\n", __func__);
- warning_printed = 1;
- }
+ /* Ignore. */
}
static const char *
@@ -1908,6 +2289,27 @@ rum_read_eeprom(struct rum_softc *sc)
}
static int
+rum_bbp_wakeup(struct rum_softc *sc)
+{
+ unsigned int ntries;
+
+ for (ntries = 0; ntries < 100; ntries++) {
+ if (rum_read(sc, RT2573_MAC_CSR12) & 8)
+ break;
+ rum_write(sc, RT2573_MAC_CSR12, 4); /* force wakeup */
+ if (rum_pause(sc, hz / 100))
+ break;
+ }
+ if (ntries == 100) {
+ device_printf(sc->sc_dev,
+ "timeout waiting for BBP/RF to wakeup\n");
+ return (ETIMEDOUT);
+ }
+
+ return (0);
+}
+
+static int
rum_bbp_init(struct rum_softc *sc)
{
int i, ntries;
@@ -1926,7 +2328,7 @@ rum_bbp_init(struct rum_softc *sc)
}
/* initialize BBP registers to default values */
- for (i = 0; i < N(rum_def_bbp); i++)
+ for (i = 0; i < nitems(rum_def_bbp); i++)
rum_bbp_write(sc, rum_def_bbp[i].reg, rum_def_bbp[i].val);
/* write vendor-specific BBP values (from EEPROM) */
@@ -1940,42 +2342,46 @@ rum_bbp_init(struct rum_softc *sc)
}
static void
+rum_clr_shkey_regs(struct rum_softc *sc)
+{
+ rum_write(sc, RT2573_SEC_CSR0, 0);
+ rum_write(sc, RT2573_SEC_CSR1, 0);
+ rum_write(sc, RT2573_SEC_CSR5, 0);
+}
+
+static int
rum_init(struct rum_softc *sc)
{
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
uint32_t tmp;
- usb_error_t error;
- int i, ntries;
-
- RUM_LOCK_ASSERT(sc, MA_OWNED);
+ int i, ret;
- rum_stop(sc);
+ RUM_LOCK(sc);
+ if (sc->sc_running) {
+ ret = 0;
+ goto end;
+ }
/* initialize MAC registers to default values */
- for (i = 0; i < N(rum_def_mac); i++)
+ for (i = 0; i < nitems(rum_def_mac); i++)
rum_write(sc, rum_def_mac[i].reg, rum_def_mac[i].val);
+ /* reset some WME parameters to default values */
+ sc->wme_params[0].wmep_aifsn = 2;
+ sc->wme_params[0].wmep_logcwmin = 4;
+ sc->wme_params[0].wmep_logcwmax = 10;
+
/* set host ready */
- rum_write(sc, RT2573_MAC_CSR1, 3);
+ rum_write(sc, RT2573_MAC_CSR1, RT2573_RESET_ASIC | RT2573_RESET_BBP);
rum_write(sc, RT2573_MAC_CSR1, 0);
/* wait for BBP/RF to wakeup */
- for (ntries = 0; ntries < 100; ntries++) {
- if (rum_read(sc, RT2573_MAC_CSR12) & 8)
- break;
- rum_write(sc, RT2573_MAC_CSR12, 4); /* force wakeup */
- if (rum_pause(sc, hz / 100))
- break;
- }
- if (ntries == 100) {
- device_printf(sc->sc_dev,
- "timeout waiting for BBP/RF to wakeup\n");
- goto fail;
- }
+ if ((ret = rum_bbp_wakeup(sc)) != 0)
+ goto end;
- if ((error = rum_bbp_init(sc)) != 0)
- goto fail;
+ if ((ret = rum_bbp_init(sc)) != 0)
+ goto end;
/* select default channel */
rum_select_band(sc, ic->ic_curchan);
@@ -1985,10 +2391,16 @@ rum_init(struct rum_softc *sc)
/* clear STA registers */
rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof sc->sta);
+ /* clear security registers (if required) */
+ if (sc->sc_clr_shkeys == 0) {
+ rum_clr_shkey_regs(sc);
+ sc->sc_clr_shkeys = 1;
+ }
+
rum_set_macaddr(sc, vap ? vap->iv_myaddr : ic->ic_macaddr);
/* initialize ASIC */
- rum_write(sc, RT2573_MAC_CSR1, 4);
+ rum_write(sc, RT2573_MAC_CSR1, RT2573_HOST_READY);
/*
* Allocate Tx and Rx xfer queues.
@@ -2012,21 +2424,25 @@ rum_init(struct rum_softc *sc)
sc->sc_running = 1;
usbd_xfer_set_stall(sc->sc_xfer[RUM_BULK_WR]);
usbd_transfer_start(sc->sc_xfer[RUM_BULK_RD]);
- return;
-fail: rum_stop(sc);
-#undef N
+end: RUM_UNLOCK(sc);
+
+ if (ret != 0)
+ rum_stop(sc);
+
+ return ret;
}
static void
rum_stop(struct rum_softc *sc)
{
- uint32_t tmp;
-
- RUM_LOCK_ASSERT(sc, MA_OWNED);
+ RUM_LOCK(sc);
+ if (!sc->sc_running) {
+ RUM_UNLOCK(sc);
+ return;
+ }
sc->sc_running = 0;
-
RUM_UNLOCK(sc);
/*
@@ -2036,16 +2452,15 @@ rum_stop(struct rum_softc *sc)
usbd_transfer_drain(sc->sc_xfer[RUM_BULK_RD]);
RUM_LOCK(sc);
-
rum_unsetup_tx_list(sc);
/* disable Rx */
- tmp = rum_read(sc, RT2573_TXRX_CSR0);
- rum_write(sc, RT2573_TXRX_CSR0, tmp | RT2573_DISABLE_RX);
+ rum_setbits(sc, RT2573_TXRX_CSR0, RT2573_DISABLE_RX);
/* reset ASIC */
- rum_write(sc, RT2573_MAC_CSR1, 3);
+ rum_write(sc, RT2573_MAC_CSR1, RT2573_RESET_ASIC | RT2573_RESET_BBP);
rum_write(sc, RT2573_MAC_CSR1, 0);
+ RUM_UNLOCK(sc);
}
static void
@@ -2082,35 +2497,318 @@ rum_load_microcode(struct rum_softc *sc, const uint8_t *ucode, size_t size)
rum_pause(sc, hz / 8);
}
-static void
-rum_prepare_beacon(struct rum_softc *sc, struct ieee80211vap *vap)
+static int
+rum_set_beacon(struct rum_softc *sc, struct ieee80211vap *vap)
{
struct ieee80211com *ic = vap->iv_ic;
+ struct rum_vap *rvp = RUM_VAP(vap);
+ struct mbuf *m = rvp->bcn_mbuf;
const struct ieee80211_txparam *tp;
struct rum_tx_desc desc;
- struct mbuf *m0;
- if (vap->iv_bss->ni_chan == IEEE80211_CHAN_ANYC)
- return;
- if (ic->ic_bsschan == IEEE80211_CHAN_ANYC)
- return;
+ RUM_LOCK_ASSERT(sc);
- m0 = ieee80211_beacon_alloc(vap->iv_bss, &RUM_VAP(vap)->bo);
- if (m0 == NULL)
- return;
+ if (m == NULL)
+ return EINVAL;
+ if (ic->ic_bsschan == IEEE80211_CHAN_ANYC)
+ return EINVAL;
tp = &vap->iv_txparms[ieee80211_chan2mode(ic->ic_bsschan)];
- rum_setup_tx_desc(sc, &desc, RT2573_TX_TIMESTAMP, RT2573_TX_HWSEQ,
- m0->m_pkthdr.len, tp->mgmtrate);
+ rum_setup_tx_desc(sc, &desc, NULL, RT2573_TX_TIMESTAMP,
+ RT2573_TX_HWSEQ, 0, 0, m->m_pkthdr.len, tp->mgmtrate);
- /* copy the first 24 bytes of Tx descriptor into NIC memory */
- rum_write_multi(sc, RT2573_HW_BEACON_BASE0, (uint8_t *)&desc, 24);
+ /* copy the Tx descriptor into NIC memory */
+ if (rum_write_multi(sc, RT2573_HW_BCN_BASE(0), (uint8_t *)&desc,
+ RT2573_TX_DESC_SIZE) != 0)
+ return EIO;
/* copy beacon header and payload into NIC memory */
- rum_write_multi(sc, RT2573_HW_BEACON_BASE0 + 24, mtod(m0, uint8_t *),
- m0->m_pkthdr.len);
+ if (rum_write_multi(sc, RT2573_HW_BCN_BASE(0) + RT2573_TX_DESC_SIZE,
+ mtod(m, uint8_t *), m->m_pkthdr.len) != 0)
+ return EIO;
- m_freem(m0);
+ return 0;
+}
+
+static int
+rum_alloc_beacon(struct rum_softc *sc, struct ieee80211vap *vap)
+{
+ struct rum_vap *rvp = RUM_VAP(vap);
+ struct ieee80211_node *ni = vap->iv_bss;
+ struct mbuf *m;
+
+ if (ni->ni_chan == IEEE80211_CHAN_ANYC)
+ return EINVAL;
+
+ m = ieee80211_beacon_alloc(ni);
+ if (m == NULL)
+ return ENOMEM;
+
+ if (rvp->bcn_mbuf != NULL)
+ m_freem(rvp->bcn_mbuf);
+
+ rvp->bcn_mbuf = m;
+
+ return (rum_set_beacon(sc, vap));
+}
+
+static void
+rum_update_beacon_cb(struct rum_softc *sc, union sec_param *data,
+ uint8_t rvp_id)
+{
+ struct ieee80211vap *vap = data->vap;
+
+ rum_set_beacon(sc, vap);
+}
+
+static void
+rum_update_beacon(struct ieee80211vap *vap, int item)
+{
+ struct ieee80211com *ic = vap->iv_ic;
+ struct rum_softc *sc = ic->ic_softc;
+ struct rum_vap *rvp = RUM_VAP(vap);
+ struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off;
+ struct ieee80211_node *ni = vap->iv_bss;
+ struct mbuf *m = rvp->bcn_mbuf;
+ int mcast = 0;
+
+ RUM_LOCK(sc);
+ if (m == NULL) {
+ m = ieee80211_beacon_alloc(ni);
+ if (m == NULL) {
+ device_printf(sc->sc_dev,
+ "%s: could not allocate beacon frame\n", __func__);
+ RUM_UNLOCK(sc);
+ return;
+ }
+ rvp->bcn_mbuf = m;
+ }
+
+ switch (item) {
+ case IEEE80211_BEACON_ERP:
+ rum_update_slot(ic);
+ break;
+ case IEEE80211_BEACON_TIM:
+ mcast = 1; /*TODO*/
+ break;
+ default:
+ break;
+ }
+ RUM_UNLOCK(sc);
+
+ setbit(bo->bo_flags, item);
+ ieee80211_beacon_update(ni, m, mcast);
+
+ rum_cmd_sleepable(sc, &vap, sizeof(vap), 0, rum_update_beacon_cb);
+}
+
+static int
+rum_common_key_set(struct rum_softc *sc, struct ieee80211_key *k,
+ uint16_t base)
+{
+
+ if (rum_write_multi(sc, base, k->wk_key, k->wk_keylen))
+ return EIO;
+
+ if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) {
+ if (rum_write_multi(sc, base + IEEE80211_KEYBUF_SIZE,
+ k->wk_txmic, 8))
+ return EIO;
+ if (rum_write_multi(sc, base + IEEE80211_KEYBUF_SIZE + 8,
+ k->wk_rxmic, 8))
+ return EIO;
+ }
+
+ return 0;
+}
+
+static void
+rum_group_key_set_cb(struct rum_softc *sc, union sec_param *data,
+ uint8_t rvp_id)
+{
+ struct ieee80211_key *k = &data->key;
+ uint8_t mode;
+
+ if (sc->sc_clr_shkeys == 0) {
+ rum_clr_shkey_regs(sc);
+ sc->sc_clr_shkeys = 1;
+ }
+
+ mode = rum_crypto_mode(sc, k->wk_cipher->ic_cipher, k->wk_keylen);
+ if (mode == 0)
+ goto print_err;
+
+ DPRINTFN(1, "setting group key %d for vap %d, mode %d "
+ "(tx %s, rx %s)\n", k->wk_keyix, rvp_id, mode,
+ (k->wk_flags & IEEE80211_KEY_XMIT) ? "on" : "off",
+ (k->wk_flags & IEEE80211_KEY_RECV) ? "on" : "off");
+
+ /* Install the key. */
+ if (rum_common_key_set(sc, k, RT2573_SKEY(rvp_id, k->wk_keyix)) != 0)
+ goto print_err;
+
+ /* Set cipher mode. */
+ if (rum_modbits(sc, rvp_id < 2 ? RT2573_SEC_CSR1 : RT2573_SEC_CSR5,
+ mode << (rvp_id % 2 + k->wk_keyix) * RT2573_SKEY_MAX,
+ RT2573_MODE_MASK << (rvp_id % 2 + k->wk_keyix) * RT2573_SKEY_MAX)
+ != 0)
+ goto print_err;
+
+ /* Mark this key as valid. */
+ if (rum_setbits(sc, RT2573_SEC_CSR0,
+ 1 << (rvp_id * RT2573_SKEY_MAX + k->wk_keyix)) != 0)
+ goto print_err;
+
+ return;
+
+print_err:
+ device_printf(sc->sc_dev, "%s: cannot set group key %d for vap %d\n",
+ __func__, k->wk_keyix, rvp_id);
+}
+
+static void
+rum_group_key_del_cb(struct rum_softc *sc, union sec_param *data,
+ uint8_t rvp_id)
+{
+ struct ieee80211_key *k = &data->key;
+
+ DPRINTF("%s: removing group key %d for vap %d\n", __func__,
+ k->wk_keyix, rvp_id);
+ rum_clrbits(sc,
+ rvp_id < 2 ? RT2573_SEC_CSR1 : RT2573_SEC_CSR5,
+ RT2573_MODE_MASK << (rvp_id % 2 + k->wk_keyix) * RT2573_SKEY_MAX);
+ rum_clrbits(sc, RT2573_SEC_CSR0,
+ rvp_id * RT2573_SKEY_MAX + k->wk_keyix);
+}
+
+static void
+rum_pair_key_set_cb(struct rum_softc *sc, union sec_param *data,
+ uint8_t rvp_id)
+{
+ struct ieee80211_key *k = &data->key;
+ uint8_t buf[IEEE80211_ADDR_LEN + 1];
+ uint8_t mode;
+
+ mode = rum_crypto_mode(sc, k->wk_cipher->ic_cipher, k->wk_keylen);
+ if (mode == 0)
+ goto print_err;
+
+ DPRINTFN(1, "setting pairwise key %d for vap %d, mode %d "
+ "(tx %s, rx %s)\n", k->wk_keyix, rvp_id, mode,
+ (k->wk_flags & IEEE80211_KEY_XMIT) ? "on" : "off",
+ (k->wk_flags & IEEE80211_KEY_RECV) ? "on" : "off");
+
+ /* Install the key. */
+ if (rum_common_key_set(sc, k, RT2573_PKEY(k->wk_keyix)) != 0)
+ goto print_err;
+
+ IEEE80211_ADDR_COPY(buf, k->wk_macaddr);
+ buf[IEEE80211_ADDR_LEN] = mode;
+
+ /* Set transmitter address and cipher mode. */
+ if (rum_write_multi(sc, RT2573_ADDR_ENTRY(k->wk_keyix),
+ buf, sizeof buf) != 0)
+ goto print_err;
+
+ /* Enable key table lookup for this vap. */
+ if (sc->vap_key_count[rvp_id]++ == 0)
+ if (rum_setbits(sc, RT2573_SEC_CSR4, 1 << rvp_id) != 0)
+ goto print_err;
+
+ /* Mark this key as valid. */
+ if (rum_setbits(sc,
+ k->wk_keyix < 32 ? RT2573_SEC_CSR2 : RT2573_SEC_CSR3,
+ 1 << (k->wk_keyix % 32)) != 0)
+ goto print_err;
+
+ return;
+
+print_err:
+ device_printf(sc->sc_dev,
+ "%s: cannot set pairwise key %d, vap %d\n", __func__, k->wk_keyix,
+ rvp_id);
+}
+
+static void
+rum_pair_key_del_cb(struct rum_softc *sc, union sec_param *data,
+ uint8_t rvp_id)
+{
+ struct ieee80211_key *k = &data->key;
+
+ DPRINTF("%s: removing key %d\n", __func__, k->wk_keyix);
+ rum_clrbits(sc, (k->wk_keyix < 32) ? RT2573_SEC_CSR2 : RT2573_SEC_CSR3,
+ 1 << (k->wk_keyix % 32));
+ sc->keys_bmap &= ~(1 << k->wk_keyix);
+ if (--sc->vap_key_count[rvp_id] == 0)
+ rum_clrbits(sc, RT2573_SEC_CSR4, 1 << rvp_id);
+}
+
+static int
+rum_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
+ ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix)
+{
+ struct rum_softc *sc = vap->iv_ic->ic_softc;
+ uint8_t i;
+
+ if (!(&vap->iv_nw_keys[0] <= k &&
+ k < &vap->iv_nw_keys[IEEE80211_WEP_NKID])) {
+ if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT)) {
+ RUM_LOCK(sc);
+ for (i = 0; i < RT2573_ADDR_MAX; i++) {
+ if ((sc->keys_bmap & (1 << i)) == 0) {
+ sc->keys_bmap |= 1 << i;
+ *keyix = i;
+ break;
+ }
+ }
+ RUM_UNLOCK(sc);
+ if (i == RT2573_ADDR_MAX) {
+ device_printf(sc->sc_dev,
+ "%s: no free space in the key table\n",
+ __func__);
+ return 0;
+ }
+ } else
+ *keyix = 0;
+ } else {
+ *keyix = k - vap->iv_nw_keys;
+ }
+ *rxkeyix = *keyix;
+ return 1;
+}
+
+static int
+rum_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
+{
+ struct rum_softc *sc = vap->iv_ic->ic_softc;
+ int group;
+
+ if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
+ /* Not for us. */
+ return 1;
+ }
+
+ group = k >= &vap->iv_nw_keys[0] && k < &vap->iv_nw_keys[IEEE80211_WEP_NKID];
+
+ return !rum_cmd_sleepable(sc, k, sizeof(*k), 0,
+ group ? rum_group_key_set_cb : rum_pair_key_set_cb);
+}
+
+static int
+rum_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
+{
+ struct rum_softc *sc = vap->iv_ic->ic_softc;
+ int group;
+
+ if (k->wk_flags & IEEE80211_KEY_SWCRYPT) {
+ /* Not for us. */
+ return 1;
+ }
+
+ group = k >= &vap->iv_nw_keys[0] && k < &vap->iv_nw_keys[IEEE80211_WEP_NKID];
+
+ return !rum_cmd_sleepable(sc, k, sizeof(*k), 0,
+ group ? rum_group_key_del_cb : rum_pair_key_del_cb);
}
static int
@@ -2118,20 +2816,17 @@ rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
const struct ieee80211_bpf_params *params)
{
struct rum_softc *sc = ni->ni_ic->ic_softc;
+ int ret;
RUM_LOCK(sc);
/* prevent management frames from being sent if we're not ready */
if (!sc->sc_running) {
- RUM_UNLOCK(sc);
- m_freem(m);
- ieee80211_free_node(ni);
- return ENETDOWN;
+ ret = ENETDOWN;
+ goto bad;
}
if (sc->tx_nfree < RUM_TX_MINFREE) {
- RUM_UNLOCK(sc);
- m_freem(m);
- ieee80211_free_node(ni);
- return EIO;
+ ret = EIO;
+ goto bad;
}
if (params == NULL) {
@@ -2139,14 +2834,14 @@ rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
* Legacy path; interpret frame contents to decide
* precisely how to send the frame.
*/
- if (rum_tx_mgt(sc, m, ni) != 0)
+ if ((ret = rum_tx_mgt(sc, m, ni)) != 0)
goto bad;
} else {
/*
* Caller supplied explicit parameters to use in
* sending the frame.
*/
- if (rum_tx_raw(sc, m, ni, params) != 0)
+ if ((ret = rum_tx_raw(sc, m, ni, params)) != 0)
goto bad;
}
RUM_UNLOCK(sc);
@@ -2154,8 +2849,9 @@ rum_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
return 0;
bad:
RUM_UNLOCK(sc);
+ m_freem(m);
ieee80211_free_node(ni);
- return EIO;
+ return ret;
}
static void
@@ -2185,29 +2881,34 @@ rum_ratectl_task(void *arg, int pending)
{
struct rum_vap *rvp = arg;
struct ieee80211vap *vap = &rvp->vap;
- struct ieee80211com *ic = vap->iv_ic;
- struct rum_softc *sc = ic->ic_softc;
+ struct rum_softc *sc = vap->iv_ic->ic_softc;
struct ieee80211_node *ni;
- int ok, fail;
- int sum, retrycnt;
+ int ok[3], fail;
+ int sum, success, retrycnt;
RUM_LOCK(sc);
- /* read and clear statistic registers (STA_CSR0 to STA_CSR10) */
+ /* read and clear statistic registers (STA_CSR0 to STA_CSR5) */
rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof(sc->sta));
- ok = (le32toh(sc->sta[4]) >> 16) + /* TX ok w/o retry */
- (le32toh(sc->sta[5]) & 0xffff); /* TX ok w/ retry */
- fail = (le32toh(sc->sta[5]) >> 16); /* TX retry-fail count */
- sum = ok+fail;
- retrycnt = (le32toh(sc->sta[5]) & 0xffff) + fail;
+ ok[0] = (le32toh(sc->sta[4]) & 0xffff); /* TX ok w/o retry */
+ ok[1] = (le32toh(sc->sta[4]) >> 16); /* TX ok w/ one retry */
+ ok[2] = (le32toh(sc->sta[5]) & 0xffff); /* TX ok w/ multiple retries */
+ fail = (le32toh(sc->sta[5]) >> 16); /* TX retry-fail count */
- ni = ieee80211_ref_node(vap->iv_bss);
- ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt);
- (void) ieee80211_ratectl_rate(ni, NULL, 0);
- ieee80211_free_node(ni);
+ success = ok[0] + ok[1] + ok[2];
+ sum = success + fail;
+ /* XXX at least */
+ retrycnt = ok[1] + ok[2] * 2 + fail * (rvp->maxretry + 1);
+
+ if (sum != 0) {
+ ni = ieee80211_ref_node(vap->iv_bss);
+ ieee80211_ratectl_tx_update(vap, ni, &sum, &ok, &retrycnt);
+ (void) ieee80211_ratectl_rate(ni, NULL, 0);
+ ieee80211_free_node(ni);
+ }
/* count TX retry-fail as Tx errors */
- if_inc_counter(ni->ni_vap->iv_ifp, IFCOUNTER_OERRORS, fail);
+ if_inc_counter(vap->iv_ifp, IFCOUNTER_OERRORS, fail);
usb_callout_reset(&rvp->ratectl_ch, hz, rum_ratectl_timeout, rvp);
RUM_UNLOCK(sc);
@@ -2217,12 +2918,9 @@ static void
rum_scan_start(struct ieee80211com *ic)
{
struct rum_softc *sc = ic->ic_softc;
- uint32_t tmp;
RUM_LOCK(sc);
- /* abort TSF synchronization */
- tmp = rum_read(sc, RT2573_TXRX_CSR9);
- rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff);
+ rum_abort_tsf_sync(sc);
rum_set_bssid(sc, ieee80211broadcastaddr);
RUM_UNLOCK(sc);
@@ -2234,8 +2932,11 @@ rum_scan_end(struct ieee80211com *ic)
struct rum_softc *sc = ic->ic_softc;
RUM_LOCK(sc);
- rum_enable_tsf_sync(sc);
- rum_set_bssid(sc, ic->ic_macaddr);
+ if (ic->ic_opmode != IEEE80211_M_AHDEMO)
+ rum_enable_tsf_sync(sc);
+ else
+ rum_enable_tsf(sc);
+ rum_set_bssid(sc, sc->sc_bssid);
RUM_UNLOCK(sc);
}
diff --git a/sys/dev/usb/wlan/if_rumreg.h b/sys/dev/usb/wlan/if_rumreg.h
index 44e627a..c673fd7 100644
--- a/sys/dev/usb/wlan/if_rumreg.h
+++ b/sys/dev/usb/wlan/if_rumreg.h
@@ -34,13 +34,36 @@
#define RT2573_WRITE_LED 0x0a
/*
- * Control and status registers.
+ * WME registers.
*/
#define RT2573_AIFSN_CSR 0x0400
#define RT2573_CWMIN_CSR 0x0404
#define RT2573_CWMAX_CSR 0x0408
+#define RT2573_TXOP01_CSR 0x040C
+#define RT2573_TXOP23_CSR 0x0410
#define RT2573_MCU_CODE_BASE 0x0800
-#define RT2573_HW_BEACON_BASE0 0x2400
+
+/*
+ * H/w encryption/decryption support
+ */
+#define KEY_SIZE (IEEE80211_KEYBUF_SIZE + IEEE80211_MICBUF_SIZE)
+#define RT2573_ADDR_MAX 64
+#define RT2573_SKEY_MAX 4
+
+#define RT2573_SKEY(vap, kidx) (0x1000 + ((vap) * RT2573_SKEY_MAX + \
+ (kidx)) * KEY_SIZE)
+#define RT2573_PKEY(id) (0x1200 + (id) * KEY_SIZE)
+
+#define RT2573_ADDR_ENTRY(id) (0x1a00 + (id) * 8)
+
+/*
+ * Shared memory area
+ */
+#define RT2573_HW_BCN_BASE(id) (0x2400 + (id) * 0x100)
+
+/*
+ * Control and status registers.
+ */
#define RT2573_MAC_CSR0 0x3000
#define RT2573_MAC_CSR1 0x3004
#define RT2573_MAC_CSR2 0x3008
@@ -95,13 +118,23 @@
#define RT2573_STA_CSR5 0x30d4
+/* possible values for register RT2573_ADDR_MODE */
+#define RT2573_MODE_MASK 0x7
+#define RT2573_MODE_NOSEC 0
+#define RT2573_MODE_WEP40 1
+#define RT2573_MODE_WEP104 2
+#define RT2573_MODE_TKIP 3
+#define RT2573_MODE_AES_CCMP 4
+#define RT2573_MODE_CKIP40 5
+#define RT2573_MODE_CKIP104 6
+
/* possible flags for register RT2573_MAC_CSR1 */
#define RT2573_RESET_ASIC (1 << 0)
#define RT2573_RESET_BBP (1 << 1)
#define RT2573_HOST_READY (1 << 2)
/* possible flags for register MAC_CSR5 */
-#define RT2573_ONE_BSSID 3
+#define RT2573_NUM_BSSID_MSK(n) (((n * 3) & 3) << 16)
/* possible flags for register TXRX_CSR0 */
/* Tx filter flags are in the low 16 bits */
@@ -122,13 +155,20 @@
#define RT2573_SHORT_PREAMBLE (1 << 18)
#define RT2573_MRR_ENABLED (1 << 19)
#define RT2573_MRR_CCK_FALLBACK (1 << 22)
+#define RT2573_LONG_RETRY(max) ((max) << 24)
+#define RT2573_LONG_RETRY_MASK (0xf << 24)
+#define RT2573_SHORT_RETRY(max) ((max) << 28)
+#define RT2573_SHORT_RETRY_MASK (0xf << 28)
/* possible flags for register TXRX_CSR9 */
-#define RT2573_TSF_TICKING (1 << 16)
-#define RT2573_TSF_MODE(x) (((x) & 0x3) << 17)
-/* TBTT stands for Target Beacon Transmission Time */
-#define RT2573_ENABLE_TBTT (1 << 19)
-#define RT2573_GENERATE_BEACON (1 << 20)
+#define RT2573_TSF_TIMER_EN (1 << 16)
+#define RT2573_TSF_SYNC_MODE(x) (((x) & 0x3) << 17)
+#define RT2573_TSF_SYNC_MODE_DIS 0
+#define RT2573_TSF_SYNC_MODE_STA 1
+#define RT2573_TSF_SYNC_MODE_IBSS 2
+#define RT2573_TSF_SYNC_MODE_HOSTAP 3
+#define RT2573_TBTT_TIMER_EN (1 << 19)
+#define RT2573_BCN_TX_EN (1 << 20)
/* possible flags for register PHY_CSR0 */
#define RT2573_PA_PE_2GHZ (1 << 16)
@@ -175,6 +215,10 @@ struct rum_tx_desc {
#define RT2573_TX_OFDM (1 << 5)
#define RT2573_TX_IFS_SIFS (1 << 6)
#define RT2573_TX_LONG_RETRY (1 << 7)
+#define RT2573_TX_TKIPMIC (1 << 8)
+#define RT2573_TX_KEY_PAIR (1 << 9)
+#define RT2573_TX_KEY_ID(id) (((id) & 0x3f) << 10)
+#define RT2573_TX_CIP_MODE(m) ((m) << 29)
uint16_t wme;
#define RT2573_QID(v) (v)
@@ -182,8 +226,9 @@ struct rum_tx_desc {
#define RT2573_LOGCWMIN(v) ((v) << 8)
#define RT2573_LOGCWMAX(v) ((v) << 12)
- uint16_t xflags;
-#define RT2573_TX_HWSEQ (1 << 12)
+ uint8_t hdrlen;
+ uint8_t xflags;
+#define RT2573_TX_HWSEQ (1 << 4)
uint8_t plcp_signal;
uint8_t plcp_service;
@@ -207,9 +252,25 @@ struct rum_rx_desc {
uint32_t flags;
#define RT2573_RX_BUSY (1 << 0)
#define RT2573_RX_DROP (1 << 1)
+#define RT2573_RX_UC2ME (1 << 2)
+#define RT2573_RX_MC (1 << 3)
+#define RT2573_RX_BC (1 << 4)
+#define RT2573_RX_MYBSS (1 << 5)
#define RT2573_RX_CRC_ERROR (1 << 6)
#define RT2573_RX_OFDM (1 << 7)
+#define RT2573_RX_DEC_MASK (3 << 8)
+#define RT2573_RX_DEC_OK (0 << 8)
+
+#define RT2573_RX_IV_ERROR (1 << 8)
+#define RT2573_RX_MIC_ERROR (2 << 8)
+#define RT2573_RX_KEY_ERROR (3 << 8)
+
+#define RT2573_RX_KEY_PAIR (1 << 28)
+
+#define RT2573_RX_CIP_MASK (7 << 29)
+#define RT2573_RX_CIP_MODE(m) ((m) << 29)
+
uint8_t rate;
uint8_t rssi;
uint8_t reserved1;
diff --git a/sys/dev/usb/wlan/if_rumvar.h b/sys/dev/usb/wlan/if_rumvar.h
index 35da6d3..9fa733e 100644
--- a/sys/dev/usb/wlan/if_rumvar.h
+++ b/sys/dev/usb/wlan/if_rumvar.h
@@ -22,6 +22,7 @@
struct rum_rx_radiotap_header {
struct ieee80211_radiotap_header wr_ihdr;
+ uint64_t wr_tsf;
uint8_t wr_flags;
uint8_t wr_rate;
uint16_t wr_chan_freq;
@@ -32,7 +33,8 @@ struct rum_rx_radiotap_header {
} __packed __aligned(8);
#define RT2573_RX_RADIOTAP_PRESENT \
- ((1 << IEEE80211_RADIOTAP_FLAGS) | \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | \
@@ -42,6 +44,7 @@ struct rum_rx_radiotap_header {
struct rum_tx_radiotap_header {
struct ieee80211_radiotap_header wt_ihdr;
+ uint64_t wt_tsf;
uint8_t wt_flags;
uint8_t wt_rate;
uint16_t wt_chan_freq;
@@ -50,7 +53,8 @@ struct rum_tx_radiotap_header {
} __packed __aligned(8);
#define RT2573_TX_RADIOTAP_PRESENT \
- ((1 << IEEE80211_RADIOTAP_FLAGS) | \
+ ((1 << IEEE80211_RADIOTAP_TSFT) | \
+ (1 << IEEE80211_RADIOTAP_FLAGS) | \
(1 << IEEE80211_RADIOTAP_RATE) | \
(1 << IEEE80211_RADIOTAP_CHANNEL) | \
(1 << IEEE80211_RADIOTAP_ANTENNA))
@@ -67,11 +71,29 @@ struct rum_tx_data {
};
typedef STAILQ_HEAD(, rum_tx_data) rum_txdhead;
+union sec_param {
+ struct ieee80211_key key;
+ struct wmeParams wme_params[WME_NUM_AC];
+ uint8_t macaddr[IEEE80211_ADDR_LEN];
+ struct ieee80211vap *vap;
+};
+#define CMD_FUNC_PROTO void (*func)(struct rum_softc *, \
+ union sec_param *, uint8_t)
+
+struct rum_cmdq {
+ union sec_param data;
+ uint8_t rvp_id;
+
+ CMD_FUNC_PROTO;
+};
+#define RUM_CMDQ_SIZE 16
+
struct rum_vap {
struct ieee80211vap vap;
- struct ieee80211_beacon_offsets bo;
+ struct mbuf *bcn_mbuf;
struct usb_callout ratectl_ch;
struct task ratectl_task;
+ uint8_t maxretry;
int (*newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
@@ -90,7 +112,7 @@ struct rum_softc {
device_t sc_dev;
struct usb_device *sc_udev;
- struct usb_xfer *sc_xfer[RUM_N_TRANSFER];
+ struct usb_xfer *sc_xfer[RUM_N_TRANSFER];
uint8_t rf_rev;
uint8_t rffreq;
@@ -103,11 +125,24 @@ struct rum_softc {
struct mtx sc_mtx;
+ struct rum_cmdq cmdq[RUM_CMDQ_SIZE];
+ struct mtx cmdq_mtx;
+ struct task cmdq_task;
+ uint8_t cmdq_first;
+ uint8_t cmdq_last;
+
uint32_t sta[6];
uint32_t rf_regs[4];
uint8_t txpow[44];
u_int sc_detached:1,
- sc_running:1;
+ sc_running:1,
+ sc_clr_shkeys:1;
+
+ uint8_t sc_bssid[IEEE80211_ADDR_LEN];
+ struct wmeParams wme_params[WME_NUM_AC];
+
+ uint8_t vap_key_count[1];
+ uint64_t keys_bmap;
struct {
uint8_t val;
@@ -125,12 +160,19 @@ struct rum_softc {
uint8_t bbp17;
struct rum_rx_radiotap_header sc_rxtap;
- int sc_rxtap_len;
-
struct rum_tx_radiotap_header sc_txtap;
- int sc_txtap_len;
};
-#define RUM_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
-#define RUM_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
-#define RUM_LOCK_ASSERT(sc, t) mtx_assert(&(sc)->sc_mtx, t)
+#define RUM_LOCK_INIT(sc) \
+ mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->sc_dev), \
+ MTX_NETWORK_LOCK, MTX_DEF);
+#define RUM_LOCK(sc) mtx_lock(&(sc)->sc_mtx)
+#define RUM_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
+#define RUM_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
+#define RUM_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_mtx)
+
+#define RUM_CMDQ_LOCK_INIT(sc) \
+ mtx_init(&(sc)->cmdq_mtx, "cmdq lock", NULL, MTX_DEF)
+#define RUM_CMDQ_LOCK(sc) mtx_lock(&(sc)->cmdq_mtx)
+#define RUM_CMDQ_UNLOCK(sc) mtx_unlock(&(sc)->cmdq_mtx)
+#define RUM_CMDQ_LOCK_DESTROY(sc) mtx_destroy(&(sc)->cmdq_mtx)
diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c
index c8707c4..83d4a88 100644
--- a/sys/dev/usb/wlan/if_run.c
+++ b/sys/dev/usb/wlan/if_run.c
@@ -382,8 +382,7 @@ static int run_newstate(struct ieee80211vap *, enum ieee80211_state, int);
static int run_wme_update(struct ieee80211com *);
static void run_wme_update_cb(void *);
static void run_key_set_cb(void *);
-static int run_key_set(struct ieee80211vap *, struct ieee80211_key *,
- const uint8_t mac[IEEE80211_ADDR_LEN]);
+static int run_key_set(struct ieee80211vap *, struct ieee80211_key *);
static void run_key_delete_cb(void *);
static int run_key_delete(struct ieee80211vap *, struct ieee80211_key *);
static void run_ratectl_to(void *);
@@ -392,6 +391,8 @@ static void run_drain_fifo(void *);
static void run_iter_func(void *, struct ieee80211_node *);
static void run_newassoc_cb(void *);
static void run_newassoc(struct ieee80211_node *, int);
+static void run_recv_mgmt(struct ieee80211_node *, struct mbuf *, int,
+ const struct ieee80211_rx_stats *, int, int);
static void run_rx_frame(struct run_softc *, struct mbuf *, uint32_t);
static void run_tx_free(struct run_endpoint_queue *pq,
struct run_tx_data *, int);
@@ -830,6 +831,21 @@ detach:
return (ENXIO);
}
+static void
+run_drain_mbufq(struct run_softc *sc)
+{
+ struct mbuf *m;
+ struct ieee80211_node *ni;
+
+ RUN_LOCK_ASSERT(sc, MA_OWNED);
+ while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
+ ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
+ m->m_pkthdr.rcvif = NULL;
+ ieee80211_free_node(ni);
+ m_freem(m);
+ }
+}
+
static int
run_detach(device_t self)
{
@@ -851,6 +867,9 @@ run_detach(device_t self)
/* free TX list, if any */
for (i = 0; i != RUN_EP_QUEUES; i++)
run_unsetup_tx_list(sc, &sc->sc_epq[i]);
+
+ /* Free TX queue */
+ run_drain_mbufq(sc);
RUN_UNLOCK(sc);
if (sc->sc_ic.ic_softc == sc) {
@@ -861,7 +880,6 @@ run_detach(device_t self)
ieee80211_ifdetach(ic);
}
- mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -939,6 +957,10 @@ run_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
/* override state transition machine */
rvp->newstate = vap->iv_newstate;
vap->iv_newstate = run_newstate;
+ if (opmode == IEEE80211_M_IBSS) {
+ rvp->recv_mgmt = vap->iv_recv_mgmt;
+ vap->iv_recv_mgmt = run_recv_mgmt;
+ }
ieee80211_ratectl_init(vap);
ieee80211_ratectl_setinterval(vap, 1000 /* 1 sec */);
@@ -1670,14 +1692,14 @@ run_get_txpower(struct run_softc *sc)
/* Fix broken Tx power entries. */
for (i = 0; i < 14; i++) {
if (sc->mac_ver >= 0x5390) {
- if (sc->txpow1[i] < 0 || sc->txpow1[i] > 27)
+ if (sc->txpow1[i] < 0 || sc->txpow1[i] > 39)
sc->txpow1[i] = 5;
} else {
if (sc->txpow1[i] < 0 || sc->txpow1[i] > 31)
sc->txpow1[i] = 5;
}
if (sc->mac_ver > 0x5390) {
- if (sc->txpow2[i] < 0 || sc->txpow2[i] > 27)
+ if (sc->txpow2[i] < 0 || sc->txpow2[i] > 39)
sc->txpow2[i] = 5;
} else if (sc->mac_ver < 0x5390) {
if (sc->txpow2[i] < 0 || sc->txpow2[i] > 31)
@@ -2157,7 +2179,8 @@ run_wme_update_cb(void *arg)
{
struct ieee80211com *ic = arg;
struct run_softc *sc = ic->ic_softc;
- struct ieee80211_wme_state *wmesp = &ic->ic_wme;
+ const struct wmeParams *ac =
+ ic->ic_wme.wme_chanParams.cap_wmeParams;
int aci, error = 0;
RUN_LOCK_ASSERT(sc, MA_OWNED);
@@ -2165,39 +2188,39 @@ run_wme_update_cb(void *arg)
/* update MAC TX configuration registers */
for (aci = 0; aci < WME_NUM_AC; aci++) {
error = run_write(sc, RT2860_EDCA_AC_CFG(aci),
- wmesp->wme_params[aci].wmep_logcwmax << 16 |
- wmesp->wme_params[aci].wmep_logcwmin << 12 |
- wmesp->wme_params[aci].wmep_aifsn << 8 |
- wmesp->wme_params[aci].wmep_txopLimit);
+ ac[aci].wmep_logcwmax << 16 |
+ ac[aci].wmep_logcwmin << 12 |
+ ac[aci].wmep_aifsn << 8 |
+ ac[aci].wmep_txopLimit);
if (error) goto err;
}
/* update SCH/DMA registers too */
error = run_write(sc, RT2860_WMM_AIFSN_CFG,
- wmesp->wme_params[WME_AC_VO].wmep_aifsn << 12 |
- wmesp->wme_params[WME_AC_VI].wmep_aifsn << 8 |
- wmesp->wme_params[WME_AC_BK].wmep_aifsn << 4 |
- wmesp->wme_params[WME_AC_BE].wmep_aifsn);
+ ac[WME_AC_VO].wmep_aifsn << 12 |
+ ac[WME_AC_VI].wmep_aifsn << 8 |
+ ac[WME_AC_BK].wmep_aifsn << 4 |
+ ac[WME_AC_BE].wmep_aifsn);
if (error) goto err;
error = run_write(sc, RT2860_WMM_CWMIN_CFG,
- wmesp->wme_params[WME_AC_VO].wmep_logcwmin << 12 |
- wmesp->wme_params[WME_AC_VI].wmep_logcwmin << 8 |
- wmesp->wme_params[WME_AC_BK].wmep_logcwmin << 4 |
- wmesp->wme_params[WME_AC_BE].wmep_logcwmin);
+ ac[WME_AC_VO].wmep_logcwmin << 12 |
+ ac[WME_AC_VI].wmep_logcwmin << 8 |
+ ac[WME_AC_BK].wmep_logcwmin << 4 |
+ ac[WME_AC_BE].wmep_logcwmin);
if (error) goto err;
error = run_write(sc, RT2860_WMM_CWMAX_CFG,
- wmesp->wme_params[WME_AC_VO].wmep_logcwmax << 12 |
- wmesp->wme_params[WME_AC_VI].wmep_logcwmax << 8 |
- wmesp->wme_params[WME_AC_BK].wmep_logcwmax << 4 |
- wmesp->wme_params[WME_AC_BE].wmep_logcwmax);
+ ac[WME_AC_VO].wmep_logcwmax << 12 |
+ ac[WME_AC_VI].wmep_logcwmax << 8 |
+ ac[WME_AC_BK].wmep_logcwmax << 4 |
+ ac[WME_AC_BE].wmep_logcwmax);
if (error) goto err;
error = run_write(sc, RT2860_WMM_TXOP0_CFG,
- wmesp->wme_params[WME_AC_BK].wmep_txopLimit << 16 |
- wmesp->wme_params[WME_AC_BE].wmep_txopLimit);
+ ac[WME_AC_BK].wmep_txopLimit << 16 |
+ ac[WME_AC_BE].wmep_txopLimit);
if (error) goto err;
error = run_write(sc, RT2860_WMM_TXOP1_CFG,
- wmesp->wme_params[WME_AC_VO].wmep_txopLimit << 16 |
- wmesp->wme_params[WME_AC_VI].wmep_txopLimit);
+ ac[WME_AC_VO].wmep_txopLimit << 16 |
+ ac[WME_AC_VI].wmep_txopLimit);
err:
if (error)
@@ -2355,8 +2378,7 @@ run_key_set_cb(void *arg)
* return 0 on error
*/
static int
-run_key_set(struct ieee80211vap *vap, struct ieee80211_key *k,
- const uint8_t mac[IEEE80211_ADDR_LEN])
+run_key_set(struct ieee80211vap *vap, struct ieee80211_key *k)
{
struct ieee80211com *ic = vap->iv_ic;
struct run_softc *sc = ic->ic_softc;
@@ -2368,7 +2390,7 @@ run_key_set(struct ieee80211vap *vap, struct ieee80211_key *k,
sc->cmdq[i].arg0 = NULL;
sc->cmdq[i].arg1 = vap;
sc->cmdq[i].k = k;
- IEEE80211_ADDR_COPY(sc->cmdq[i].mac, mac);
+ IEEE80211_ADDR_COPY(sc->cmdq[i].mac, k->wk_macaddr);
ieee80211_runtask(ic, &sc->cmdq_task);
/*
@@ -2725,6 +2747,34 @@ run_maxrssi_chain(struct run_softc *sc, const struct rt2860_rxwi *rxwi)
}
static void
+run_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int subtype,
+ const struct ieee80211_rx_stats *rxs, int rssi, int nf)
+{
+ struct ieee80211vap *vap = ni->ni_vap;
+ struct run_softc *sc = vap->iv_ic->ic_softc;
+ struct run_vap *rvp = RUN_VAP(vap);
+ uint64_t ni_tstamp, rx_tstamp;
+
+ rvp->recv_mgmt(ni, m, subtype, rxs, rssi, nf);
+
+ if (vap->iv_state == IEEE80211_S_RUN &&
+ (subtype == IEEE80211_FC0_SUBTYPE_BEACON ||
+ subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) {
+ ni_tstamp = le64toh(ni->ni_tstamp.tsf);
+ RUN_LOCK(sc);
+ run_get_tsf(sc, &rx_tstamp);
+ RUN_UNLOCK(sc);
+ rx_tstamp = le64toh(rx_tstamp);
+
+ if (ni_tstamp >= rx_tstamp) {
+ DPRINTF("ibss merge, tsf %ju tstamp %ju\n",
+ (uintmax_t)rx_tstamp, (uintmax_t)ni_tstamp);
+ (void) ieee80211_ibss_merge(ni);
+ }
+ }
+}
+
+static void
run_rx_frame(struct run_softc *sc, struct mbuf *m, uint32_t dmalen)
{
struct ieee80211com *ic = &sc->sc_ic;
@@ -4834,11 +4884,11 @@ run_update_beacon(struct ieee80211vap *vap, int item)
setbit(bo->bo_flags, item);
if (rvp->beacon_mbuf == NULL) {
- rvp->beacon_mbuf = ieee80211_beacon_alloc(ni, bo);
+ rvp->beacon_mbuf = ieee80211_beacon_alloc(ni);
if (rvp->beacon_mbuf == NULL)
return;
}
- ieee80211_beacon_update(ni, bo, rvp->beacon_mbuf, mcast);
+ ieee80211_beacon_update(ni, rvp->beacon_mbuf, mcast);
i = RUN_CMDQ_GET(&sc->cmdq_store);
DPRINTF("cmdq_store=%d\n", i);
@@ -4872,8 +4922,7 @@ run_update_beacon_cb(void *arg)
* is taking care of apropriate calls.
*/
if (rvp->beacon_mbuf == NULL) {
- rvp->beacon_mbuf = ieee80211_beacon_alloc(ni,
- &vap->iv_bcn_off);
+ rvp->beacon_mbuf = ieee80211_beacon_alloc(ni);
if (rvp->beacon_mbuf == NULL)
return;
}
@@ -6140,6 +6189,8 @@ run_stop(void *arg)
RUN_LOCK(sc);
+ run_drain_mbufq(sc);
+
if (sc->rx_m != NULL) {
m_free(sc->rx_m);
sc->rx_m = NULL;
diff --git a/sys/dev/usb/wlan/if_runreg.h b/sys/dev/usb/wlan/if_runreg.h
index aa54a72..de71d5a 100644
--- a/sys/dev/usb/wlan/if_runreg.h
+++ b/sys/dev/usb/wlan/if_runreg.h
@@ -274,7 +274,6 @@
#define RT2860_USB_TXOP_HALT (1 << 20)
#define RT2860_USB_TX_CLEAR (1 << 19)
#define RT2860_USB_PHY_WD_EN (1 << 16)
-#define RT2860_USB_PHY_MAN_RST (1 << 15)
#define RT2860_USB_RX_AGG_LMT(x) ((x) << 8) /* in unit of 1KB */
#define RT2860_USB_RX_AGG_TO(x) ((x) & 0xff) /* in unit of 33ns */
diff --git a/sys/dev/usb/wlan/if_runvar.h b/sys/dev/usb/wlan/if_runvar.h
index bbefbb0..3af5b22 100644
--- a/sys/dev/usb/wlan/if_runvar.h
+++ b/sys/dev/usb/wlan/if_runvar.h
@@ -123,6 +123,10 @@ struct run_vap {
int (*newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
+ void (*recv_mgmt)(struct ieee80211_node *,
+ struct mbuf *, int,
+ const struct ieee80211_rx_stats *,
+ int, int);
uint8_t rvp_id;
};
diff --git a/sys/dev/usb/wlan/if_upgt.c b/sys/dev/usb/wlan/if_upgt.c
index b882fe3..516caf0 100644
--- a/sys/dev/usb/wlan/if_upgt.c
+++ b/sys/dev/usb/wlan/if_upgt.c
@@ -956,10 +956,7 @@ upgt_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
return NULL;
- uvp = (struct upgt_vap *) malloc(sizeof(struct upgt_vap),
- M_80211_VAP, M_NOWAIT | M_ZERO);
- if (uvp == NULL)
- return NULL;
+ uvp = malloc(sizeof(struct upgt_vap), M_80211_VAP, M_WAITOK | M_ZERO);
vap = &uvp->vap;
/* enable s/w bmiss handling for sta mode */
diff --git a/sys/dev/usb/wlan/if_ural.c b/sys/dev/usb/wlan/if_ural.c
index bff4de5..6f6686f 100644
--- a/sys/dev/usb/wlan/if_ural.c
+++ b/sys/dev/usb/wlan/if_ural.c
@@ -698,12 +698,9 @@ ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ni = ieee80211_ref_node(vap->iv_bss);
if (vap->iv_opmode != IEEE80211_M_MONITOR) {
- if (ic->ic_bsschan == IEEE80211_CHAN_ANYC) {
- RAL_UNLOCK(sc);
- IEEE80211_LOCK(ic);
- ieee80211_free_node(ni);
- return (-1);
- }
+ if (ic->ic_bsschan == IEEE80211_CHAN_ANYC)
+ goto fail;
+
ural_update_slot(sc);
ural_set_txpreamble(sc);
ural_set_basicrates(sc, ic->ic_bsschan);
@@ -713,23 +710,17 @@ ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
vap->iv_opmode == IEEE80211_M_IBSS) {
- m = ieee80211_beacon_alloc(ni, &vap->iv_bcn_off);
+ m = ieee80211_beacon_alloc(ni);
if (m == NULL) {
device_printf(sc->sc_dev,
"could not allocate beacon\n");
- RAL_UNLOCK(sc);
- IEEE80211_LOCK(ic);
- ieee80211_free_node(ni);
- return (-1);
+ goto fail;
}
ieee80211_ref_node(ni);
if (ural_tx_bcn(sc, m, ni) != 0) {
device_printf(sc->sc_dev,
"could not send beacon\n");
- RAL_UNLOCK(sc);
- IEEE80211_LOCK(ic);
- ieee80211_free_node(ni);
- return (-1);
+ goto fail;
}
}
@@ -755,6 +746,12 @@ ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
RAL_UNLOCK(sc);
IEEE80211_LOCK(ic);
return (uvp->newstate(vap, nstate, arg));
+
+fail:
+ RAL_UNLOCK(sc);
+ IEEE80211_LOCK(ic);
+ ieee80211_free_node(ni);
+ return (-1);
}
diff --git a/sys/dev/usb/wlan/if_urtwn.c b/sys/dev/usb/wlan/if_urtwn.c
index b1e3804..eb11f7b 100644
--- a/sys/dev/usb/wlan/if_urtwn.c
+++ b/sys/dev/usb/wlan/if_urtwn.c
@@ -1775,7 +1775,7 @@ urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni,
struct r92c_tx_desc *txd;
uint8_t raid, type;
uint16_t sum;
- int i, hasqos, xferlen;
+ int i, xferlen;
struct usb_xfer *urtwn_pipes[4] = {
sc->sc_xfer[URTWN_BULK_TX_BE],
sc->sc_xfer[URTWN_BULK_TX_BK],
@@ -1816,8 +1816,6 @@ urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni,
break;
}
- hasqos = 0;
-
/* Fill Tx descriptor. */
txd = (struct r92c_tx_desc *)data->buf;
memset(txd, 0, sizeof(*txd));
@@ -1873,7 +1871,7 @@ urtwn_tx_start(struct urtwn_softc *sc, struct ieee80211_node *ni,
/* Set sequence number (already little endian). */
txd->txdseq |= *(uint16_t *)wh->i_seq;
- if (!hasqos) {
+ if (!IEEE80211_QOS_HAS_SEQ(wh)) {
/* Use HW sequence numbering for non-QoS frames. */
txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ);
txd->txdseq |= htole16(0x8000);
diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c
index 5a59d37..ed70d19 100644
--- a/sys/dev/usb/wlan/if_zyd.c
+++ b/sys/dev/usb/wlan/if_zyd.c
@@ -420,6 +420,22 @@ detach:
return (ENXIO); /* failure */
}
+static void
+zyd_drain_mbufq(struct zyd_softc *sc)
+{
+ struct mbuf *m;
+ struct ieee80211_node *ni;
+
+ ZYD_LOCK_ASSERT(sc, MA_OWNED);
+ while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
+ ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
+ m->m_pkthdr.rcvif = NULL;
+ ieee80211_free_node(ni);
+ m_freem(m);
+ }
+}
+
+
static int
zyd_detach(device_t dev)
{
@@ -433,6 +449,7 @@ zyd_detach(device_t dev)
*/
ZYD_LOCK(sc);
sc->sc_flags |= ZYD_FLAG_DETACHED;
+ zyd_drain_mbufq(sc);
STAILQ_INIT(&sc->tx_q);
STAILQ_INIT(&sc->tx_free);
ZYD_UNLOCK(sc);
@@ -451,7 +468,6 @@ zyd_detach(device_t dev)
if (ic->ic_softc == sc)
ieee80211_ifdetach(ic);
- mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -2443,7 +2459,6 @@ zyd_tx_start(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
k = ieee80211_crypto_encap(ni, m0);
if (k == NULL) {
- m_freem(m0);
return (ENOBUFS);
}
/* packet header may have moved, reset our local pointer */
@@ -2555,6 +2570,7 @@ zyd_start(struct zyd_softc *sc)
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
if (zyd_tx_start(sc, m, ni) != 0) {
ieee80211_free_node(ni);
+ m_freem(m);
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
break;
@@ -2592,6 +2608,7 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
if (zyd_tx_start(sc, m, ni) != 0) {
ZYD_UNLOCK(sc);
ieee80211_free_node(ni);
+ m_freem(m);
return (EIO);
}
ZYD_UNLOCK(sc);
@@ -2738,6 +2755,7 @@ zyd_stop(struct zyd_softc *sc)
ZYD_LOCK_ASSERT(sc, MA_OWNED);
sc->sc_flags &= ~ZYD_FLAG_RUNNING;
+ zyd_drain_mbufq(sc);
/*
* Drain all the transfers, if not already drained:
diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c
index abb3bd5..0d7c1c1 100644
--- a/sys/dev/wpi/if_wpi.c
+++ b/sys/dev/wpi/if_wpi.c
@@ -254,8 +254,7 @@ static void wpi_del_key_cb(void *, struct ieee80211_node *);
static int wpi_process_key(struct ieee80211vap *,
const struct ieee80211_key *, int);
static int wpi_key_set(struct ieee80211vap *,
- const struct ieee80211_key *,
- const uint8_t mac[IEEE80211_ADDR_LEN]);
+ const struct ieee80211_key *);
static int wpi_key_delete(struct ieee80211vap *,
const struct ieee80211_key *);
static int wpi_post_alive(struct wpi_softc *);
@@ -4355,7 +4354,6 @@ static int
wpi_setup_beacon(struct wpi_softc *sc, struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off;
struct wpi_vap *wvp = WPI_VAP(vap);
struct wpi_buf *bcn = &wvp->wv_bcbuf;
struct mbuf *m;
@@ -4366,7 +4364,7 @@ wpi_setup_beacon(struct wpi_softc *sc, struct ieee80211_node *ni)
if (ni->ni_chan == IEEE80211_CHAN_ANYC)
return EINVAL;
- m = ieee80211_beacon_alloc(ni, bo);
+ m = ieee80211_beacon_alloc(ni);
if (m == NULL) {
device_printf(sc->sc_dev,
"%s: could not allocate beacon frame\n", __func__);
@@ -4399,7 +4397,7 @@ wpi_update_beacon(struct ieee80211vap *vap, int item)
WPI_VAP_LOCK(wvp);
if (bcn->m == NULL) {
- bcn->m = ieee80211_beacon_alloc(ni, bo);
+ bcn->m = ieee80211_beacon_alloc(ni);
if (bcn->m == NULL) {
device_printf(sc->sc_dev,
"%s: could not allocate beacon frame\n", __func__);
@@ -4417,7 +4415,7 @@ wpi_update_beacon(struct ieee80211vap *vap, int item)
mcast = 1; /* TODO */
setbit(bo->bo_flags, item);
- ieee80211_beacon_update(ni, bo, bcn->m, mcast);
+ ieee80211_beacon_update(ni, bcn->m, mcast);
WPI_VAP_LOCK(wvp);
wpi_config_beacon(wvp);
@@ -4799,8 +4797,7 @@ wpi_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k,
}
static int
-wpi_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
- const uint8_t mac[IEEE80211_ADDR_LEN])
+wpi_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
{
return wpi_process_key(vap, k, 1);
}
diff --git a/sys/dev/wtap/if_wtap.c b/sys/dev/wtap/if_wtap.c
index 7c15c35..847ffcb 100644
--- a/sys/dev/wtap/if_wtap.c
+++ b/sys/dev/wtap/if_wtap.c
@@ -205,7 +205,7 @@ wtap_beacon_alloc(struct wtap_softc *sc, struct ieee80211_node *ni)
* we assume the mbuf routines will return us something
* with this alignment (perhaps should assert).
*/
- avp->beacon = ieee80211_beacon_alloc(ni, &vap->iv_bcn_off);
+ avp->beacon = ieee80211_beacon_alloc(ni);
if (avp->beacon == NULL) {
printf("%s: cannot get mbuf\n", __func__);
return ENOMEM;
@@ -242,7 +242,7 @@ wtap_beacon_intrp(void *arg)
* of the TIM bitmap).
*/
m = m_dup(avp->beacon, M_NOWAIT);
- if (ieee80211_beacon_update(avp->bf_node, &vap->iv_bcn_off, m, 0)) {
+ if (ieee80211_beacon_update(avp->bf_node, m, 0)) {
printf("%s, need to remap the memory because the beacon frame"
" changed size.\n",__func__);
}
diff --git a/sys/kern/subr_sbuf.c b/sys/kern/subr_sbuf.c
index 3c36b28..5314590 100644
--- a/sys/kern/subr_sbuf.c
+++ b/sys/kern/subr_sbuf.c
@@ -623,6 +623,10 @@ sbuf_vprintf(struct sbuf *s, const char *fmt, va_list ap)
va_copy(ap_copy, ap);
len = vsnprintf(&s->s_buf[s->s_len], SBUF_FREESPACE(s) + 1,
fmt, ap_copy);
+ if (len < 0) {
+ s->s_error = errno;
+ return (-1);
+ }
va_end(ap_copy);
if (SBUF_FREESPACE(s) >= len)
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 0fab000..70dc565 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -2050,11 +2050,10 @@ vfs_vmio_iodone(struct buf *bp)
(intmax_t)foff, (uintmax_t)m->pindex));
vm_page_sunbusy(m);
- vm_object_pip_subtract(obj, 1);
foff = (foff + PAGE_SIZE) & ~(off_t)PAGE_MASK;
iosize -= resid;
}
- vm_object_pip_wakeupn(obj, 0);
+ vm_object_pip_wakeupn(obj, bp->b_npages);
VM_OBJECT_WUNLOCK(obj);
if (bogus && buf_mapped(bp)) {
BUF_CHECK_MAPPED(bp);
@@ -3923,10 +3922,9 @@ vfs_unbusy_pages(struct buf *bp)
} else
BUF_CHECK_UNMAPPED(bp);
}
- vm_object_pip_subtract(obj, 1);
vm_page_sunbusy(m);
}
- vm_object_pip_wakeupn(obj, 0);
+ vm_object_pip_wakeupn(obj, bp->b_npages);
VM_OBJECT_WUNLOCK(obj);
}
diff --git a/sys/mips/conf/WZR-300HP b/sys/mips/conf/WZR-300HP
index 8f84776..c8280cc 100644
--- a/sys/mips/conf/WZR-300HP
+++ b/sys/mips/conf/WZR-300HP
@@ -28,9 +28,6 @@ device geom_uncompress # compressed in-memory filesystem hackery!
options ROOTDEVNAME=\"ufs:/dev/map/rootfs.uncompress\"
-# options MD_ROOT
-# options MD_ROOT_SIZE="6144"
-
options AR71XX_ATH_EEPROM # Fetch EEPROM/PCI config from flash
options ATH_EEPROM_FIRMWARE # Use EEPROM from flash
device firmware # Used by the above
@@ -42,10 +39,11 @@ device miiproxy # MDIO bus <-> MII PHY rendezvous
device etherswitch
device arswitch
-# Enable GPIO
-device gpio
-device gpioled
-
# hwpmc
device hwpmc_mips24k
device hwpmc
+
+# load these via modules, shrink kernel
+nodevice if_bridge
+nodevice bridgestp
+nodevice random
diff --git a/sys/mips/conf/WZR-300HP.hints b/sys/mips/conf/WZR-300HP.hints
index 07d8a71..2f22198 100644
--- a/sys/mips/conf/WZR-300HP.hints
+++ b/sys/mips/conf/WZR-300HP.hints
@@ -5,11 +5,11 @@
# arge1 MDIO bus
hint.argemdio.0.at="nexus0"
-hint.argemdio.0.maddr=0x1a000000
+hint.argemdio.0.maddr=0x19000000
hint.argemdio.0.msize=0x1000
hint.argemdio.0.order=0
-hint.arge.0.phymask=0x0
+hint.arge.0.phymask=0x1
hint.arge.0.media=1000
hint.arge.0.fduplex=1
hint.arge.0.eeprommac=0x1f05120c
@@ -17,9 +17,9 @@ hint.arge.0.mdio=mdioproxy1 # .. off of the switch mdiobus
# arge1: nail to 1000/full, RMII - connected to the switch
-hint.arge.1.media=1000 # Map to 1000/full
-hint.arge.1.fduplex=1 #
-hint.arge.1.phymask=0x0 # no directly mapped PHYs
+#hint.arge.1.media=1000 # Map to 1000/full
+#hint.arge.1.fduplex=1 #
+#hint.arge.1.phymask=0x0 # no directly mapped PHYs
#
# AR7240 switch config
@@ -28,7 +28,7 @@ hint.arswitch.0.at="mdio0"
hint.arswitch.0.is_7240=1 # We need to be explicitly told this
hint.arswitch.0.numphys=4 # 4 active switch PHYs (PHY 0 -> 3)
hint.arswitch.0.phy4cpu=1 # Yes, PHY 4 == dedicated PHY
-hint.arswitch.0.is_rgmii=0 # No, not RGMII
+hint.arswitch.0.is_rgmii=1 # No, not RGMII
hint.arswitch.0.is_gmii=0 # No, not GMII
# ath0 - slot 0
diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c
index 5903abd..33d583c 100644
--- a/sys/net/if_gif.c
+++ b/sys/net/if_gif.c
@@ -197,6 +197,8 @@ gif_clone_create(struct if_clone *ifc, int unit, caddr_t params)
GIF2IFP(sc)->if_transmit = gif_transmit;
GIF2IFP(sc)->if_qflush = gif_qflush;
GIF2IFP(sc)->if_output = gif_output;
+ GIF2IFP(sc)->if_capabilities |= IFCAP_LINKSTATE;
+ GIF2IFP(sc)->if_capenable |= IFCAP_LINKSTATE;
if_attach(GIF2IFP(sc));
bpfattach(GIF2IFP(sc), DLT_NULL, sizeof(u_int32_t));
if (ng_gif_attach_p != NULL)
@@ -1040,10 +1042,13 @@ gif_set_tunnel(struct ifnet *ifp, struct sockaddr *src, struct sockaddr *dst)
#if defined(INET) || defined(INET6)
bad:
#endif
- if (error == 0 && sc->gif_family != 0)
+ if (error == 0 && sc->gif_family != 0) {
ifp->if_drv_flags |= IFF_DRV_RUNNING;
- else
+ if_link_state_change(ifp, LINK_STATE_UP);
+ } else {
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ if_link_state_change(ifp, LINK_STATE_DOWN);
+ }
return (error);
}
@@ -1065,4 +1070,5 @@ gif_delete_tunnel(struct ifnet *ifp)
free(sc->gif_hdr, M_GIF);
}
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ if_link_state_change(ifp, LINK_STATE_DOWN);
}
diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c
index c38ec3a..ffd94d8 100644
--- a/sys/net/if_gre.c
+++ b/sys/net/if_gre.c
@@ -179,6 +179,8 @@ gre_clone_create(struct if_clone *ifc, int unit, caddr_t params)
GRE2IFP(sc)->if_ioctl = gre_ioctl;
GRE2IFP(sc)->if_transmit = gre_transmit;
GRE2IFP(sc)->if_qflush = gre_qflush;
+ GRE2IFP(sc)->if_capabilities |= IFCAP_LINKSTATE;
+ GRE2IFP(sc)->if_capenable |= IFCAP_LINKSTATE;
if_attach(GRE2IFP(sc));
bpfattach(GRE2IFP(sc), DLT_NULL, sizeof(u_int32_t));
GRE_LIST_LOCK();
@@ -623,7 +625,7 @@ gre_set_tunnel(struct ifnet *ifp, struct sockaddr *src,
default:
return (EAFNOSUPPORT);
}
- if (sc->gre_family != src->sa_family)
+ if (sc->gre_family != 0)
gre_detach(sc);
GRE_WLOCK(sc);
if (sc->gre_family != 0)
@@ -648,8 +650,10 @@ gre_set_tunnel(struct ifnet *ifp, struct sockaddr *src,
break;
#endif
}
- if (error == 0)
+ if (error == 0) {
ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ if_link_state_change(ifp, LINK_STATE_UP);
+ }
return (error);
}
@@ -668,6 +672,7 @@ gre_delete_tunnel(struct ifnet *ifp)
free(sc->gre_hdr, M_GRE);
}
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ if_link_state_change(ifp, LINK_STATE_DOWN);
}
int
diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c
index b623493..ab67b93 100644
--- a/sys/net/if_lagg.c
+++ b/sys/net/if_lagg.c
@@ -221,13 +221,6 @@ static const struct lagg_proto {
.pr_portreq = lacp_portreq,
},
{
- .pr_num = LAGG_PROTO_ETHERCHANNEL,
- .pr_attach = lagg_lb_attach,
- .pr_detach = lagg_lb_detach,
- .pr_start = lagg_lb_start,
- .pr_input = lagg_lb_input,
- },
- {
.pr_num = LAGG_PROTO_BROADCAST,
.pr_start = lagg_bcast_start,
.pr_input = lagg_bcast_input,
@@ -1125,7 +1118,6 @@ lagg_port2req(struct lagg_port *lp, struct lagg_reqport *rp)
case LAGG_PROTO_ROUNDROBIN:
case LAGG_PROTO_LOADBALANCE:
- case LAGG_PROTO_ETHERCHANNEL:
case LAGG_PROTO_BROADCAST:
if (LAGG_PORTACTIVE(lp))
rp->rp_flags |= LAGG_PORT_ACTIVE;
@@ -1759,7 +1751,6 @@ lagg_linkstate(struct lagg_softc *sc)
break;
case LAGG_PROTO_ROUNDROBIN:
case LAGG_PROTO_LOADBALANCE:
- case LAGG_PROTO_ETHERCHANNEL:
case LAGG_PROTO_BROADCAST:
speed = 0;
SLIST_FOREACH(lp, &sc->sc_ports, lp_entries)
diff --git a/sys/net/if_lagg.h b/sys/net/if_lagg.h
index bb5ea23..956c238 100644
--- a/sys/net/if_lagg.h
+++ b/sys/net/if_lagg.h
@@ -53,7 +53,6 @@ typedef enum {
LAGG_PROTO_FAILOVER, /* active failover */
LAGG_PROTO_LOADBALANCE, /* loadbalance */
LAGG_PROTO_LACP, /* 802.3ad lacp */
- LAGG_PROTO_ETHERCHANNEL,/* Cisco FEC */
LAGG_PROTO_BROADCAST, /* broadcast */
LAGG_PROTO_MAX,
} lagg_proto;
@@ -66,7 +65,6 @@ struct lagg_protos {
#define LAGG_PROTO_DEFAULT LAGG_PROTO_FAILOVER
#define LAGG_PROTOS { \
{ "failover", LAGG_PROTO_FAILOVER }, \
- { "fec", LAGG_PROTO_ETHERCHANNEL }, \
{ "lacp", LAGG_PROTO_LACP }, \
{ "loadbalance", LAGG_PROTO_LOADBALANCE }, \
{ "roundrobin", LAGG_PROTO_ROUNDROBIN }, \
diff --git a/sys/net/if_me.c b/sys/net/if_me.c
index ff79713..7a09222 100644
--- a/sys/net/if_me.c
+++ b/sys/net/if_me.c
@@ -192,6 +192,8 @@ me_clone_create(struct if_clone *ifc, int unit, caddr_t params)
ME2IFP(sc)->if_ioctl = me_ioctl;
ME2IFP(sc)->if_transmit = me_transmit;
ME2IFP(sc)->if_qflush = me_qflush;
+ ME2IFP(sc)->if_capabilities |= IFCAP_LINKSTATE;
+ ME2IFP(sc)->if_capenable |= IFCAP_LINKSTATE;
if_attach(ME2IFP(sc));
bpfattach(ME2IFP(sc), DLT_NULL, sizeof(u_int32_t));
ME_LIST_LOCK();
@@ -376,8 +378,10 @@ me_set_tunnel(struct ifnet *ifp, struct sockaddr_in *src,
if (sc->me_ecookie == NULL)
sc->me_ecookie = encap_attach_func(AF_INET, IPPROTO_MOBILE,
me_encapcheck, &in_mobile_protosw, sc);
- if (sc->me_ecookie != NULL)
+ if (sc->me_ecookie != NULL) {
ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ if_link_state_change(ifp, LINK_STATE_UP);
+ }
return (0);
}
@@ -395,6 +399,7 @@ me_delete_tunnel(struct ifnet *ifp)
sc->me_dst.s_addr = 0;
ME_WUNLOCK(sc);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+ if_link_state_change(ifp, LINK_STATE_DOWN);
}
static uint16_t
diff --git a/sys/net80211/ieee80211_crypto.c b/sys/net80211/ieee80211_crypto.c
index d338506..6e55847 100644
--- a/sys/net80211/ieee80211_crypto.c
+++ b/sys/net80211/ieee80211_crypto.c
@@ -89,8 +89,7 @@ null_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k)
return 1;
}
static int
-null_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k,
- const uint8_t mac[IEEE80211_ADDR_LEN])
+null_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k)
{
return 1;
}
@@ -132,7 +131,7 @@ dev_key_delete(struct ieee80211vap *vap,
static __inline int
dev_key_set(struct ieee80211vap *vap, const struct ieee80211_key *key)
{
- return vap->iv_key_set(vap, key, key->wk_macaddr);
+ return vap->iv_key_set(vap, key);
}
/*
@@ -521,17 +520,21 @@ ieee80211_crypto_setkey(struct ieee80211vap *vap, struct ieee80211_key *key)
return dev_key_set(vap, key);
}
-/*
- * Add privacy headers appropriate for the specified key.
- */
+uint8_t
+ieee80211_crypto_get_keyid(struct ieee80211vap *vap, struct ieee80211_key *k)
+{
+ if (k >= &vap->iv_nw_keys[0] &&
+ k < &vap->iv_nw_keys[IEEE80211_WEP_NKID])
+ return (k - vap->iv_nw_keys);
+ else
+ return (0);
+}
+
struct ieee80211_key *
-ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m)
+ieee80211_crypto_get_txkey(struct ieee80211_node *ni, struct mbuf *m)
{
struct ieee80211vap *vap = ni->ni_vap;
- struct ieee80211_key *k;
struct ieee80211_frame *wh;
- const struct ieee80211_cipher *cip;
- uint8_t keyid;
/*
* Multicast traffic always uses the multicast key.
@@ -550,14 +553,27 @@ ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m)
vap->iv_stats.is_tx_nodefkey++;
return NULL;
}
- keyid = vap->iv_def_txkey;
- k = &vap->iv_nw_keys[vap->iv_def_txkey];
- } else {
- keyid = 0;
- k = &ni->ni_ucastkey;
+ return &vap->iv_nw_keys[vap->iv_def_txkey];
}
- cip = k->wk_cipher;
- return (cip->ic_encap(k, m, keyid<<6) ? k : NULL);
+
+ return &ni->ni_ucastkey;
+}
+
+/*
+ * Add privacy headers appropriate for the specified key.
+ */
+struct ieee80211_key *
+ieee80211_crypto_encap(struct ieee80211_node *ni, struct mbuf *m)
+{
+ struct ieee80211_key *k;
+ const struct ieee80211_cipher *cip;
+
+ if ((k = ieee80211_crypto_get_txkey(ni, m)) != NULL) {
+ cip = k->wk_cipher;
+ return (cip->ic_encap(k, m) ? k : NULL);
+ }
+
+ return NULL;
}
/*
diff --git a/sys/net80211/ieee80211_crypto.h b/sys/net80211/ieee80211_crypto.h
index d7ac436..cca166d 100644
--- a/sys/net80211/ieee80211_crypto.h
+++ b/sys/net80211/ieee80211_crypto.h
@@ -178,8 +178,8 @@ struct ieee80211_cipher {
void* (*ic_attach)(struct ieee80211vap *, struct ieee80211_key *);
void (*ic_detach)(struct ieee80211_key *);
int (*ic_setkey)(struct ieee80211_key *);
- int (*ic_encap)(struct ieee80211_key *, struct mbuf *,
- uint8_t keyid);
+ void (*ic_setiv)(struct ieee80211_key *, uint8_t *);
+ int (*ic_encap)(struct ieee80211_key *, struct mbuf *);
int (*ic_decap)(struct ieee80211_key *, struct mbuf *, int);
int (*ic_enmic)(struct ieee80211_key *, struct mbuf *, int);
int (*ic_demic)(struct ieee80211_key *, struct mbuf *, int);
@@ -193,6 +193,10 @@ void ieee80211_crypto_register(const struct ieee80211_cipher *);
void ieee80211_crypto_unregister(const struct ieee80211_cipher *);
int ieee80211_crypto_available(u_int cipher);
+uint8_t ieee80211_crypto_get_keyid(struct ieee80211vap *vap,
+ struct ieee80211_key *k);
+struct ieee80211_key *ieee80211_crypto_get_txkey(struct ieee80211_node *,
+ struct mbuf *);
struct ieee80211_key *ieee80211_crypto_encap(struct ieee80211_node *,
struct mbuf *);
struct ieee80211_key *ieee80211_crypto_decap(struct ieee80211_node *,
diff --git a/sys/net80211/ieee80211_crypto_ccmp.c b/sys/net80211/ieee80211_crypto_ccmp.c
index 485a9cd..9fdd5e0 100644
--- a/sys/net80211/ieee80211_crypto_ccmp.c
+++ b/sys/net80211/ieee80211_crypto_ccmp.c
@@ -63,7 +63,8 @@ struct ccmp_ctx {
static void *ccmp_attach(struct ieee80211vap *, struct ieee80211_key *);
static void ccmp_detach(struct ieee80211_key *);
static int ccmp_setkey(struct ieee80211_key *);
-static int ccmp_encap(struct ieee80211_key *k, struct mbuf *, uint8_t keyid);
+static void ccmp_setiv(struct ieee80211_key *, uint8_t *);
+static int ccmp_encap(struct ieee80211_key *, struct mbuf *);
static int ccmp_decap(struct ieee80211_key *, struct mbuf *, int);
static int ccmp_enmic(struct ieee80211_key *, struct mbuf *, int);
static int ccmp_demic(struct ieee80211_key *, struct mbuf *, int);
@@ -78,6 +79,7 @@ static const struct ieee80211_cipher ccmp = {
.ic_attach = ccmp_attach,
.ic_detach = ccmp_detach,
.ic_setkey = ccmp_setkey,
+ .ic_setiv = ccmp_setiv,
.ic_encap = ccmp_encap,
.ic_decap = ccmp_decap,
.ic_enmic = ccmp_enmic,
@@ -134,11 +136,31 @@ ccmp_setkey(struct ieee80211_key *k)
return 1;
}
+static void
+ccmp_setiv(struct ieee80211_key *k, uint8_t *ivp)
+{
+ struct ccmp_ctx *ctx = k->wk_private;
+ struct ieee80211vap *vap = ctx->cc_vap;
+ uint8_t keyid;
+
+ keyid = ieee80211_crypto_get_keyid(vap, k) << 6;
+
+ k->wk_keytsc++;
+ ivp[0] = k->wk_keytsc >> 0; /* PN0 */
+ ivp[1] = k->wk_keytsc >> 8; /* PN1 */
+ ivp[2] = 0; /* Reserved */
+ ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */
+ ivp[4] = k->wk_keytsc >> 16; /* PN2 */
+ ivp[5] = k->wk_keytsc >> 24; /* PN3 */
+ ivp[6] = k->wk_keytsc >> 32; /* PN4 */
+ ivp[7] = k->wk_keytsc >> 40; /* PN5 */
+}
+
/*
* Add privacy headers appropriate for the specified key.
*/
static int
-ccmp_encap(struct ieee80211_key *k, struct mbuf *m, uint8_t keyid)
+ccmp_encap(struct ieee80211_key *k, struct mbuf *m)
{
struct ccmp_ctx *ctx = k->wk_private;
struct ieee80211com *ic = ctx->cc_ic;
@@ -157,15 +179,7 @@ ccmp_encap(struct ieee80211_key *k, struct mbuf *m, uint8_t keyid)
ovbcopy(ivp + ccmp.ic_header, ivp, hdrlen);
ivp += hdrlen;
- k->wk_keytsc++; /* XXX wrap at 48 bits */
- ivp[0] = k->wk_keytsc >> 0; /* PN0 */
- ivp[1] = k->wk_keytsc >> 8; /* PN1 */
- ivp[2] = 0; /* Reserved */
- ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */
- ivp[4] = k->wk_keytsc >> 16; /* PN2 */
- ivp[5] = k->wk_keytsc >> 24; /* PN3 */
- ivp[6] = k->wk_keytsc >> 32; /* PN4 */
- ivp[7] = k->wk_keytsc >> 40; /* PN5 */
+ ccmp_setiv(k, ivp);
/*
* Finally, do software encrypt if needed.
diff --git a/sys/net80211/ieee80211_crypto_none.c b/sys/net80211/ieee80211_crypto_none.c
index b1ffbb4..30f2fc3 100644
--- a/sys/net80211/ieee80211_crypto_none.c
+++ b/sys/net80211/ieee80211_crypto_none.c
@@ -48,7 +48,8 @@ __FBSDID("$FreeBSD$");
static void *none_attach(struct ieee80211vap *, struct ieee80211_key *);
static void none_detach(struct ieee80211_key *);
static int none_setkey(struct ieee80211_key *);
-static int none_encap(struct ieee80211_key *, struct mbuf *, uint8_t);
+static void none_setiv(struct ieee80211_key *, uint8_t *);
+static int none_encap(struct ieee80211_key *, struct mbuf *);
static int none_decap(struct ieee80211_key *, struct mbuf *, int);
static int none_enmic(struct ieee80211_key *, struct mbuf *, int);
static int none_demic(struct ieee80211_key *, struct mbuf *, int);
@@ -62,6 +63,7 @@ const struct ieee80211_cipher ieee80211_cipher_none = {
.ic_attach = none_attach,
.ic_detach = none_detach,
.ic_setkey = none_setkey,
+ .ic_setiv = none_setiv,
.ic_encap = none_encap,
.ic_decap = none_decap,
.ic_enmic = none_enmic,
@@ -87,20 +89,28 @@ none_setkey(struct ieee80211_key *k)
return 1;
}
+static void
+none_setiv(struct ieee80211_key *k, uint8_t *ivp)
+{
+}
+
static int
-none_encap(struct ieee80211_key *k, struct mbuf *m, uint8_t keyid)
+none_encap(struct ieee80211_key *k, struct mbuf *m)
{
struct ieee80211vap *vap = k->wk_private;
#ifdef IEEE80211_DEBUG
struct ieee80211_frame *wh = mtod(m, struct ieee80211_frame *);
#endif
+ uint8_t keyid;
+
+ keyid = ieee80211_crypto_get_keyid(vap, k);
/*
* The specified key is not setup; this can
* happen, at least, when changing keys.
*/
IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_CRYPTO, wh->i_addr1,
- "key id %u is not set (encap)", keyid>>6);
+ "key id %u is not set (encap)", keyid);
vap->iv_stats.is_tx_badcipher++;
return 0;
}
diff --git a/sys/net80211/ieee80211_crypto_tkip.c b/sys/net80211/ieee80211_crypto_tkip.c
index 16673de..8b33a79 100644
--- a/sys/net80211/ieee80211_crypto_tkip.c
+++ b/sys/net80211/ieee80211_crypto_tkip.c
@@ -54,7 +54,8 @@ __FBSDID("$FreeBSD$");
static void *tkip_attach(struct ieee80211vap *, struct ieee80211_key *);
static void tkip_detach(struct ieee80211_key *);
static int tkip_setkey(struct ieee80211_key *);
-static int tkip_encap(struct ieee80211_key *, struct mbuf *m, uint8_t keyid);
+static void tkip_setiv(struct ieee80211_key *, uint8_t *);
+static int tkip_encap(struct ieee80211_key *, struct mbuf *);
static int tkip_enmic(struct ieee80211_key *, struct mbuf *, int);
static int tkip_decap(struct ieee80211_key *, struct mbuf *, int);
static int tkip_demic(struct ieee80211_key *, struct mbuf *, int);
@@ -69,6 +70,7 @@ static const struct ieee80211_cipher tkip = {
.ic_attach = tkip_attach,
.ic_detach = tkip_detach,
.ic_setkey = tkip_setkey,
+ .ic_setiv = tkip_setiv,
.ic_encap = tkip_encap,
.ic_decap = tkip_decap,
.ic_enmic = tkip_enmic,
@@ -84,7 +86,6 @@ struct tkip_ctx {
struct ieee80211vap *tc_vap; /* for diagnostics+statistics */
u16 tx_ttak[5];
- int tx_phase1_done;
u8 tx_rc4key[16]; /* XXX for test module; make locals? */
u16 rx_ttak[5];
@@ -143,16 +144,35 @@ tkip_setkey(struct ieee80211_key *k)
__func__, k->wk_keylen, 128/NBBY);
return 0;
}
- k->wk_keytsc = 1; /* TSC starts at 1 */
ctx->rx_phase1_done = 0;
return 1;
}
+static void
+tkip_setiv(struct ieee80211_key *k, uint8_t *ivp)
+{
+ struct tkip_ctx *ctx = k->wk_private;
+ struct ieee80211vap *vap = ctx->tc_vap;
+ uint8_t keyid;
+
+ keyid = ieee80211_crypto_get_keyid(vap, k) << 6;
+
+ k->wk_keytsc++;
+ ivp[0] = k->wk_keytsc >> 8; /* TSC1 */
+ ivp[1] = (ivp[0] | 0x20) & 0x7f; /* WEP seed */
+ ivp[2] = k->wk_keytsc >> 0; /* TSC0 */
+ ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */
+ ivp[4] = k->wk_keytsc >> 16; /* TSC2 */
+ ivp[5] = k->wk_keytsc >> 24; /* TSC3 */
+ ivp[6] = k->wk_keytsc >> 32; /* TSC4 */
+ ivp[7] = k->wk_keytsc >> 40; /* TSC5 */
+}
+
/*
* Add privacy headers and do any s/w encryption required.
*/
static int
-tkip_encap(struct ieee80211_key *k, struct mbuf *m, uint8_t keyid)
+tkip_encap(struct ieee80211_key *k, struct mbuf *m)
{
struct tkip_ctx *ctx = k->wk_private;
struct ieee80211vap *vap = ctx->tc_vap;
@@ -185,24 +205,14 @@ tkip_encap(struct ieee80211_key *k, struct mbuf *m, uint8_t keyid)
memmove(ivp, ivp + tkip.ic_header, hdrlen);
ivp += hdrlen;
- ivp[0] = k->wk_keytsc >> 8; /* TSC1 */
- ivp[1] = (ivp[0] | 0x20) & 0x7f; /* WEP seed */
- ivp[2] = k->wk_keytsc >> 0; /* TSC0 */
- ivp[3] = keyid | IEEE80211_WEP_EXTIV; /* KeyID | ExtID */
- ivp[4] = k->wk_keytsc >> 16; /* TSC2 */
- ivp[5] = k->wk_keytsc >> 24; /* TSC3 */
- ivp[6] = k->wk_keytsc >> 32; /* TSC4 */
- ivp[7] = k->wk_keytsc >> 40; /* TSC5 */
+ tkip_setiv(k, ivp);
/*
* Finally, do software encrypt if needed.
*/
- if (k->wk_flags & IEEE80211_KEY_SWENCRYPT) {
- if (!tkip_encrypt(ctx, k, m, hdrlen))
- return 0;
- /* NB: tkip_encrypt handles wk_keytsc */
- } else
- k->wk_keytsc++;
+ if ((k->wk_flags & IEEE80211_KEY_SWENCRYPT) &&
+ !tkip_encrypt(ctx, k, m, hdrlen))
+ return 0;
return 1;
}
@@ -931,10 +941,9 @@ tkip_encrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
ctx->tc_vap->iv_stats.is_crypto_tkip++;
wh = mtod(m, struct ieee80211_frame *);
- if (!ctx->tx_phase1_done) {
+ if ((u16)(key->wk_keytsc) == 0 || key->wk_keytsc == 1) {
tkip_mixing_phase1(ctx->tx_ttak, key->wk_key, wh->i_addr2,
(u32)(key->wk_keytsc >> 16));
- ctx->tx_phase1_done = 1;
}
tkip_mixing_phase2(ctx->tx_rc4key, key->wk_key, ctx->tx_ttak,
(u16) key->wk_keytsc);
@@ -945,9 +954,6 @@ tkip_encrypt(struct tkip_ctx *ctx, struct ieee80211_key *key,
icv);
(void) m_append(m, IEEE80211_WEP_CRCLEN, icv); /* XXX check return */
- key->wk_keytsc++;
- if ((u16)(key->wk_keytsc) == 0)
- ctx->tx_phase1_done = 0;
return 1;
}
diff --git a/sys/net80211/ieee80211_crypto_wep.c b/sys/net80211/ieee80211_crypto_wep.c
index 2e84dd0..dbcf765 100644
--- a/sys/net80211/ieee80211_crypto_wep.c
+++ b/sys/net80211/ieee80211_crypto_wep.c
@@ -50,8 +50,9 @@ __FBSDID("$FreeBSD$");
static void *wep_attach(struct ieee80211vap *, struct ieee80211_key *);
static void wep_detach(struct ieee80211_key *);
static int wep_setkey(struct ieee80211_key *);
-static int wep_encap(struct ieee80211_key *, struct mbuf *, uint8_t keyid);
-static int wep_decap(struct ieee80211_key *, struct mbuf *, int hdrlen);
+static void wep_setiv(struct ieee80211_key *, uint8_t *);
+static int wep_encap(struct ieee80211_key *, struct mbuf *);
+static int wep_decap(struct ieee80211_key *, struct mbuf *, int);
static int wep_enmic(struct ieee80211_key *, struct mbuf *, int);
static int wep_demic(struct ieee80211_key *, struct mbuf *, int);
@@ -64,6 +65,7 @@ static const struct ieee80211_cipher wep = {
.ic_attach = wep_attach,
.ic_detach = wep_detach,
.ic_setkey = wep_setkey,
+ .ic_setiv = wep_setiv,
.ic_encap = wep_encap,
.ic_decap = wep_decap,
.ic_enmic = wep_enmic,
@@ -117,29 +119,15 @@ wep_setkey(struct ieee80211_key *k)
return k->wk_keylen >= 40/NBBY;
}
-/*
- * Add privacy headers appropriate for the specified key.
- */
-static int
-wep_encap(struct ieee80211_key *k, struct mbuf *m, uint8_t keyid)
+static void
+wep_setiv(struct ieee80211_key *k, uint8_t *ivp)
{
struct wep_ctx *ctx = k->wk_private;
- struct ieee80211com *ic = ctx->wc_ic;
+ struct ieee80211vap *vap = ctx->wc_vap;
uint32_t iv;
- uint8_t *ivp;
- int hdrlen;
-
- hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
+ uint8_t keyid;
- /*
- * Copy down 802.11 header and add the IV + KeyID.
- */
- M_PREPEND(m, wep.ic_header, M_NOWAIT);
- if (m == NULL)
- return 0;
- ivp = mtod(m, uint8_t *);
- ovbcopy(ivp + wep.ic_header, ivp, hdrlen);
- ivp += hdrlen;
+ keyid = ieee80211_crypto_get_keyid(vap, k) << 6;
/*
* XXX
@@ -182,6 +170,32 @@ wep_encap(struct ieee80211_key *k, struct mbuf *m, uint8_t keyid)
ivp[0] = iv >> 16;
#endif
ivp[3] = keyid;
+}
+
+/*
+ * Add privacy headers appropriate for the specified key.
+ */
+static int
+wep_encap(struct ieee80211_key *k, struct mbuf *m)
+{
+ struct wep_ctx *ctx = k->wk_private;
+ struct ieee80211com *ic = ctx->wc_ic;
+ uint8_t *ivp;
+ int hdrlen;
+
+ hdrlen = ieee80211_hdrspace(ic, mtod(m, void *));
+
+ /*
+ * Copy down 802.11 header and add the IV + KeyID.
+ */
+ M_PREPEND(m, wep.ic_header, M_NOWAIT);
+ if (m == NULL)
+ return 0;
+ ivp = mtod(m, uint8_t *);
+ ovbcopy(ivp + wep.ic_header, ivp, hdrlen);
+ ivp += hdrlen;
+
+ wep_setiv(k, ivp);
/*
* Finally, do software encrypt if needed.
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index 1c7ddb9..6388dac 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -957,7 +957,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
- case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */
+ case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only) */
error = ieee80211_ioctl_getwmeparam(vap, ireq);
break;
case IEEE80211_IOC_DTIM_PERIOD:
@@ -1757,13 +1757,14 @@ ieee80211_ioctl_setwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq)
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_wme_state *wme = &ic->ic_wme;
struct wmeParams *wmep, *chanp;
- int isbss, ac;
+ int isbss, ac, aggrmode;
if ((ic->ic_caps & IEEE80211_C_WME) == 0)
return EOPNOTSUPP;
isbss = (ireq->i_len & IEEE80211_WMEPARAM_BSS);
ac = (ireq->i_len & IEEE80211_WMEPARAM_VAL);
+ aggrmode = (wme->wme_flags & WME_F_AGGRMODE);
if (ac >= WME_NUM_AC)
ac = WME_AC_BE;
if (isbss) {
@@ -1775,47 +1776,28 @@ ieee80211_ioctl_setwmeparam(struct ieee80211vap *vap, struct ieee80211req *ireq)
}
switch (ireq->i_type) {
case IEEE80211_IOC_WME_CWMIN: /* WME: CWmin */
- if (isbss) {
- wmep->wmep_logcwmin = ireq->i_val;
- if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
- chanp->wmep_logcwmin = ireq->i_val;
- } else {
- wmep->wmep_logcwmin = chanp->wmep_logcwmin =
- ireq->i_val;
- }
+ wmep->wmep_logcwmin = ireq->i_val;
+ if (!isbss || !aggrmode)
+ chanp->wmep_logcwmin = ireq->i_val;
break;
case IEEE80211_IOC_WME_CWMAX: /* WME: CWmax */
- if (isbss) {
- wmep->wmep_logcwmax = ireq->i_val;
- if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
- chanp->wmep_logcwmax = ireq->i_val;
- } else {
- wmep->wmep_logcwmax = chanp->wmep_logcwmax =
- ireq->i_val;
- }
+ wmep->wmep_logcwmax = ireq->i_val;
+ if (!isbss || !aggrmode)
+ chanp->wmep_logcwmax = ireq->i_val;
break;
case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
- if (isbss) {
- wmep->wmep_aifsn = ireq->i_val;
- if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
- chanp->wmep_aifsn = ireq->i_val;
- } else {
- wmep->wmep_aifsn = chanp->wmep_aifsn = ireq->i_val;
- }
+ wmep->wmep_aifsn = ireq->i_val;
+ if (!isbss || !aggrmode)
+ chanp->wmep_aifsn = ireq->i_val;
break;
case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
- if (isbss) {
- wmep->wmep_txopLimit = ireq->i_val;
- if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
- chanp->wmep_txopLimit = ireq->i_val;
- } else {
- wmep->wmep_txopLimit = chanp->wmep_txopLimit =
- ireq->i_val;
- }
+ wmep->wmep_txopLimit = ireq->i_val;
+ if (!isbss || !aggrmode)
+ chanp->wmep_txopLimit = ireq->i_val;
break;
case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
wmep->wmep_acm = ireq->i_val;
- if ((wme->wme_flags & WME_F_AGGRMODE) == 0)
+ if (!aggrmode)
chanp->wmep_acm = ireq->i_val;
break;
case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only)*/
@@ -2945,7 +2927,7 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
case IEEE80211_IOC_WME_AIFS: /* WME: AIFS */
case IEEE80211_IOC_WME_TXOPLIMIT: /* WME: txops limit */
case IEEE80211_IOC_WME_ACM: /* WME: ACM (bss only) */
- case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (bss only) */
+ case IEEE80211_IOC_WME_ACKPOLICY: /* WME: ACK policy (!bss only) */
error = ieee80211_ioctl_setwmeparam(vap, ireq);
break;
case IEEE80211_IOC_DTIM_PERIOD:
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c
index 27fe929..19af613 100644
--- a/sys/net80211/ieee80211_output.c
+++ b/sys/net80211/ieee80211_output.c
@@ -2860,9 +2860,10 @@ ieee80211_tx_mgt_cb(struct ieee80211_node *ni, void *arg, int status)
static void
ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm,
- struct ieee80211_beacon_offsets *bo, struct ieee80211_node *ni)
+ struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
+ struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off;
struct ieee80211com *ic = ni->ni_ic;
struct ieee80211_rateset *rs = &ni->ni_rates;
uint16_t capinfo;
@@ -3021,8 +3022,7 @@ ieee80211_beacon_construct(struct mbuf *m, uint8_t *frm,
* Allocate a beacon frame and fillin the appropriate bits.
*/
struct mbuf *
-ieee80211_beacon_alloc(struct ieee80211_node *ni,
- struct ieee80211_beacon_offsets *bo)
+ieee80211_beacon_alloc(struct ieee80211_node *ni)
{
struct ieee80211vap *vap = ni->ni_vap;
struct ieee80211com *ic = ni->ni_ic;
@@ -3104,7 +3104,7 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni,
vap->iv_stats.is_tx_nobuf++;
return NULL;
}
- ieee80211_beacon_construct(m, frm, bo, ni);
+ ieee80211_beacon_construct(m, frm, ni);
M_PREPEND(m, sizeof(struct ieee80211_frame), M_NOWAIT);
KASSERT(m != NULL, ("no space for 802.11 header?"));
@@ -3125,10 +3125,10 @@ ieee80211_beacon_alloc(struct ieee80211_node *ni,
* Update the dynamic parts of a beacon frame based on the current state.
*/
int
-ieee80211_beacon_update(struct ieee80211_node *ni,
- struct ieee80211_beacon_offsets *bo, struct mbuf *m, int mcast)
+ieee80211_beacon_update(struct ieee80211_node *ni, struct mbuf *m, int mcast)
{
struct ieee80211vap *vap = ni->ni_vap;
+ struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off;
struct ieee80211com *ic = ni->ni_ic;
int len_changed = 0;
uint16_t capinfo;
@@ -3158,7 +3158,7 @@ ieee80211_beacon_update(struct ieee80211_node *ni,
* clear IEEE80211_BEACON_CSA.
*/
ieee80211_beacon_construct(m,
- mtod(m, uint8_t*) + sizeof(struct ieee80211_frame), bo, ni);
+ mtod(m, uint8_t*) + sizeof(struct ieee80211_frame), ni);
/* XXX do WME aggressive mode processing? */
IEEE80211_UNLOCK(ic);
diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h
index 273e759..4305863 100644
--- a/sys/net80211/ieee80211_proto.h
+++ b/sys/net80211/ieee80211_proto.h
@@ -346,8 +346,7 @@ struct ieee80211_beacon_offsets {
uint8_t *bo_meshconf; /* start of MESHCONF element */
uint8_t *bo_spare[3];
};
-struct mbuf *ieee80211_beacon_alloc(struct ieee80211_node *,
- struct ieee80211_beacon_offsets *);
+struct mbuf *ieee80211_beacon_alloc(struct ieee80211_node *);
/*
* Beacon frame updates are signaled through calls to iv_update_beacon
@@ -375,7 +374,7 @@ enum {
IEEE80211_BEACON_MESHCONF = 11, /* Mesh Configuration */
};
int ieee80211_beacon_update(struct ieee80211_node *,
- struct ieee80211_beacon_offsets *, struct mbuf *, int mcast);
+ struct mbuf *, int mcast);
void ieee80211_csa_startswitch(struct ieee80211com *,
struct ieee80211_channel *, int mode, int count);
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index 17f37d3..5c5b1c9 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -461,8 +461,7 @@ struct ieee80211vap {
int (*iv_key_delete)(struct ieee80211vap *,
const struct ieee80211_key *);
int (*iv_key_set)(struct ieee80211vap *,
- const struct ieee80211_key *,
- const uint8_t mac[IEEE80211_ADDR_LEN]);
+ const struct ieee80211_key *);
void (*iv_key_update_begin)(struct ieee80211vap *);
void (*iv_key_update_end)(struct ieee80211vap *);
diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
index 4098ffb..23e7a9b 100644
--- a/sys/netinet6/nd6.c
+++ b/sys/netinet6/nd6.c
@@ -134,6 +134,7 @@ static int regen_tmpaddr(struct in6_ifaddr *);
static void nd6_free(struct llentry *, int);
static void nd6_free_redirect(const struct llentry *);
static void nd6_llinfo_timer(void *);
+static void nd6_llinfo_settimer_locked(struct llentry *, long);
static void clear_llinfo_pqueue(struct llentry *);
static void nd6_rtrequest(int, struct rtentry *, struct rt_addrinfo *);
static int nd6_resolve_slow(struct ifnet *, struct mbuf *,
@@ -483,7 +484,7 @@ skip1:
/*
* ND6 timer routine to handle ND6 entries
*/
-void
+static void
nd6_llinfo_settimer_locked(struct llentry *ln, long tick)
{
int canceled;
@@ -512,12 +513,13 @@ nd6_llinfo_settimer_locked(struct llentry *ln, long tick)
}
/*
-* Gets source address of the first packet in hold queue
-* and stores it in @src.
-* Returns pointer to @src (if hold queue is not empty) or NULL.
-*
-*/
-static struct in6_addr *
+ * Gets source address of the first packet in hold queue
+ * and stores it in @src.
+ * Returns pointer to @src (if hold queue is not empty) or NULL.
+ *
+ * Set noinline to be dtrace-friendly
+ */
+static __noinline struct in6_addr *
nd6_llinfo_get_holdsrc(struct llentry *ln, struct in6_addr *src)
{
struct ip6_hdr hdr;
@@ -530,7 +532,7 @@ nd6_llinfo_get_holdsrc(struct llentry *ln, struct in6_addr *src)
* assume every packet in la_hold has the same IP header
*/
m = ln->la_hold;
- if (sizeof(hdr) < m->m_len)
+ if (sizeof(hdr) > m->m_len)
return (NULL);
m_copydata(m, 0, sizeof(hdr), (caddr_t)&hdr);
@@ -541,8 +543,10 @@ nd6_llinfo_get_holdsrc(struct llentry *ln, struct in6_addr *src)
/*
* Switch @lle state to new state optionally arming timers.
+ *
+ * Set noinline to be dtrace-friendly
*/
-void
+__noinline void
nd6_llinfo_setstate(struct llentry *lle, int newstate)
{
struct ifnet *ifp;
@@ -576,17 +580,12 @@ nd6_llinfo_setstate(struct llentry *lle, int newstate)
lle->ln_state = newstate;
}
-
-void
-nd6_llinfo_settimer(struct llentry *ln, long tick)
-{
-
- LLE_WLOCK(ln);
- nd6_llinfo_settimer_locked(ln, tick);
- LLE_WUNLOCK(ln);
-}
-
-static void
+/*
+ * Timer-dependent part of nd state machine.
+ *
+ * Set noinline to be dtrace-friendly
+ */
+static __noinline void
nd6_llinfo_timer(void *arg)
{
struct llentry *ln;
@@ -810,8 +809,31 @@ nd6_timer(void *arg)
goto addrloop;
}
}
+ } else if ((ia6->ia6_flags & IN6_IFF_TENTATIVE) != 0) {
+ /*
+ * Schedule DAD for a tentative address. This happens
+ * if the interface was down or not running
+ * when the address was configured.
+ */
+ int delay;
+
+ delay = arc4random() %
+ (MAX_RTR_SOLICITATION_DELAY * hz);
+ nd6_dad_start((struct ifaddr *)ia6, delay);
} else {
/*
+ * Check status of the interface. If it is down,
+ * mark the address as tentative for future DAD.
+ */
+ if ((ia6->ia_ifp->if_flags & IFF_UP) == 0 ||
+ (ia6->ia_ifp->if_drv_flags & IFF_DRV_RUNNING)
+ == 0 ||
+ (ND_IFINFO(ia6->ia_ifp)->flags &
+ ND6_IFF_IFDISABLED) != 0) {
+ ia6->ia6_flags &= ~IN6_IFF_DUPLICATED;
+ ia6->ia6_flags |= IN6_IFF_TENTATIVE;
+ }
+ /*
* A new RA might have made a deprecated address
* preferred.
*/
@@ -1156,8 +1178,10 @@ nd6_is_addr_neighbor(const struct sockaddr_in6 *addr, struct ifnet *ifp)
* Since the function would cause significant changes in the kernel, DO NOT
* make it global, unless you have a strong reason for the change, and are sure
* that the change is safe.
+ *
+ * Set noinline to be dtrace-friendly
*/
-static void
+static __noinline void
nd6_free(struct llentry *ln, int gc)
{
struct nd_defrouter *dr;
@@ -1452,7 +1476,8 @@ nd6_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp)
/* Mark all IPv6 address as tentative. */
ND_IFINFO(ifp)->flags |= ND6_IFF_IFDISABLED;
- if ((ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD) == 0) {
+ if (V_ip6_dad_count > 0 &&
+ (ND_IFINFO(ifp)->flags & ND6_IFF_NO_DAD) == 0) {
IF_ADDR_RLOCK(ifp);
TAILQ_FOREACH(ifa, &ifp->if_addrhead,
ifa_link) {
@@ -1725,9 +1750,12 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
lltable_link_entry(LLTABLE6(ifp), ln);
IF_AFDATA_WUNLOCK(ifp);
if (ln_tmp == NULL) {
- /* No existing lle, mark as new entry */
+ /* No existing lle, mark as new entry (6,7) */
is_newentry = 1;
nd6_llinfo_setstate(ln, ND6_LLINFO_STALE);
+ if (lladdr != NULL) /* (7) */
+ EVENTHANDLER_INVOKE(lle_event, ln,
+ LLENTRY_RESOLVED);
} else {
lltable_free_entry(LLTABLE6(ifp), ln);
ln = ln_tmp;
@@ -1764,10 +1792,9 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
*/
do_update = 0;
- if (!is_newentry && llchange != 0)
+ if (is_newentry == 0 && llchange != 0) {
do_update = 1; /* (3,5) */
- if (lladdr) { /* (3-5) and (7) */
/*
* Record source link-layer address
* XXX is it dependent to ifp->if_type?
@@ -1778,10 +1805,8 @@ nd6_cache_lladdr(struct ifnet *ifp, struct in6_addr *from, char *lladdr,
EVENTHANDLER_INVOKE(lle_event, ln, LLENTRY_RESOLVED);
- if (do_update) {
- if (ln->la_hold != NULL)
- nd6_grab_holdchain(ln, &chain, &sin6);
- }
+ if (ln->la_hold != NULL)
+ nd6_grab_holdchain(ln, &chain, &sin6);
}
/* Calculates new router status */
@@ -2011,8 +2036,10 @@ nd6_resolve(struct ifnet *ifp, int is_gw, struct mbuf *m,
* Heavy version.
* Function assume that destination LLE does not exist,
* is invalid or stale, so LLE_EXCLUSIVE lock needs to be acquired.
+ *
+ * Set noinline to be dtrace-friendly
*/
-static int
+static __noinline int
nd6_resolve_slow(struct ifnet *ifp, struct mbuf *m,
const struct sockaddr_in6 *dst, u_char *desten, uint32_t *pflags)
{
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
index c5f0eea..4c39a09 100644
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -408,8 +408,6 @@ struct llentry *nd6_lookup(const struct in6_addr *, int, struct ifnet *);
struct llentry *nd6_alloc(const struct in6_addr *, int, struct ifnet *);
void nd6_setmtu(struct ifnet *);
void nd6_llinfo_setstate(struct llentry *lle, int newstate);
-void nd6_llinfo_settimer(struct llentry *, long);
-void nd6_llinfo_settimer_locked(struct llentry *, long);
void nd6_timer(void *);
void nd6_purge(struct ifnet *);
int nd6_resolve(struct ifnet *, int, struct mbuf *,
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
index 7c3c87c..199dbee 100644
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -85,11 +85,11 @@ static struct dadq *nd6_dad_find(struct ifaddr *, struct nd_opt_nonce *);
static void nd6_dad_add(struct dadq *dp);
static void nd6_dad_del(struct dadq *dp);
static void nd6_dad_rele(struct dadq *);
-static void nd6_dad_starttimer(struct dadq *, int);
+static void nd6_dad_starttimer(struct dadq *, int, int);
static void nd6_dad_stoptimer(struct dadq *);
static void nd6_dad_timer(struct dadq *);
static void nd6_dad_duplicated(struct ifaddr *, struct dadq *);
-static void nd6_dad_ns_output(struct dadq *, struct ifaddr *);
+static void nd6_dad_ns_output(struct dadq *);
static void nd6_dad_ns_input(struct ifaddr *, struct nd_opt_nonce *);
static void nd6_dad_na_input(struct ifaddr *);
static void nd6_na_output_fib(struct ifnet *, const struct in6_addr *,
@@ -1199,9 +1199,11 @@ nd6_dad_find(struct ifaddr *ifa, struct nd_opt_nonce *n)
}
static void
-nd6_dad_starttimer(struct dadq *dp, int ticks)
+nd6_dad_starttimer(struct dadq *dp, int ticks, int send_ns)
{
+ if (send_ns != 0)
+ nd6_dad_ns_output(dp);
callout_reset(&dp->dad_timer_ch, ticks,
(void (*)(void *))nd6_dad_timer, (void *)dp);
}
@@ -1240,6 +1242,7 @@ nd6_dad_start(struct ifaddr *ifa, int delay)
struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
struct dadq *dp;
char ip6buf[INET6_ADDRSTRLEN];
+ int send_ns;
/*
* If we don't need DAD, don't do it.
@@ -1276,8 +1279,10 @@ nd6_dad_start(struct ifaddr *ifa, int delay)
return;
}
if ((dp = nd6_dad_find(ifa, NULL)) != NULL) {
- /* DAD already in progress */
- nd6_dad_rele(dp);
+ /*
+ * DAD already in progress. Let the existing entry
+ * to finish it.
+ */
return;
}
@@ -1310,13 +1315,12 @@ nd6_dad_start(struct ifaddr *ifa, int delay)
dp->dad_ns_lcount = dp->dad_loopbackprobe = 0;
refcount_init(&dp->dad_refcnt, 1);
nd6_dad_add(dp);
+ send_ns = 0;
if (delay == 0) {
- nd6_dad_ns_output(dp, ifa);
- nd6_dad_starttimer(dp,
- (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
- } else {
- nd6_dad_starttimer(dp, delay);
+ send_ns = 1;
+ delay = (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000;
}
+ nd6_dad_starttimer(dp, delay, send_ns);
}
/*
@@ -1386,7 +1390,8 @@ nd6_dad_timer(struct dadq *dp)
if ((dp->dad_ns_tcount > V_dad_maxtry) &&
(((ifp->if_flags & IFF_UP) == 0) ||
((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0))) {
- nd6log((LOG_INFO, "%s: could not run DAD, driver problem?\n",
+ nd6log((LOG_INFO, "%s: could not run DAD "
+ "because the interface was down or not running.\n",
if_name(ifa->ifa_ifp)));
goto err;
}
@@ -1396,9 +1401,8 @@ nd6_dad_timer(struct dadq *dp)
/*
* We have more NS to go. Send NS packet for DAD.
*/
- nd6_dad_ns_output(dp, ifa);
nd6_dad_starttimer(dp,
- (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
+ (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000, 1);
goto done;
} else {
/*
@@ -1426,11 +1430,11 @@ nd6_dad_timer(struct dadq *dp)
* Send an NS immediately and increase dad_count by
* V_nd6_mmaxtries - 1.
*/
- nd6_dad_ns_output(dp, ifa);
dp->dad_count =
dp->dad_ns_ocount + V_nd6_mmaxtries - 1;
nd6_dad_starttimer(dp,
- (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000);
+ (long)ND_IFINFO(ifa->ifa_ifp)->retrans * hz / 1000,
+ 1);
goto done;
} else {
/*
@@ -1517,10 +1521,10 @@ nd6_dad_duplicated(struct ifaddr *ifa, struct dadq *dp)
}
static void
-nd6_dad_ns_output(struct dadq *dp, struct ifaddr *ifa)
+nd6_dad_ns_output(struct dadq *dp)
{
- struct in6_ifaddr *ia = (struct in6_ifaddr *)ifa;
- struct ifnet *ifp = ifa->ifa_ifp;
+ struct in6_ifaddr *ia = (struct in6_ifaddr *)dp->dad_ifa;
+ struct ifnet *ifp = dp->dad_ifa->ifa_ifp;
int i;
dp->dad_ns_tcount++;
diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c
index 107c4b8..7ed4c1d 100644
--- a/sys/netpfil/ipfw/ip_fw_sockopt.c
+++ b/sys/netpfil/ipfw/ip_fw_sockopt.c
@@ -1531,7 +1531,7 @@ check_ipfw_rule_body(ipfw_insn *cmd, int cmd_len, struct rule_check_info *ci)
case O_IP_SRC_MASK:
case O_IP_DST_MASK:
/* only odd command lengths */
- if ( !(cmdlen & 1) || cmdlen > 31)
+ if ((cmdlen & 1) == 0)
goto bad_size;
break;
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index a3a9a10..8492f2e 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -149,6 +149,8 @@ static int sysctl_vm_page_blacklist(SYSCTL_HANDLER_ARGS);
SYSCTL_PROC(_vm, OID_AUTO, page_blacklist, CTLTYPE_STRING | CTLFLAG_RD |
CTLFLAG_MPSAFE, NULL, 0, sysctl_vm_page_blacklist, "A", "Blacklist pages");
+/* Is the page daemon waiting for free pages? */
+static int vm_pageout_pages_needed;
static uma_zone_t fakepg_zone;
diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c
index 0a18e6d..e0d00f5 100644
--- a/sys/vm/vm_pageout.c
+++ b/sys/vm/vm_pageout.c
@@ -157,7 +157,6 @@ SYSINIT(vmdaemon, SI_SUB_KTHREAD_VM, SI_ORDER_FIRST, kproc_start, &vm_kp);
int vm_pages_needed; /* Event on which pageout daemon sleeps */
int vm_pageout_deficit; /* Estimated number of pages deficit */
-int vm_pageout_pages_needed; /* flag saying that the pageout daemon needs pages */
int vm_pageout_wakeup_thresh;
#if !defined(NO_SWAPPING)
diff --git a/sys/vm/vm_pageout.h b/sys/vm/vm_pageout.h
index c7b4e90..9c8da8b 100644
--- a/sys/vm/vm_pageout.h
+++ b/sys/vm/vm_pageout.h
@@ -73,7 +73,6 @@
extern int vm_page_max_wired;
extern int vm_pages_needed; /* should be some "event" structure */
-extern int vm_pageout_pages_needed;
extern int vm_pageout_deficit;
extern int vm_pageout_page_count;
OpenPOWER on IntegriCloud