2013-07-30 02:07:57 +00:00
|
|
|
/* $OpenBSD: if_rsu.c,v 1.17 2013/04/15 09:23:01 mglocker Exp $ */
|
|
|
|
|
|
|
|
/*-
|
|
|
|
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
|
|
__FBSDID("$FreeBSD$");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Driver for Realtek RTL8188SU/RTL8191SU/RTL8192SU.
|
|
|
|
*
|
|
|
|
* TODO:
|
2015-09-21 02:32:11 +00:00
|
|
|
* o 11n HT40 support
|
2013-07-30 02:07:57 +00:00
|
|
|
* o h/w crypto
|
|
|
|
* o hostap / ibss / mesh
|
2015-09-21 02:32:11 +00:00
|
|
|
* o sensible RSSI levels
|
|
|
|
* o power-save operation
|
2013-07-30 02:07:57 +00:00
|
|
|
*/
|
2015-09-12 23:10:34 +00:00
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/endian.h>
|
|
|
|
#include <sys/sockio.h>
|
|
|
|
#include <sys/mbuf.h>
|
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/conf.h>
|
|
|
|
#include <sys/bus.h>
|
|
|
|
#include <sys/rman.h>
|
|
|
|
#include <sys/firmware.h>
|
|
|
|
#include <sys/module.h>
|
|
|
|
|
|
|
|
#include <machine/bus.h>
|
|
|
|
#include <machine/resource.h>
|
|
|
|
|
|
|
|
#include <net/bpf.h>
|
|
|
|
#include <net/if.h>
|
2013-10-26 17:58:36 +00:00
|
|
|
#include <net/if_var.h>
|
2013-07-30 02:07:57 +00:00
|
|
|
#include <net/if_arp.h>
|
|
|
|
#include <net/if_dl.h>
|
|
|
|
#include <net/if_media.h>
|
|
|
|
#include <net/if_types.h>
|
|
|
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <netinet/in_systm.h>
|
|
|
|
#include <netinet/in_var.h>
|
|
|
|
#include <netinet/if_ether.h>
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
|
|
|
|
#include <net80211/ieee80211_var.h>
|
|
|
|
#include <net80211/ieee80211_regdomain.h>
|
|
|
|
#include <net80211/ieee80211_radiotap.h>
|
|
|
|
|
|
|
|
#include <dev/usb/usb.h>
|
|
|
|
#include <dev/usb/usbdi.h>
|
|
|
|
#include "usbdevs.h"
|
|
|
|
|
|
|
|
#define USB_DEBUG_VAR rsu_debug
|
|
|
|
#include <dev/usb/usb_debug.h>
|
|
|
|
|
|
|
|
#include <dev/usb/wlan/if_rsureg.h>
|
|
|
|
|
|
|
|
#ifdef USB_DEBUG
|
|
|
|
static int rsu_debug = 0;
|
|
|
|
SYSCTL_NODE(_hw_usb, OID_AUTO, rsu, CTLFLAG_RW, 0, "USB rsu");
|
2015-01-05 15:04:17 +00:00
|
|
|
SYSCTL_INT(_hw_usb_rsu, OID_AUTO, debug, CTLFLAG_RWTUN, &rsu_debug, 0,
|
2013-07-30 02:07:57 +00:00
|
|
|
"Debug level");
|
2015-09-12 23:10:34 +00:00
|
|
|
#define RSU_DPRINTF(_sc, _flg, ...) \
|
|
|
|
do \
|
|
|
|
if (((_flg) == (RSU_DEBUG_ANY)) || (rsu_debug & (_flg))) \
|
|
|
|
device_printf((_sc)->sc_dev, __VA_ARGS__); \
|
|
|
|
while (0)
|
|
|
|
#else
|
|
|
|
#define RSU_DPRINTF(_sc, _flg, ...)
|
2013-07-30 02:07:57 +00:00
|
|
|
#endif
|
|
|
|
|
2015-09-21 02:32:11 +00:00
|
|
|
static int rsu_enable_11n = 1;
|
2015-09-18 04:12:11 +00:00
|
|
|
TUNABLE_INT("hw.usb.rsu.enable_11n", &rsu_enable_11n);
|
|
|
|
|
2015-09-12 23:10:34 +00:00
|
|
|
#define RSU_DEBUG_ANY 0xffffffff
|
|
|
|
#define RSU_DEBUG_TX 0x00000001
|
|
|
|
#define RSU_DEBUG_RX 0x00000002
|
|
|
|
#define RSU_DEBUG_RESET 0x00000004
|
|
|
|
#define RSU_DEBUG_CALIB 0x00000008
|
|
|
|
#define RSU_DEBUG_STATE 0x00000010
|
|
|
|
#define RSU_DEBUG_SCAN 0x00000020
|
|
|
|
#define RSU_DEBUG_FWCMD 0x00000040
|
|
|
|
#define RSU_DEBUG_TXDONE 0x00000080
|
|
|
|
#define RSU_DEBUG_FW 0x00000100
|
|
|
|
#define RSU_DEBUG_FWDBG 0x00000200
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
static const STRUCT_USB_HOST_ID rsu_devs[] = {
|
|
|
|
#define RSU_HT_NOT_SUPPORTED 0
|
|
|
|
#define RSU_HT_SUPPORTED 1
|
|
|
|
#define RSU_DEV_HT(v,p) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, \
|
|
|
|
RSU_HT_SUPPORTED) }
|
|
|
|
#define RSU_DEV(v,p) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, \
|
|
|
|
RSU_HT_NOT_SUPPORTED) }
|
|
|
|
RSU_DEV(ASUS, RTL8192SU),
|
|
|
|
RSU_DEV(AZUREWAVE, RTL8192SU_4),
|
|
|
|
RSU_DEV_HT(ACCTON, RTL8192SU),
|
|
|
|
RSU_DEV_HT(ASUS, USBN10),
|
|
|
|
RSU_DEV_HT(AZUREWAVE, RTL8192SU_1),
|
|
|
|
RSU_DEV_HT(AZUREWAVE, RTL8192SU_2),
|
|
|
|
RSU_DEV_HT(AZUREWAVE, RTL8192SU_3),
|
|
|
|
RSU_DEV_HT(AZUREWAVE, RTL8192SU_5),
|
|
|
|
RSU_DEV_HT(BELKIN, RTL8192SU_1),
|
|
|
|
RSU_DEV_HT(BELKIN, RTL8192SU_2),
|
|
|
|
RSU_DEV_HT(BELKIN, RTL8192SU_3),
|
|
|
|
RSU_DEV_HT(CONCEPTRONIC2, RTL8192SU_1),
|
|
|
|
RSU_DEV_HT(CONCEPTRONIC2, RTL8192SU_2),
|
|
|
|
RSU_DEV_HT(CONCEPTRONIC2, RTL8192SU_3),
|
|
|
|
RSU_DEV_HT(COREGA, RTL8192SU),
|
|
|
|
RSU_DEV_HT(DLINK2, DWA131A1),
|
|
|
|
RSU_DEV_HT(DLINK2, RTL8192SU_1),
|
|
|
|
RSU_DEV_HT(DLINK2, RTL8192SU_2),
|
|
|
|
RSU_DEV_HT(EDIMAX, RTL8192SU_1),
|
|
|
|
RSU_DEV_HT(EDIMAX, RTL8192SU_2),
|
2013-11-12 02:34:48 +00:00
|
|
|
RSU_DEV_HT(EDIMAX, EW7622UMN),
|
2013-07-30 02:07:57 +00:00
|
|
|
RSU_DEV_HT(GUILLEMOT, HWGUN54),
|
|
|
|
RSU_DEV_HT(GUILLEMOT, HWNUM300),
|
|
|
|
RSU_DEV_HT(HAWKING, RTL8192SU_1),
|
|
|
|
RSU_DEV_HT(HAWKING, RTL8192SU_2),
|
|
|
|
RSU_DEV_HT(PLANEX2, GWUSNANO),
|
|
|
|
RSU_DEV_HT(REALTEK, RTL8171),
|
|
|
|
RSU_DEV_HT(REALTEK, RTL8172),
|
|
|
|
RSU_DEV_HT(REALTEK, RTL8173),
|
|
|
|
RSU_DEV_HT(REALTEK, RTL8174),
|
|
|
|
RSU_DEV_HT(REALTEK, RTL8192SU),
|
|
|
|
RSU_DEV_HT(REALTEK, RTL8712),
|
|
|
|
RSU_DEV_HT(REALTEK, RTL8713),
|
|
|
|
RSU_DEV_HT(SENAO, RTL8192SU_1),
|
|
|
|
RSU_DEV_HT(SENAO, RTL8192SU_2),
|
|
|
|
RSU_DEV_HT(SITECOMEU, WL349V1),
|
|
|
|
RSU_DEV_HT(SITECOMEU, WL353),
|
|
|
|
RSU_DEV_HT(SWEEX2, LW154),
|
2014-11-19 05:38:45 +00:00
|
|
|
RSU_DEV_HT(TRENDNET, TEW646UBH),
|
2013-07-30 02:07:57 +00:00
|
|
|
#undef RSU_DEV_HT
|
|
|
|
#undef RSU_DEV
|
|
|
|
};
|
|
|
|
|
|
|
|
static device_probe_t rsu_match;
|
|
|
|
static device_attach_t rsu_attach;
|
|
|
|
static device_detach_t rsu_detach;
|
2014-06-04 09:18:13 +00:00
|
|
|
static usb_callback_t rsu_bulk_tx_callback_be_bk;
|
|
|
|
static usb_callback_t rsu_bulk_tx_callback_vi_vo;
|
2015-09-17 03:19:09 +00:00
|
|
|
static usb_callback_t rsu_bulk_tx_callback_h2c;
|
2013-07-30 02:07:57 +00:00
|
|
|
static usb_callback_t rsu_bulk_rx_callback;
|
|
|
|
static usb_error_t rsu_do_request(struct rsu_softc *,
|
|
|
|
struct usb_device_request *, void *);
|
|
|
|
static struct ieee80211vap *
|
|
|
|
rsu_vap_create(struct ieee80211com *, const char name[],
|
|
|
|
int, enum ieee80211_opmode, int, const uint8_t bssid[],
|
|
|
|
const uint8_t mac[]);
|
|
|
|
static void rsu_vap_delete(struct ieee80211vap *);
|
|
|
|
static void rsu_scan_start(struct ieee80211com *);
|
|
|
|
static void rsu_scan_end(struct ieee80211com *);
|
|
|
|
static void rsu_set_channel(struct ieee80211com *);
|
2015-05-25 19:53:29 +00:00
|
|
|
static void rsu_update_mcast(struct ieee80211com *);
|
2013-07-30 02:07:57 +00:00
|
|
|
static int rsu_alloc_rx_list(struct rsu_softc *);
|
|
|
|
static void rsu_free_rx_list(struct rsu_softc *);
|
|
|
|
static int rsu_alloc_tx_list(struct rsu_softc *);
|
|
|
|
static void rsu_free_tx_list(struct rsu_softc *);
|
|
|
|
static void rsu_free_list(struct rsu_softc *, struct rsu_data [], int);
|
|
|
|
static struct rsu_data *_rsu_getbuf(struct rsu_softc *);
|
|
|
|
static struct rsu_data *rsu_getbuf(struct rsu_softc *);
|
2015-09-18 07:26:34 +00:00
|
|
|
static void rsu_freebuf(struct rsu_softc *, struct rsu_data *);
|
2013-07-30 02:07:57 +00:00
|
|
|
static int rsu_write_region_1(struct rsu_softc *, uint16_t, uint8_t *,
|
|
|
|
int);
|
|
|
|
static void rsu_write_1(struct rsu_softc *, uint16_t, uint8_t);
|
|
|
|
static void rsu_write_2(struct rsu_softc *, uint16_t, uint16_t);
|
|
|
|
static void rsu_write_4(struct rsu_softc *, uint16_t, uint32_t);
|
|
|
|
static int rsu_read_region_1(struct rsu_softc *, uint16_t, uint8_t *,
|
|
|
|
int);
|
|
|
|
static uint8_t rsu_read_1(struct rsu_softc *, uint16_t);
|
|
|
|
static uint16_t rsu_read_2(struct rsu_softc *, uint16_t);
|
|
|
|
static uint32_t rsu_read_4(struct rsu_softc *, uint16_t);
|
|
|
|
static int rsu_fw_iocmd(struct rsu_softc *, uint32_t);
|
|
|
|
static uint8_t rsu_efuse_read_1(struct rsu_softc *, uint16_t);
|
|
|
|
static int rsu_read_rom(struct rsu_softc *);
|
|
|
|
static int rsu_fw_cmd(struct rsu_softc *, uint8_t, void *, int);
|
|
|
|
static void rsu_calib_task(void *, int);
|
2015-09-21 02:30:22 +00:00
|
|
|
static void rsu_tx_task(void *, int);
|
2013-07-30 02:07:57 +00:00
|
|
|
static int rsu_newstate(struct ieee80211vap *, enum ieee80211_state, int);
|
|
|
|
#ifdef notyet
|
|
|
|
static void rsu_set_key(struct rsu_softc *, const struct ieee80211_key *);
|
|
|
|
static void rsu_delete_key(struct rsu_softc *, const struct ieee80211_key *);
|
|
|
|
#endif
|
|
|
|
static int rsu_site_survey(struct rsu_softc *, struct ieee80211vap *);
|
|
|
|
static int rsu_join_bss(struct rsu_softc *, struct ieee80211_node *);
|
|
|
|
static int rsu_disconnect(struct rsu_softc *);
|
|
|
|
static void rsu_event_survey(struct rsu_softc *, uint8_t *, int);
|
|
|
|
static void rsu_event_join_bss(struct rsu_softc *, uint8_t *, int);
|
|
|
|
static void rsu_rx_event(struct rsu_softc *, uint8_t, uint8_t *, int);
|
|
|
|
static void rsu_rx_multi_event(struct rsu_softc *, uint8_t *, int);
|
|
|
|
static int8_t rsu_get_rssi(struct rsu_softc *, int, void *);
|
|
|
|
static struct mbuf *
|
|
|
|
rsu_rx_frame(struct rsu_softc *, uint8_t *, int, int *);
|
|
|
|
static struct mbuf *
|
|
|
|
rsu_rx_multi_frame(struct rsu_softc *, uint8_t *, int, int *);
|
|
|
|
static struct mbuf *
|
|
|
|
rsu_rxeof(struct usb_xfer *, struct rsu_data *, int *);
|
|
|
|
static void rsu_txeof(struct usb_xfer *, struct rsu_data *);
|
|
|
|
static int rsu_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
|
|
|
const struct ieee80211_bpf_params *);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
static void rsu_init(struct rsu_softc *);
|
2013-07-30 02:07:57 +00:00
|
|
|
static int rsu_tx_start(struct rsu_softc *, struct ieee80211_node *,
|
2014-05-21 16:52:55 +00:00
|
|
|
struct mbuf *, struct rsu_data *);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
static int rsu_transmit(struct ieee80211com *, struct mbuf *);
|
|
|
|
static void rsu_start(struct rsu_softc *);
|
2015-09-21 02:30:22 +00:00
|
|
|
static void _rsu_start(struct rsu_softc *);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
static void rsu_parent(struct ieee80211com *);
|
|
|
|
static void rsu_stop(struct rsu_softc *);
|
2015-09-17 03:01:19 +00:00
|
|
|
static void rsu_ms_delay(struct rsu_softc *, int);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
static device_method_t rsu_methods[] = {
|
|
|
|
DEVMETHOD(device_probe, rsu_match),
|
|
|
|
DEVMETHOD(device_attach, rsu_attach),
|
|
|
|
DEVMETHOD(device_detach, rsu_detach),
|
|
|
|
|
|
|
|
DEVMETHOD_END
|
|
|
|
};
|
|
|
|
|
|
|
|
static driver_t rsu_driver = {
|
|
|
|
.name = "rsu",
|
|
|
|
.methods = rsu_methods,
|
|
|
|
.size = sizeof(struct rsu_softc)
|
|
|
|
};
|
|
|
|
|
|
|
|
static devclass_t rsu_devclass;
|
|
|
|
|
|
|
|
DRIVER_MODULE(rsu, uhub, rsu_driver, rsu_devclass, NULL, 0);
|
|
|
|
MODULE_DEPEND(rsu, wlan, 1, 1, 1);
|
|
|
|
MODULE_DEPEND(rsu, usb, 1, 1, 1);
|
|
|
|
MODULE_DEPEND(rsu, firmware, 1, 1, 1);
|
|
|
|
MODULE_VERSION(rsu, 1);
|
|
|
|
|
2014-06-04 09:18:13 +00:00
|
|
|
static uint8_t rsu_wme_ac_xfer_map[4] = {
|
|
|
|
[WME_AC_BE] = RSU_BULK_TX_BE_BK,
|
|
|
|
[WME_AC_BK] = RSU_BULK_TX_BE_BK,
|
|
|
|
[WME_AC_VI] = RSU_BULK_TX_VI_VO,
|
|
|
|
[WME_AC_VO] = RSU_BULK_TX_VI_VO,
|
|
|
|
};
|
|
|
|
|
2015-09-17 03:19:09 +00:00
|
|
|
/* XXX hard-coded */
|
|
|
|
#define RSU_H2C_ENDPOINT 3
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
static const struct usb_config rsu_config[RSU_N_TRANSFER] = {
|
|
|
|
[RSU_BULK_RX] = {
|
|
|
|
.type = UE_BULK,
|
|
|
|
.endpoint = UE_ADDR_ANY,
|
|
|
|
.direction = UE_DIR_IN,
|
|
|
|
.bufsize = RSU_RXBUFSZ,
|
|
|
|
.flags = {
|
|
|
|
.pipe_bof = 1,
|
|
|
|
.short_xfer_ok = 1
|
|
|
|
},
|
|
|
|
.callback = rsu_bulk_rx_callback
|
|
|
|
},
|
2014-06-04 09:18:13 +00:00
|
|
|
[RSU_BULK_TX_BE_BK] = {
|
2013-07-30 02:07:57 +00:00
|
|
|
.type = UE_BULK,
|
|
|
|
.endpoint = 0x06,
|
|
|
|
.direction = UE_DIR_OUT,
|
|
|
|
.bufsize = RSU_TXBUFSZ,
|
|
|
|
.flags = {
|
|
|
|
.ext_buffer = 1,
|
|
|
|
.pipe_bof = 1,
|
|
|
|
.force_short_xfer = 1
|
|
|
|
},
|
2014-06-04 09:18:13 +00:00
|
|
|
.callback = rsu_bulk_tx_callback_be_bk,
|
2013-07-30 02:07:57 +00:00
|
|
|
.timeout = RSU_TX_TIMEOUT
|
|
|
|
},
|
2014-06-04 09:18:13 +00:00
|
|
|
[RSU_BULK_TX_VI_VO] = {
|
2013-07-30 02:07:57 +00:00
|
|
|
.type = UE_BULK,
|
|
|
|
.endpoint = 0x04,
|
|
|
|
.direction = UE_DIR_OUT,
|
|
|
|
.bufsize = RSU_TXBUFSZ,
|
|
|
|
.flags = {
|
|
|
|
.ext_buffer = 1,
|
|
|
|
.pipe_bof = 1,
|
|
|
|
.force_short_xfer = 1
|
|
|
|
},
|
2014-06-04 09:18:13 +00:00
|
|
|
.callback = rsu_bulk_tx_callback_vi_vo,
|
2013-07-30 02:07:57 +00:00
|
|
|
.timeout = RSU_TX_TIMEOUT
|
|
|
|
},
|
2015-09-17 03:19:09 +00:00
|
|
|
[RSU_BULK_TX_H2C] = {
|
|
|
|
.type = UE_BULK,
|
|
|
|
.endpoint = 0x0d,
|
|
|
|
.direction = UE_DIR_OUT,
|
|
|
|
.bufsize = RSU_TXBUFSZ,
|
|
|
|
.flags = {
|
|
|
|
.ext_buffer = 1,
|
|
|
|
.pipe_bof = 1,
|
|
|
|
.short_xfer_ok = 1
|
|
|
|
},
|
|
|
|
.callback = rsu_bulk_tx_callback_h2c,
|
|
|
|
.timeout = RSU_TX_TIMEOUT
|
|
|
|
},
|
2013-07-30 02:07:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_match(device_t self)
|
|
|
|
{
|
|
|
|
struct usb_attach_arg *uaa = device_get_ivars(self);
|
|
|
|
|
|
|
|
if (uaa->usb_mode != USB_MODE_HOST ||
|
|
|
|
uaa->info.bIfaceIndex != 0 ||
|
|
|
|
uaa->info.bConfigIndex != 0)
|
|
|
|
return (ENXIO);
|
|
|
|
|
|
|
|
return (usbd_lookup_id_by_uaa(rsu_devs, sizeof(rsu_devs), uaa));
|
|
|
|
}
|
|
|
|
|
2015-09-13 19:17:26 +00:00
|
|
|
static int
|
|
|
|
rsu_send_mgmt(struct ieee80211_node *ni, int type, int arg)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (ENOTSUP);
|
|
|
|
}
|
|
|
|
|
2015-09-17 03:13:01 +00:00
|
|
|
static void
|
|
|
|
rsu_update_chw(struct ieee80211com *ic)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_ampdu_enable(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Firmware handles this; not our problem */
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_wme_update(struct ieee80211com *ic)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Firmware handles this; not our problem */
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
static int
|
|
|
|
rsu_attach(device_t self)
|
|
|
|
{
|
|
|
|
struct usb_attach_arg *uaa = device_get_ivars(self);
|
|
|
|
struct rsu_softc *sc = device_get_softc(self);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2013-07-30 02:07:57 +00:00
|
|
|
int error;
|
|
|
|
uint8_t iface_index, bands;
|
2015-09-17 03:08:02 +00:00
|
|
|
struct usb_interface *iface;
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
device_set_usb_desc(self);
|
|
|
|
sc->sc_udev = uaa->device;
|
|
|
|
sc->sc_dev = self;
|
2015-09-18 04:12:11 +00:00
|
|
|
if (rsu_enable_11n)
|
|
|
|
sc->sc_ht = !! (USB_GET_DRIVER_INFO(uaa) & RSU_HT_SUPPORTED);
|
2015-09-17 03:08:02 +00:00
|
|
|
|
|
|
|
/* Get number of endpoints */
|
|
|
|
iface = usbd_get_iface(sc->sc_udev, 0);
|
|
|
|
sc->sc_nendpoints = iface->idesc->bNumEndpoints;
|
2013-07-30 02:07:57 +00:00
|
|
|
|
2015-09-17 03:42:18 +00:00
|
|
|
/* Endpoints are hard-coded for now, so enforce 4-endpoint only */
|
|
|
|
if (sc->sc_nendpoints != 4) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"the driver currently only supports 4-endpoint devices\n");
|
|
|
|
return (ENXIO);
|
|
|
|
}
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
mtx_init(&sc->sc_mtx, device_get_nameunit(self), MTX_NETWORK_LOCK,
|
|
|
|
MTX_DEF);
|
|
|
|
TIMEOUT_TASK_INIT(taskqueue_thread, &sc->calib_task, 0,
|
|
|
|
rsu_calib_task, sc);
|
2015-09-21 02:30:22 +00:00
|
|
|
TASK_INIT(&sc->tx_task, 0, rsu_tx_task, sc);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
mbufq_init(&sc->sc_snd, ifqmaxlen);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
2014-05-22 06:28:09 +00:00
|
|
|
/* Allocate Tx/Rx buffers. */
|
|
|
|
error = rsu_alloc_rx_list(sc);
|
|
|
|
if (error != 0) {
|
|
|
|
device_printf(sc->sc_dev, "could not allocate Rx buffers\n");
|
|
|
|
goto fail_usb;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = rsu_alloc_tx_list(sc);
|
|
|
|
if (error != 0) {
|
|
|
|
device_printf(sc->sc_dev, "could not allocate Tx buffers\n");
|
|
|
|
rsu_free_rx_list(sc);
|
|
|
|
goto fail_usb;
|
|
|
|
}
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
iface_index = 0;
|
|
|
|
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
|
|
|
|
rsu_config, RSU_N_TRANSFER, sc, &sc->sc_mtx);
|
|
|
|
if (error) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"could not allocate USB transfers, err=%s\n",
|
|
|
|
usbd_errstr(error));
|
2013-07-31 06:05:34 +00:00
|
|
|
goto fail_usb;
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
/* Read chip revision. */
|
|
|
|
sc->cut = MS(rsu_read_4(sc, R92S_PMC_FSM), R92S_PMC_FSM_CUT);
|
|
|
|
if (sc->cut != 3)
|
|
|
|
sc->cut = (sc->cut >> 1) + 1;
|
|
|
|
error = rsu_read_rom(sc);
|
2015-01-03 11:04:17 +00:00
|
|
|
RSU_UNLOCK(sc);
|
2013-07-30 02:07:57 +00:00
|
|
|
if (error != 0) {
|
|
|
|
device_printf(self, "could not read ROM\n");
|
2013-07-31 06:05:34 +00:00
|
|
|
goto fail_rom;
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
IEEE80211_ADDR_COPY(ic->ic_macaddr, &sc->rom[0x12]);
|
2013-07-30 02:07:57 +00:00
|
|
|
device_printf(self, "MAC/BB RTL8712 cut %d\n", sc->cut);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
|
2015-05-25 18:50:26 +00:00
|
|
|
ic->ic_softc = sc;
|
2015-05-25 13:51:13 +00:00
|
|
|
ic->ic_name = device_get_nameunit(self);
|
2013-07-30 02:07:57 +00:00
|
|
|
ic->ic_phytype = IEEE80211_T_OFDM; /* Not only, but not used. */
|
|
|
|
ic->ic_opmode = IEEE80211_M_STA; /* Default to BSS mode. */
|
|
|
|
|
|
|
|
/* Set device capabilities. */
|
|
|
|
ic->ic_caps =
|
|
|
|
IEEE80211_C_STA | /* station mode */
|
2015-09-12 23:10:34 +00:00
|
|
|
#if 0
|
2013-07-30 02:07:57 +00:00
|
|
|
IEEE80211_C_BGSCAN | /* Background scan. */
|
2015-09-12 23:10:34 +00:00
|
|
|
#endif
|
2013-07-30 02:07:57 +00:00
|
|
|
IEEE80211_C_SHPREAMBLE | /* Short preamble supported. */
|
2015-09-17 04:45:29 +00:00
|
|
|
IEEE80211_C_WME | /* WME/QoS */
|
2013-07-30 02:07:57 +00:00
|
|
|
IEEE80211_C_SHSLOT | /* Short slot time supported. */
|
|
|
|
IEEE80211_C_WPA; /* WPA/RSN. */
|
|
|
|
|
|
|
|
/* Check if HT support is present. */
|
2015-09-18 04:12:11 +00:00
|
|
|
if (sc->sc_ht) {
|
|
|
|
device_printf(sc->sc_dev, "%s: enabling 11n\n", __func__);
|
|
|
|
|
|
|
|
/* Enable basic HT */
|
|
|
|
ic->ic_htcaps = IEEE80211_HTC_HT |
|
|
|
|
IEEE80211_HTC_AMPDU |
|
|
|
|
IEEE80211_HTC_AMSDU |
|
|
|
|
IEEE80211_HTCAP_MAXAMSDU_3839 |
|
|
|
|
IEEE80211_HTCAP_SMPS_OFF;
|
|
|
|
|
2015-09-20 22:52:40 +00:00
|
|
|
/*
|
|
|
|
* XXX HT40 isn't working in this driver yet - there's
|
|
|
|
* something missing. Disable it for now.
|
|
|
|
*/
|
|
|
|
#if 0
|
2015-09-18 04:12:11 +00:00
|
|
|
ic->ic_htcaps |= IEEE80211_HTCAP_CHWIDTH40;
|
2015-09-20 22:52:40 +00:00
|
|
|
#endif
|
2015-09-18 04:12:11 +00:00
|
|
|
|
|
|
|
/* set number of spatial streams */
|
|
|
|
ic->ic_txstream = 1;
|
|
|
|
ic->ic_rxstream = 1;
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set supported .11b and .11g rates. */
|
|
|
|
bands = 0;
|
|
|
|
setbit(&bands, IEEE80211_MODE_11B);
|
|
|
|
setbit(&bands, IEEE80211_MODE_11G);
|
2015-09-18 04:12:11 +00:00
|
|
|
if (sc->sc_ht)
|
|
|
|
setbit(&bands, IEEE80211_MODE_11NG);
|
2013-07-30 02:07:57 +00:00
|
|
|
ieee80211_init_channels(ic, NULL, &bands);
|
|
|
|
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
ieee80211_ifattach(ic);
|
2013-07-30 02:07:57 +00:00
|
|
|
ic->ic_raw_xmit = rsu_raw_xmit;
|
|
|
|
ic->ic_scan_start = rsu_scan_start;
|
|
|
|
ic->ic_scan_end = rsu_scan_end;
|
|
|
|
ic->ic_set_channel = rsu_set_channel;
|
|
|
|
ic->ic_vap_create = rsu_vap_create;
|
|
|
|
ic->ic_vap_delete = rsu_vap_delete;
|
|
|
|
ic->ic_update_mcast = rsu_update_mcast;
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
ic->ic_parent = rsu_parent;
|
|
|
|
ic->ic_transmit = rsu_transmit;
|
2015-09-13 19:17:26 +00:00
|
|
|
ic->ic_send_mgmt = rsu_send_mgmt;
|
2015-09-17 03:13:01 +00:00
|
|
|
ic->ic_update_chw = rsu_update_chw;
|
|
|
|
ic->ic_ampdu_enable = rsu_ampdu_enable;
|
|
|
|
ic->ic_wme.wme_update = rsu_wme_update;
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr,
|
|
|
|
sizeof(sc->sc_txtap), RSU_TX_RADIOTAP_PRESENT,
|
|
|
|
&sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
|
|
|
|
RSU_RX_RADIOTAP_PRESENT);
|
|
|
|
|
|
|
|
if (bootverbose)
|
|
|
|
ieee80211_announce(ic);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
|
2013-07-31 06:05:34 +00:00
|
|
|
fail_rom:
|
|
|
|
usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER);
|
|
|
|
fail_usb:
|
|
|
|
mtx_destroy(&sc->sc_mtx);
|
2013-07-30 02:07:57 +00:00
|
|
|
return (ENXIO);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_detach(device_t self)
|
|
|
|
{
|
|
|
|
struct rsu_softc *sc = device_get_softc(self);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2013-07-30 02:07:57 +00:00
|
|
|
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
RSU_LOCK(sc);
|
|
|
|
rsu_stop(sc);
|
|
|
|
RSU_UNLOCK(sc);
|
2013-07-30 02:07:57 +00:00
|
|
|
usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER);
|
2015-09-21 02:12:01 +00:00
|
|
|
|
|
|
|
/* Frames are freed; detach from net80211 */
|
2013-07-30 02:07:57 +00:00
|
|
|
ieee80211_ifdetach(ic);
|
|
|
|
|
|
|
|
taskqueue_drain_timeout(taskqueue_thread, &sc->calib_task);
|
2015-09-21 02:30:22 +00:00
|
|
|
taskqueue_drain(taskqueue_thread, &sc->tx_task);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
/* Free Tx/Rx buffers. */
|
|
|
|
rsu_free_tx_list(sc);
|
|
|
|
rsu_free_rx_list(sc);
|
|
|
|
|
|
|
|
mtx_destroy(&sc->sc_mtx);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static usb_error_t
|
|
|
|
rsu_do_request(struct rsu_softc *sc, struct usb_device_request *req,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
usb_error_t err;
|
|
|
|
int ntries = 10;
|
|
|
|
|
|
|
|
RSU_ASSERT_LOCKED(sc);
|
|
|
|
|
|
|
|
while (ntries--) {
|
|
|
|
err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx,
|
|
|
|
req, data, 0, NULL, 250 /* ms */);
|
2014-05-20 12:22:53 +00:00
|
|
|
if (err == 0 || err == USB_ERR_NOT_CONFIGURED)
|
2013-07-30 02:07:57 +00:00
|
|
|
break;
|
|
|
|
DPRINTFN(1, "Control request failed, %s (retrying)\n",
|
|
|
|
usbd_errstr(err));
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 10);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (err);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct ieee80211vap *
|
|
|
|
rsu_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
|
|
|
|
enum ieee80211_opmode opmode, int flags,
|
|
|
|
const uint8_t bssid[IEEE80211_ADDR_LEN],
|
|
|
|
const uint8_t mac[IEEE80211_ADDR_LEN])
|
|
|
|
{
|
|
|
|
struct rsu_vap *uvp;
|
|
|
|
struct ieee80211vap *vap;
|
|
|
|
|
|
|
|
if (!TAILQ_EMPTY(&ic->ic_vaps)) /* only one at a time */
|
|
|
|
return (NULL);
|
|
|
|
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
uvp = malloc(sizeof(struct rsu_vap), M_80211_VAP, M_WAITOK | M_ZERO);
|
2013-07-30 02:07:57 +00:00
|
|
|
vap = &uvp->vap;
|
2013-11-06 12:57:01 +00:00
|
|
|
|
|
|
|
if (ieee80211_vap_setup(ic, vap, name, unit, opmode,
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
flags, bssid) != 0) {
|
2013-11-06 12:57:01 +00:00
|
|
|
/* out of memory */
|
|
|
|
free(uvp, M_80211_VAP);
|
|
|
|
return (NULL);
|
|
|
|
}
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
/* override state transition machine */
|
|
|
|
uvp->newstate = vap->iv_newstate;
|
|
|
|
vap->iv_newstate = rsu_newstate;
|
|
|
|
|
2015-09-18 05:59:15 +00:00
|
|
|
/* Limits from the r92su driver */
|
|
|
|
vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_16;
|
|
|
|
vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_32K;
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
/* complete setup */
|
|
|
|
ieee80211_vap_attach(vap, ieee80211_media_change,
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
ieee80211_media_status, mac);
|
2013-07-30 02:07:57 +00:00
|
|
|
ic->ic_opmode = opmode;
|
|
|
|
|
|
|
|
return (vap);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_vap_delete(struct ieee80211vap *vap)
|
|
|
|
{
|
|
|
|
struct rsu_vap *uvp = RSU_VAP(vap);
|
|
|
|
|
|
|
|
ieee80211_vap_detach(vap);
|
|
|
|
free(uvp, M_80211_VAP);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_scan_start(struct ieee80211com *ic)
|
|
|
|
{
|
2015-08-20 05:13:54 +00:00
|
|
|
struct rsu_softc *sc = ic->ic_softc;
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
int error;
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
/* Scanning is done by the firmware. */
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
error = rsu_site_survey(sc, TAILQ_FIRST(&ic->ic_vaps));
|
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
if (error != 0)
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"could not send site survey command\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_scan_end(struct ieee80211com *ic)
|
|
|
|
{
|
|
|
|
/* Nothing to do here. */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_set_channel(struct ieee80211com *ic __unused)
|
|
|
|
{
|
|
|
|
/* We are unable to switch channels, yet. */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2015-05-25 19:53:29 +00:00
|
|
|
rsu_update_mcast(struct ieee80211com *ic)
|
2013-07-30 02:07:57 +00:00
|
|
|
{
|
|
|
|
/* XXX do nothing? */
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_alloc_list(struct rsu_softc *sc, struct rsu_data data[],
|
|
|
|
int ndata, int maxsz)
|
|
|
|
{
|
|
|
|
int i, error;
|
|
|
|
|
|
|
|
for (i = 0; i < ndata; i++) {
|
|
|
|
struct rsu_data *dp = &data[i];
|
|
|
|
dp->sc = sc;
|
|
|
|
dp->m = NULL;
|
|
|
|
dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT);
|
|
|
|
if (dp->buf == NULL) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"could not allocate buffer\n");
|
|
|
|
error = ENOMEM;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
dp->ni = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
fail:
|
|
|
|
rsu_free_list(sc, data, ndata);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_alloc_rx_list(struct rsu_softc *sc)
|
|
|
|
{
|
|
|
|
int error, i;
|
|
|
|
|
|
|
|
error = rsu_alloc_list(sc, sc->sc_rx, RSU_RX_LIST_COUNT,
|
|
|
|
RSU_RXBUFSZ);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
STAILQ_INIT(&sc->sc_rx_active);
|
|
|
|
STAILQ_INIT(&sc->sc_rx_inactive);
|
|
|
|
|
|
|
|
for (i = 0; i < RSU_RX_LIST_COUNT; i++)
|
|
|
|
STAILQ_INSERT_HEAD(&sc->sc_rx_inactive, &sc->sc_rx[i], next);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_alloc_tx_list(struct rsu_softc *sc)
|
|
|
|
{
|
|
|
|
int error, i;
|
|
|
|
|
|
|
|
error = rsu_alloc_list(sc, sc->sc_tx, RSU_TX_LIST_COUNT,
|
|
|
|
RSU_TXBUFSZ);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
STAILQ_INIT(&sc->sc_tx_inactive);
|
2014-05-21 16:52:55 +00:00
|
|
|
|
2014-06-04 09:18:13 +00:00
|
|
|
for (i = 0; i != RSU_N_TRANSFER; i++) {
|
2014-05-21 16:52:55 +00:00
|
|
|
STAILQ_INIT(&sc->sc_tx_active[i]);
|
|
|
|
STAILQ_INIT(&sc->sc_tx_pending[i]);
|
|
|
|
}
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
for (i = 0; i < RSU_TX_LIST_COUNT; i++) {
|
|
|
|
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, &sc->sc_tx[i], next);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_free_tx_list(struct rsu_softc *sc)
|
|
|
|
{
|
2014-05-22 06:28:09 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
/* prevent further allocations from TX list(s) */
|
|
|
|
STAILQ_INIT(&sc->sc_tx_inactive);
|
|
|
|
|
2014-06-04 09:18:13 +00:00
|
|
|
for (i = 0; i != RSU_N_TRANSFER; i++) {
|
2014-05-22 06:28:09 +00:00
|
|
|
STAILQ_INIT(&sc->sc_tx_active[i]);
|
|
|
|
STAILQ_INIT(&sc->sc_tx_pending[i]);
|
|
|
|
}
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
rsu_free_list(sc, sc->sc_tx, RSU_TX_LIST_COUNT);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_free_rx_list(struct rsu_softc *sc)
|
|
|
|
{
|
2014-05-22 06:28:09 +00:00
|
|
|
/* prevent further allocations from RX list(s) */
|
|
|
|
STAILQ_INIT(&sc->sc_rx_inactive);
|
|
|
|
STAILQ_INIT(&sc->sc_rx_active);
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
rsu_free_list(sc, sc->sc_rx, RSU_RX_LIST_COUNT);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_free_list(struct rsu_softc *sc, struct rsu_data data[], int ndata)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ndata; i++) {
|
|
|
|
struct rsu_data *dp = &data[i];
|
|
|
|
|
|
|
|
if (dp->buf != NULL) {
|
|
|
|
free(dp->buf, M_USBDEV);
|
|
|
|
dp->buf = NULL;
|
|
|
|
}
|
|
|
|
if (dp->ni != NULL) {
|
|
|
|
ieee80211_free_node(dp->ni);
|
|
|
|
dp->ni = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct rsu_data *
|
|
|
|
_rsu_getbuf(struct rsu_softc *sc)
|
|
|
|
{
|
|
|
|
struct rsu_data *bf;
|
|
|
|
|
|
|
|
bf = STAILQ_FIRST(&sc->sc_tx_inactive);
|
|
|
|
if (bf != NULL)
|
|
|
|
STAILQ_REMOVE_HEAD(&sc->sc_tx_inactive, next);
|
|
|
|
else
|
|
|
|
bf = NULL;
|
2015-09-18 07:55:33 +00:00
|
|
|
return (bf);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct rsu_data *
|
|
|
|
rsu_getbuf(struct rsu_softc *sc)
|
|
|
|
{
|
|
|
|
struct rsu_data *bf;
|
|
|
|
|
|
|
|
RSU_ASSERT_LOCKED(sc);
|
|
|
|
|
|
|
|
bf = _rsu_getbuf(sc);
|
2015-09-21 02:12:01 +00:00
|
|
|
if (bf == NULL) {
|
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_TX, "%s: no buffers\n", __func__);
|
|
|
|
}
|
2013-07-30 02:07:57 +00:00
|
|
|
return (bf);
|
|
|
|
}
|
|
|
|
|
2015-09-18 07:26:34 +00:00
|
|
|
static void
|
|
|
|
rsu_freebuf(struct rsu_softc *sc, struct rsu_data *bf)
|
|
|
|
{
|
|
|
|
|
|
|
|
RSU_ASSERT_LOCKED(sc);
|
|
|
|
STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, bf, next);
|
|
|
|
}
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
static int
|
|
|
|
rsu_write_region_1(struct rsu_softc *sc, uint16_t addr, uint8_t *buf,
|
|
|
|
int len)
|
|
|
|
{
|
|
|
|
usb_device_request_t req;
|
|
|
|
|
|
|
|
req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
|
|
|
|
req.bRequest = R92S_REQ_REGS;
|
|
|
|
USETW(req.wValue, addr);
|
|
|
|
USETW(req.wIndex, 0);
|
|
|
|
USETW(req.wLength, len);
|
|
|
|
|
|
|
|
return (rsu_do_request(sc, &req, buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_write_1(struct rsu_softc *sc, uint16_t addr, uint8_t val)
|
|
|
|
{
|
|
|
|
rsu_write_region_1(sc, addr, &val, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_write_2(struct rsu_softc *sc, uint16_t addr, uint16_t val)
|
|
|
|
{
|
|
|
|
val = htole16(val);
|
|
|
|
rsu_write_region_1(sc, addr, (uint8_t *)&val, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_write_4(struct rsu_softc *sc, uint16_t addr, uint32_t val)
|
|
|
|
{
|
|
|
|
val = htole32(val);
|
|
|
|
rsu_write_region_1(sc, addr, (uint8_t *)&val, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_read_region_1(struct rsu_softc *sc, uint16_t addr, uint8_t *buf,
|
|
|
|
int len)
|
|
|
|
{
|
|
|
|
usb_device_request_t req;
|
|
|
|
|
|
|
|
req.bmRequestType = UT_READ_VENDOR_DEVICE;
|
|
|
|
req.bRequest = R92S_REQ_REGS;
|
|
|
|
USETW(req.wValue, addr);
|
|
|
|
USETW(req.wIndex, 0);
|
|
|
|
USETW(req.wLength, len);
|
|
|
|
|
|
|
|
return (rsu_do_request(sc, &req, buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t
|
|
|
|
rsu_read_1(struct rsu_softc *sc, uint16_t addr)
|
|
|
|
{
|
|
|
|
uint8_t val;
|
|
|
|
|
|
|
|
if (rsu_read_region_1(sc, addr, &val, 1) != 0)
|
|
|
|
return (0xff);
|
|
|
|
return (val);
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint16_t
|
|
|
|
rsu_read_2(struct rsu_softc *sc, uint16_t addr)
|
|
|
|
{
|
|
|
|
uint16_t val;
|
|
|
|
|
|
|
|
if (rsu_read_region_1(sc, addr, (uint8_t *)&val, 2) != 0)
|
|
|
|
return (0xffff);
|
|
|
|
return (le16toh(val));
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
rsu_read_4(struct rsu_softc *sc, uint16_t addr)
|
|
|
|
{
|
|
|
|
uint32_t val;
|
|
|
|
|
|
|
|
if (rsu_read_region_1(sc, addr, (uint8_t *)&val, 4) != 0)
|
|
|
|
return (0xffffffff);
|
|
|
|
return (le32toh(val));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_fw_iocmd(struct rsu_softc *sc, uint32_t iocmd)
|
|
|
|
{
|
|
|
|
int ntries;
|
|
|
|
|
|
|
|
rsu_write_4(sc, R92S_IOCMD_CTRL, iocmd);
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
for (ntries = 0; ntries < 50; ntries++) {
|
|
|
|
if (rsu_read_4(sc, R92S_IOCMD_CTRL) == 0)
|
|
|
|
return (0);
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
return (ETIMEDOUT);
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint8_t
|
|
|
|
rsu_efuse_read_1(struct rsu_softc *sc, uint16_t addr)
|
|
|
|
{
|
|
|
|
uint32_t reg;
|
|
|
|
int ntries;
|
|
|
|
|
|
|
|
reg = rsu_read_4(sc, R92S_EFUSE_CTRL);
|
|
|
|
reg = RW(reg, R92S_EFUSE_CTRL_ADDR, addr);
|
|
|
|
reg &= ~R92S_EFUSE_CTRL_VALID;
|
|
|
|
rsu_write_4(sc, R92S_EFUSE_CTRL, reg);
|
|
|
|
/* Wait for read operation to complete. */
|
|
|
|
for (ntries = 0; ntries < 100; ntries++) {
|
|
|
|
reg = rsu_read_4(sc, R92S_EFUSE_CTRL);
|
|
|
|
if (reg & R92S_EFUSE_CTRL_VALID)
|
|
|
|
return (MS(reg, R92S_EFUSE_CTRL_DATA));
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"could not read efuse byte at address 0x%x\n", addr);
|
|
|
|
return (0xff);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_read_rom(struct rsu_softc *sc)
|
|
|
|
{
|
|
|
|
uint8_t *rom = sc->rom;
|
|
|
|
uint16_t addr = 0;
|
|
|
|
uint32_t reg;
|
|
|
|
uint8_t off, msk;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Make sure that ROM type is eFuse and that autoload succeeded. */
|
|
|
|
reg = rsu_read_1(sc, R92S_EE_9346CR);
|
|
|
|
if ((reg & (R92S_9356SEL | R92S_EEPROM_EN)) != R92S_EEPROM_EN)
|
|
|
|
return (EIO);
|
|
|
|
|
|
|
|
/* Turn on 2.5V to prevent eFuse leakage. */
|
|
|
|
reg = rsu_read_1(sc, R92S_EFUSE_TEST + 3);
|
|
|
|
rsu_write_1(sc, R92S_EFUSE_TEST + 3, reg | 0x80);
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
rsu_write_1(sc, R92S_EFUSE_TEST + 3, reg & ~0x80);
|
|
|
|
|
|
|
|
/* Read full ROM image. */
|
|
|
|
memset(&sc->rom, 0xff, sizeof(sc->rom));
|
|
|
|
while (addr < 512) {
|
|
|
|
reg = rsu_efuse_read_1(sc, addr);
|
|
|
|
if (reg == 0xff)
|
|
|
|
break;
|
|
|
|
addr++;
|
|
|
|
off = reg >> 4;
|
|
|
|
msk = reg & 0xf;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
|
|
if (msk & (1 << i))
|
|
|
|
continue;
|
|
|
|
rom[off * 8 + i * 2 + 0] =
|
|
|
|
rsu_efuse_read_1(sc, addr);
|
|
|
|
addr++;
|
|
|
|
rom[off * 8 + i * 2 + 1] =
|
|
|
|
rsu_efuse_read_1(sc, addr);
|
|
|
|
addr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef USB_DEBUG
|
|
|
|
if (rsu_debug >= 5) {
|
|
|
|
/* Dump ROM content. */
|
|
|
|
printf("\n");
|
|
|
|
for (i = 0; i < sizeof(sc->rom); i++)
|
|
|
|
printf("%02x:", rom[i]);
|
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_fw_cmd(struct rsu_softc *sc, uint8_t code, void *buf, int len)
|
|
|
|
{
|
2015-09-17 03:19:09 +00:00
|
|
|
const uint8_t which = RSU_H2C_ENDPOINT;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct rsu_data *data;
|
|
|
|
struct r92s_tx_desc *txd;
|
|
|
|
struct r92s_fw_cmd_hdr *cmd;
|
2014-05-21 16:52:55 +00:00
|
|
|
int cmdsz;
|
|
|
|
int xferlen;
|
2013-07-30 02:07:57 +00:00
|
|
|
|
2015-09-18 07:55:33 +00:00
|
|
|
RSU_ASSERT_LOCKED(sc);
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
data = rsu_getbuf(sc);
|
|
|
|
if (data == NULL)
|
|
|
|
return (ENOMEM);
|
|
|
|
|
|
|
|
/* Round-up command length to a multiple of 8 bytes. */
|
|
|
|
cmdsz = (len + 7) & ~7;
|
|
|
|
|
|
|
|
xferlen = sizeof(*txd) + sizeof(*cmd) + cmdsz;
|
|
|
|
KASSERT(xferlen <= RSU_TXBUFSZ, ("%s: invalid length", __func__));
|
|
|
|
memset(data->buf, 0, xferlen);
|
|
|
|
|
|
|
|
/* Setup Tx descriptor. */
|
|
|
|
txd = (struct r92s_tx_desc *)data->buf;
|
|
|
|
txd->txdw0 = htole32(
|
|
|
|
SM(R92S_TXDW0_OFFSET, sizeof(*txd)) |
|
|
|
|
SM(R92S_TXDW0_PKTLEN, sizeof(*cmd) + cmdsz) |
|
|
|
|
R92S_TXDW0_OWN | R92S_TXDW0_FSG | R92S_TXDW0_LSG);
|
|
|
|
txd->txdw1 = htole32(SM(R92S_TXDW1_QSEL, R92S_TXDW1_QSEL_H2C));
|
|
|
|
|
|
|
|
/* Setup command header. */
|
|
|
|
cmd = (struct r92s_fw_cmd_hdr *)&txd[1];
|
|
|
|
cmd->len = htole16(cmdsz);
|
|
|
|
cmd->code = code;
|
|
|
|
cmd->seq = sc->cmd_seq;
|
|
|
|
sc->cmd_seq = (sc->cmd_seq + 1) & 0x7f;
|
|
|
|
|
|
|
|
/* Copy command payload. */
|
|
|
|
memcpy(&cmd[1], buf, len);
|
|
|
|
|
2015-09-13 04:12:51 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_TX | RSU_DEBUG_FWCMD,
|
2015-09-12 23:10:34 +00:00
|
|
|
"%s: Tx cmd code=0x%x len=0x%x\n",
|
|
|
|
__func__, code, cmdsz);
|
2013-07-30 02:07:57 +00:00
|
|
|
data->buflen = xferlen;
|
2014-05-21 16:52:55 +00:00
|
|
|
STAILQ_INSERT_TAIL(&sc->sc_tx_pending[which], data, next);
|
2014-06-04 09:18:13 +00:00
|
|
|
usbd_transfer_start(sc->sc_xfer[which]);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
|
|
|
static void
|
|
|
|
rsu_calib_task(void *arg, int pending __unused)
|
|
|
|
{
|
|
|
|
struct rsu_softc *sc = arg;
|
|
|
|
uint32_t reg;
|
|
|
|
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_CALIB, "%s: running calibration task\n",
|
|
|
|
__func__);
|
2014-06-04 09:18:13 +00:00
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
RSU_LOCK(sc);
|
|
|
|
#ifdef notyet
|
|
|
|
/* Read WPS PBC status. */
|
|
|
|
rsu_write_1(sc, R92S_MAC_PINMUX_CTRL,
|
|
|
|
R92S_GPIOMUX_EN | SM(R92S_GPIOSEL_GPIO, R92S_GPIOSEL_GPIO_JTAG));
|
|
|
|
rsu_write_1(sc, R92S_GPIO_IO_SEL,
|
|
|
|
rsu_read_1(sc, R92S_GPIO_IO_SEL) & ~R92S_GPIO_WPS);
|
|
|
|
reg = rsu_read_1(sc, R92S_GPIO_CTRL);
|
|
|
|
if (reg != 0xff && (reg & R92S_GPIO_WPS))
|
|
|
|
DPRINTF(("WPS PBC is pushed\n"));
|
|
|
|
#endif
|
|
|
|
/* Read current signal level. */
|
|
|
|
if (rsu_fw_iocmd(sc, 0xf4000001) == 0) {
|
|
|
|
reg = rsu_read_4(sc, R92S_IOCMD_DATA);
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_CALIB, "%s: RSSI=%d%%\n",
|
|
|
|
__func__, reg >> 4);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
2014-06-04 09:18:13 +00:00
|
|
|
if (sc->sc_calibrating)
|
|
|
|
taskqueue_enqueue_timeout(taskqueue_thread, &sc->calib_task, hz);
|
|
|
|
RSU_UNLOCK(sc);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
|
2015-09-21 02:30:22 +00:00
|
|
|
static void
|
|
|
|
rsu_tx_task(void *arg, int pending __unused)
|
|
|
|
{
|
|
|
|
struct rsu_softc *sc = arg;
|
|
|
|
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
_rsu_start(sc);
|
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
}
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
static int
|
|
|
|
rsu_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
|
|
|
{
|
|
|
|
struct rsu_vap *uvp = RSU_VAP(vap);
|
|
|
|
struct ieee80211com *ic = vap->iv_ic;
|
2015-08-20 05:13:54 +00:00
|
|
|
struct rsu_softc *sc = ic->ic_softc;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct ieee80211_node *ni;
|
|
|
|
struct ieee80211_rateset *rs;
|
|
|
|
enum ieee80211_state ostate;
|
|
|
|
int error, startcal = 0;
|
|
|
|
|
|
|
|
ostate = vap->iv_state;
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_STATE, "%s: %s -> %s\n",
|
|
|
|
__func__,
|
|
|
|
ieee80211_state_name[ostate],
|
2013-07-30 02:07:57 +00:00
|
|
|
ieee80211_state_name[nstate]);
|
|
|
|
|
|
|
|
IEEE80211_UNLOCK(ic);
|
|
|
|
if (ostate == IEEE80211_S_RUN) {
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
/* Stop calibration. */
|
|
|
|
sc->sc_calibrating = 0;
|
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
taskqueue_drain_timeout(taskqueue_thread, &sc->calib_task);
|
2015-09-21 02:30:22 +00:00
|
|
|
taskqueue_drain(taskqueue_thread, &sc->tx_task);
|
2013-07-30 02:07:57 +00:00
|
|
|
/* Disassociate from our current BSS. */
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
rsu_disconnect(sc);
|
|
|
|
} else
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
switch (nstate) {
|
|
|
|
case IEEE80211_S_INIT:
|
|
|
|
break;
|
|
|
|
case IEEE80211_S_AUTH:
|
|
|
|
ni = ieee80211_ref_node(vap->iv_bss);
|
|
|
|
error = rsu_join_bss(sc, ni);
|
|
|
|
ieee80211_free_node(ni);
|
|
|
|
if (error != 0) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"could not send join command\n");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IEEE80211_S_RUN:
|
|
|
|
ni = ieee80211_ref_node(vap->iv_bss);
|
|
|
|
rs = &ni->ni_rates;
|
|
|
|
/* Indicate highest supported rate. */
|
|
|
|
ni->ni_txrate = rs->rs_rates[rs->rs_nrates - 1];
|
|
|
|
ieee80211_free_node(ni);
|
|
|
|
startcal = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
sc->sc_calibrating = 1;
|
2014-06-04 09:18:13 +00:00
|
|
|
/* Start periodic calibration. */
|
|
|
|
taskqueue_enqueue_timeout(taskqueue_thread, &sc->calib_task, hz);
|
2013-07-30 02:07:57 +00:00
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
IEEE80211_LOCK(ic);
|
|
|
|
return (uvp->newstate(vap, nstate, arg));
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef notyet
|
|
|
|
static void
|
|
|
|
rsu_set_key(struct rsu_softc *sc, const struct ieee80211_key *k)
|
|
|
|
{
|
|
|
|
struct r92s_fw_cmd_set_key key;
|
|
|
|
|
|
|
|
memset(&key, 0, sizeof(key));
|
|
|
|
/* Map net80211 cipher to HW crypto algorithm. */
|
|
|
|
switch (k->wk_cipher->ic_cipher) {
|
|
|
|
case IEEE80211_CIPHER_WEP:
|
|
|
|
if (k->wk_keylen < 8)
|
|
|
|
key.algo = R92S_KEY_ALGO_WEP40;
|
|
|
|
else
|
|
|
|
key.algo = R92S_KEY_ALGO_WEP104;
|
|
|
|
break;
|
|
|
|
case IEEE80211_CIPHER_TKIP:
|
|
|
|
key.algo = R92S_KEY_ALGO_TKIP;
|
|
|
|
break;
|
|
|
|
case IEEE80211_CIPHER_AES_CCM:
|
|
|
|
key.algo = R92S_KEY_ALGO_AES;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
key.id = k->wk_keyix;
|
|
|
|
key.grpkey = (k->wk_flags & IEEE80211_KEY_GROUP) != 0;
|
|
|
|
memcpy(key.key, k->wk_key, MIN(k->wk_keylen, sizeof(key.key)));
|
|
|
|
(void)rsu_fw_cmd(sc, R92S_CMD_SET_KEY, &key, sizeof(key));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_delete_key(struct rsu_softc *sc, const struct ieee80211_key *k)
|
|
|
|
{
|
|
|
|
struct r92s_fw_cmd_set_key key;
|
|
|
|
|
|
|
|
memset(&key, 0, sizeof(key));
|
|
|
|
key.id = k->wk_keyix;
|
|
|
|
(void)rsu_fw_cmd(sc, R92S_CMD_SET_KEY, &key, sizeof(key));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_site_survey(struct rsu_softc *sc, struct ieee80211vap *vap)
|
|
|
|
{
|
|
|
|
struct r92s_fw_cmd_sitesurvey cmd;
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2015-09-18 07:55:33 +00:00
|
|
|
int r;
|
|
|
|
|
|
|
|
RSU_ASSERT_LOCKED(sc);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
if ((ic->ic_flags & IEEE80211_F_ASCAN) || sc->sc_scan_pass == 1)
|
2013-07-30 02:07:57 +00:00
|
|
|
cmd.active = htole32(1);
|
|
|
|
cmd.limit = htole32(48);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
if (sc->sc_scan_pass == 1 && vap->iv_des_nssid > 0) {
|
2013-07-30 02:07:57 +00:00
|
|
|
/* Do a directed scan for second pass. */
|
|
|
|
cmd.ssidlen = htole32(vap->iv_des_ssid[0].len);
|
|
|
|
memcpy(cmd.ssid, vap->iv_des_ssid[0].ssid,
|
|
|
|
vap->iv_des_ssid[0].len);
|
|
|
|
|
|
|
|
}
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
DPRINTF("sending site survey command, pass=%d\n", sc->sc_scan_pass);
|
2015-09-18 07:55:33 +00:00
|
|
|
r = rsu_fw_cmd(sc, R92S_CMD_SITE_SURVEY, &cmd, sizeof(cmd));
|
|
|
|
if (r == 0) {
|
|
|
|
sc->sc_scanning = 1;
|
|
|
|
}
|
|
|
|
return (r);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_join_bss(struct rsu_softc *sc, struct ieee80211_node *ni)
|
|
|
|
{
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct ieee80211vap *vap = ni->ni_vap;
|
|
|
|
struct ndis_wlan_bssid_ex *bss;
|
|
|
|
struct ndis_802_11_fixed_ies *fixed;
|
|
|
|
struct r92s_fw_cmd_auth auth;
|
2014-06-04 16:58:35 +00:00
|
|
|
uint8_t buf[sizeof(*bss) + 128] __aligned(4);
|
|
|
|
uint8_t *frm;
|
2013-07-30 02:07:57 +00:00
|
|
|
uint8_t opmode;
|
|
|
|
int error;
|
2015-09-18 07:55:33 +00:00
|
|
|
int cnt;
|
|
|
|
char *msg = "rsujoin";
|
|
|
|
|
|
|
|
RSU_ASSERT_LOCKED(sc);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Until net80211 scanning doesn't automatically finish
|
|
|
|
* before we tell it to, let's just wait until any pending
|
|
|
|
* scan is done.
|
|
|
|
*
|
|
|
|
* XXX TODO: yes, this releases and re-acquires the lock.
|
|
|
|
* We should re-verify the state whenever we re-attempt this!
|
|
|
|
*/
|
|
|
|
cnt = 0;
|
|
|
|
while (sc->sc_scanning && cnt < 10) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: still scanning! (attempt %d)\n",
|
|
|
|
__func__, cnt);
|
|
|
|
msleep(msg, &sc->sc_mtx, 0, msg, hz / 2);
|
|
|
|
cnt++;
|
|
|
|
}
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
/* Let the FW decide the opmode based on the capinfo field. */
|
|
|
|
opmode = NDIS802_11AUTOUNKNOWN;
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_RESET,
|
|
|
|
"%s: setting operating mode to %d\n",
|
|
|
|
__func__, opmode);
|
2013-07-30 02:07:57 +00:00
|
|
|
error = rsu_fw_cmd(sc, R92S_CMD_SET_OPMODE, &opmode, sizeof(opmode));
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
memset(&auth, 0, sizeof(auth));
|
|
|
|
if (vap->iv_flags & IEEE80211_F_WPA) {
|
|
|
|
auth.mode = R92S_AUTHMODE_WPA;
|
2014-06-04 16:58:35 +00:00
|
|
|
auth.dot1x = (ni->ni_authmode == IEEE80211_AUTH_8021X);
|
2013-07-30 02:07:57 +00:00
|
|
|
} else
|
|
|
|
auth.mode = R92S_AUTHMODE_OPEN;
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_RESET,
|
|
|
|
"%s: setting auth mode to %d\n",
|
|
|
|
__func__, auth.mode);
|
2013-07-30 02:07:57 +00:00
|
|
|
error = rsu_fw_cmd(sc, R92S_CMD_SET_AUTH, &auth, sizeof(auth));
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
bss = (struct ndis_wlan_bssid_ex *)buf;
|
|
|
|
IEEE80211_ADDR_COPY(bss->macaddr, ni->ni_bssid);
|
|
|
|
bss->ssid.ssidlen = htole32(ni->ni_esslen);
|
|
|
|
memcpy(bss->ssid.ssid, ni->ni_essid, ni->ni_esslen);
|
|
|
|
if (vap->iv_flags & (IEEE80211_F_PRIVACY | IEEE80211_F_WPA))
|
|
|
|
bss->privacy = htole32(1);
|
|
|
|
bss->rssi = htole32(ni->ni_avgrssi);
|
|
|
|
if (ic->ic_curmode == IEEE80211_MODE_11B)
|
|
|
|
bss->networktype = htole32(NDIS802_11DS);
|
|
|
|
else
|
|
|
|
bss->networktype = htole32(NDIS802_11OFDM24);
|
|
|
|
bss->config.len = htole32(sizeof(bss->config));
|
|
|
|
bss->config.bintval = htole32(ni->ni_intval);
|
|
|
|
bss->config.dsconfig = htole32(ieee80211_chan2ieee(ic, ni->ni_chan));
|
|
|
|
bss->inframode = htole32(NDIS802_11INFRASTRUCTURE);
|
2015-09-12 23:10:34 +00:00
|
|
|
/* XXX verify how this is supposed to look! */
|
2013-07-30 02:07:57 +00:00
|
|
|
memcpy(bss->supprates, ni->ni_rates.rs_rates,
|
|
|
|
ni->ni_rates.rs_nrates);
|
|
|
|
/* Write the fixed fields of the beacon frame. */
|
|
|
|
fixed = (struct ndis_802_11_fixed_ies *)&bss[1];
|
|
|
|
memcpy(&fixed->tstamp, ni->ni_tstamp.data, 8);
|
|
|
|
fixed->bintval = htole16(ni->ni_intval);
|
|
|
|
fixed->capabilities = htole16(ni->ni_capinfo);
|
|
|
|
/* Write IEs to be included in the association request. */
|
|
|
|
frm = (uint8_t *)&fixed[1];
|
|
|
|
frm = ieee80211_add_rsn(frm, vap);
|
|
|
|
frm = ieee80211_add_wpa(frm, vap);
|
|
|
|
frm = ieee80211_add_qos(frm, ni);
|
2015-09-18 04:12:11 +00:00
|
|
|
if ((ic->ic_flags & IEEE80211_F_WME) &&
|
|
|
|
(ni->ni_ies.wme_ie != NULL))
|
|
|
|
frm = ieee80211_add_wme_info(frm, &ic->ic_wme);
|
2013-07-30 02:07:57 +00:00
|
|
|
if (ni->ni_flags & IEEE80211_NODE_HT)
|
|
|
|
frm = ieee80211_add_htcap(frm, ni);
|
|
|
|
bss->ieslen = htole32(frm - (uint8_t *)fixed);
|
|
|
|
bss->len = htole32(((frm - buf) + 3) & ~3);
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_RESET | RSU_DEBUG_FWCMD,
|
|
|
|
"%s: sending join bss command to %s chan %d\n",
|
|
|
|
__func__,
|
2013-07-30 02:07:57 +00:00
|
|
|
ether_sprintf(bss->macaddr), le32toh(bss->config.dsconfig));
|
|
|
|
return (rsu_fw_cmd(sc, R92S_CMD_JOIN_BSS, buf, sizeof(buf)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_disconnect(struct rsu_softc *sc)
|
|
|
|
{
|
|
|
|
uint32_t zero = 0; /* :-) */
|
|
|
|
|
|
|
|
/* Disassociate from our current BSS. */
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_STATE | RSU_DEBUG_FWCMD,
|
|
|
|
"%s: sending disconnect command\n", __func__);
|
2013-07-30 02:07:57 +00:00
|
|
|
return (rsu_fw_cmd(sc, R92S_CMD_DISCONNECT, &zero, sizeof(zero)));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
|
|
|
|
{
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct ieee80211_frame *wh;
|
|
|
|
struct ndis_wlan_bssid_ex *bss;
|
2015-09-15 03:01:40 +00:00
|
|
|
struct ieee80211_rx_stats rxs;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct mbuf *m;
|
|
|
|
int pktlen;
|
|
|
|
|
|
|
|
if (__predict_false(len < sizeof(*bss)))
|
|
|
|
return;
|
|
|
|
bss = (struct ndis_wlan_bssid_ex *)buf;
|
|
|
|
if (__predict_false(len < sizeof(*bss) + le32toh(bss->ieslen)))
|
|
|
|
return;
|
|
|
|
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_SCAN,
|
|
|
|
"%s: found BSS %s: len=%d chan=%d inframode=%d "
|
2015-09-13 05:22:20 +00:00
|
|
|
"networktype=%d privacy=%d, RSSI=%d\n",
|
2015-09-12 23:10:34 +00:00
|
|
|
__func__,
|
2013-07-30 02:07:57 +00:00
|
|
|
ether_sprintf(bss->macaddr), le32toh(bss->len),
|
|
|
|
le32toh(bss->config.dsconfig), le32toh(bss->inframode),
|
2015-09-13 05:22:20 +00:00
|
|
|
le32toh(bss->networktype), le32toh(bss->privacy),
|
|
|
|
le32toh(bss->rssi));
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
/* Build a fake beacon frame to let net80211 do all the parsing. */
|
2015-09-12 23:10:34 +00:00
|
|
|
/* XXX TODO: just call the new scan API methods! */
|
2013-07-30 02:07:57 +00:00
|
|
|
pktlen = sizeof(*wh) + le32toh(bss->ieslen);
|
|
|
|
if (__predict_false(pktlen > MCLBYTES))
|
|
|
|
return;
|
2014-01-10 14:47:20 +00:00
|
|
|
m = m_get2(pktlen, M_NOWAIT, MT_DATA, M_PKTHDR);
|
2013-07-30 02:07:57 +00:00
|
|
|
if (__predict_false(m == NULL))
|
|
|
|
return;
|
|
|
|
wh = mtod(m, struct ieee80211_frame *);
|
|
|
|
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
|
|
|
|
IEEE80211_FC0_SUBTYPE_BEACON;
|
|
|
|
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
|
2013-12-04 12:07:46 +00:00
|
|
|
USETW(wh->i_dur, 0);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
IEEE80211_ADDR_COPY(wh->i_addr1, ieee80211broadcastaddr);
|
2013-07-30 02:07:57 +00:00
|
|
|
IEEE80211_ADDR_COPY(wh->i_addr2, bss->macaddr);
|
|
|
|
IEEE80211_ADDR_COPY(wh->i_addr3, bss->macaddr);
|
|
|
|
*(uint16_t *)wh->i_seq = 0;
|
|
|
|
memcpy(&wh[1], (uint8_t *)&bss[1], le32toh(bss->ieslen));
|
|
|
|
|
|
|
|
/* Finalize mbuf. */
|
|
|
|
m->m_pkthdr.len = m->m_len = pktlen;
|
2015-09-15 03:01:40 +00:00
|
|
|
|
|
|
|
/* Set channel flags for input path */
|
|
|
|
bzero(&rxs, sizeof(rxs));
|
|
|
|
rxs.r_flags |= IEEE80211_R_IEEE | IEEE80211_R_FREQ;
|
|
|
|
rxs.r_flags |= IEEE80211_R_NF | IEEE80211_R_RSSI;
|
|
|
|
rxs.c_ieee = le32toh(bss->config.dsconfig);
|
|
|
|
rxs.c_freq = ieee80211_ieee2mhz(rxs.c_ieee, IEEE80211_CHAN_2GHZ);
|
|
|
|
rxs.rssi = le32toh(bss->rssi);
|
|
|
|
rxs.nf = 0; /* XXX */
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
/* XXX avoid a LOR */
|
|
|
|
RSU_UNLOCK(sc);
|
2015-09-15 03:01:40 +00:00
|
|
|
ieee80211_input_mimo_all(ic, m, &rxs);
|
2013-07-30 02:07:57 +00:00
|
|
|
RSU_LOCK(sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
|
|
|
|
{
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
|
|
|
struct ieee80211_node *ni = vap->iv_bss;
|
|
|
|
struct r92s_event_join_bss *rsp;
|
2014-06-04 16:58:35 +00:00
|
|
|
uint32_t tmp;
|
2013-07-30 02:07:57 +00:00
|
|
|
int res;
|
|
|
|
|
|
|
|
if (__predict_false(len < sizeof(*rsp)))
|
|
|
|
return;
|
|
|
|
rsp = (struct r92s_event_join_bss *)buf;
|
|
|
|
res = (int)le32toh(rsp->join_res);
|
|
|
|
|
2015-09-13 04:12:51 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_STATE | RSU_DEBUG_FWCMD,
|
|
|
|
"%s: Rx join BSS event len=%d res=%d\n",
|
|
|
|
__func__, len, res);
|
2015-09-18 07:55:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX Don't do this; there's likely a better way to tell
|
|
|
|
* the caller we failed.
|
|
|
|
*/
|
2013-07-30 02:07:57 +00:00
|
|
|
if (res <= 0) {
|
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
return;
|
|
|
|
}
|
2015-09-18 07:55:33 +00:00
|
|
|
|
2014-06-04 16:58:35 +00:00
|
|
|
tmp = le32toh(rsp->associd);
|
|
|
|
if (tmp >= vap->iv_max_aid) {
|
|
|
|
DPRINTF("Assoc ID overflow\n");
|
|
|
|
tmp = 1;
|
|
|
|
}
|
2015-09-13 04:12:51 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_STATE | RSU_DEBUG_FWCMD,
|
|
|
|
"%s: associated with %s associd=%d\n",
|
|
|
|
__func__, ether_sprintf(rsp->bss.macaddr), tmp);
|
|
|
|
/* XXX is this required? What's the top two bits for again? */
|
2014-06-04 16:58:35 +00:00
|
|
|
ni->ni_associd = tmp | 0xc000;
|
2013-07-30 02:07:57 +00:00
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
ieee80211_new_state(vap, IEEE80211_S_RUN,
|
|
|
|
IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
}
|
|
|
|
|
2015-09-18 05:03:01 +00:00
|
|
|
static void
|
|
|
|
rsu_event_addba_req_report(struct rsu_softc *sc, uint8_t *buf, int len)
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
|
|
|
struct r92s_add_ba_event *ba = (void *) buf;
|
|
|
|
struct ieee80211_node *ni;
|
|
|
|
|
|
|
|
if (len < sizeof(*ba)) {
|
|
|
|
device_printf(sc->sc_dev, "%s: short read (%d)\n", __func__, len);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vap == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
device_printf(sc->sc_dev, "%s: mac=%s, tid=%d, ssn=%d\n",
|
|
|
|
__func__,
|
|
|
|
ether_sprintf(ba->mac_addr),
|
|
|
|
(int) ba->tid,
|
|
|
|
(int) le16toh(ba->ssn));
|
|
|
|
|
|
|
|
/* XXX do node lookup; this is STA specific */
|
|
|
|
|
|
|
|
ni = ieee80211_ref_node(vap->iv_bss);
|
|
|
|
ieee80211_ampdu_rx_start_ext(ni, ba->tid, le16toh(ba->ssn) >> 4, 32);
|
|
|
|
ieee80211_free_node(ni);
|
|
|
|
}
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
static void
|
|
|
|
rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
|
|
|
|
{
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
|
|
|
|
2015-09-13 04:12:51 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_RX | RSU_DEBUG_FWCMD,
|
2015-09-12 23:10:34 +00:00
|
|
|
"%s: Rx event code=%d len=%d\n", __func__, code, len);
|
2013-07-30 02:07:57 +00:00
|
|
|
switch (code) {
|
|
|
|
case R92S_EVT_SURVEY:
|
2015-09-18 04:12:11 +00:00
|
|
|
rsu_event_survey(sc, buf, len);
|
2013-07-30 02:07:57 +00:00
|
|
|
break;
|
|
|
|
case R92S_EVT_SURVEY_DONE:
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_SCAN,
|
|
|
|
"%s: site survey pass %d done, found %d BSS\n",
|
|
|
|
__func__, sc->sc_scan_pass, le32toh(*(uint32_t *)buf));
|
2015-09-18 07:55:33 +00:00
|
|
|
sc->sc_scanning = 0;
|
2013-07-30 02:07:57 +00:00
|
|
|
if (vap->iv_state != IEEE80211_S_SCAN)
|
|
|
|
break; /* Ignore if not scanning. */
|
2015-09-18 07:55:33 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX TODO: This needs to be done without a transition to
|
|
|
|
* the SCAN state again. Grr.
|
|
|
|
*/
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
if (sc->sc_scan_pass == 0 && vap->iv_des_nssid != 0) {
|
2013-07-30 02:07:57 +00:00
|
|
|
/* Schedule a directed scan for hidden APs. */
|
2015-09-18 04:12:11 +00:00
|
|
|
/* XXX bad! */
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
sc->sc_scan_pass = 1;
|
2013-07-30 02:07:57 +00:00
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
break;
|
|
|
|
}
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
sc->sc_scan_pass = 0;
|
2013-07-30 02:07:57 +00:00
|
|
|
break;
|
|
|
|
case R92S_EVT_JOIN_BSS:
|
|
|
|
if (vap->iv_state == IEEE80211_S_AUTH)
|
|
|
|
rsu_event_join_bss(sc, buf, len);
|
|
|
|
break;
|
|
|
|
case R92S_EVT_DEL_STA:
|
2015-09-13 04:12:51 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_FWCMD | RSU_DEBUG_STATE,
|
|
|
|
"%s: disassociated from %s\n", __func__,
|
|
|
|
ether_sprintf(buf));
|
2013-07-30 02:07:57 +00:00
|
|
|
if (vap->iv_state == IEEE80211_S_RUN &&
|
|
|
|
IEEE80211_ADDR_EQ(vap->iv_bss->ni_bssid, buf)) {
|
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case R92S_EVT_WPS_PBC:
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_RX | RSU_DEBUG_FWCMD,
|
|
|
|
"%s: WPS PBC pushed.\n", __func__);
|
2013-07-30 02:07:57 +00:00
|
|
|
break;
|
|
|
|
case R92S_EVT_FWDBG:
|
2015-09-12 23:10:34 +00:00
|
|
|
buf[60] = '\0';
|
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_FWDBG, "FWDBG: %s\n", (char *)buf);
|
2013-07-30 02:07:57 +00:00
|
|
|
break;
|
2015-09-18 05:03:01 +00:00
|
|
|
|
|
|
|
case R92S_EVT_ADDBA_REQ_REPORT:
|
|
|
|
rsu_event_addba_req_report(sc, buf, len);
|
|
|
|
break;
|
2014-06-04 09:18:13 +00:00
|
|
|
default:
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_ANY, "%s: unhandled code (%d)\n",
|
|
|
|
__func__, code);
|
2014-06-04 09:18:13 +00:00
|
|
|
break;
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_rx_multi_event(struct rsu_softc *sc, uint8_t *buf, int len)
|
|
|
|
{
|
|
|
|
struct r92s_fw_cmd_hdr *cmd;
|
|
|
|
int cmdsz;
|
|
|
|
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_RX, "%s: Rx events len=%d\n", __func__, len);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
/* Skip Rx status. */
|
|
|
|
buf += sizeof(struct r92s_rx_stat);
|
|
|
|
len -= sizeof(struct r92s_rx_stat);
|
|
|
|
|
|
|
|
/* Process all events. */
|
|
|
|
for (;;) {
|
|
|
|
/* Check that command header fits. */
|
|
|
|
if (__predict_false(len < sizeof(*cmd)))
|
|
|
|
break;
|
|
|
|
cmd = (struct r92s_fw_cmd_hdr *)buf;
|
|
|
|
/* Check that command payload fits. */
|
|
|
|
cmdsz = le16toh(cmd->len);
|
|
|
|
if (__predict_false(len < sizeof(*cmd) + cmdsz))
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Process firmware event. */
|
|
|
|
rsu_rx_event(sc, cmd->code, (uint8_t *)&cmd[1], cmdsz);
|
|
|
|
|
|
|
|
if (!(cmd->seq & R92S_FW_CMD_MORE))
|
|
|
|
break;
|
|
|
|
buf += sizeof(*cmd) + cmdsz;
|
|
|
|
len -= sizeof(*cmd) + cmdsz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int8_t
|
|
|
|
rsu_get_rssi(struct rsu_softc *sc, int rate, void *physt)
|
|
|
|
{
|
|
|
|
static const int8_t cckoff[] = { 14, -2, -20, -40 };
|
|
|
|
struct r92s_rx_phystat *phy;
|
|
|
|
struct r92s_rx_cck *cck;
|
|
|
|
uint8_t rpt;
|
|
|
|
int8_t rssi;
|
|
|
|
|
|
|
|
if (rate <= 3) {
|
|
|
|
cck = (struct r92s_rx_cck *)physt;
|
|
|
|
rpt = (cck->agc_rpt >> 6) & 0x3;
|
|
|
|
rssi = cck->agc_rpt & 0x3e;
|
|
|
|
rssi = cckoff[rpt] - rssi;
|
|
|
|
} else { /* OFDM/HT. */
|
|
|
|
phy = (struct r92s_rx_phystat *)physt;
|
|
|
|
rssi = ((le32toh(phy->phydw1) >> 1) & 0x7f) - 106;
|
|
|
|
}
|
|
|
|
return (rssi);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct mbuf *
|
|
|
|
rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
|
|
|
|
{
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct ieee80211_frame *wh;
|
|
|
|
struct r92s_rx_stat *stat;
|
|
|
|
uint32_t rxdw0, rxdw3;
|
|
|
|
struct mbuf *m;
|
|
|
|
uint8_t rate;
|
|
|
|
int infosz;
|
|
|
|
|
|
|
|
stat = (struct r92s_rx_stat *)buf;
|
|
|
|
rxdw0 = le32toh(stat->rxdw0);
|
|
|
|
rxdw3 = le32toh(stat->rxdw3);
|
|
|
|
|
|
|
|
if (__predict_false(rxdw0 & R92S_RXDW0_CRCERR)) {
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
counter_u64_add(ic->ic_ierrors, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (__predict_false(pktlen < sizeof(*wh) || pktlen > MCLBYTES)) {
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
counter_u64_add(ic->ic_ierrors, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
rate = MS(rxdw3, R92S_RXDW3_RATE);
|
|
|
|
infosz = MS(rxdw0, R92S_RXDW0_INFOSZ) * 8;
|
|
|
|
|
|
|
|
/* Get RSSI from PHY status descriptor if present. */
|
|
|
|
if (infosz != 0)
|
|
|
|
*rssi = rsu_get_rssi(sc, rate, &stat[1]);
|
|
|
|
else
|
|
|
|
*rssi = 0;
|
|
|
|
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_RX,
|
|
|
|
"%s: Rx frame len=%d rate=%d infosz=%d rssi=%d\n",
|
|
|
|
__func__,
|
2013-07-30 02:07:57 +00:00
|
|
|
pktlen, rate, infosz, *rssi);
|
|
|
|
|
2014-01-10 14:47:20 +00:00
|
|
|
m = m_get2(pktlen, M_NOWAIT, MT_DATA, M_PKTHDR);
|
2013-07-30 02:07:57 +00:00
|
|
|
if (__predict_false(m == NULL)) {
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
counter_u64_add(ic->ic_ierrors, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
/* Hardware does Rx TCP checksum offload. */
|
|
|
|
if (rxdw3 & R92S_RXDW3_TCPCHKVALID) {
|
|
|
|
if (__predict_true(rxdw3 & R92S_RXDW3_TCPCHKRPT))
|
|
|
|
m->m_pkthdr.csum_flags |= CSUM_DATA_VALID;
|
|
|
|
}
|
|
|
|
wh = (struct ieee80211_frame *)((uint8_t *)&stat[1] + infosz);
|
|
|
|
memcpy(mtod(m, uint8_t *), wh, pktlen);
|
|
|
|
m->m_pkthdr.len = m->m_len = pktlen;
|
|
|
|
|
|
|
|
if (ieee80211_radiotap_active(ic)) {
|
|
|
|
struct rsu_rx_radiotap_header *tap = &sc->sc_rxtap;
|
|
|
|
|
|
|
|
/* Map HW rate index to 802.11 rate. */
|
|
|
|
tap->wr_flags = 2;
|
|
|
|
if (!(rxdw3 & R92S_RXDW3_HTC)) {
|
|
|
|
switch (rate) {
|
|
|
|
/* CCK. */
|
|
|
|
case 0: tap->wr_rate = 2; break;
|
|
|
|
case 1: tap->wr_rate = 4; break;
|
|
|
|
case 2: tap->wr_rate = 11; break;
|
|
|
|
case 3: tap->wr_rate = 22; break;
|
|
|
|
/* OFDM. */
|
|
|
|
case 4: tap->wr_rate = 12; break;
|
|
|
|
case 5: tap->wr_rate = 18; break;
|
|
|
|
case 6: tap->wr_rate = 24; break;
|
|
|
|
case 7: tap->wr_rate = 36; break;
|
|
|
|
case 8: tap->wr_rate = 48; break;
|
|
|
|
case 9: tap->wr_rate = 72; break;
|
|
|
|
case 10: tap->wr_rate = 96; break;
|
|
|
|
case 11: tap->wr_rate = 108; break;
|
|
|
|
}
|
|
|
|
} else if (rate >= 12) { /* MCS0~15. */
|
|
|
|
/* Bit 7 set means HT MCS instead of rate. */
|
|
|
|
tap->wr_rate = 0x80 | (rate - 12);
|
|
|
|
}
|
|
|
|
tap->wr_dbm_antsignal = *rssi;
|
|
|
|
tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
|
|
|
|
tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (m);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct mbuf *
|
|
|
|
rsu_rx_multi_frame(struct rsu_softc *sc, uint8_t *buf, int len, int *rssi)
|
|
|
|
{
|
|
|
|
struct r92s_rx_stat *stat;
|
|
|
|
uint32_t rxdw0;
|
|
|
|
int totlen, pktlen, infosz, npkts;
|
|
|
|
struct mbuf *m, *m0 = NULL, *prevm = NULL;
|
|
|
|
|
|
|
|
/* Get the number of encapsulated frames. */
|
|
|
|
stat = (struct r92s_rx_stat *)buf;
|
|
|
|
npkts = MS(le32toh(stat->rxdw2), R92S_RXDW2_PKTCNT);
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_RX,
|
|
|
|
"%s: Rx %d frames in one chunk\n", __func__, npkts);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
/* Process all of them. */
|
|
|
|
while (npkts-- > 0) {
|
|
|
|
if (__predict_false(len < sizeof(*stat)))
|
|
|
|
break;
|
|
|
|
stat = (struct r92s_rx_stat *)buf;
|
|
|
|
rxdw0 = le32toh(stat->rxdw0);
|
|
|
|
|
|
|
|
pktlen = MS(rxdw0, R92S_RXDW0_PKTLEN);
|
|
|
|
if (__predict_false(pktlen == 0))
|
|
|
|
break;
|
|
|
|
|
|
|
|
infosz = MS(rxdw0, R92S_RXDW0_INFOSZ) * 8;
|
|
|
|
|
|
|
|
/* Make sure everything fits in xfer. */
|
|
|
|
totlen = sizeof(*stat) + infosz + pktlen;
|
|
|
|
if (__predict_false(totlen > len))
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Process 802.11 frame. */
|
|
|
|
m = rsu_rx_frame(sc, buf, pktlen, rssi);
|
|
|
|
if (m0 == NULL)
|
|
|
|
m0 = m;
|
|
|
|
if (prevm == NULL)
|
|
|
|
prevm = m;
|
|
|
|
else {
|
|
|
|
prevm->m_next = m;
|
|
|
|
prevm = m;
|
|
|
|
}
|
|
|
|
/* Next chunk is 128-byte aligned. */
|
|
|
|
totlen = (totlen + 127) & ~127;
|
|
|
|
buf += totlen;
|
|
|
|
len -= totlen;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (m0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct mbuf *
|
|
|
|
rsu_rxeof(struct usb_xfer *xfer, struct rsu_data *data, int *rssi)
|
|
|
|
{
|
|
|
|
struct rsu_softc *sc = data->sc;
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct r92s_rx_stat *stat;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
usbd_xfer_status(xfer, &len, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
if (__predict_false(len < sizeof(*stat))) {
|
|
|
|
DPRINTF("xfer too short %d\n", len);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
counter_u64_add(ic->ic_ierrors, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
/* Determine if it is a firmware C2H event or an 802.11 frame. */
|
|
|
|
stat = (struct r92s_rx_stat *)data->buf;
|
|
|
|
if ((le32toh(stat->rxdw1) & 0x1ff) == 0x1ff) {
|
|
|
|
rsu_rx_multi_event(sc, data->buf, len);
|
|
|
|
/* No packets to process. */
|
|
|
|
return (NULL);
|
|
|
|
} else
|
|
|
|
return (rsu_rx_multi_frame(sc, data->buf, len, rssi));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
|
|
|
|
{
|
|
|
|
struct rsu_softc *sc = usbd_xfer_softc(xfer);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct ieee80211_frame *wh;
|
|
|
|
struct ieee80211_node *ni;
|
|
|
|
struct mbuf *m = NULL, *next;
|
|
|
|
struct rsu_data *data;
|
|
|
|
int rssi = 1;
|
|
|
|
|
|
|
|
RSU_ASSERT_LOCKED(sc);
|
|
|
|
|
|
|
|
switch (USB_GET_STATE(xfer)) {
|
|
|
|
case USB_ST_TRANSFERRED:
|
|
|
|
data = STAILQ_FIRST(&sc->sc_rx_active);
|
|
|
|
if (data == NULL)
|
|
|
|
goto tr_setup;
|
|
|
|
STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next);
|
|
|
|
m = rsu_rxeof(xfer, data, &rssi);
|
|
|
|
STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
case USB_ST_SETUP:
|
|
|
|
tr_setup:
|
|
|
|
data = STAILQ_FIRST(&sc->sc_rx_inactive);
|
|
|
|
if (data == NULL) {
|
|
|
|
KASSERT(m == NULL, ("mbuf isn't NULL"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next);
|
|
|
|
STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next);
|
|
|
|
usbd_xfer_set_frame_data(xfer, 0, data->buf,
|
|
|
|
usbd_xfer_max_len(xfer));
|
|
|
|
usbd_transfer_submit(xfer);
|
|
|
|
/*
|
|
|
|
* To avoid LOR we should unlock our private mutex here to call
|
|
|
|
* ieee80211_input() because here is at the end of a USB
|
|
|
|
* callback and safe to unlock.
|
|
|
|
*/
|
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
while (m != NULL) {
|
|
|
|
next = m->m_next;
|
|
|
|
m->m_next = NULL;
|
|
|
|
wh = mtod(m, struct ieee80211_frame *);
|
|
|
|
ni = ieee80211_find_rxnode(ic,
|
|
|
|
(struct ieee80211_frame_min *)wh);
|
|
|
|
if (ni != NULL) {
|
2015-09-18 05:03:01 +00:00
|
|
|
if (ni->ni_flags & IEEE80211_NODE_HT)
|
|
|
|
m->m_flags |= M_AMPDU;
|
2013-07-30 02:07:57 +00:00
|
|
|
(void)ieee80211_input(ni, m, rssi, 0);
|
|
|
|
ieee80211_free_node(ni);
|
|
|
|
} else
|
|
|
|
(void)ieee80211_input_all(ic, m, rssi, 0);
|
|
|
|
m = next;
|
|
|
|
}
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* needs it to the inactive queue due to a error. */
|
|
|
|
data = STAILQ_FIRST(&sc->sc_rx_active);
|
|
|
|
if (data != NULL) {
|
|
|
|
STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next);
|
|
|
|
STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
|
|
|
|
}
|
|
|
|
if (error != USB_ERR_CANCELLED) {
|
|
|
|
usbd_xfer_set_stall(xfer);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
counter_u64_add(ic->ic_ierrors, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
goto tr_setup;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_txeof(struct usb_xfer *xfer, struct rsu_data *data)
|
|
|
|
{
|
2015-09-12 23:10:34 +00:00
|
|
|
#ifdef USB_DEBUG
|
|
|
|
struct rsu_softc *sc = usbd_xfer_softc(xfer);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_TXDONE, "%s: called; data=%p\n",
|
|
|
|
__func__,
|
|
|
|
data);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
if (data->m) {
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
/* XXX status? */
|
|
|
|
ieee80211_tx_complete(data->ni, data->m, 0);
|
2013-07-30 02:07:57 +00:00
|
|
|
data->m = NULL;
|
|
|
|
data->ni = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-05-21 16:52:55 +00:00
|
|
|
rsu_bulk_tx_callback_sub(struct usb_xfer *xfer, usb_error_t error,
|
|
|
|
uint8_t which)
|
2013-07-30 02:07:57 +00:00
|
|
|
{
|
|
|
|
struct rsu_softc *sc = usbd_xfer_softc(xfer);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct rsu_data *data;
|
|
|
|
|
|
|
|
RSU_ASSERT_LOCKED(sc);
|
|
|
|
|
|
|
|
switch (USB_GET_STATE(xfer)) {
|
|
|
|
case USB_ST_TRANSFERRED:
|
2014-05-21 16:52:55 +00:00
|
|
|
data = STAILQ_FIRST(&sc->sc_tx_active[which]);
|
2013-07-30 02:07:57 +00:00
|
|
|
if (data == NULL)
|
|
|
|
goto tr_setup;
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_TXDONE, "%s: transfer done %p\n",
|
|
|
|
__func__, data);
|
2014-05-21 16:52:55 +00:00
|
|
|
STAILQ_REMOVE_HEAD(&sc->sc_tx_active[which], next);
|
2013-07-30 02:07:57 +00:00
|
|
|
rsu_txeof(xfer, data);
|
2015-09-18 07:26:34 +00:00
|
|
|
rsu_freebuf(sc, data);
|
2013-07-30 02:07:57 +00:00
|
|
|
/* FALLTHROUGH */
|
|
|
|
case USB_ST_SETUP:
|
|
|
|
tr_setup:
|
2014-05-21 16:52:55 +00:00
|
|
|
data = STAILQ_FIRST(&sc->sc_tx_pending[which]);
|
2013-07-30 02:07:57 +00:00
|
|
|
if (data == NULL) {
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_TXDONE,
|
|
|
|
"%s: empty pending queue sc %p\n", __func__, sc);
|
2013-07-30 02:07:57 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-05-21 16:52:55 +00:00
|
|
|
STAILQ_REMOVE_HEAD(&sc->sc_tx_pending[which], next);
|
|
|
|
STAILQ_INSERT_TAIL(&sc->sc_tx_active[which], data, next);
|
2013-07-30 02:07:57 +00:00
|
|
|
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_TXDONE,
|
|
|
|
"%s: submitting transfer %p\n",
|
|
|
|
__func__,
|
|
|
|
data);
|
2013-07-30 02:07:57 +00:00
|
|
|
usbd_transfer_submit(xfer);
|
|
|
|
break;
|
|
|
|
default:
|
2014-05-21 16:52:55 +00:00
|
|
|
data = STAILQ_FIRST(&sc->sc_tx_active[which]);
|
|
|
|
if (data != NULL) {
|
|
|
|
STAILQ_REMOVE_HEAD(&sc->sc_tx_active[which], next);
|
|
|
|
rsu_txeof(xfer, data);
|
2015-09-18 07:26:34 +00:00
|
|
|
rsu_freebuf(sc, data);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
counter_u64_add(ic->ic_oerrors, 1);
|
2014-05-21 16:52:55 +00:00
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
if (error != USB_ERR_CANCELLED) {
|
|
|
|
usbd_xfer_set_stall(xfer);
|
|
|
|
goto tr_setup;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-21 16:52:55 +00:00
|
|
|
static void
|
2014-06-04 09:18:13 +00:00
|
|
|
rsu_bulk_tx_callback_be_bk(struct usb_xfer *xfer, usb_error_t error)
|
2014-05-21 16:52:55 +00:00
|
|
|
{
|
2015-09-21 02:30:22 +00:00
|
|
|
struct rsu_softc *sc = usbd_xfer_softc(xfer);
|
|
|
|
|
2014-06-04 09:18:13 +00:00
|
|
|
rsu_bulk_tx_callback_sub(xfer, error, RSU_BULK_TX_BE_BK);
|
2015-09-21 02:30:22 +00:00
|
|
|
|
|
|
|
/* This kicks the TX taskqueue */
|
|
|
|
rsu_start(sc);
|
2014-05-21 16:52:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-06-04 09:18:13 +00:00
|
|
|
rsu_bulk_tx_callback_vi_vo(struct usb_xfer *xfer, usb_error_t error)
|
2014-05-21 16:52:55 +00:00
|
|
|
{
|
2015-09-21 02:30:22 +00:00
|
|
|
struct rsu_softc *sc = usbd_xfer_softc(xfer);
|
|
|
|
|
2014-06-04 09:18:13 +00:00
|
|
|
rsu_bulk_tx_callback_sub(xfer, error, RSU_BULK_TX_VI_VO);
|
2015-09-21 02:30:22 +00:00
|
|
|
|
|
|
|
/* This kicks the TX taskqueue */
|
|
|
|
rsu_start(sc);
|
2014-05-21 16:52:55 +00:00
|
|
|
}
|
|
|
|
|
2015-09-17 03:19:09 +00:00
|
|
|
static void
|
|
|
|
rsu_bulk_tx_callback_h2c(struct usb_xfer *xfer, usb_error_t error)
|
|
|
|
{
|
2015-09-21 02:30:22 +00:00
|
|
|
struct rsu_softc *sc = usbd_xfer_softc(xfer);
|
|
|
|
|
2015-09-17 03:19:09 +00:00
|
|
|
rsu_bulk_tx_callback_sub(xfer, error, RSU_BULK_TX_H2C);
|
2015-09-21 02:30:22 +00:00
|
|
|
|
|
|
|
/* This kicks the TX taskqueue */
|
|
|
|
rsu_start(sc);
|
2015-09-17 03:19:09 +00:00
|
|
|
}
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
static int
|
|
|
|
rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
|
2014-05-21 16:52:55 +00:00
|
|
|
struct mbuf *m0, struct rsu_data *data)
|
2013-07-30 02:07:57 +00:00
|
|
|
{
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct ieee80211vap *vap = ni->ni_vap;
|
|
|
|
struct ieee80211_frame *wh;
|
|
|
|
struct ieee80211_key *k = NULL;
|
|
|
|
struct r92s_tx_desc *txd;
|
2014-05-21 16:52:55 +00:00
|
|
|
uint8_t type;
|
2015-09-17 04:45:29 +00:00
|
|
|
int prio = 0;
|
2014-05-21 16:52:55 +00:00
|
|
|
uint8_t which;
|
|
|
|
int hasqos;
|
|
|
|
int xferlen;
|
2015-09-17 04:45:29 +00:00
|
|
|
int qid;
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
RSU_ASSERT_LOCKED(sc);
|
|
|
|
|
|
|
|
wh = mtod(m0, struct ieee80211_frame *);
|
|
|
|
type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
|
|
|
|
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_TX, "%s: data=%p, m=%p\n",
|
|
|
|
__func__, data, m0);
|
|
|
|
|
2014-01-08 08:06:56 +00:00
|
|
|
if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
|
2013-07-30 02:07:57 +00:00
|
|
|
k = ieee80211_crypto_encap(ni, m0);
|
|
|
|
if (k == NULL) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"ieee80211_crypto_encap returns NULL.\n");
|
|
|
|
/* XXX we don't expect the fragmented frames */
|
|
|
|
m_freem(m0);
|
|
|
|
return (ENOBUFS);
|
|
|
|
}
|
|
|
|
wh = mtod(m0, struct ieee80211_frame *);
|
|
|
|
}
|
2015-09-17 04:45:29 +00:00
|
|
|
/* If we have QoS then use it */
|
|
|
|
/* XXX TODO: mbuf WME/PRI versus TID? */
|
|
|
|
if (IEEE80211_QOS_HAS_SEQ(wh)) {
|
|
|
|
/* Has QoS */
|
|
|
|
prio = M_WME_GETAC(m0);
|
|
|
|
which = rsu_wme_ac_xfer_map[prio];
|
|
|
|
hasqos = 1;
|
|
|
|
} else {
|
|
|
|
/* Non-QoS TID */
|
|
|
|
/* XXX TODO: tid=0 for non-qos TID? */
|
|
|
|
which = rsu_wme_ac_xfer_map[WME_AC_BE];
|
|
|
|
hasqos = 0;
|
|
|
|
prio = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
qid = rsu_ac2qid[prio];
|
|
|
|
#if 0
|
2013-07-30 02:07:57 +00:00
|
|
|
switch (type) {
|
|
|
|
case IEEE80211_FC0_TYPE_CTL:
|
|
|
|
case IEEE80211_FC0_TYPE_MGT:
|
2014-06-04 09:18:13 +00:00
|
|
|
which = rsu_wme_ac_xfer_map[WME_AC_VO];
|
2013-07-30 02:07:57 +00:00
|
|
|
break;
|
|
|
|
default:
|
2014-06-04 09:18:13 +00:00
|
|
|
which = rsu_wme_ac_xfer_map[M_WME_GETAC(m0)];
|
2013-07-30 02:07:57 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
hasqos = 0;
|
2015-09-17 04:45:29 +00:00
|
|
|
#endif
|
2015-09-18 04:12:11 +00:00
|
|
|
|
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_TX, "%s: pri=%d, which=%d, hasqos=%d\n",
|
|
|
|
__func__,
|
|
|
|
prio,
|
|
|
|
which,
|
|
|
|
hasqos);
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
/* Fill Tx descriptor. */
|
|
|
|
txd = (struct r92s_tx_desc *)data->buf;
|
|
|
|
memset(txd, 0, sizeof(*txd));
|
|
|
|
|
|
|
|
txd->txdw0 |= htole32(
|
|
|
|
SM(R92S_TXDW0_PKTLEN, m0->m_pkthdr.len) |
|
|
|
|
SM(R92S_TXDW0_OFFSET, sizeof(*txd)) |
|
|
|
|
R92S_TXDW0_OWN | R92S_TXDW0_FSG | R92S_TXDW0_LSG);
|
|
|
|
|
|
|
|
txd->txdw1 |= htole32(
|
2015-09-17 04:45:29 +00:00
|
|
|
SM(R92S_TXDW1_MACID, R92S_MACID_BSS) | SM(R92S_TXDW1_QSEL, qid));
|
2013-07-30 02:07:57 +00:00
|
|
|
if (!hasqos)
|
|
|
|
txd->txdw1 |= htole32(R92S_TXDW1_NONQOS);
|
|
|
|
#ifdef notyet
|
|
|
|
if (k != NULL) {
|
|
|
|
switch (k->wk_cipher->ic_cipher) {
|
|
|
|
case IEEE80211_CIPHER_WEP:
|
|
|
|
cipher = R92S_TXDW1_CIPHER_WEP;
|
|
|
|
break;
|
|
|
|
case IEEE80211_CIPHER_TKIP:
|
|
|
|
cipher = R92S_TXDW1_CIPHER_TKIP;
|
|
|
|
break;
|
|
|
|
case IEEE80211_CIPHER_AES_CCM:
|
|
|
|
cipher = R92S_TXDW1_CIPHER_AES;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cipher = R92S_TXDW1_CIPHER_NONE;
|
|
|
|
}
|
|
|
|
txd->txdw1 |= htole32(
|
|
|
|
SM(R92S_TXDW1_CIPHER, cipher) |
|
|
|
|
SM(R92S_TXDW1_KEYIDX, k->k_id));
|
|
|
|
}
|
|
|
|
#endif
|
2015-09-18 04:12:11 +00:00
|
|
|
/* XXX todo: set AGGEN bit if appropriate? */
|
2013-07-30 02:07:57 +00:00
|
|
|
txd->txdw2 |= htole32(R92S_TXDW2_BK);
|
|
|
|
if (IEEE80211_IS_MULTICAST(wh->i_addr1))
|
|
|
|
txd->txdw2 |= htole32(R92S_TXDW2_BMCAST);
|
|
|
|
/*
|
|
|
|
* Firmware will use and increment the sequence number for the
|
2015-09-17 04:45:29 +00:00
|
|
|
* specified priority.
|
2013-07-30 02:07:57 +00:00
|
|
|
*/
|
2015-09-17 04:45:29 +00:00
|
|
|
txd->txdw3 |= htole32(SM(R92S_TXDW3_SEQ, prio));
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
if (ieee80211_radiotap_active_vap(vap)) {
|
|
|
|
struct rsu_tx_radiotap_header *tap = &sc->sc_txtap;
|
|
|
|
|
|
|
|
tap->wt_flags = 0;
|
|
|
|
tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq);
|
|
|
|
tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags);
|
|
|
|
ieee80211_radiotap_tx(vap, m0);
|
|
|
|
}
|
2015-09-12 23:10:34 +00:00
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
xferlen = sizeof(*txd) + m0->m_pkthdr.len;
|
|
|
|
m_copydata(m0, 0, m0->m_pkthdr.len, (caddr_t)&txd[1]);
|
|
|
|
|
|
|
|
data->buflen = xferlen;
|
|
|
|
data->ni = ni;
|
|
|
|
data->m = m0;
|
2014-05-21 16:52:55 +00:00
|
|
|
STAILQ_INSERT_TAIL(&sc->sc_tx_pending[which], data, next);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
2014-05-21 16:52:55 +00:00
|
|
|
/* start transfer, if any */
|
2014-06-04 09:18:13 +00:00
|
|
|
usbd_transfer_start(sc->sc_xfer[which]);
|
2013-07-30 02:07:57 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
static int
|
|
|
|
rsu_transmit(struct ieee80211com *ic, struct mbuf *m)
|
2013-07-30 02:07:57 +00:00
|
|
|
{
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct rsu_softc *sc = ic->ic_softc;
|
|
|
|
int error;
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
RSU_LOCK(sc);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
if (!sc->sc_running) {
|
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
return (ENXIO);
|
|
|
|
}
|
|
|
|
error = mbufq_enqueue(&sc->sc_snd, m);
|
|
|
|
if (error) {
|
2015-09-21 02:12:01 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_TX,
|
|
|
|
"%s: mbufq_enable: failed (%d)\n",
|
|
|
|
__func__,
|
|
|
|
error);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
return (error);
|
|
|
|
}
|
2013-07-30 02:07:57 +00:00
|
|
|
RSU_UNLOCK(sc);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
|
2015-09-21 02:30:22 +00:00
|
|
|
/* This kicks the TX taskqueue */
|
|
|
|
rsu_start(sc);
|
|
|
|
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
return (0);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
|
2015-09-21 02:12:01 +00:00
|
|
|
static void
|
|
|
|
rsu_drain_mbufq(struct rsu_softc *sc)
|
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
struct ieee80211_node *ni;
|
|
|
|
|
|
|
|
RSU_ASSERT_LOCKED(sc);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
static void
|
2015-09-21 02:30:22 +00:00
|
|
|
_rsu_start(struct rsu_softc *sc)
|
2013-07-30 02:07:57 +00:00
|
|
|
{
|
|
|
|
struct ieee80211_node *ni;
|
|
|
|
struct rsu_data *bf;
|
2014-05-21 16:52:55 +00:00
|
|
|
struct mbuf *m;
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
RSU_ASSERT_LOCKED(sc);
|
|
|
|
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
|
|
|
bf = rsu_getbuf(sc);
|
|
|
|
if (bf == NULL) {
|
2015-09-21 02:12:01 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_TX,
|
|
|
|
"%s: failed to get buffer\n", __func__);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
mbufq_prepend(&sc->sc_snd, m);
|
2013-07-30 02:07:57 +00:00
|
|
|
break;
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
}
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
|
|
|
|
m->m_pkthdr.rcvif = NULL;
|
|
|
|
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
if (rsu_tx_start(sc, ni, m, bf) != 0) {
|
2015-09-21 02:12:01 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_TX,
|
|
|
|
"%s: failed to transmit\n", __func__);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
if_inc_counter(ni->ni_vap->iv_ifp,
|
|
|
|
IFCOUNTER_OERRORS, 1);
|
2015-09-18 07:26:34 +00:00
|
|
|
rsu_freebuf(sc, bf);
|
2013-07-30 02:07:57 +00:00
|
|
|
ieee80211_free_node(ni);
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
break;
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-21 02:30:22 +00:00
|
|
|
static void
|
|
|
|
rsu_start(struct rsu_softc *sc)
|
|
|
|
{
|
|
|
|
|
|
|
|
taskqueue_enqueue(taskqueue_thread, &sc->tx_task);
|
|
|
|
}
|
|
|
|
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
static void
|
|
|
|
rsu_parent(struct ieee80211com *ic)
|
2013-07-30 02:07:57 +00:00
|
|
|
{
|
2015-08-20 05:13:54 +00:00
|
|
|
struct rsu_softc *sc = ic->ic_softc;
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
int startall = 0;
|
|
|
|
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
if (ic->ic_nrunning > 0) {
|
|
|
|
if (!sc->sc_running) {
|
|
|
|
rsu_init(sc);
|
|
|
|
startall = 1;
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
} else if (sc->sc_running)
|
|
|
|
rsu_stop(sc);
|
|
|
|
RSU_UNLOCK(sc);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
if (startall)
|
|
|
|
ieee80211_start_all(ic);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Power on sequence for A-cut adapters.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
rsu_power_on_acut(struct rsu_softc *sc)
|
|
|
|
{
|
|
|
|
uint32_t reg;
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_SPS0_CTRL + 1, 0x53);
|
|
|
|
rsu_write_1(sc, R92S_SPS0_CTRL + 0, 0x57);
|
|
|
|
|
|
|
|
/* Enable AFE macro block's bandgap and Mbias. */
|
|
|
|
rsu_write_1(sc, R92S_AFE_MISC,
|
|
|
|
rsu_read_1(sc, R92S_AFE_MISC) |
|
|
|
|
R92S_AFE_MISC_BGEN | R92S_AFE_MISC_MBEN);
|
|
|
|
/* Enable LDOA15 block. */
|
|
|
|
rsu_write_1(sc, R92S_LDOA15_CTRL,
|
|
|
|
rsu_read_1(sc, R92S_LDOA15_CTRL) | R92S_LDA15_EN);
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_SPS1_CTRL,
|
|
|
|
rsu_read_1(sc, R92S_SPS1_CTRL) | R92S_SPS1_LDEN);
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 2000);
|
2013-07-30 02:07:57 +00:00
|
|
|
/* Enable switch regulator block. */
|
|
|
|
rsu_write_1(sc, R92S_SPS1_CTRL,
|
|
|
|
rsu_read_1(sc, R92S_SPS1_CTRL) | R92S_SPS1_SWEN);
|
|
|
|
|
|
|
|
rsu_write_4(sc, R92S_SPS1_CTRL, 0x00a7b267);
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_SYS_ISO_CTRL + 1,
|
|
|
|
rsu_read_1(sc, R92S_SYS_ISO_CTRL + 1) | 0x08);
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
|
|
|
|
rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) | 0x20);
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_SYS_ISO_CTRL + 1,
|
|
|
|
rsu_read_1(sc, R92S_SYS_ISO_CTRL + 1) & ~0x90);
|
|
|
|
|
|
|
|
/* Enable AFE clock. */
|
|
|
|
rsu_write_1(sc, R92S_AFE_XTAL_CTRL + 1,
|
|
|
|
rsu_read_1(sc, R92S_AFE_XTAL_CTRL + 1) & ~0x04);
|
|
|
|
/* Enable AFE PLL macro block. */
|
|
|
|
rsu_write_1(sc, R92S_AFE_PLL_CTRL,
|
|
|
|
rsu_read_1(sc, R92S_AFE_PLL_CTRL) | 0x11);
|
|
|
|
/* Attach AFE PLL to MACTOP/BB. */
|
|
|
|
rsu_write_1(sc, R92S_SYS_ISO_CTRL,
|
|
|
|
rsu_read_1(sc, R92S_SYS_ISO_CTRL) & ~0x11);
|
|
|
|
|
|
|
|
/* Switch to 40MHz clock instead of 80MHz. */
|
|
|
|
rsu_write_2(sc, R92S_SYS_CLKR,
|
|
|
|
rsu_read_2(sc, R92S_SYS_CLKR) & ~R92S_SYS_CLKSEL);
|
|
|
|
|
|
|
|
/* Enable MAC clock. */
|
|
|
|
rsu_write_2(sc, R92S_SYS_CLKR,
|
|
|
|
rsu_read_2(sc, R92S_SYS_CLKR) |
|
|
|
|
R92S_MAC_CLK_EN | R92S_SYS_CLK_EN);
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_PMC_FSM, 0x02);
|
|
|
|
|
|
|
|
/* Enable digital core and IOREG R/W. */
|
|
|
|
rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
|
|
|
|
rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) | 0x08);
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
|
|
|
|
rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) | 0x80);
|
|
|
|
|
|
|
|
/* Switch the control path to firmware. */
|
|
|
|
reg = rsu_read_2(sc, R92S_SYS_CLKR);
|
|
|
|
reg = (reg & ~R92S_SWHW_SEL) | R92S_FWHW_SEL;
|
|
|
|
rsu_write_2(sc, R92S_SYS_CLKR, reg);
|
|
|
|
|
|
|
|
rsu_write_2(sc, R92S_CR, 0x37fc);
|
|
|
|
|
|
|
|
/* Fix USB RX FIFO issue. */
|
|
|
|
rsu_write_1(sc, 0xfe5c,
|
|
|
|
rsu_read_1(sc, 0xfe5c) | 0x80);
|
|
|
|
rsu_write_1(sc, 0x00ab,
|
|
|
|
rsu_read_1(sc, 0x00ab) | 0xc0);
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_SYS_CLKR,
|
|
|
|
rsu_read_1(sc, R92S_SYS_CLKR) & ~R92S_SYS_CPU_CLKSEL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Power on sequence for B-cut and C-cut adapters.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
rsu_power_on_bcut(struct rsu_softc *sc)
|
|
|
|
{
|
|
|
|
uint32_t reg;
|
|
|
|
int ntries;
|
|
|
|
|
|
|
|
/* Prevent eFuse leakage. */
|
|
|
|
rsu_write_1(sc, 0x37, 0xb0);
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 10);
|
2013-07-30 02:07:57 +00:00
|
|
|
rsu_write_1(sc, 0x37, 0x30);
|
|
|
|
|
|
|
|
/* Switch the control path to hardware. */
|
|
|
|
reg = rsu_read_2(sc, R92S_SYS_CLKR);
|
|
|
|
if (reg & R92S_FWHW_SEL) {
|
|
|
|
rsu_write_2(sc, R92S_SYS_CLKR,
|
|
|
|
reg & ~(R92S_SWHW_SEL | R92S_FWHW_SEL));
|
|
|
|
}
|
|
|
|
rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
|
|
|
|
rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) & ~0x8c);
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_SPS0_CTRL + 1, 0x53);
|
|
|
|
rsu_write_1(sc, R92S_SPS0_CTRL + 0, 0x57);
|
|
|
|
|
|
|
|
reg = rsu_read_1(sc, R92S_AFE_MISC);
|
|
|
|
rsu_write_1(sc, R92S_AFE_MISC, reg | R92S_AFE_MISC_BGEN);
|
|
|
|
rsu_write_1(sc, R92S_AFE_MISC, reg | R92S_AFE_MISC_BGEN |
|
|
|
|
R92S_AFE_MISC_MBEN | R92S_AFE_MISC_I32_EN);
|
|
|
|
|
|
|
|
/* Enable PLL. */
|
|
|
|
rsu_write_1(sc, R92S_LDOA15_CTRL,
|
|
|
|
rsu_read_1(sc, R92S_LDOA15_CTRL) | R92S_LDA15_EN);
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_LDOV12D_CTRL,
|
|
|
|
rsu_read_1(sc, R92S_LDOV12D_CTRL) | R92S_LDV12_EN);
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_SYS_ISO_CTRL + 1,
|
|
|
|
rsu_read_1(sc, R92S_SYS_ISO_CTRL + 1) | 0x08);
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
|
|
|
|
rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) | 0x20);
|
|
|
|
|
|
|
|
/* Support 64KB IMEM. */
|
|
|
|
rsu_write_1(sc, R92S_SYS_ISO_CTRL + 1,
|
|
|
|
rsu_read_1(sc, R92S_SYS_ISO_CTRL + 1) & ~0x97);
|
|
|
|
|
|
|
|
/* Enable AFE clock. */
|
|
|
|
rsu_write_1(sc, R92S_AFE_XTAL_CTRL + 1,
|
|
|
|
rsu_read_1(sc, R92S_AFE_XTAL_CTRL + 1) & ~0x04);
|
|
|
|
/* Enable AFE PLL macro block. */
|
|
|
|
reg = rsu_read_1(sc, R92S_AFE_PLL_CTRL);
|
|
|
|
rsu_write_1(sc, R92S_AFE_PLL_CTRL, reg | 0x11);
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
rsu_write_1(sc, R92S_AFE_PLL_CTRL, reg | 0x51);
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
rsu_write_1(sc, R92S_AFE_PLL_CTRL, reg | 0x11);
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
/* Attach AFE PLL to MACTOP/BB. */
|
|
|
|
rsu_write_1(sc, R92S_SYS_ISO_CTRL,
|
|
|
|
rsu_read_1(sc, R92S_SYS_ISO_CTRL) & ~0x11);
|
|
|
|
|
|
|
|
/* Switch to 40MHz clock. */
|
|
|
|
rsu_write_1(sc, R92S_SYS_CLKR, 0x00);
|
|
|
|
/* Disable CPU clock and 80MHz SSC. */
|
|
|
|
rsu_write_1(sc, R92S_SYS_CLKR,
|
|
|
|
rsu_read_1(sc, R92S_SYS_CLKR) | 0xa0);
|
|
|
|
/* Enable MAC clock. */
|
|
|
|
rsu_write_2(sc, R92S_SYS_CLKR,
|
|
|
|
rsu_read_2(sc, R92S_SYS_CLKR) |
|
|
|
|
R92S_MAC_CLK_EN | R92S_SYS_CLK_EN);
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_PMC_FSM, 0x02);
|
|
|
|
|
|
|
|
/* Enable digital core and IOREG R/W. */
|
|
|
|
rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
|
|
|
|
rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) | 0x08);
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
|
|
|
|
rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) | 0x80);
|
|
|
|
|
|
|
|
/* Switch the control path to firmware. */
|
|
|
|
reg = rsu_read_2(sc, R92S_SYS_CLKR);
|
|
|
|
reg = (reg & ~R92S_SWHW_SEL) | R92S_FWHW_SEL;
|
|
|
|
rsu_write_2(sc, R92S_SYS_CLKR, reg);
|
|
|
|
|
|
|
|
rsu_write_2(sc, R92S_CR, 0x37fc);
|
|
|
|
|
|
|
|
/* Fix USB RX FIFO issue. */
|
|
|
|
rsu_write_1(sc, 0xfe5c,
|
|
|
|
rsu_read_1(sc, 0xfe5c) | 0x80);
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_SYS_CLKR,
|
|
|
|
rsu_read_1(sc, R92S_SYS_CLKR) & ~R92S_SYS_CPU_CLKSEL);
|
|
|
|
|
|
|
|
rsu_write_1(sc, 0xfe1c, 0x80);
|
|
|
|
|
|
|
|
/* Make sure TxDMA is ready to download firmware. */
|
|
|
|
for (ntries = 0; ntries < 20; ntries++) {
|
|
|
|
reg = rsu_read_1(sc, R92S_TCR);
|
|
|
|
if ((reg & (R92S_TCR_IMEM_CHK_RPT | R92S_TCR_EMEM_CHK_RPT)) ==
|
|
|
|
(R92S_TCR_IMEM_CHK_RPT | R92S_TCR_EMEM_CHK_RPT))
|
|
|
|
break;
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
if (ntries == 20) {
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_RESET | RSU_DEBUG_TX,
|
|
|
|
"%s: TxDMA is not ready\n",
|
|
|
|
__func__);
|
2013-07-30 02:07:57 +00:00
|
|
|
/* Reset TxDMA. */
|
|
|
|
reg = rsu_read_1(sc, R92S_CR);
|
|
|
|
rsu_write_1(sc, R92S_CR, reg & ~R92S_CR_TXDMA_EN);
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
rsu_write_1(sc, R92S_CR, reg | R92S_CR_TXDMA_EN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rsu_power_off(struct rsu_softc *sc)
|
|
|
|
{
|
|
|
|
/* Turn RF off. */
|
|
|
|
rsu_write_1(sc, R92S_RF_CTRL, 0x00);
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 5);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
/* Turn MAC off. */
|
|
|
|
/* Switch control path. */
|
|
|
|
rsu_write_1(sc, R92S_SYS_CLKR + 1, 0x38);
|
|
|
|
/* Reset MACTOP. */
|
|
|
|
rsu_write_1(sc, R92S_SYS_FUNC_EN + 1, 0x70);
|
|
|
|
rsu_write_1(sc, R92S_PMC_FSM, 0x06);
|
|
|
|
rsu_write_1(sc, R92S_SYS_ISO_CTRL + 0, 0xf9);
|
|
|
|
rsu_write_1(sc, R92S_SYS_ISO_CTRL + 1, 0xe8);
|
|
|
|
|
|
|
|
/* Disable AFE PLL. */
|
|
|
|
rsu_write_1(sc, R92S_AFE_PLL_CTRL, 0x00);
|
|
|
|
/* Disable A15V. */
|
|
|
|
rsu_write_1(sc, R92S_LDOA15_CTRL, 0x54);
|
|
|
|
/* Disable eFuse 1.2V. */
|
|
|
|
rsu_write_1(sc, R92S_SYS_FUNC_EN + 1, 0x50);
|
|
|
|
rsu_write_1(sc, R92S_LDOV12D_CTRL, 0x24);
|
|
|
|
/* Enable AFE macro block's bandgap and Mbias. */
|
|
|
|
rsu_write_1(sc, R92S_AFE_MISC, 0x30);
|
|
|
|
/* Disable 1.6V LDO. */
|
|
|
|
rsu_write_1(sc, R92S_SPS0_CTRL + 0, 0x56);
|
|
|
|
rsu_write_1(sc, R92S_SPS0_CTRL + 1, 0x43);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-07-30 16:17:30 +00:00
|
|
|
rsu_fw_loadsection(struct rsu_softc *sc, const uint8_t *buf, int len)
|
2013-07-30 02:07:57 +00:00
|
|
|
{
|
2014-06-04 09:18:13 +00:00
|
|
|
const uint8_t which = rsu_wme_ac_xfer_map[WME_AC_VO];
|
2013-07-30 02:07:57 +00:00
|
|
|
struct rsu_data *data;
|
|
|
|
struct r92s_tx_desc *txd;
|
|
|
|
int mlen;
|
|
|
|
|
|
|
|
while (len > 0) {
|
|
|
|
data = rsu_getbuf(sc);
|
|
|
|
if (data == NULL)
|
|
|
|
return (ENOMEM);
|
|
|
|
txd = (struct r92s_tx_desc *)data->buf;
|
|
|
|
memset(txd, 0, sizeof(*txd));
|
|
|
|
if (len <= RSU_TXBUFSZ - sizeof(*txd)) {
|
|
|
|
/* Last chunk. */
|
|
|
|
txd->txdw0 |= htole32(R92S_TXDW0_LINIP);
|
|
|
|
mlen = len;
|
|
|
|
} else
|
|
|
|
mlen = RSU_TXBUFSZ - sizeof(*txd);
|
|
|
|
txd->txdw0 |= htole32(SM(R92S_TXDW0_PKTLEN, mlen));
|
|
|
|
memcpy(&txd[1], buf, mlen);
|
|
|
|
data->buflen = sizeof(*txd) + mlen;
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_TX | RSU_DEBUG_FW | RSU_DEBUG_RESET,
|
|
|
|
"%s: starting transfer %p\n",
|
|
|
|
__func__, data);
|
2014-05-21 16:52:55 +00:00
|
|
|
STAILQ_INSERT_TAIL(&sc->sc_tx_pending[which], data, next);
|
2013-07-30 02:07:57 +00:00
|
|
|
buf += mlen;
|
|
|
|
len -= mlen;
|
|
|
|
}
|
2014-06-04 09:18:13 +00:00
|
|
|
usbd_transfer_start(sc->sc_xfer[which]);
|
2013-07-30 02:07:57 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_load_firmware(struct rsu_softc *sc)
|
|
|
|
{
|
2013-07-30 16:17:30 +00:00
|
|
|
const struct r92s_fw_hdr *hdr;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct r92s_fw_priv *dmem;
|
2015-09-18 04:12:11 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
2013-07-30 16:17:30 +00:00
|
|
|
const uint8_t *imem, *emem;
|
2013-07-30 02:07:57 +00:00
|
|
|
int imemsz, ememsz;
|
|
|
|
const struct firmware *fw;
|
|
|
|
size_t size;
|
|
|
|
uint32_t reg;
|
|
|
|
int ntries, error;
|
|
|
|
|
2014-06-04 09:18:13 +00:00
|
|
|
if (rsu_read_1(sc, R92S_TCR) & R92S_TCR_FWRDY) {
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_FW | RSU_DEBUG_RESET,
|
|
|
|
"%s: Firmware already loaded\n",
|
|
|
|
__func__);
|
2014-06-04 09:18:13 +00:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
/* Read firmware image from the filesystem. */
|
|
|
|
if ((fw = firmware_get("rsu-rtl8712fw")) == NULL) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"%s: failed load firmware of file rsu-rtl8712fw\n",
|
|
|
|
__func__);
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
return (ENXIO);
|
|
|
|
}
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
size = fw->datasize;
|
|
|
|
if (size < sizeof(*hdr)) {
|
|
|
|
device_printf(sc->sc_dev, "firmware too short\n");
|
|
|
|
error = EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
2013-07-30 16:17:30 +00:00
|
|
|
hdr = (const struct r92s_fw_hdr *)fw->data;
|
2013-07-30 02:07:57 +00:00
|
|
|
if (hdr->signature != htole16(0x8712) &&
|
|
|
|
hdr->signature != htole16(0x8192)) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"invalid firmware signature 0x%x\n",
|
|
|
|
le16toh(hdr->signature));
|
|
|
|
error = EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
DPRINTF("FW V%d %02x-%02x %02x:%02x\n", le16toh(hdr->version),
|
|
|
|
hdr->month, hdr->day, hdr->hour, hdr->minute);
|
|
|
|
|
|
|
|
/* Make sure that driver and firmware are in sync. */
|
|
|
|
if (hdr->privsz != htole32(sizeof(*dmem))) {
|
|
|
|
device_printf(sc->sc_dev, "unsupported firmware image\n");
|
|
|
|
error = EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
/* Get FW sections sizes. */
|
|
|
|
imemsz = le32toh(hdr->imemsz);
|
|
|
|
ememsz = le32toh(hdr->sramsz);
|
|
|
|
/* Check that all FW sections fit in image. */
|
|
|
|
if (size < sizeof(*hdr) + imemsz + ememsz) {
|
|
|
|
device_printf(sc->sc_dev, "firmware too short\n");
|
|
|
|
error = EINVAL;
|
|
|
|
goto fail;
|
|
|
|
}
|
2013-07-30 16:17:30 +00:00
|
|
|
imem = (const uint8_t *)&hdr[1];
|
2013-07-30 02:07:57 +00:00
|
|
|
emem = imem + imemsz;
|
|
|
|
|
|
|
|
/* Load IMEM section. */
|
|
|
|
error = rsu_fw_loadsection(sc, imem, imemsz);
|
|
|
|
if (error != 0) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"could not load firmware section %s\n", "IMEM");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
/* Wait for load to complete. */
|
2014-05-22 06:28:09 +00:00
|
|
|
for (ntries = 0; ntries != 50; ntries++) {
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 10);
|
2014-06-04 09:18:13 +00:00
|
|
|
reg = rsu_read_1(sc, R92S_TCR);
|
2013-07-30 02:07:57 +00:00
|
|
|
if (reg & R92S_TCR_IMEM_CODE_DONE)
|
|
|
|
break;
|
|
|
|
}
|
2014-05-22 06:28:09 +00:00
|
|
|
if (ntries == 50) {
|
|
|
|
device_printf(sc->sc_dev, "timeout waiting for IMEM transfer\n");
|
2013-07-30 02:07:57 +00:00
|
|
|
error = ETIMEDOUT;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
/* Load EMEM section. */
|
|
|
|
error = rsu_fw_loadsection(sc, emem, ememsz);
|
|
|
|
if (error != 0) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"could not load firmware section %s\n", "EMEM");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
/* Wait for load to complete. */
|
2014-05-22 12:01:43 +00:00
|
|
|
for (ntries = 0; ntries != 50; ntries++) {
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 10);
|
2013-07-30 02:07:57 +00:00
|
|
|
reg = rsu_read_2(sc, R92S_TCR);
|
|
|
|
if (reg & R92S_TCR_EMEM_CODE_DONE)
|
|
|
|
break;
|
|
|
|
}
|
2014-05-22 12:01:43 +00:00
|
|
|
if (ntries == 50) {
|
2014-05-22 06:28:09 +00:00
|
|
|
device_printf(sc->sc_dev, "timeout waiting for EMEM transfer\n");
|
2013-07-30 02:07:57 +00:00
|
|
|
error = ETIMEDOUT;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
/* Enable CPU. */
|
|
|
|
rsu_write_1(sc, R92S_SYS_CLKR,
|
|
|
|
rsu_read_1(sc, R92S_SYS_CLKR) | R92S_SYS_CPU_CLKSEL);
|
|
|
|
if (!(rsu_read_1(sc, R92S_SYS_CLKR) & R92S_SYS_CPU_CLKSEL)) {
|
|
|
|
device_printf(sc->sc_dev, "could not enable system clock\n");
|
|
|
|
error = EIO;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
rsu_write_2(sc, R92S_SYS_FUNC_EN,
|
|
|
|
rsu_read_2(sc, R92S_SYS_FUNC_EN) | R92S_FEN_CPUEN);
|
|
|
|
if (!(rsu_read_2(sc, R92S_SYS_FUNC_EN) & R92S_FEN_CPUEN)) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"could not enable microcontroller\n");
|
|
|
|
error = EIO;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
/* Wait for CPU to initialize. */
|
|
|
|
for (ntries = 0; ntries < 100; ntries++) {
|
2014-06-04 09:18:13 +00:00
|
|
|
if (rsu_read_1(sc, R92S_TCR) & R92S_TCR_IMEM_RDY)
|
2013-07-30 02:07:57 +00:00
|
|
|
break;
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
if (ntries == 100) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"timeout waiting for microcontroller\n");
|
|
|
|
error = ETIMEDOUT;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update DMEM section before loading. */
|
2013-07-30 16:17:30 +00:00
|
|
|
dmem = __DECONST(struct r92s_fw_priv *, &hdr->priv);
|
2013-07-30 02:07:57 +00:00
|
|
|
memset(dmem, 0, sizeof(*dmem));
|
|
|
|
dmem->hci_sel = R92S_HCI_SEL_USB | R92S_HCI_SEL_8172;
|
2015-09-17 03:42:18 +00:00
|
|
|
dmem->nendpoints = sc->sc_nendpoints;
|
|
|
|
/* XXX TODO: rf_config should come from ROM */
|
|
|
|
dmem->rf_config = 0x11; /* 1T1R */
|
2013-07-30 02:07:57 +00:00
|
|
|
dmem->vcs_type = R92S_VCS_TYPE_AUTO;
|
|
|
|
dmem->vcs_mode = R92S_VCS_MODE_RTS_CTS;
|
2015-09-17 03:42:18 +00:00
|
|
|
dmem->turbo_mode = 0;
|
2015-09-18 04:12:11 +00:00
|
|
|
dmem->bw40_en = !! (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40);
|
|
|
|
dmem->amsdu2ampdu_en = !! (sc->sc_ht);
|
|
|
|
dmem->ampdu_en = !! (sc->sc_ht);
|
|
|
|
dmem->agg_offload = !! (sc->sc_ht);
|
2015-09-17 07:04:15 +00:00
|
|
|
dmem->qos_en = 1;
|
2013-07-30 02:07:57 +00:00
|
|
|
/* Load DMEM section. */
|
|
|
|
error = rsu_fw_loadsection(sc, (uint8_t *)dmem, sizeof(*dmem));
|
|
|
|
if (error != 0) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"could not load firmware section %s\n", "DMEM");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
/* Wait for load to complete. */
|
|
|
|
for (ntries = 0; ntries < 100; ntries++) {
|
2014-06-04 09:18:13 +00:00
|
|
|
if (rsu_read_1(sc, R92S_TCR) & R92S_TCR_DMEM_CODE_DONE)
|
2013-07-30 02:07:57 +00:00
|
|
|
break;
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
if (ntries == 100) {
|
|
|
|
device_printf(sc->sc_dev, "timeout waiting for %s transfer\n",
|
|
|
|
"DMEM");
|
|
|
|
error = ETIMEDOUT;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
/* Wait for firmware readiness. */
|
|
|
|
for (ntries = 0; ntries < 60; ntries++) {
|
2014-06-04 09:18:13 +00:00
|
|
|
if (!(rsu_read_1(sc, R92S_TCR) & R92S_TCR_FWRDY))
|
2013-07-30 02:07:57 +00:00
|
|
|
break;
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 1);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
if (ntries == 60) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"timeout waiting for firmware readiness\n");
|
|
|
|
error = ETIMEDOUT;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
fail:
|
|
|
|
firmware_put(fw, FIRMWARE_UNLOAD);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
|
|
|
const struct ieee80211_bpf_params *params)
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = ni->ni_ic;
|
2015-08-20 05:13:54 +00:00
|
|
|
struct rsu_softc *sc = ic->ic_softc;
|
2013-07-30 02:07:57 +00:00
|
|
|
struct rsu_data *bf;
|
|
|
|
|
|
|
|
/* prevent management frames from being sent if we're not ready */
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
if (!sc->sc_running) {
|
2013-07-30 02:07:57 +00:00
|
|
|
m_freem(m);
|
|
|
|
ieee80211_free_node(ni);
|
|
|
|
return (ENETDOWN);
|
|
|
|
}
|
|
|
|
RSU_LOCK(sc);
|
|
|
|
bf = rsu_getbuf(sc);
|
|
|
|
if (bf == NULL) {
|
|
|
|
ieee80211_free_node(ni);
|
|
|
|
m_freem(m);
|
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
return (ENOBUFS);
|
|
|
|
}
|
2014-05-21 16:52:55 +00:00
|
|
|
if (rsu_tx_start(sc, ni, m, bf) != 0) {
|
2013-07-30 02:07:57 +00:00
|
|
|
ieee80211_free_node(ni);
|
2015-09-18 07:26:34 +00:00
|
|
|
rsu_freebuf(sc, bf);
|
2013-07-30 02:07:57 +00:00
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
return (EIO);
|
|
|
|
}
|
|
|
|
RSU_UNLOCK(sc);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
rsu_init(struct rsu_softc *sc)
|
2013-07-30 02:07:57 +00:00
|
|
|
{
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
|
|
|
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
2013-07-30 02:07:57 +00:00
|
|
|
struct r92s_set_pwr_mode cmd;
|
|
|
|
int error;
|
2014-05-22 06:28:09 +00:00
|
|
|
int i;
|
2013-07-30 02:07:57 +00:00
|
|
|
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
RSU_ASSERT_LOCKED(sc);
|
|
|
|
|
2015-09-21 02:12:01 +00:00
|
|
|
/* Ensure the mbuf queue is drained */
|
|
|
|
rsu_drain_mbufq(sc);
|
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
/* Init host async commands ring. */
|
|
|
|
sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
|
|
|
|
|
|
|
|
/* Power on adapter. */
|
|
|
|
if (sc->cut == 1)
|
|
|
|
rsu_power_on_acut(sc);
|
|
|
|
else
|
|
|
|
rsu_power_on_bcut(sc);
|
2014-06-04 09:18:13 +00:00
|
|
|
|
2013-07-30 02:07:57 +00:00
|
|
|
/* Load firmware. */
|
|
|
|
error = rsu_load_firmware(sc);
|
|
|
|
if (error != 0)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
/* Enable Rx TCP checksum offload. */
|
|
|
|
rsu_write_4(sc, R92S_RCR,
|
|
|
|
rsu_read_4(sc, R92S_RCR) | 0x04000000);
|
|
|
|
/* Append PHY status. */
|
|
|
|
rsu_write_4(sc, R92S_RCR,
|
|
|
|
rsu_read_4(sc, R92S_RCR) | 0x02000000);
|
|
|
|
|
|
|
|
rsu_write_4(sc, R92S_CR,
|
|
|
|
rsu_read_4(sc, R92S_CR) & ~0xff000000);
|
|
|
|
|
|
|
|
/* Use 128 bytes pages. */
|
|
|
|
rsu_write_1(sc, 0x00b5,
|
|
|
|
rsu_read_1(sc, 0x00b5) | 0x01);
|
|
|
|
/* Enable USB Rx aggregation. */
|
|
|
|
rsu_write_1(sc, 0x00bd,
|
|
|
|
rsu_read_1(sc, 0x00bd) | 0x80);
|
|
|
|
/* Set USB Rx aggregation threshold. */
|
|
|
|
rsu_write_1(sc, 0x00d9, 0x01);
|
|
|
|
/* Set USB Rx aggregation timeout (1.7ms/4). */
|
|
|
|
rsu_write_1(sc, 0xfe5b, 0x04);
|
|
|
|
/* Fix USB Rx FIFO issue. */
|
|
|
|
rsu_write_1(sc, 0xfe5c,
|
|
|
|
rsu_read_1(sc, 0xfe5c) | 0x80);
|
|
|
|
|
|
|
|
/* Set MAC address. */
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
IEEE80211_ADDR_COPY(macaddr, vap ? vap->iv_myaddr : ic->ic_macaddr);
|
|
|
|
rsu_write_region_1(sc, R92S_MACID, macaddr, IEEE80211_ADDR_LEN);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
2014-05-20 15:47:37 +00:00
|
|
|
/* It really takes 1.5 seconds for the firmware to boot: */
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(sc, 2000);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_RESET, "%s: setting MAC address to %s\n",
|
|
|
|
__func__,
|
|
|
|
ether_sprintf(macaddr));
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS, macaddr,
|
2013-07-30 02:07:57 +00:00
|
|
|
IEEE80211_ADDR_LEN);
|
|
|
|
if (error != 0) {
|
|
|
|
device_printf(sc->sc_dev, "could not set MAC address\n");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
rsu_write_1(sc, R92S_USB_HRPWM,
|
|
|
|
R92S_USB_HRPWM_PS_ST_ACTIVE | R92S_USB_HRPWM_PS_ALL_ON);
|
|
|
|
|
2015-09-13 04:41:13 +00:00
|
|
|
/* Set PS mode fully active */
|
2013-07-30 02:07:57 +00:00
|
|
|
memset(&cmd, 0, sizeof(cmd));
|
|
|
|
cmd.mode = R92S_PS_MODE_ACTIVE;
|
2015-09-12 23:10:34 +00:00
|
|
|
RSU_DPRINTF(sc, RSU_DEBUG_RESET, "%s: setting ps mode to %d\n",
|
|
|
|
__func__, cmd.mode);
|
2013-07-30 02:07:57 +00:00
|
|
|
error = rsu_fw_cmd(sc, R92S_CMD_SET_PWR_MODE, &cmd, sizeof(cmd));
|
|
|
|
if (error != 0) {
|
|
|
|
device_printf(sc->sc_dev, "could not set PS mode\n");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
2015-09-18 04:12:11 +00:00
|
|
|
if (ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40) {
|
2013-07-30 02:07:57 +00:00
|
|
|
/* Enable 40MHz mode. */
|
|
|
|
error = rsu_fw_iocmd(sc,
|
|
|
|
SM(R92S_IOCMD_CLASS, 0xf4) |
|
|
|
|
SM(R92S_IOCMD_INDEX, 0x00) |
|
|
|
|
SM(R92S_IOCMD_VALUE, 0x0007));
|
|
|
|
if (error != 0) {
|
|
|
|
device_printf(sc->sc_dev,
|
|
|
|
"could not enable 40MHz mode\n");
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
sc->sc_scan_pass = 0;
|
2013-07-30 02:07:57 +00:00
|
|
|
usbd_transfer_start(sc->sc_xfer[RSU_BULK_RX]);
|
|
|
|
|
|
|
|
/* We're ready to go. */
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
sc->sc_running = 1;
|
2015-09-18 07:55:33 +00:00
|
|
|
sc->sc_scanning = 0;
|
2013-07-30 02:07:57 +00:00
|
|
|
return;
|
|
|
|
fail:
|
2014-05-22 06:28:09 +00:00
|
|
|
/* Need to stop all failed transfers, if any */
|
|
|
|
for (i = 0; i != RSU_N_TRANSFER; i++)
|
|
|
|
usbd_transfer_stop(sc->sc_xfer[i]);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
rsu_stop(struct rsu_softc *sc)
|
2013-07-30 02:07:57 +00:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
Replay r286410. Change KPI of how device drivers that provide wireless
connectivity interact with the net80211 stack.
Historical background: originally wireless devices created an interface,
just like Ethernet devices do. Name of an interface matched the name of
the driver that created. Later, wlan(4) layer was introduced, and the
wlanX interfaces become the actual interface, leaving original ones as
"a parent interface" of wlanX. Kernelwise, the KPI between net80211 layer
and a driver became a mix of methods that pass a pointer to struct ifnet
as identifier and methods that pass pointer to struct ieee80211com. From
user point of view, the parent interface just hangs on in the ifconfig
list, and user can't do anything useful with it.
Now, the struct ifnet goes away. The struct ieee80211com is the only
KPI between a device driver and net80211. Details:
- The struct ieee80211com is embedded into drivers softc.
- Packets are sent via new ic_transmit method, which is very much like
the previous if_transmit.
- Bringing parent up/down is done via new ic_parent method, which notifies
driver about any changes: number of wlan(4) interfaces, number of them
in promisc or allmulti state.
- Device specific ioctls (if any) are received on new ic_ioctl method.
- Packets/errors accounting are done by the stack. In certain cases, when
driver experiences errors and can not attribute them to any specific
interface, driver updates ic_oerrors or ic_ierrors counters.
Details on interface configuration with new world order:
- A sequence of commands needed to bring up wireless DOESN"T change.
- /etc/rc.conf parameters DON'T change.
- List of devices that can be used to create wlan(4) interfaces is
now provided by net.wlan.devices sysctl.
Most drivers in this change were converted by me, except of wpi(4),
that was done by Andriy Voskoboinyk. Big thanks to Kevin Lo for testing
changes to at least 8 drivers. Thanks to pluknet@, Oliver Hartmann,
Olivier Cochard, gjb@, mmoll@, op@ and lev@, who also participated in
testing.
Reviewed by: adrian
Sponsored by: Netflix
Sponsored by: Nginx, Inc.
2015-08-27 08:56:39 +00:00
|
|
|
sc->sc_running = 0;
|
2013-07-30 02:07:57 +00:00
|
|
|
sc->sc_calibrating = 0;
|
|
|
|
taskqueue_cancel_timeout(taskqueue_thread, &sc->calib_task, NULL);
|
2015-09-21 02:30:22 +00:00
|
|
|
taskqueue_cancel(taskqueue_thread, &sc->tx_task, NULL);
|
2013-07-30 02:07:57 +00:00
|
|
|
|
|
|
|
/* Power off adapter. */
|
|
|
|
rsu_power_off(sc);
|
|
|
|
|
|
|
|
for (i = 0; i < RSU_N_TRANSFER; i++)
|
|
|
|
usbd_transfer_stop(sc->sc_xfer[i]);
|
2015-09-21 02:12:01 +00:00
|
|
|
|
|
|
|
/* Ensure the mbuf queue is drained */
|
|
|
|
rsu_drain_mbufq(sc);
|
2013-07-30 02:07:57 +00:00
|
|
|
}
|
|
|
|
|
2015-09-17 03:01:19 +00:00
|
|
|
/*
|
|
|
|
* Note: usb_pause_mtx() actually releases the mutex before calling pause(),
|
|
|
|
* which breaks any kind of driver serialisation.
|
|
|
|
*/
|
2014-05-20 15:47:37 +00:00
|
|
|
static void
|
2015-09-17 03:01:19 +00:00
|
|
|
rsu_ms_delay(struct rsu_softc *sc, int ms)
|
2014-05-20 15:47:37 +00:00
|
|
|
{
|
2015-09-17 03:01:19 +00:00
|
|
|
|
|
|
|
//usb_pause_mtx(&sc->sc_mtx, hz / 1000);
|
|
|
|
DELAY(ms * 1000);
|
2014-05-20 15:47:37 +00:00
|
|
|
}
|