urtwn and hostap

Matthew Grooms mgrooms at shrew.net
Thu Sep 17 06:39:38 UTC 2015


Seems to behave better now and hostap appears to be working ...

#ifconfig wlan0 create wlandev urtwn0 wlanmode hostap
#ifconfig wlan0 list caps
drivercaps=2181c401<STA,HOSTAP,SHSLOT,SHPREAMBLE,MONITOR,WPA1,WPA2,BGSCAN>

#ifconfig wlan0 up ssid freebsdap mode 11g channel 1
#ifconfig bridge0 create up addm em0 addm wlan0

#ifconfig wlan0
wlan0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> metric 
0 mtu 1500
         ether 00:c3:e1:16:11:32
         nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
         media: IEEE 802.11 Wireless Ethernet autoselect mode 11g <hostap>
         status: running
         ssid freebsdap channel 1 (2412 MHz 11g) bssid 00:c3:e1:16:11:32
         country US authmode OPEN privacy OFF txpower 0 scanvalid 60
         protmode CTS dtimperiod 1 -dfs
         groups: wlan

#ifconfig bridge0
bridge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 
1500
         ether 02:df:20:d2:42:00
         nd6 options=1<PERFORMNUD>
         groups: bridge
         id 00:00:00:00:00:00 priority 32768 hellotime 2 fwddelay 15
         maxage 20 holdcnt 6 proto rstp maxaddr 2000 timeout 1200
         root id 00:00:00:00:00:00 priority 32768 ifcost 0 port 0
         member: wlan0 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP>
                 ifmaxaddr 0 port 3 priority 128 path cost 370370
         member: em0 flags=143<LEARNING,DISCOVER,AUTOEDGE,AUTOPTP>
                 ifmaxaddr 0 port 1 priority 128 path cost 20000

The speed leaves a lot to be desired. Throughput for the associated host 
is typically about 2Mbit down and 6Mbit up. I'm assume that's indicative 
of a problem. Occasionally I also see the this message on the console 
when I'm bringing the adapter up ...

wlan0: ieee80211_new_state_locked: pending INIT -> SCAN transition lost

If I down and up the adapter again, it seems to correct itself. Not sure 
what that's all about. I am passing the USB adapter through to a VM 
inside of ESXi to test the patch, so maybe that has something to do with 
these quirks. I'll try to run some tests with the adapter associated to 
a physical AP tomorrow to get a baseline.

Thanks,

-Matthew

On 9/16/2015 11:24 AM, Adrian Chadd wrote:
> The only one to look at is ath(4). I've not fixed/hacked on any other
> hostap chips. :)
>
> if_ath_beacon.c has the logic - it gets a reference when creating a
> beacon frame.
>
>
>
> -adrian
>
>
> On 16 September 2015 at 09:21, Matthew Grooms <mgrooms at shrew.net> wrote:
>> On 9/16/2015 10:58 AM, Adrian Chadd wrote:
>>> I think the net80211 beacon create routine doesn't allocate a node
>>> ref. Yeah, it doesn't. You have to do ieee80211_ref_node() after
>>> calling becaon_create(), and deref it if the tx fails. The TX success
>>> will free the node ref for you.
>>>
>> Got it. I'll take another look at one of the drivers that support hostap to
>> make sure I'm following the same pattern. Thanks again for the feedback!
>>
>> -Matthew
>>
>>
>>> -adrian
>>>
>>>
>>> On 16 September 2015 at 04:27, Idwer Vollering <vidwer at gmail.com> wrote:
>>>> 2015-09-16 8:06 GMT+02:00 Matthew Grooms <mgrooms at shrew.net>:
>>>>
>>>>> It looks like my screenshot got scrubbed. Here is my hopefully faithful
>>>>> transcription ...
>>>>>
>>>>> Fatal trap 9: general protection fault while in kernel mode
>>>>> cpuid = 3; apic id = 03
>>>>> instruction pointer = 0x20:0xffffffff80a01105
>>>>> stack pointer           = 0x28:0xfffffe0092fe86f0
>>>>> frame pointer         = 0x28:0xfffffe0092fe8740
>>>>> code segment         = base 0x0, limit 0xfffff, type 0x1b
>>>>>                                    = DPL 0, pres 1, long 1, def32 0, gran
>>>>> 1
>>>>> processor eflags     = interrupt enabled, resume, IOPL = 0
>>>>> current process      = 716 (ifconfig)
>>>>> [thread pid 716 tid 100082 ]
>>>>> Stopped at      __mtx_lock_flags+0x55:  movq    (%r13),%rax
>>>>> db> bt
>>>>> Tracing pid 716 tid 100082 td 0xffffff800512814d0
>>>>> __mtx_lock_flags() at __mtx_lock_flags+0x55/frame 0xfffffe0092fe8740
>>>>> ieee80211_free_node() at ieee80211_free_node()_0x38/frame
>>>>> 0xfffffe0092fe8780
>>>>> ieee80211_node_vdetach() at ieee80211_node_vdetach()+0x2d/frame
>>>>> 0xfffffe0092fe87a0
>>>>> ieee80211_vap_detach() at ieee80211_vap_detach()+0x35e/frame
>>>>> 0xfffffe0092fe87d0
>>>>> urtwn_vap_delete() at urtwn_vap_delete()+0xe/frame 0xfffffe0092fe87f0
>>>>> if_clone_destroyif() at if_clone_destroyif()+0x1aa/frame
>>>>> 0xfffffe0092fe8840
>>>>> if_clone_destroy() at if_clone_destroy()0x8e/frame 0xfffffe0092fe8860
>>>>> kern_ioctl() at kern_ioctl()+0x230/frame 0xfffffe0092fe88c0
>>>>> sys_ioctl() at sys_ioctl()+0x153/frame 0xfffffe0092fe89a0
>>>>> amd64_syscall() at amd64_syscall()+0x282/frame 0xfffffe0092fe8ab0
>>>>> Xfast_syscall() at Xfast_syscall()+0xfb/frame 0xfffffe0092fe8ab0
>>>>> -- syscall (54, FreeBSD ELF64, sys_ioctl), rip = 0x8011e8c8a, rsp =
>>>>> 0x7fffffffe2f8, rbp = 0x7fffffffe310 --
>>>>> db>
>>>> Assuming dumpdev="AUTO" is set in /etc/rc.conf, you should have
>>>> entered 'dump' at the db> blinker :)
>>>>
>>>> The trap details are found in /var/crash/, run kgdb: "kgdb
>>>> /boot/kernel/kernel /var/crash/vmcore.last", then run 'bt' and 'up' at
>>>> its prompt.
>>>>
>>>>> -Matthew
>>>>> _______________________________________________
>>>>> freebsd-wireless at freebsd.org mailing list
>>>>> https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
>>>>> To unsubscribe, send any mail to
>>>>> "freebsd-wireless-unsubscribe at freebsd.org"
>>>> _______________________________________________
>>>> freebsd-wireless at freebsd.org mailing list
>>>> https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
>>>> To unsubscribe, send any mail to
>>>> "freebsd-wireless-unsubscribe at freebsd.org"
>>> _______________________________________________
>>> freebsd-wireless at freebsd.org mailing list
>>> https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
>>> To unsubscribe, send any mail to
>>> "freebsd-wireless-unsubscribe at freebsd.org"
>>
>> _______________________________________________
>> freebsd-wireless at freebsd.org mailing list
>> https://lists.freebsd.org/mailman/listinfo/freebsd-wireless
>> To unsubscribe, send any mail to "freebsd-wireless-unsubscribe at freebsd.org"

-------------- next part --------------
Index: sys/dev/usb/wlan/if_urtwn.c
===================================================================
--- sys/dev/usb/wlan/if_urtwn.c	(revision 287342)
+++ sys/dev/usb/wlan/if_urtwn.c	(working copy)
@@ -181,6 +181,8 @@
 static struct mbuf *	urtwn_rxeof(struct usb_xfer *, struct urtwn_data *,
 			    int *, int8_t *);
 static void		urtwn_txeof(struct usb_xfer *, struct urtwn_data *);
+int			urtwn_txbcn(struct ieee80211vap *vap,
+			    struct ieee80211_node *);
 static int		urtwn_alloc_list(struct urtwn_softc *,
 			    struct urtwn_data[], int, int);
 static int		urtwn_alloc_rx_list(struct urtwn_softc *);
@@ -436,6 +438,10 @@
 		| IEEE80211_C_WPA		/* 802.11i */
 		;
 
+	if (sc->chip & URTWN_CHIP_88E)
+		ic->ic_caps |=
+		    IEEE80211_C_HOSTAP;		/* HostAp mode supported */
+
 	bands = 0;
 	setbit(&bands, IEEE80211_MODE_11B);
 	setbit(&bands, IEEE80211_MODE_11G);
@@ -857,6 +863,39 @@
 	sc->sc_txtimer = 0;
 }
 
+/*
+ * Push a beacon frame into the chip and check if it was accepted.  Beacon will
+ * be repeated by the chip every R92C_BCN_INTERVAL.
+ */
+int
+urtwn_txbcn(struct ieee80211vap *vap, struct ieee80211_node *ni)
+{
+	struct ieee80211com *ic = ni->ni_ic;
+	struct urtwn_softc *sc = ic->ic_softc;
+	struct urtwn_data *bf;
+	struct mbuf *m;
+
+	ieee80211_ref_node(ni);
+	m = ieee80211_beacon_alloc(ni, &URTWN_VAP(vap)->bo);
+
+	bf = urtwn_getbuf(sc);
+	if (bf == NULL) {
+		ieee80211_free_node(ni);
+		m_freem(m);
+		return (ENOBUFS);
+	}
+
+	if (urtwn_tx_start(sc, ni, m, bf) != 0) {
+		ieee80211_free_node(ni);
+		STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
+		return (EIO);
+	}
+
+	sc->sc_txtimer = 5;
+
+	return (0);
+}
+
 static void
 urtwn_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
 {
@@ -1466,6 +1505,7 @@
 	struct ieee80211_node *ni;
 	enum ieee80211_state ostate;
 	uint32_t reg;
+	int error;
 
 	ostate = vap->iv_state;
 	DPRINTF("%s -> %s\n", ieee80211_state_name[ostate],
@@ -1553,23 +1593,68 @@
 		}
 
 		ni = ieee80211_ref_node(vap->iv_bss);
-		/* Set media status to 'Associated'. */
-		reg = urtwn_read_4(sc, R92C_CR);
-		reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_INFRA);
-		urtwn_write_4(sc, R92C_CR, reg);
 
-		/* Set BSSID. */
-		urtwn_write_4(sc, R92C_BSSID + 0, LE_READ_4(&ni->ni_bssid[0]));
-		urtwn_write_4(sc, R92C_BSSID + 4, LE_READ_2(&ni->ni_bssid[4]));
+		if (ic->ic_opmode == IEEE80211_M_STA) {
+			/* Set BSSID. */
+			urtwn_write_4(sc, R92C_BSSID + 0,
+				LE_READ_4(&ni->ni_bssid[0]));
+			urtwn_write_4(sc, R92C_BSSID + 4,
+				LE_READ_2(&ni->ni_bssid[4]));
 
-		if (ic->ic_curmode == IEEE80211_MODE_11B)
-			urtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 0);
-		else	/* 802.11b/g */
-			urtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 3);
+			if (ic->ic_curmode == IEEE80211_MODE_11B)
+				urtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 0);
+			else	/* 802.11b/g */
+				urtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 3);
 
-		/* Enable Rx of data frames. */
-		urtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
+			/* Enable Rx of data frames. */
+			urtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
 
+			/* Allow Rx from our BSSID only. */
+			urtwn_write_4(sc, R92C_RCR, urtwn_read_4(sc, R92C_RCR) |
+			    R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN);
+
+			/* Set media status to 'Associated'. */
+			reg = urtwn_read_4(sc, R92C_CR);
+			reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_INFRA);
+			urtwn_write_4(sc, R92C_CR, reg);
+		}
+
+		if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
+			/* Set media status to 'AP'. */
+			reg = urtwn_read_4(sc, R92C_CR);
+			reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_AP);
+			urtwn_write_4(sc, R92C_CR, reg);
+
+			/* Set BSSID. */
+			urtwn_write_4(sc, R92C_BSSID + 0,
+			    LE_READ_4(&ni->ni_bssid[0]));
+			urtwn_write_4(sc, R92C_BSSID + 4,
+			    LE_READ_2(&ni->ni_bssid[4]));
+
+			/*
+			 * If 3rd or 4th bits are set to zero chip will stop
+			 * repeating beacon after first transmission for port0
+			 * and port1 respectively. This will cause STAs to
+			 * disconnect after short period of time.
+			 */
+			reg = urtwn_read_1(sc, R92C_MBID_NUM);
+			reg |= 0x8;
+			reg |= 0x10;
+			urtwn_write_1(sc, R92C_MBID_NUM, reg);
+
+			/* Invalidate cam entries */
+			urtwn_cam_init(sc);
+
+			/* Set chan/bw */
+			urtwn_set_chan(sc, ic->ic_curchan, NULL);
+
+			/* Push beacon frame into the chip */
+			error = urtwn_txbcn(vap, ni);
+			if (error != 0)
+				printf("%s: unable to push beacon into the"
+				    " chip\n", device_get_nameunit(sc->sc_dev));
+		}
+
 		/* Flush all AC queues. */
 		urtwn_write_1(sc, R92C_TXPAUSE, 0);
 
@@ -1576,11 +1661,6 @@
 		/* Set beacon interval. */
 		urtwn_write_2(sc, R92C_BCN_INTERVAL, ni->ni_intval);
 
-		/* Allow Rx from our BSSID only. */
-		urtwn_write_4(sc, R92C_RCR,
-		    urtwn_read_4(sc, R92C_RCR) |
-		    R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN);
-
 		/* Enable TSF synchronization. */
 		urtwn_tsf_sync_enable(sc);
 
@@ -1754,7 +1834,7 @@
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct usb_xfer *xfer;
 	struct r92c_tx_desc *txd;
-	uint8_t raid, type;
+	uint8_t raid, type, subtype;
 	uint16_t sum;
 	int i, hasqos, xferlen;
 	struct usb_xfer *urtwn_pipes[4] = {
@@ -1771,6 +1851,7 @@
 	 */
 	wh = mtod(m0, struct ieee80211_frame *);
 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+	subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
 
 	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
 		k = ieee80211_crypto_encap(ni, m0);
@@ -1819,7 +1900,7 @@
 		if (sc->chip & URTWN_CHIP_88E) {
 			txd->txdw1 |= htole32(
 			    SM(R88E_TXDW1_MACID, URTWN_MACID_BSS) |
-			    SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_BE) |
+			    SM(R92C_TXDW1_QSEL, R88E_TXDW1_QSEL_BE) |
 			    SM(R92C_TXDW1_RAID, raid));
 			txd->txdw2 |= htole32(R88E_TXDW2_AGGBK);
 		} else {
@@ -1843,9 +1924,20 @@
 		/* Send data at OFDM54. */
 		txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, 11));
 	} else {
+		/*
+		 * If beacon frame is pushed into wrong queue, the chip won't
+		 * start repeating it.
+		 */
+		if (subtype == IEEE80211_FC0_SUBTYPE_BEACON &&
+		    sc->chip & URTWN_CHIP_88E)
+			txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL,
+			    R88E_TXDW1_QSEL_MGNT));
+		else
+			txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL,
+			    R92C_TXDW1_QSEL_MGNT));
+
 		txd->txdw1 |= htole32(
 		    SM(R92C_TXDW1_MACID, 0) |
-		    SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT) |
 		    SM(R92C_TXDW1_RAID, R92C_RAID_11B));
 
 		/* Force CCK1. */
Index: sys/dev/usb/wlan/if_urtwnreg.h
===================================================================
--- sys/dev/usb/wlan/if_urtwnreg.h	(revision 287342)
+++ sys/dev/usb/wlan/if_urtwnreg.h	(working copy)
@@ -1019,7 +1019,9 @@
 #define R92C_TXDW1_QSEL_M	0x00001f00
 #define R92C_TXDW1_QSEL_S	8
 #define R92C_TXDW1_QSEL_BE	0x00
+#define R88E_TXDW1_QSEL_BE	0x03
 #define R92C_TXDW1_QSEL_MGNT	0x12
+#define R88E_TXDW1_QSEL_MGNT	0x10
 #define R92C_TXDW1_RAID_M	0x000f0000
 #define R92C_TXDW1_RAID_S	16
 #define R92C_TXDW1_CIPHER_M	0x00c00000


More information about the freebsd-wireless mailing list