Re: athn(4) USB open firmware support

2018-02-04 Thread Kevin Lo
On Sun, Feb 04, 2018 at 09:54:35PM +0100, Stefan Sperling wrote:
> 
> On Sun, Feb 04, 2018 at 11:15:01AM +0100, Stefan Sperling wrote:
> > On Sun, Feb 04, 2018 at 12:01:58AM +0100, Stefan Sperling wrote:
> > > I have also briefly tested hostap with both AR9271 and AR7010 and it
> > > now seems to work well enough to justify removing the BUGS section from
> > > the athn(4) page.
> > 
> > I have to retract the above statement.
> > I've done some more testing and hostap mode still has serious problems.
> > But it can be fixed later. I've already got some ideas about what's wrong.
> 
> Here is a new version with fixed hostap mode.
> 
> There were two major problems for hostap with the previous code:
> 
> 1) The previous code tried to add each new node to the firmware's table
> when an ASSOC request is about to be confirmed. But that is too late.
> We need to add the new client to the firmware's node table already
> when net80211 tries to acknowledge the AUTH request.
> Otherwise our AUTH response will be dropped by the device because it
> has no destination node in the firmware. The client will now keep
> trying to AUTH, and until it has done so it won't try to ASSOC.
> The fix requires a new function hook in net80211 which drivers can set if
> they need to do something before an incoming AUTH request is acknowledged.
> Some client capabilities are not available this early, so this driver
> still needs to update the node's rate set when an ASSOC request is
> acknowledged (otherwise we'd break 11n support).
> 
> 2) There is only room for 8 nodes in the firmware's node table.
> The previous code used a counter to keep track of nodes added/removed,
> but for hostap a counter is insufficient as nodes will show up and leave
> in no particular order.
> What is needed instead is a bitmask which keeps track of free node slots.
> Since there are only 8 slots, we need to be a bit aggressive about removing
> inactive clients when the table is full and a new client wants to connect.
> However, it is still hard for new clients to steal slots which are being
> legitimately used. We rely on net80211's inactivity timer to detect inactive
> clients. It takes about a minute or so for a new client to associate to
> an AP with a full table and no active clients. I think this is acceptable.
> 
> This diff keeps growing Can I commit?

A quick test went fine for me.

Tested in hostap mode and client mode with:
athn0 at uhub0 port 2 configuration 1 interface 0 "ATHEROS USB2.0 WLAN" rev 
2.00/1.08 addr 2
athn0: AR9271 rev 1 (1T1R), ROM rev 13, address xx:xx:xx:xx:xx:xx

In client mode, I see TCP download rates go up to 750KB/s; when running an AP
with this device, TCP download rates for iwn are a little slower.

ok kevlo@



Re: athn(4) USB open firmware support

2018-02-04 Thread Stefan Sperling
On Sun, Feb 04, 2018 at 11:15:01AM +0100, Stefan Sperling wrote:
> On Sun, Feb 04, 2018 at 12:01:58AM +0100, Stefan Sperling wrote:
> > I have also briefly tested hostap with both AR9271 and AR7010 and it
> > now seems to work well enough to justify removing the BUGS section from
> > the athn(4) page.
> 
> I have to retract the above statement.
> I've done some more testing and hostap mode still has serious problems.
> But it can be fixed later. I've already got some ideas about what's wrong.

Here is a new version with fixed hostap mode.

There were two major problems for hostap with the previous code:

1) The previous code tried to add each new node to the firmware's table
when an ASSOC request is about to be confirmed. But that is too late.
We need to add the new client to the firmware's node table already
when net80211 tries to acknowledge the AUTH request.
Otherwise our AUTH response will be dropped by the device because it
has no destination node in the firmware. The client will now keep
trying to AUTH, and until it has done so it won't try to ASSOC.
The fix requires a new function hook in net80211 which drivers can set if
they need to do something before an incoming AUTH request is acknowledged.
Some client capabilities are not available this early, so this driver
still needs to update the node's rate set when an ASSOC request is
acknowledged (otherwise we'd break 11n support).

2) There is only room for 8 nodes in the firmware's node table.
The previous code used a counter to keep track of nodes added/removed,
but for hostap a counter is insufficient as nodes will show up and leave
in no particular order.
What is needed instead is a bitmask which keeps track of free node slots.
Since there are only 8 slots, we need to be a bit aggressive about removing
inactive clients when the table is full and a new client wants to connect.
However, it is still hard for new clients to steal slots which are being
legitimately used. We rely on net80211's inactivity timer to detect inactive
clients. It takes about a minute or so for a new client to associate to
an AP with a full table and no active clients. I think this is acceptable.

This diff keeps growing Can I commit?

Index: dev/usb/if_athn_usb.c
===
RCS file: /cvs/src/sys/dev/usb/if_athn_usb.c,v
retrieving revision 1.48
diff -u -p -r1.48 if_athn_usb.c
--- dev/usb/if_athn_usb.c   26 Oct 2017 15:00:28 -  1.48
+++ dev/usb/if_athn_usb.c   4 Feb 2018 20:27:26 -
@@ -130,17 +130,27 @@ void  athn_usb_newstate_cb(struct athn_u
 void   athn_usb_newassoc(struct ieee80211com *,
struct ieee80211_node *, int);
 void   athn_usb_newassoc_cb(struct athn_usb_softc *, void *);
-void   athn_usb_node_leave(struct ieee80211com *,
+struct ieee80211_node *athn_usb_node_alloc(struct ieee80211com *);
+void   athn_usb_count_active_sta(void *, struct ieee80211_node *);
+void   athn_usb_newauth_cb(struct athn_usb_softc *, void *);
+intathn_usb_newauth(struct ieee80211com *,
+   struct ieee80211_node *, int, uint16_t);
+void   athn_usb_node_free(struct ieee80211com *,
struct ieee80211_node *);
-void   athn_usb_node_leave_cb(struct athn_usb_softc *, void *);
+void   athn_usb_node_free_cb(struct athn_usb_softc *, void *);
 intathn_usb_ampdu_tx_start(struct ieee80211com *,
struct ieee80211_node *, uint8_t);
 void   athn_usb_ampdu_tx_start_cb(struct athn_usb_softc *, void *);
 void   athn_usb_ampdu_tx_stop(struct ieee80211com *,
struct ieee80211_node *, uint8_t);
 void   athn_usb_ampdu_tx_stop_cb(struct athn_usb_softc *, void *);
+void   athn_usb_clean_nodes(void *, struct ieee80211_node *);
 intathn_usb_create_node(struct athn_usb_softc *,
struct ieee80211_node *);
+intathn_usb_node_set_rates(struct athn_usb_softc *,
+   struct ieee80211_node *);
+intathn_usb_remove_node(struct athn_usb_softc *,
+   struct ieee80211_node *);
 void   athn_usb_rx_enable(struct athn_softc *);
 intathn_set_chan(struct athn_softc *, struct ieee80211_channel *,
struct ieee80211_channel *);
@@ -159,6 +169,7 @@ voidathn_usb_delete_key_cb(struct athn
 void   athn_usb_bcneof(struct usbd_xfer *, void *,
usbd_status);
 void   athn_usb_swba(struct athn_usb_softc *);
+void   athn_usb_tx_status(void *, struct ieee80211_node *);
 void   athn_usb_rx_wmi_ctrl(struct athn_usb_softc *, uint8_t *, int);
 void   athn_usb_intr(struct usbd_xfer *, void *,
usbd_status);
@@ -319,8 +330,13 @@ athn_usb_attachhook(struct device *self)
ifp->if_ioctl = athn_usb_ioctl;
ifp->if_start = 

Re: athn(4) USB open firmware support

2018-02-04 Thread Stefan Sperling
On Sun, Feb 04, 2018 at 12:01:58AM +0100, Stefan Sperling wrote:
> I have also briefly tested hostap with both AR9271 and AR7010 and it
> now seems to work well enough to justify removing the BUGS section from
> the athn(4) page.

I have to retract the above statement.
I've done some more testing and hostap mode still has serious problems.
But it can be fixed later. I've already got some ideas about what's wrong.



Re: athn(4) USB open firmware support

2018-02-03 Thread Stefan Sperling
On Fri, Nov 17, 2017 at 12:28:35AM +0100, Stefan Sperling wrote:
> This diff switches athn(4) USB devices to open source firmware.
> 
> I only have an AR9271 device which I can test with:
> athn0 at uhub1 port 2 configuration 1 interface 0 "ATHEROS USB2.0 WLAN" rev 
> 2.00/1.08 addr 3
> athn0: AR9271 rev 1 (1T1R), ROM rev 13, address xx:xx:xx:xx:xx:xx
> 
> The diff switches AR7010 devices over as well because this new code
> will *not* support the old binary-only firmware anyway.
> But it is possible that AR7010 devices don't work yet with this diff.
> Can anybody help and test such a device? And if anyone would like to
> donate an AR7010 device for me to develop with, that would be appreciated.

I have received an AR7010 device from Stuart Henderson and now have
this device working as well. It actually didn't work properly even
with the old firmware due to existing bugs in the driver.

This new diff also makes use of the open firmware's Tx rate reports.
Tx rate scaling is always done in firmware on these devices and there
seems to be no way around that. What the driver can do is show which
Tx rate the firmware has most recently chosen in 'ifconfig athn0' output.
We could tweak the Tx rate scaling algo in firmware code of course :-)

I have also briefly tested hostap with both AR9271 and AR7010 and it
now seems to work well enough to justify removing the BUGS section from
the athn(4) page. I still wouldn't recommend using such a device as
primary AP because it can only support up to 8 clients, and association
to AR9271 was a bit flaky in my testing.

> The new firmware package 'athn-firmware-1.1p3', which contains the open
> firmware files, is required. Specifically, the diff needs these files
> from the new firmware package:
> 
>   /etc/firmware/athn-open-ar7010
>   /etc/firmware/athn-open-ar9271

This new firmware has been in fw_update for some time now so we can
commit this change without disrupting users tracking -current.

We should keep the old firmware file around for a while, just in case
this change needs to be reverted for some reason.

ok?

Index: if_athn_usb.c
===
RCS file: /cvs/src/sys/dev/usb/if_athn_usb.c,v
retrieving revision 1.48
diff -u -p -r1.48 if_athn_usb.c
--- if_athn_usb.c   26 Oct 2017 15:00:28 -  1.48
+++ if_athn_usb.c   3 Feb 2018 22:08:54 -
@@ -159,6 +159,7 @@ voidathn_usb_delete_key_cb(struct athn
 void   athn_usb_bcneof(struct usbd_xfer *, void *,
usbd_status);
 void   athn_usb_swba(struct athn_usb_softc *);
+void   athn_usb_tx_status(void *, struct ieee80211_node *);
 void   athn_usb_rx_wmi_ctrl(struct athn_usb_softc *, uint8_t *, int);
 void   athn_usb_intr(struct usbd_xfer *, void *,
usbd_status);
@@ -629,12 +630,9 @@ athn_usb_load_firmware(struct athn_usb_s
/* Determine which firmware image to load. */
if (usc->flags & ATHN_USB_FLAG_AR7010) {
dd = usbd_get_device_descriptor(usc->sc_udev);
-   if (UGETW(dd->bcdDevice) == 0x0202)
-   name = "athn-ar7010-11";
-   else
-   name = "athn-ar7010";
+   name = "athn-open-ar7010";
} else
-   name = "athn-ar9271";
+   name = "athn-open-ar9271";
/* Read firmware image from the filesystem. */
if ((error = loadfirmware(name, , )) != 0) {
printf("%s: failed loadfirmware of file %s (error %d)\n",
@@ -1033,7 +1031,6 @@ athn_usb_newstate_cb(struct athn_usb_sof
 
s = splnet();
ostate = ic->ic_state;
-   DPRINTF(("newstate %d -> %d\n", ostate, cmd->state));
 
if (ostate == IEEE80211_S_RUN) {
sta_index = ((struct athn_node *)ic->ic_bss)->sta_index;
@@ -1053,13 +1050,21 @@ athn_usb_newstate_cb(struct athn_usb_sof
case IEEE80211_S_SCAN:
/* Make the LED blink while scanning. */
athn_set_led(sc, !sc->led_state);
-   (void)athn_usb_switch_chan(sc, ic->ic_bss->ni_chan, NULL);
+   error = athn_usb_switch_chan(sc, ic->ic_bss->ni_chan, NULL);
+   if (error)
+   printf("%s: could not switch to channel %d\n",
+   usc->usb_dev.dv_xname,
+   ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan));
if (!usbd_is_dying(usc->sc_udev))
timeout_add_msec(>scan_to, 200);
break;
case IEEE80211_S_AUTH:
athn_set_led(sc, 0);
error = athn_usb_switch_chan(sc, ic->ic_bss->ni_chan, NULL);
+   if (error)
+   printf("%s: could not switch to channel %d\n",
+   usc->usb_dev.dv_xname,
+   ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan));
break;
case 

Re: athn(4) USB open firmware support

2017-11-17 Thread Kevin Lo
On Fri, Nov 17, 2017 at 12:28:35AM +0100, Stefan Sperling wrote:
> 
> This diff switches athn(4) USB devices to open source firmware.
> 
> I only have an AR9271 device which I can test with:
> athn0 at uhub1 port 2 configuration 1 interface 0 "ATHEROS USB2.0 WLAN" rev 
> 2.00/1.08 addr 3
> athn0: AR9271 rev 1 (1T1R), ROM rev 13, address xx:xx:xx:xx:xx:xx
> 
> The diff switches AR7010 devices over as well because this new code
> will *not* support the old binary-only firmware anyway.
> But it is possible that AR7010 devices don't work yet with this diff.
> Can anybody help and test such a device? And if anyone would like to
> donate an AR7010 device for me to develop with, that would be appreciated.
> 
> The new firmware package 'athn-firmware-1.1p3', which contains the open
> firmware files, is required. Specifically, the diff needs these files
> from the new firmware package:
> 
>   /etc/firmware/athn-open-ar7010
>   /etc/firmware/athn-open-ar9271
> 
> The firmware mirrors currently still ship version 1.1p2 which lacks the
> open firmware files. But the pre-built firmware images are already part
> of package mirrors, so a new firmware package can be built without
> having to first cross-compile the firmware, like this:
> 
>   pkg_delete athn-firmware  # else conflict during install, no idea why
>   cd /usr/ports/sysutils/firmware/athn
>   make FETCH_PACKAGES=Yes install
> 
> Thanks again to bentley@ for porting both the required cross toolchain
> and the open ath9k firmware during p2k17!

Thanks for stepping up and getting this done.  Tested on TP-LINK TL-WN722N,
and it works for me :)

$ dmesg | grep athn0
athn0 at uhub0 port 4 configuration 1 interface 0 "ATHEROS USB2.0 WLAN" rev 
2.00/1.08 addr 3
athn0: AR9271 rev 1 (1T1R), ROM rev 13, address d8:5d:4c:98:60:f9

$ pkg_info -L athn-firmware-1.1p3
Information for inst:athn-firmware-1.1p3

Files:
/etc/firmware/athn-ar7010
/etc/firmware/athn-open-ar7010
/etc/firmware/athn-ar7010-11
/etc/firmware/athn-ar9271
/etc/firmware/athn-open-ar9271
/etc/firmware/athn-license

$ ifconfig athn0
athn0: flags=8843 mtu 1500
lladdr d8:5d:4c:98:60:f9
index 6 priority 4 llprio 3
groups: wlan egress
media: IEEE802.11 autoselect (HT-MCS0 mode 11n)
status: active
ieee80211: nwid bf-2.4g chan 3 bssid f4:28:53:6c:04:1a -20dBm wpakey 
0xd5d0c0f79932dd4619e08d995981d9aa9acc622d6f3a40f0dd4fb2e8bdbc8c98 wpaprotos 
wpa2 wpaakms psk wpaciphers ccmp wpagroupcipher ccmp
inet 172.29.30.123 netmask 0xff00 broadcast 172.29.30.255



athn(4) USB open firmware support

2017-11-16 Thread Stefan Sperling
This diff switches athn(4) USB devices to open source firmware.

I only have an AR9271 device which I can test with:
athn0 at uhub1 port 2 configuration 1 interface 0 "ATHEROS USB2.0 WLAN" rev 
2.00/1.08 addr 3
athn0: AR9271 rev 1 (1T1R), ROM rev 13, address xx:xx:xx:xx:xx:xx

The diff switches AR7010 devices over as well because this new code
will *not* support the old binary-only firmware anyway.
But it is possible that AR7010 devices don't work yet with this diff.
Can anybody help and test such a device? And if anyone would like to
donate an AR7010 device for me to develop with, that would be appreciated.

The new firmware package 'athn-firmware-1.1p3', which contains the open
firmware files, is required. Specifically, the diff needs these files
from the new firmware package:

  /etc/firmware/athn-open-ar7010
  /etc/firmware/athn-open-ar9271

The firmware mirrors currently still ship version 1.1p2 which lacks the
open firmware files. But the pre-built firmware images are already part
of package mirrors, so a new firmware package can be built without
having to first cross-compile the firmware, like this:

  pkg_delete athn-firmware  # else conflict during install, no idea why
  cd /usr/ports/sysutils/firmware/athn
  make FETCH_PACKAGES=Yes install

Thanks again to bentley@ for porting both the required cross toolchain
and the open ath9k firmware during p2k17!

Index: if_athn_usb.c
===
RCS file: /cvs/src/sys/dev/usb/if_athn_usb.c,v
retrieving revision 1.48
diff -u -p -r1.48 if_athn_usb.c
--- if_athn_usb.c   26 Oct 2017 15:00:28 -  1.48
+++ if_athn_usb.c   16 Nov 2017 23:24:55 -
@@ -629,12 +629,9 @@ athn_usb_load_firmware(struct athn_usb_s
/* Determine which firmware image to load. */
if (usc->flags & ATHN_USB_FLAG_AR7010) {
dd = usbd_get_device_descriptor(usc->sc_udev);
-   if (UGETW(dd->bcdDevice) == 0x0202)
-   name = "athn-ar7010-11";
-   else
-   name = "athn-ar7010";
+   name = "athn-open-ar7010";
} else
-   name = "athn-ar9271";
+   name = "athn-open-ar9271";
/* Read firmware image from the filesystem. */
if ((error = loadfirmware(name, , )) != 0) {
printf("%s: failed loadfirmware of file %s (error %d)\n",
@@ -1033,7 +1030,9 @@ athn_usb_newstate_cb(struct athn_usb_sof
 
s = splnet();
ostate = ic->ic_state;
-   DPRINTF(("newstate %d -> %d\n", ostate, cmd->state));
+   DPRINTF(("newstate %s -> %s\n",
+   ieee80211_state_name[ostate],
+   ieee80211_state_name[cmd->state]));
 
if (ostate == IEEE80211_S_RUN) {
sta_index = ((struct athn_node *)ic->ic_bss)->sta_index;
@@ -1228,8 +1227,6 @@ athn_usb_create_node(struct athn_usb_sof
memset(, 0, sizeof(sta));
IEEE80211_ADDR_COPY(sta.macaddr, ni->ni_macaddr);
IEEE80211_ADDR_COPY(sta.bssid, ni->ni_bssid);
-   sta.associd = htobe16(ni->ni_associd);
-   sta.valid = 1;
sta.sta_index = an->sta_index;
sta.maxampdu = 0x;
if (ni->ni_flags & IEEE80211_NODE_HT)
@@ -1522,7 +1519,6 @@ void
 athn_usb_rx_wmi_ctrl(struct athn_usb_softc *usc, uint8_t *buf, int len)
 {
struct ar_wmi_cmd_hdr *wmi;
-   struct ar_wmi_evt_txrate *txrate;
uint16_t cmd_id;
 
if (__predict_false(len < sizeof(*wmi)))
@@ -1547,10 +1543,16 @@ athn_usb_rx_wmi_ctrl(struct athn_usb_sof
athn_usb_swba(usc);
break;
 #endif
-   case AR_WMI_EVT_TXRATE:
-   txrate = (struct ar_wmi_evt_txrate *)[1];
-   DPRINTF(("txrate=%d\n", betoh32(txrate->txrate)));
+   case AR_WMI_EVT_TXSTATUS: {
+#ifdef ATH_DEBUG
+   struct ar_wmi_evt_txstatus *ts;
+   int i;
+   ts = (struct ar_wmi_evt_txstatus *)[1];
+   for (i = 0; i < ts->count && i < AR_HTC_MAX_TX_STATUS; i++)
+   DPRINTF(("ts[%d]=%d\n", i, ts->ts[i].rate));
+#endif
break;
+   }
case AR_WMI_EVT_FATAL:
printf("%s: fatal firmware error\n", usc->usb_dev.dv_xname);
break;
@@ -2286,13 +2288,9 @@ athn_usb_init(struct ifnet *ifp)
 
/* Update target capabilities. */
memset(, 0, sizeof(hic));
-   hic.flags = htobe32(0x400c2400);
-   hic.flags_ext = htobe32(0x00106080);
hic.ampdu_limit = htobe32(0x);
hic.ampdu_subframes = 20;
-   hic.protmode = 1;   /* XXX */
-   hic.lg_txchainmask = sc->txchainmask;
-   hic.ht_txchainmask = sc->txchainmask;
+   hic.txchainmask = sc->txchainmask;
DPRINTF(("updating target configuration\n"));
error = athn_usb_wmi_xcmd(usc, AR_WMI_CMD_TARGET_IC_UPDATE,
, sizeof(hic), NULL);
Index: if_athn_usb.h
===
RCS