Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 7 Feb 2015 23:11:39 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r278366 - head/sys/dev/wpi
Message-ID:  <201502072311.t17NBduF070960@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Sat Feb  7 23:11:38 2015
New Revision: 278366
URL: https://svnweb.freebsd.org/changeset/base/278366

Log:
  Big wpi(4) overhaul! Not by me!
  
  This is a sync against iwn(4) and openbsd.
  
  - Add power management support;
  - Add background scanning support;
  - Fix few LORs;
  - Handle rfkill switch state changes properly;
  - Fix recovering after firmware failure;
  - Add more error checking;
  - Cleanup & disable by default debug output;
  - Update macroses names;
  - Other various fixes;
  - Add IBSS support:
    - don't set data_ntries field for management frames;
  - Add AHDEMO support:
      - fix padding;
  - Sync eeprom functions;
  - Use CMD_RXON_ASSOC where possible;
  - Enable HW CCMP encryption/decryption for pairwise keys;
  - Fix filter flags for CMD_RXON.
  
  Tested (by submitter) - iwn 3945 NIC.  I have one somewhere; I'll
  validate this later on and revert it if it's a problem.
  
  Thanks!
  
  PR:		197143
  Submitted by:	Andriy Voskoboinyk <s3erios@gmail.com>

Added:
  head/sys/dev/wpi/if_wpi_debug.h   (contents, props changed)
Modified:
  head/sys/dev/wpi/if_wpi.c
  head/sys/dev/wpi/if_wpireg.h
  head/sys/dev/wpi/if_wpivar.h

Modified: head/sys/dev/wpi/if_wpi.c
==============================================================================
--- head/sys/dev/wpi/if_wpi.c	Sat Feb  7 23:09:03 2015	(r278365)
+++ head/sys/dev/wpi/if_wpi.c	Sat Feb  7 23:11:38 2015	(r278366)
@@ -16,8 +16,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#define VERSION "20071127"
-
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
@@ -60,6 +58,7 @@ __FBSDID("$FreeBSD$");
  */
 
 #include "opt_wlan.h"
+#include "opt_wpi.h"
 
 #include <sys/param.h>
 #include <sys/sysctl.h>
@@ -93,51 +92,20 @@ __FBSDID("$FreeBSD$");
 #include <net/if_media.h>
 #include <net/if_types.h>
 
-#include <net80211/ieee80211_var.h>
-#include <net80211/ieee80211_radiotap.h>
-#include <net80211/ieee80211_regdomain.h>
-#include <net80211/ieee80211_ratectl.h>
-
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/in_var.h>
-#include <netinet/ip.h>
 #include <netinet/if_ether.h>
+#include <netinet/ip.h>
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_radiotap.h>
+#include <net80211/ieee80211_regdomain.h>
+#include <net80211/ieee80211_ratectl.h>
 
 #include <dev/wpi/if_wpireg.h>
 #include <dev/wpi/if_wpivar.h>
-
-#define WPI_DEBUG
-
-#ifdef WPI_DEBUG
-#define DPRINTF(x)	do { if (wpi_debug != 0) printf x; } while (0)
-#define DPRINTFN(n, x)	do { if (wpi_debug & n) printf x; } while (0)
-#define	WPI_DEBUG_SET	(wpi_debug != 0)
-
-enum {
-	WPI_DEBUG_UNUSED	= 0x00000001,   /* Unused */
-	WPI_DEBUG_HW		= 0x00000002,   /* Stage 1 (eeprom) debugging */
-	WPI_DEBUG_TX		= 0x00000004,   /* Stage 2 TX intrp debugging*/
-	WPI_DEBUG_RX		= 0x00000008,   /* Stage 2 RX intrp debugging */
-	WPI_DEBUG_CMD		= 0x00000010,   /* Stage 2 CMD intrp debugging*/
-	WPI_DEBUG_FIRMWARE	= 0x00000020,   /* firmware(9) loading debug  */
-	WPI_DEBUG_DMA		= 0x00000040,   /* DMA (de)allocations/syncs  */
-	WPI_DEBUG_SCANNING	= 0x00000080,   /* Stage 2 Scanning debugging */
-	WPI_DEBUG_NOTIFY	= 0x00000100,   /* State 2 Noftif intr debug */
-	WPI_DEBUG_TEMP		= 0x00000200,   /* TXPower/Temp Calibration */
-	WPI_DEBUG_OPS		= 0x00000400,   /* wpi_ops taskq debug */
-	WPI_DEBUG_WATCHDOG	= 0x00000800,   /* Watch dog debug */
-	WPI_DEBUG_ANY		= 0xffffffff
-};
-
-static int wpi_debug;
-SYSCTL_INT(_debug, OID_AUTO, wpi, CTLFLAG_RWTUN, &wpi_debug, 0, "wpi debug level");
-
-#else
-#define DPRINTF(x)
-#define DPRINTFN(n, x)
-#define WPI_DEBUG_SET	0
-#endif
+#include <dev/wpi/if_wpi_debug.h>
 
 struct wpi_ident {
 	uint16_t	vendor;
@@ -158,99 +126,138 @@ static const struct wpi_ident wpi_ident_
 	{ 0, 0, 0, NULL }
 };
 
+static int	wpi_probe(device_t);
+static int	wpi_attach(device_t);
+static void	wpi_radiotap_attach(struct wpi_softc *);
+static void	wpi_sysctlattach(struct wpi_softc *);
 static struct ieee80211vap *wpi_vap_create(struct ieee80211com *,
 		    const char [IFNAMSIZ], int, enum ieee80211_opmode, int,
 		    const uint8_t [IEEE80211_ADDR_LEN],
 		    const uint8_t [IEEE80211_ADDR_LEN]);
 static void	wpi_vap_delete(struct ieee80211vap *);
+static int	wpi_detach(device_t);
+static int	wpi_shutdown(device_t);
+static int	wpi_suspend(device_t);
+static int	wpi_resume(device_t);
+static int	wpi_nic_lock(struct wpi_softc *);
+static int	wpi_read_prom_data(struct wpi_softc *, uint32_t, void *, int);
+static void	wpi_dma_map_addr(void *, bus_dma_segment_t *, int, int);
 static int	wpi_dma_contig_alloc(struct wpi_softc *, struct wpi_dma_info *,
-		    void **, bus_size_t, bus_size_t, int);
+		    void **, bus_size_t, bus_size_t);
 static void	wpi_dma_contig_free(struct wpi_dma_info *);
-static void	wpi_dma_map_addr(void *, bus_dma_segment_t *, int, int);
 static int	wpi_alloc_shared(struct wpi_softc *);
 static void	wpi_free_shared(struct wpi_softc *);
-static int	wpi_alloc_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
-static void	wpi_reset_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
-static void	wpi_free_rx_ring(struct wpi_softc *, struct wpi_rx_ring *);
+static int	wpi_alloc_fwmem(struct wpi_softc *);
+static void	wpi_free_fwmem(struct wpi_softc *);
+static int	wpi_alloc_rx_ring(struct wpi_softc *);
+static void	wpi_update_rx_ring(struct wpi_softc *);
+static void	wpi_reset_rx_ring(struct wpi_softc *);
+static void	wpi_free_rx_ring(struct wpi_softc *);
 static int	wpi_alloc_tx_ring(struct wpi_softc *, struct wpi_tx_ring *,
-		    int, int);
+		    int);
+static void	wpi_update_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
 static void	wpi_reset_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
 static void	wpi_free_tx_ring(struct wpi_softc *, struct wpi_tx_ring *);
+static int	wpi_read_eeprom(struct wpi_softc *,
+		    uint8_t macaddr[IEEE80211_ADDR_LEN]);
+static uint32_t	wpi_eeprom_channel_flags(struct wpi_eeprom_chan *);
+static void	wpi_read_eeprom_band(struct wpi_softc *, int);
+static int	wpi_read_eeprom_channels(struct wpi_softc *, int);
+static struct wpi_eeprom_chan *wpi_find_eeprom_channel(struct wpi_softc *,
+		    struct ieee80211_channel *);
+static int	wpi_setregdomain(struct ieee80211com *,
+		    struct ieee80211_regdomain *, int,
+		    struct ieee80211_channel[]);
+static int	wpi_read_eeprom_group(struct wpi_softc *, int);
+static void	wpi_node_free(struct ieee80211_node *);
+static struct ieee80211_node *wpi_node_alloc(struct ieee80211vap *,
+		    const uint8_t mac[IEEE80211_ADDR_LEN]);
 static int	wpi_newstate(struct ieee80211vap *, enum ieee80211_state, int);
-static void	wpi_mem_lock(struct wpi_softc *);
-static void	wpi_mem_unlock(struct wpi_softc *);
-static uint32_t	wpi_mem_read(struct wpi_softc *, uint16_t);
-static void	wpi_mem_write(struct wpi_softc *, uint16_t, uint32_t);
-static void	wpi_mem_write_region_4(struct wpi_softc *, uint16_t,
-		    const uint32_t *, int);
-static uint16_t	wpi_read_prom_data(struct wpi_softc *, uint32_t, void *, int);
-static int	wpi_alloc_fwmem(struct wpi_softc *);
-static void	wpi_free_fwmem(struct wpi_softc *);
-static int	wpi_load_firmware(struct wpi_softc *);
-static void	wpi_unload_firmware(struct wpi_softc *);
-static int	wpi_load_microcode(struct wpi_softc *, const uint8_t *, int);
-static void	wpi_rx_intr(struct wpi_softc *, struct wpi_rx_desc *,
+static void	wpi_calib_timeout(void *);
+static void	wpi_rx_done(struct wpi_softc *, struct wpi_rx_desc *,
 		    struct wpi_rx_data *);
-static void	wpi_tx_intr(struct wpi_softc *, struct wpi_rx_desc *);
-static void	wpi_cmd_intr(struct wpi_softc *, struct wpi_rx_desc *);
+static void	wpi_rx_statistics(struct wpi_softc *, struct wpi_rx_desc *,
+		    struct wpi_rx_data *);
+static void	wpi_tx_done(struct wpi_softc *, struct wpi_rx_desc *);
+static void	wpi_cmd_done(struct wpi_softc *, struct wpi_rx_desc *);
 static void	wpi_notif_intr(struct wpi_softc *);
+static void	wpi_wakeup_intr(struct wpi_softc *);
+static void	wpi_fatal_intr(struct wpi_softc *);
 static void	wpi_intr(void *);
-static uint8_t	wpi_plcp_signal(int);
-static void	wpi_watchdog(void *);
+static int	wpi_cmd2(struct wpi_softc *, struct wpi_buf *);
 static int	wpi_tx_data(struct wpi_softc *, struct mbuf *,
-		    struct ieee80211_node *, int);
-static void	wpi_start(struct ifnet *);
-static void	wpi_start_locked(struct ifnet *);
+		    struct ieee80211_node *);
+static int	wpi_tx_data_raw(struct wpi_softc *, struct mbuf *,
+		    struct ieee80211_node *,
+		    const struct ieee80211_bpf_params *);
 static int	wpi_raw_xmit(struct ieee80211_node *, struct mbuf *,
 		    const struct ieee80211_bpf_params *);
-static void	wpi_scan_start(struct ieee80211com *);
-static void	wpi_scan_end(struct ieee80211com *);
-static void	wpi_set_channel(struct ieee80211com *);
-static void	wpi_scan_curchan(struct ieee80211_scan_state *, unsigned long);
-static void	wpi_scan_mindwell(struct ieee80211_scan_state *);
+static void	wpi_start(struct ifnet *);
+static void	wpi_start_locked(struct ifnet *);
+static void	wpi_watchdog_rfkill(void *);
+static void	wpi_watchdog(void *);
 static int	wpi_ioctl(struct ifnet *, u_long, caddr_t);
-static void	wpi_read_eeprom(struct wpi_softc *,
-		    uint8_t macaddr[IEEE80211_ADDR_LEN]);
-static void	wpi_read_eeprom_channels(struct wpi_softc *, int);
-static void	wpi_read_eeprom_group(struct wpi_softc *, int);
-static int	wpi_cmd(struct wpi_softc *, int, const void *, int, int);
-static int	wpi_wme_update(struct ieee80211com *);
+static int	wpi_cmd(struct wpi_softc *, int, const void *, size_t, int);
 static int	wpi_mrr_setup(struct wpi_softc *);
+static int	wpi_add_node(struct wpi_softc *, struct ieee80211_node *);
+static int	wpi_add_broadcast_node(struct wpi_softc *, int);
+static int	wpi_add_ibss_node(struct wpi_softc *, struct ieee80211_node *);
+static void	wpi_del_node(struct wpi_softc *, struct ieee80211_node *);
+static int	wpi_updateedca(struct ieee80211com *);
+static void	wpi_set_promisc(struct wpi_softc *);
+static void	wpi_update_promisc(struct ifnet *);
+static void	wpi_update_mcast(struct ifnet *);
 static void	wpi_set_led(struct wpi_softc *, uint8_t, uint8_t, uint8_t);
-static void	wpi_enable_tsf(struct wpi_softc *, struct ieee80211_node *);
-#if 0
-static int	wpi_setup_beacon(struct wpi_softc *, struct ieee80211_node *);
-#endif
+static int	wpi_set_timing(struct wpi_softc *, struct ieee80211_node *);
+static void	wpi_power_calibration(struct wpi_softc *);
+static int	wpi_set_txpower(struct wpi_softc *, int);
+static int	wpi_get_power_index(struct wpi_softc *,
+		    struct wpi_power_group *, struct ieee80211_channel *, int);
+static int	wpi_set_pslevel(struct wpi_softc *, uint8_t, int, int);
+static int	wpi_send_btcoex(struct wpi_softc *);
+static int	wpi_send_rxon(struct wpi_softc *, int, int);
+static int	wpi_config(struct wpi_softc *);
+static uint16_t	wpi_get_active_dwell_time(struct wpi_softc *,
+		    struct ieee80211_channel *, uint8_t);
+static uint16_t	wpi_limit_dwell(struct wpi_softc *, uint16_t);
+static uint16_t	wpi_get_passive_dwell_time(struct wpi_softc *,
+		    struct ieee80211_channel *);
+static int	wpi_scan(struct wpi_softc *, struct ieee80211_channel *);
 static int	wpi_auth(struct wpi_softc *, struct ieee80211vap *);
+static void	wpi_update_beacon(struct ieee80211vap *, int);
+static int	wpi_setup_beacon(struct wpi_softc *, struct ieee80211_node *);
 static int	wpi_run(struct wpi_softc *, struct ieee80211vap *);
-static int	wpi_scan(struct wpi_softc *);
-static int	wpi_config(struct wpi_softc *);
-static void	wpi_stop_master(struct wpi_softc *);
-static int	wpi_power_up(struct wpi_softc *);
-static int	wpi_reset(struct wpi_softc *);
-static void	wpi_hwreset(void *, int);
-static void	wpi_rfreset(void *, int);
-static void	wpi_hw_config(struct wpi_softc *);
+static int	wpi_key_alloc(struct ieee80211vap *, struct ieee80211_key *,
+		    ieee80211_keyix *, ieee80211_keyix *);
+static int	wpi_key_set(struct ieee80211vap *,
+		    const struct ieee80211_key *,
+		    const uint8_t mac[IEEE80211_ADDR_LEN]);
+static int	wpi_key_delete(struct ieee80211vap *,
+		    const struct ieee80211_key *);
+static int	wpi_post_alive(struct wpi_softc *);
+static int	wpi_load_bootcode(struct wpi_softc *, const uint8_t *, int);
+static int	wpi_load_firmware(struct wpi_softc *);
+static int	wpi_read_firmware(struct wpi_softc *);
+static void	wpi_unload_firmware(struct wpi_softc *);
+static int	wpi_clock_wait(struct wpi_softc *);
+static int	wpi_apm_init(struct wpi_softc *);
+static void	wpi_apm_stop_master(struct wpi_softc *);
+static void	wpi_apm_stop(struct wpi_softc *);
+static void	wpi_nic_config(struct wpi_softc *);
+static int	wpi_hw_init(struct wpi_softc *);
+static void	wpi_hw_stop(struct wpi_softc *);
+static void	wpi_radio_on(void *, int);
+static void	wpi_radio_off(void *, int);
+static void	wpi_init_locked(struct wpi_softc *);
 static void	wpi_init(void *);
-static void	wpi_init_locked(struct wpi_softc *, int);
-static void	wpi_stop(struct wpi_softc *);
 static void	wpi_stop_locked(struct wpi_softc *);
-
-static int	wpi_set_txpower(struct wpi_softc *, struct ieee80211_channel *,
-		    int);
-static void	wpi_calib_timeout(void *);
-static void	wpi_power_calibration(struct wpi_softc *, int);
-static int	wpi_get_power_index(struct wpi_softc *,
-		    struct wpi_power_group *, struct ieee80211_channel *, int);
-#ifdef WPI_DEBUG
-static const char *wpi_cmd_str(int);
-#endif
-static int wpi_probe(device_t);
-static int wpi_attach(device_t);
-static int wpi_detach(device_t);
-static int wpi_shutdown(device_t);
-static int wpi_suspend(device_t);
-static int wpi_resume(device_t);
+static void	wpi_stop(struct wpi_softc *);
+static void	wpi_scan_start(struct ieee80211com *);
+static void	wpi_scan_end(struct ieee80211com *);
+static void	wpi_set_channel(struct ieee80211com *);
+static void	wpi_scan_curchan(struct ieee80211_scan_state *, unsigned long);
+static void	wpi_scan_mindwell(struct ieee80211_scan_state *);
+static void	wpi_hw_reset(void *, int);
 
 static device_method_t wpi_methods[] = {
 	/* Device interface */
@@ -269,25 +276,15 @@ static driver_t wpi_driver = {
 	wpi_methods,
 	sizeof (struct wpi_softc)
 };
-
 static devclass_t wpi_devclass;
 
 DRIVER_MODULE(wpi, pci, wpi_driver, wpi_devclass, NULL, NULL);
 
 MODULE_VERSION(wpi, 1);
 
-static const uint8_t wpi_ridx_to_plcp[] = {
-	/* OFDM: IEEE Std 802.11a-1999, pp. 14 Table 80 */
-	/* R1-R4 (ral/ural is R4-R1) */
-	0xd, 0xf, 0x5, 0x7, 0x9, 0xb, 0x1, 0x3,
-	/* CCK: device-dependent */
-	10, 20, 55, 110
-};
-
-static const uint8_t wpi_ridx_to_rate[] = {
-	12, 18, 24, 36, 48, 72, 96, 108, /* OFDM */
-	2, 4, 11, 22 /*CCK */
-};
+MODULE_DEPEND(wpi, pci,  1, 1, 1);
+MODULE_DEPEND(wpi, wlan, 1, 1, 1);
+MODULE_DEPEND(wpi, firmware, 1, 1, 1);
 
 static int
 wpi_probe(device_t dev)
@@ -304,202 +301,38 @@ wpi_probe(device_t dev)
 	return ENXIO;
 }
 
-/**
- * Load the firmare image from disk to the allocated dma buffer.
- * we also maintain the reference to the firmware pointer as there
- * is times where we may need to reload the firmware but we are not
- * in a context that can access the filesystem (ie taskq cause by restart)
- *
- * @return 0 on success, an errno on failure
- */
-static int
-wpi_load_firmware(struct wpi_softc *sc)
-{
-	const struct firmware *fp;
-	struct wpi_dma_info *dma = &sc->fw_dma;
-	const struct wpi_firmware_hdr *hdr;
-	const uint8_t *itext, *idata, *rtext, *rdata, *btext;
-	uint32_t itextsz, idatasz, rtextsz, rdatasz, btextsz;
-	int error;
-
-	DPRINTFN(WPI_DEBUG_FIRMWARE,
-	    ("Attempting Loading Firmware from wpi_fw module\n"));
-
-	WPI_UNLOCK(sc);
-
-	if (sc->fw_fp == NULL && (sc->fw_fp = firmware_get("wpifw")) == NULL) {
-		device_printf(sc->sc_dev,
-		    "could not load firmware image 'wpifw'\n");
-		error = ENOENT;
-		WPI_LOCK(sc);
-		goto fail;
-	}
-
-	fp = sc->fw_fp;
-
-	WPI_LOCK(sc);
-
-	/* Validate the firmware is minimum a particular version */
-	if (fp->version < WPI_FW_MINVERSION) {
-	    device_printf(sc->sc_dev,
-			   "firmware version is too old. Need %d, got %d\n",
-			   WPI_FW_MINVERSION,
-			   fp->version);
-	    error = ENXIO;
-	    goto fail;
-	}
-
-	if (fp->datasize < sizeof (struct wpi_firmware_hdr)) {
-		device_printf(sc->sc_dev,
-		    "firmware file too short: %zu bytes\n", fp->datasize);
-		error = ENXIO;
-		goto fail;
-	}
-
-	hdr = (const struct wpi_firmware_hdr *)fp->data;
-
-	/*     |  RUNTIME FIRMWARE   |    INIT FIRMWARE    | BOOT FW  |
-	   |HDR|<--TEXT-->|<--DATA-->|<--TEXT-->|<--DATA-->|<--TEXT-->| */
-
-	rtextsz = le32toh(hdr->rtextsz);
-	rdatasz = le32toh(hdr->rdatasz);
-	itextsz = le32toh(hdr->itextsz);
-	idatasz = le32toh(hdr->idatasz);
-	btextsz = le32toh(hdr->btextsz);
-
-	/* check that all firmware segments are present */
-	if (fp->datasize < sizeof (struct wpi_firmware_hdr) +
-		rtextsz + rdatasz + itextsz + idatasz + btextsz) {
-		device_printf(sc->sc_dev,
-		    "firmware file too short: %zu bytes\n", fp->datasize);
-		error = ENXIO; /* XXX appropriate error code? */
-		goto fail;
-	}
-
-	/* get pointers to firmware segments */
-	rtext = (const uint8_t *)(hdr + 1);
-	rdata = rtext + rtextsz;
-	itext = rdata + rdatasz;
-	idata = itext + itextsz;
-	btext = idata + idatasz;
-
-	DPRINTFN(WPI_DEBUG_FIRMWARE,
-	    ("Firmware Version: Major %d, Minor %d, Driver %d, \n"
-	     "runtime (text: %u, data: %u) init (text: %u, data %u) boot (text %u)\n",
-	     (le32toh(hdr->version) & 0xff000000) >> 24,
-	     (le32toh(hdr->version) & 0x00ff0000) >> 16,
-	     (le32toh(hdr->version) & 0x0000ffff),
-	     rtextsz, rdatasz,
-	     itextsz, idatasz, btextsz));
-
-	DPRINTFN(WPI_DEBUG_FIRMWARE,("rtext 0x%x\n", *(const uint32_t *)rtext));
-	DPRINTFN(WPI_DEBUG_FIRMWARE,("rdata 0x%x\n", *(const uint32_t *)rdata));
-	DPRINTFN(WPI_DEBUG_FIRMWARE,("itext 0x%x\n", *(const uint32_t *)itext));
-	DPRINTFN(WPI_DEBUG_FIRMWARE,("idata 0x%x\n", *(const uint32_t *)idata));
-	DPRINTFN(WPI_DEBUG_FIRMWARE,("btext 0x%x\n", *(const uint32_t *)btext));
-
-	/* sanity checks */
-	if (rtextsz > WPI_FW_MAIN_TEXT_MAXSZ ||
-	    rdatasz > WPI_FW_MAIN_DATA_MAXSZ ||
-	    itextsz > WPI_FW_INIT_TEXT_MAXSZ ||
-	    idatasz > WPI_FW_INIT_DATA_MAXSZ ||
-	    btextsz > WPI_FW_BOOT_TEXT_MAXSZ ||
-	    (btextsz & 3) != 0) {
-		device_printf(sc->sc_dev, "firmware invalid\n");
-		error = EINVAL;
-		goto fail;
-	}
-
-	/* copy initialization images into pre-allocated DMA-safe memory */
-	memcpy(dma->vaddr, idata, idatasz);
-	memcpy(dma->vaddr + WPI_FW_INIT_DATA_MAXSZ, itext, itextsz);
-
-	bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_PREWRITE);
-
-	/* tell adapter where to find initialization images */
-	wpi_mem_lock(sc);
-	wpi_mem_write(sc, WPI_MEM_DATA_BASE, dma->paddr);
-	wpi_mem_write(sc, WPI_MEM_DATA_SIZE, idatasz);
-	wpi_mem_write(sc, WPI_MEM_TEXT_BASE,
-	    dma->paddr + WPI_FW_INIT_DATA_MAXSZ);
-	wpi_mem_write(sc, WPI_MEM_TEXT_SIZE, itextsz);
-	wpi_mem_unlock(sc);
-
-	/* load firmware boot code */
-	if ((error = wpi_load_microcode(sc, btext, btextsz)) != 0) {
-	    device_printf(sc->sc_dev, "Failed to load microcode\n");
-	    goto fail;
-	}
-
-	/* now press "execute" */
-	WPI_WRITE(sc, WPI_RESET, 0);
-
-	/* wait at most one second for the first alive notification */
-	if ((error = msleep(sc, &sc->sc_mtx, PCATCH, "wpiinit", hz)) != 0) {
-		device_printf(sc->sc_dev,
-		    "timeout waiting for adapter to initialize\n");
-		goto fail;
-	}
-
-	/* copy runtime images into pre-allocated DMA-sage memory */
-	memcpy(dma->vaddr, rdata, rdatasz);
-	memcpy(dma->vaddr + WPI_FW_MAIN_DATA_MAXSZ, rtext, rtextsz);
-	bus_dmamap_sync(dma->tag, dma->map, BUS_DMASYNC_PREWRITE);
-
-	/* tell adapter where to find runtime images */
-	wpi_mem_lock(sc);
-	wpi_mem_write(sc, WPI_MEM_DATA_BASE, dma->paddr);
-	wpi_mem_write(sc, WPI_MEM_DATA_SIZE, rdatasz);
-	wpi_mem_write(sc, WPI_MEM_TEXT_BASE,
-	    dma->paddr + WPI_FW_MAIN_DATA_MAXSZ);
-	wpi_mem_write(sc, WPI_MEM_TEXT_SIZE, WPI_FW_UPDATED | rtextsz);
-	wpi_mem_unlock(sc);
-
-	/* wait at most one second for the first alive notification */
-	if ((error = msleep(sc, &sc->sc_mtx, PCATCH, "wpiinit", hz)) != 0) {
-		device_printf(sc->sc_dev,
-		    "timeout waiting for adapter to initialize2\n");
-		goto fail;
-	}
-
-	DPRINTFN(WPI_DEBUG_FIRMWARE,
-	    ("Firmware loaded to driver successfully\n"));
-	return error;
-fail:
-	wpi_unload_firmware(sc);
-	return error;
-}
-
-/**
- * Free the referenced firmware image
- */
-static void
-wpi_unload_firmware(struct wpi_softc *sc)
-{
-
-	if (sc->fw_fp) {
-		WPI_UNLOCK(sc);
-		firmware_put(sc->fw_fp, FIRMWARE_UNLOAD);
-		WPI_LOCK(sc);
-		sc->fw_fp = NULL;
-	}
-}
-
 static int
 wpi_attach(device_t dev)
 {
-	struct wpi_softc *sc = device_get_softc(dev);
-	struct ifnet *ifp;
+	struct wpi_softc *sc = (struct wpi_softc *)device_get_softc(dev);
 	struct ieee80211com *ic;
-	int ac, error, rid, supportsa = 1;
-	uint32_t tmp;
+	struct ifnet *ifp;
+	int i, error, rid, supportsa = 1;
 	const struct wpi_ident *ident;
 	uint8_t macaddr[IEEE80211_ADDR_LEN];
 
 	sc->sc_dev = dev;
 
-	if (bootverbose || WPI_DEBUG_SET)
-	    device_printf(sc->sc_dev,"Driver Revision %s\n", VERSION);
+#ifdef	WPI_DEBUG
+	error = resource_int_value(device_get_name(sc->sc_dev),
+	    device_get_unit(sc->sc_dev), "debug", &(sc->sc_debug));
+	if (error != 0)
+		sc->sc_debug = 0;
+#else
+	sc->sc_debug = 0;
+#endif
+
+	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
+
+	/*
+	 * Get the offset of the PCI Express Capability Structure in PCI
+	 * Configuration Space.
+	 */
+	error = pci_find_cap(dev, PCIY_EXPRESS, &sc->sc_cap_off);
+	if (error != 0) {
+		device_printf(dev, "PCIe capability structure not found!\n");
+		return error;
+	}
 
 	/*
 	 * Some card's only support 802.11b/g not a, check to see if
@@ -514,131 +347,118 @@ wpi_attach(device_t dev)
 		}
 	}
 
-	/* Create the tasks that can be queued */
-	TASK_INIT(&sc->sc_restarttask, 0, wpi_hwreset, sc);
-	TASK_INIT(&sc->sc_radiotask, 0, wpi_rfreset, sc);
-
-	WPI_LOCK_INIT(sc);
-
-	callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0);
-	callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0);
-
-	/* disable the retry timeout register */
+	/* Clear device-specific "PCI retry timeout" register (41h). */
 	pci_write_config(dev, 0x41, 0, 1);
 
-	/* enable bus-mastering */
+	/* Enable bus-mastering. */
 	pci_enable_busmaster(dev);
 
 	rid = PCIR_BAR(0);
 	sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
 	    RF_ACTIVE);
 	if (sc->mem == NULL) {
-		device_printf(dev, "could not allocate memory resource\n");
+		device_printf(dev, "can't map mem space\n");
 		error = ENOMEM;
-		goto fail;
+		return error;
 	}
-
 	sc->sc_st = rman_get_bustag(sc->mem);
 	sc->sc_sh = rman_get_bushandle(sc->mem);
 
+	i = 1;
 	rid = 0;
-	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
-	    RF_ACTIVE | RF_SHAREABLE);
+	if (pci_alloc_msi(dev, &i) == 0)
+		rid = 1;
+	/* Install interrupt handler. */
+	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE |
+	    (rid != 0 ? 0 : RF_SHAREABLE));
 	if (sc->irq == NULL) {
-		device_printf(dev, "could not allocate interrupt resource\n");
+		device_printf(dev, "can't map interrupt\n");
 		error = ENOMEM;
 		goto fail;
 	}
 
-	/*
-	 * Allocate DMA memory for firmware transfers.
-	 */
-	if ((error = wpi_alloc_fwmem(sc)) != 0) {
-		printf(": could not allocate firmware memory\n");
-		error = ENOMEM;
-		goto fail;
-	}
+	WPI_LOCK_INIT(sc);
 
-	/*
-	 * Put adapter into a known state.
-	 */
-	if ((error = wpi_reset(sc)) != 0) {
-		device_printf(dev, "could not reset adapter\n");
+	sc->sc_unr = new_unrhdr(WPI_ID_IBSS_MIN, WPI_ID_IBSS_MAX, &sc->sc_mtx);
+
+	/* Allocate DMA memory for firmware transfers. */
+	if ((error = wpi_alloc_fwmem(sc)) != 0) {
+		device_printf(dev,
+		    "could not allocate memory for firmware, error %d\n",
+		    error);
 		goto fail;
 	}
 
-	wpi_mem_lock(sc);
-	tmp = wpi_mem_read(sc, WPI_MEM_PCIDEV);
-	if (bootverbose || WPI_DEBUG_SET)
-	    device_printf(sc->sc_dev, "Hardware Revision (0x%X)\n", tmp);
-
-	wpi_mem_unlock(sc);
-
-	/* Allocate shared page */
+	/* Allocate shared page. */
 	if ((error = wpi_alloc_shared(sc)) != 0) {
 		device_printf(dev, "could not allocate shared page\n");
 		goto fail;
 	}
 
-	/* tx data queues  - 4 for QoS purposes */
-	for (ac = 0; ac < WME_NUM_AC; ac++) {
-		error = wpi_alloc_tx_ring(sc, &sc->txq[ac], WPI_TX_RING_COUNT, ac);
-		if (error != 0) {
-		    device_printf(dev, "could not allocate Tx ring %d\n",ac);
-		    goto fail;
+	/* Allocate TX rings - 4 for QoS purposes, 1 for commands. */
+	for (i = 0; i < WPI_NTXQUEUES; i++) {
+		if ((error = wpi_alloc_tx_ring(sc, &sc->txq[i], i)) != 0) {
+			device_printf(dev,
+			    "could not allocate TX ring %d, error %d\n", i,
+			    error);
+			goto fail;
 		}
 	}
 
-	/* command queue to talk to the card's firmware */
-	error = wpi_alloc_tx_ring(sc, &sc->cmdq, WPI_CMD_RING_COUNT, 4);
-	if (error != 0) {
-		device_printf(dev, "could not allocate command ring\n");
+	/* Allocate RX ring. */
+	if ((error = wpi_alloc_rx_ring(sc)) != 0) {
+		device_printf(dev, "could not allocate RX ring, error %d\n",
+		    error);
 		goto fail;
 	}
 
-	/* receive data queue */
-	error = wpi_alloc_rx_ring(sc, &sc->rxq);
-	if (error != 0) {
-		device_printf(dev, "could not allocate Rx ring\n");
-		goto fail;
-	}
+	/* Clear pending interrupts. */
+	WPI_WRITE(sc, WPI_INT, 0xffffffff);
 
 	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
 	if (ifp == NULL) {
-		device_printf(dev, "can not if_alloc()\n");
-		error = ENOMEM;
+		device_printf(dev, "can not allocate ifnet structure\n");
 		goto fail;
 	}
-	ic = ifp->if_l2com;
 
+	ic = ifp->if_l2com;
 	ic->ic_ifp = ifp;
 	ic->ic_phytype = IEEE80211_T_OFDM;	/* not only, but not used */
 	ic->ic_opmode = IEEE80211_M_STA;	/* default to BSS mode */
 
-	/* set device capabilities */
+	/* Set device capabilities. */
 	ic->ic_caps =
 		  IEEE80211_C_STA		/* station mode supported */
+		| IEEE80211_C_IBSS		/* IBSS mode supported */
 		| IEEE80211_C_MONITOR		/* monitor mode supported */
+		| IEEE80211_C_AHDEMO		/* adhoc demo mode */
+		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
 		| IEEE80211_C_TXPMGT		/* tx power management */
 		| IEEE80211_C_SHSLOT		/* short slot time supported */
-		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
 		| IEEE80211_C_WPA		/* 802.11i */
-/* XXX looks like WME is partly supported? */
+		| IEEE80211_C_SHPREAMBLE	/* short preamble supported */
 #if 0
-		| IEEE80211_C_IBSS		/* IBSS mode support */
-		| IEEE80211_C_BGSCAN		/* capable of bg scanning */
-		| IEEE80211_C_WME		/* 802.11e */
 		| IEEE80211_C_HOSTAP		/* Host access point mode */
 #endif
+		| IEEE80211_C_WME		/* 802.11e */
+		| IEEE80211_C_PMGT		/* Station-side power mgmt */
 		;
 
+	ic->ic_cryptocaps =
+		  IEEE80211_CRYPTO_AES_CCM;
+
 	/*
 	 * Read in the eeprom and also setup the channels for
 	 * net80211. We don't set the rates as net80211 does this for us
 	 */
-	wpi_read_eeprom(sc, macaddr);
+	if ((error = wpi_read_eeprom(sc, macaddr)) != 0) {
+		device_printf(dev, "could not read EEPROM, error %d\n",
+		    error);
+		goto fail;
+        }
 
-	if (bootverbose || WPI_DEBUG_SET) {
+#ifdef	WPI_DEBUG
+	if (bootverbose) {
 	    device_printf(sc->sc_dev, "Regulatory Domain: %.4s\n", sc->domain);
 	    device_printf(sc->sc_dev, "Hardware Type: %c\n",
 			  sc->type > 1 ? 'B': '?');
@@ -650,6 +470,7 @@ wpi_attach(device_t dev)
 	    /* XXX hw_config uses the PCIDEV for the Hardware rev. Must check
 	       what sc->rev really represents - benjsc 20070615 */
 	}
+#endif
 
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 	ifp->if_softc = sc;
@@ -662,99 +483,90 @@ wpi_attach(device_t dev)
 	IFQ_SET_READY(&ifp->if_snd);
 
 	ieee80211_ifattach(ic, macaddr);
-	/* override default methods */
+	ic->ic_vap_create = wpi_vap_create;
+	ic->ic_vap_delete = wpi_vap_delete;
 	ic->ic_raw_xmit = wpi_raw_xmit;
-	ic->ic_wme.wme_update = wpi_wme_update;
+	ic->ic_node_alloc = wpi_node_alloc;
+	sc->sc_node_free = ic->ic_node_free;
+	ic->ic_node_free = wpi_node_free;
+	ic->ic_wme.wme_update = wpi_updateedca;
+	ic->ic_update_promisc = wpi_update_promisc;
+	ic->ic_update_mcast = wpi_update_mcast;
 	ic->ic_scan_start = wpi_scan_start;
 	ic->ic_scan_end = wpi_scan_end;
 	ic->ic_set_channel = wpi_set_channel;
+	sc->sc_scan_curchan = ic->ic_scan_curchan;
 	ic->ic_scan_curchan = wpi_scan_curchan;
 	ic->ic_scan_mindwell = wpi_scan_mindwell;
+	ic->ic_setregdomain = wpi_setregdomain;
 
-	ic->ic_vap_create = wpi_vap_create;
-	ic->ic_vap_delete = wpi_vap_delete;
+	wpi_radiotap_attach(sc);
 
-	ieee80211_radiotap_attach(ic,
-	    &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
-		WPI_TX_RADIOTAP_PRESENT,
-	    &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
-		WPI_RX_RADIOTAP_PRESENT);
+	callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0);
+	callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0);
+	callout_init_mtx(&sc->watchdog_rfkill, &sc->sc_mtx, 0);
+	TASK_INIT(&sc->sc_reinittask, 0, wpi_hw_reset, sc);
+	TASK_INIT(&sc->sc_radiooff_task, 0, wpi_radio_off, sc);
+	TASK_INIT(&sc->sc_radioon_task, 0, wpi_radio_on, sc);
+
+	wpi_sysctlattach(sc);
 
 	/*
 	 * Hook our interrupt after all initialization is complete.
 	 */
-	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET |INTR_MPSAFE,
+	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE,
 	    NULL, wpi_intr, sc, &sc->sc_ih);
 	if (error != 0) {
-		device_printf(dev, "could not set up interrupt\n");
+		device_printf(dev, "can't establish interrupt, error %d\n",
+		    error);
 		goto fail;
 	}
 
 	if (bootverbose)
 		ieee80211_announce(ic);
-#ifdef XXX_DEBUG
-	ieee80211_announce_channels(ic);
+
+#ifdef WPI_DEBUG
+	if (sc->sc_debug & WPI_DEBUG_HW)
+		ieee80211_announce_channels(ic);
 #endif
+
+	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
 	return 0;
 
 fail:	wpi_detach(dev);
-	return ENXIO;
+	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END_ERR, __func__);
+	return error;
 }
 
-static int
-wpi_detach(device_t dev)
+/*
+ * Attach the interface to 802.11 radiotap.
+ */
+static void
+wpi_radiotap_attach(struct wpi_softc *sc)
 {
-	struct wpi_softc *sc = device_get_softc(dev);
 	struct ifnet *ifp = sc->sc_ifp;
-	struct ieee80211com *ic;
-	int ac;
+	struct ieee80211com *ic = ifp->if_l2com;
+	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
+	ieee80211_radiotap_attach(ic,
+	    &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap),
+		WPI_TX_RADIOTAP_PRESENT,
+	    &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
+		WPI_RX_RADIOTAP_PRESENT);
+	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
+}
 
-	if (sc->irq != NULL)
-		bus_teardown_intr(dev, sc->irq, sc->sc_ih);
+static void
+wpi_sysctlattach(struct wpi_softc *sc)
+{
+#ifdef  WPI_DEBUG
+	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
+	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
 
-	if (ifp != NULL) {
-		ic = ifp->if_l2com;
-
-		ieee80211_draintask(ic, &sc->sc_restarttask);
-		ieee80211_draintask(ic, &sc->sc_radiotask);
-		wpi_stop(sc);
-		callout_drain(&sc->watchdog_to);
-		callout_drain(&sc->calib_to);
-		ieee80211_ifdetach(ic);
-	}
-
-	WPI_LOCK(sc);
-	if (sc->txq[0].data_dmat) {
-		for (ac = 0; ac < WME_NUM_AC; ac++)
-			wpi_free_tx_ring(sc, &sc->txq[ac]);
-
-		wpi_free_tx_ring(sc, &sc->cmdq);
-		wpi_free_rx_ring(sc, &sc->rxq);
-		wpi_free_shared(sc);
-	}
-
-	if (sc->fw_fp != NULL) {
-		wpi_unload_firmware(sc);
-	}
-
-	if (sc->fw_dma.tag)
-		wpi_free_fwmem(sc);
-	WPI_UNLOCK(sc);
-
-	if (sc->irq != NULL)
-		bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq),
-		    sc->irq);
-	if (sc->mem != NULL)
-		bus_release_resource(dev, SYS_RES_MEMORY,
-		    rman_get_rid(sc->mem), sc->mem);
-
-	if (ifp != NULL)
-		if_free(ifp);
-
-	WPI_LOCK_DESTROY(sc);
-
-	return 0;
-}
+	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+	    "debug", CTLFLAG_RW, &sc->sc_debug, sc->sc_debug,
+		"control debugging printfs");
+#endif
+}
 
 static struct ieee80211vap *
 wpi_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit,
@@ -763,22 +575,32 @@ wpi_vap_create(struct ieee80211com *ic, 
     const uint8_t mac[IEEE80211_ADDR_LEN])
 {
 	struct wpi_vap *wvp;
+	struct wpi_buf *bcn;
 	struct ieee80211vap *vap;
 
 	if (!TAILQ_EMPTY(&ic->ic_vaps))		/* only one at a time */
 		return NULL;
+
 	wvp = (struct wpi_vap *) malloc(sizeof(struct wpi_vap),
 	    M_80211_VAP, M_NOWAIT | M_ZERO);
 	if (wvp == NULL)
 		return NULL;
 	vap = &wvp->vap;
 	ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
-	/* override with driver methods */
+
+	bcn = &wvp->wv_bcbuf;
+	bcn->data = NULL;
+
+	/* Override with driver methods. */
 	wvp->newstate = vap->iv_newstate;
+	vap->iv_key_alloc = wpi_key_alloc;
+	vap->iv_key_set = wpi_key_set;
+	vap->iv_key_delete = wpi_key_delete;
 	vap->iv_newstate = wpi_newstate;
+	vap->iv_update_beacon = wpi_update_beacon;
 
 	ieee80211_ratectl_init(vap);
-	/* complete setup */
+	/* Complete setup. */
 	ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status);
 	ic->ic_opmode = opmode;
 	return vap;
@@ -788,127 +610,291 @@ static void
 wpi_vap_delete(struct ieee80211vap *vap)
 {
 	struct wpi_vap *wvp = WPI_VAP(vap);
+	struct wpi_buf *bcn = &wvp->wv_bcbuf;
 
 	ieee80211_ratectl_deinit(vap);
 	ieee80211_vap_detach(vap);
+
+	if (bcn->data != NULL)
+		free(bcn->data, M_DEVBUF);
 	free(wvp, M_80211_VAP);
 }
 
-static void
-wpi_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
+static int
+wpi_detach(device_t dev)
 {
-	if (error != 0)
-		return;
+	struct wpi_softc *sc = device_get_softc(dev);
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic;
+	int qid;
 
-	KASSERT(nsegs == 1, ("too many DMA segments, %d should be 1", nsegs));
+	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_BEGIN, __func__);
 
-	*(bus_addr_t *)arg = segs[0].ds_addr;
+	if (ifp != NULL) {
+		ic = ifp->if_l2com;
+
+		ieee80211_draintask(ic, &sc->sc_reinittask);
+		ieee80211_draintask(ic, &sc->sc_radiooff_task);
+
+		wpi_stop(sc);
+
+		callout_drain(&sc->watchdog_to);
+		callout_drain(&sc->watchdog_rfkill);
+		callout_drain(&sc->calib_to);
+		ieee80211_ifdetach(ic);
+	}
+
+	/* Uninstall interrupt handler. */
+	if (sc->irq != NULL) {
+		bus_teardown_intr(dev, sc->irq, sc->sc_ih);
+		bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq),
+		    sc->irq);
+		pci_release_msi(dev);
+	}
+
+	if (sc->txq[0].data_dmat) {
+		/* Free DMA resources. */
+		for (qid = 0; qid < WPI_NTXQUEUES; qid++)
+			wpi_free_tx_ring(sc, &sc->txq[qid]);
+
+		wpi_free_rx_ring(sc);
+		wpi_free_shared(sc);
+	}
+
+	if (sc->fw_dma.tag)
+		wpi_free_fwmem(sc);
+		
+	if (sc->mem != NULL)
+		bus_release_resource(dev, SYS_RES_MEMORY,
+		    rman_get_rid(sc->mem), sc->mem);
+
+	if (ifp != NULL)
+		if_free(ifp);
+
+	delete_unrhdr(sc->sc_unr);
+
+	DPRINTF(sc, WPI_DEBUG_TRACE, TRACE_STR_END, __func__);
+	WPI_LOCK_DESTROY(sc);
+	return 0;
+}
+
+static int

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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502072311.t17NBduF070960>