Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 18 Jun 2011 12:00:49 +0000 (UTC)
From:      Bernhard Schmidt <bschmidt@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r223248 - stable/8/sys/dev/iwn
Message-ID:  <201106181200.p5IC0ngB039919@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bschmidt
Date: Sat Jun 18 12:00:49 2011
New Revision: 223248
URL: http://svn.freebsd.org/changeset/base/223248

Log:
  MFC r220721,220723-220726:
  - Rename some stuff in favour of the OpenBSD names:
    - prefer EDCA over WME
    - qid for a TXQ ID
    - reg for register values
  - Shuffle code around a bit. Mostly to group functional connected things,
    others to get the same order as the OpenBSD code.
  - Sync debug and error messages with OpenBSD. The device capability
    announcements are now hidden behind bootverbose.
  - Sync comments with OpenBSD.
  - Whitespace sync, some more style(9) conform then others.

Modified:
  stable/8/sys/dev/iwn/if_iwn.c
  stable/8/sys/dev/iwn/if_iwnreg.h
  stable/8/sys/dev/iwn/if_iwnvar.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/dev/iwn/if_iwn.c
==============================================================================
--- stable/8/sys/dev/iwn/if_iwn.c	Sat Jun 18 11:56:40 2011	(r223247)
+++ stable/8/sys/dev/iwn/if_iwn.c	Sat Jun 18 12:00:49 2011	(r223248)
@@ -72,16 +72,61 @@ __FBSDID("$FreeBSD$");
 #include <dev/iwn/if_iwnreg.h>
 #include <dev/iwn/if_iwnvar.h>
 
+struct iwn_ident {
+	uint16_t	vendor;
+	uint16_t	device;
+	const char	*name;
+};
+
+static const struct iwn_ident iwn_ident_table [] = {
+	{ 0x8086, 0x4229, "Intel(R) PRO/Wireless 4965BGN" },
+	{ 0x8086, 0x422D, "Intel(R) PRO/Wireless 4965BGN" },
+	{ 0x8086, 0x4230, "Intel(R) PRO/Wireless 4965BGN" },
+	{ 0x8086, 0x4233, "Intel(R) PRO/Wireless 4965BGN" },
+	{ 0x8086, 0x4232, "Intel(R) PRO/Wireless 5100" },
+	{ 0x8086, 0x4237, "Intel(R) PRO/Wireless 5100" },
+	{ 0x8086, 0x423C, "Intel(R) PRO/Wireless 5150" },
+	{ 0x8086, 0x423D, "Intel(R) PRO/Wireless 5150" },
+	{ 0x8086, 0x4235, "Intel(R) PRO/Wireless 5300" },
+	{ 0x8086, 0x4236, "Intel(R) PRO/Wireless 5300" },
+	{ 0x8086, 0x423A, "Intel(R) PRO/Wireless 5350" },
+	{ 0x8086, 0x423B, "Intel(R) PRO/Wireless 5350" },
+	{ 0x8086, 0x0083, "Intel(R) PRO/Wireless 1000" },
+	{ 0x8086, 0x0084, "Intel(R) PRO/Wireless 1000" },
+	{ 0x8086, 0x008D, "Intel(R) PRO/Wireless 6000" },
+	{ 0x8086, 0x008E, "Intel(R) PRO/Wireless 6000" },
+	{ 0x8086, 0x4238, "Intel(R) PRO/Wireless 6000" },
+	{ 0x8086, 0x4239, "Intel(R) PRO/Wireless 6000" },
+	{ 0x8086, 0x422B, "Intel(R) PRO/Wireless 6000" },
+	{ 0x8086, 0x422C, "Intel(R) PRO/Wireless 6000" },
+	{ 0x8086, 0x0087, "Intel(R) PRO/Wireless 6250" },
+	{ 0x8086, 0x0089, "Intel(R) PRO/Wireless 6250" },
+	{ 0x8086, 0x0082, "Intel(R) PRO/Wireless 6205a" },
+	{ 0x8086, 0x0085, "Intel(R) PRO/Wireless 6205a" },
+#ifdef notyet
+	{ 0x8086, 0x008a, "Intel(R) PRO/Wireless 6205b" },
+	{ 0x8086, 0x008b, "Intel(R) PRO/Wireless 6205b" },
+	{ 0x8086, 0x008f, "Intel(R) PRO/Wireless 6205b" },
+	{ 0x8086, 0x0090, "Intel(R) PRO/Wireless 6205b" },
+	{ 0x8086, 0x0091, "Intel(R) PRO/Wireless 6205b" },
+#endif
+	{ 0, 0, NULL }
+};
+
 static int	iwn_probe(device_t);
 static int	iwn_attach(device_t);
 static const struct iwn_hal *iwn_hal_attach(struct iwn_softc *);
 static void	iwn_radiotap_attach(struct iwn_softc *);
+static void	iwn_sysctlattach(struct iwn_softc *);
 static struct ieee80211vap *iwn_vap_create(struct ieee80211com *,
 		    const char name[IFNAMSIZ], int unit, int opmode,
 		    int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
 		    const uint8_t mac[IEEE80211_ADDR_LEN]);
 static void	iwn_vap_delete(struct ieee80211vap *);
 static int	iwn_detach(device_t);
+static int	iwn_shutdown(device_t);
+static int	iwn_suspend(device_t);
+static int	iwn_resume(device_t);
 static int	iwn_nic_lock(struct iwn_softc *);
 static int	iwn_eeprom_lock(struct iwn_softc *);
 static int	iwn_init_otprom(struct iwn_softc *);
@@ -116,8 +161,12 @@ static void	iwn_read_eeprom_band(struct 
 #if 0	/* HT */
 static void	iwn_read_eeprom_ht40(struct iwn_softc *, int);
 #endif
-static void	iwn_read_eeprom_channels(struct iwn_softc *, int,
-		    uint32_t);
+static void	iwn_read_eeprom_channels(struct iwn_softc *, int, uint32_t);
+static struct iwn_eeprom_chan *iwn_find_eeprom_channel(struct iwn_softc *,
+		    struct ieee80211_channel *);
+static int	iwn_setregdomain(struct ieee80211com *,
+		    struct ieee80211_regdomain *, int,
+		    struct ieee80211_channel[]);
 static void	iwn_read_eeprom_enhinfo(struct iwn_softc *);
 static struct ieee80211_node *iwn_node_alloc(struct ieee80211vap *,
 		    const uint8_t mac[IEEE80211_ADDR_LEN]);
@@ -176,7 +225,7 @@ static int	iwn5000_add_node(struct iwn_s
 static int	iwn_set_link_quality(struct iwn_softc *,
 		    struct ieee80211_node *);
 static int	iwn_add_broadcast_node(struct iwn_softc *, int);
-static int	iwn_wme_update(struct ieee80211com *);
+static int	iwn_updateedca(struct ieee80211com *);
 static void	iwn_update_mcast(struct ifnet *);
 static void	iwn_set_led(struct iwn_softc *, uint8_t, uint8_t, uint8_t);
 static int	iwn_set_critical_temp(struct iwn_softc *);
@@ -219,10 +268,12 @@ static void	iwn_ampdu_tx_stop(struct iee
 		    struct ieee80211_node *, uint8_t);
 static void	iwn4965_ampdu_tx_start(struct iwn_softc *,
 		    struct ieee80211_node *, uint8_t, uint16_t);
-static void	iwn4965_ampdu_tx_stop(struct iwn_softc *, uint8_t, uint16_t);
+static void	iwn4965_ampdu_tx_stop(struct iwn_softc *,
+		    uint8_t, uint16_t);
 static void	iwn5000_ampdu_tx_start(struct iwn_softc *,
 		    struct ieee80211_node *, uint8_t, uint16_t);
-static void	iwn5000_ampdu_tx_stop(struct iwn_softc *, uint8_t, uint16_t);
+static void	iwn5000_ampdu_tx_stop(struct iwn_softc *,
+		    uint8_t, uint16_t);
 #endif
 static int	iwn5000_query_calibration(struct iwn_softc *);
 static int	iwn5000_send_calibration(struct iwn_softc *);
@@ -251,27 +302,18 @@ static int	iwn5000_nic_config(struct iwn
 static int	iwn_hw_prepare(struct iwn_softc *);
 static int	iwn_hw_init(struct iwn_softc *);
 static void	iwn_hw_stop(struct iwn_softc *);
+static void	iwn_radio_on(void *, int);
+static void	iwn_radio_off(void *, int);
 static void	iwn_init_locked(struct iwn_softc *);
 static void	iwn_init(void *);
 static void	iwn_stop_locked(struct iwn_softc *);
 static void	iwn_stop(struct iwn_softc *);
-static void 	iwn_scan_start(struct ieee80211com *);
-static void 	iwn_scan_end(struct ieee80211com *);
-static void 	iwn_set_channel(struct ieee80211com *);
-static void 	iwn_scan_curchan(struct ieee80211_scan_state *, unsigned long);
-static void 	iwn_scan_mindwell(struct ieee80211_scan_state *);
-static struct iwn_eeprom_chan *iwn_find_eeprom_channel(struct iwn_softc *,
-		    struct ieee80211_channel *);
-static int	iwn_setregdomain(struct ieee80211com *,
-		    struct ieee80211_regdomain *, int,
-		    struct ieee80211_channel []);
+static void	iwn_scan_start(struct ieee80211com *);
+static void	iwn_scan_end(struct ieee80211com *);
+static void	iwn_set_channel(struct ieee80211com *);
+static void	iwn_scan_curchan(struct ieee80211_scan_state *, unsigned long);
+static void	iwn_scan_mindwell(struct ieee80211_scan_state *);
 static void	iwn_hw_reset(void *, int);
-static void	iwn_radio_on(void *, int);
-static void	iwn_radio_off(void *, int);
-static void	iwn_sysctlattach(struct iwn_softc *);
-static int	iwn_shutdown(device_t);
-static int	iwn_suspend(device_t);
-static int	iwn_resume(device_t);
 
 #define IWN_DEBUG
 #ifdef IWN_DEBUG
@@ -298,51 +340,75 @@ enum {
 		printf(fmt, __VA_ARGS__);		\
 } while (0)
 
-static const char *iwn_intr_str(uint8_t);
+static const char *
+iwn_intr_str(uint8_t cmd)
+{
+	switch (cmd) {
+	/* Notifications */
+	case IWN_UC_READY:		return "UC_READY";
+	case IWN_ADD_NODE_DONE:		return "ADD_NODE_DONE";
+	case IWN_TX_DONE:		return "TX_DONE";
+	case IWN_START_SCAN:		return "START_SCAN";
+	case IWN_STOP_SCAN:		return "STOP_SCAN";
+	case IWN_RX_STATISTICS:		return "RX_STATS";
+	case IWN_BEACON_STATISTICS:	return "BEACON_STATS";
+	case IWN_STATE_CHANGED:		return "STATE_CHANGED";
+	case IWN_BEACON_MISSED:		return "BEACON_MISSED";
+	case IWN_RX_PHY:		return "RX_PHY";
+	case IWN_MPDU_RX_DONE:		return "MPDU_RX_DONE";
+	case IWN_RX_DONE:		return "RX_DONE";
+
+	/* Command Notifications */
+	case IWN_CMD_RXON:		return "IWN_CMD_RXON";
+	case IWN_CMD_RXON_ASSOC:	return "IWN_CMD_RXON_ASSOC";
+	case IWN_CMD_EDCA_PARAMS:	return "IWN_CMD_EDCA_PARAMS";
+	case IWN_CMD_TIMING:		return "IWN_CMD_TIMING";
+	case IWN_CMD_LINK_QUALITY:	return "IWN_CMD_LINK_QUALITY";
+	case IWN_CMD_SET_LED:		return "IWN_CMD_SET_LED";
+	case IWN5000_CMD_WIMAX_COEX:	return "IWN5000_CMD_WIMAX_COEX";
+	case IWN5000_CMD_CALIB_CONFIG:	return "IWN5000_CMD_CALIB_CONFIG";
+	case IWN5000_CMD_CALIB_RESULT:	return "IWN5000_CMD_CALIB_RESULT";
+	case IWN5000_CMD_CALIB_COMPLETE: return "IWN5000_CMD_CALIB_COMPLETE";
+	case IWN_CMD_SET_POWER_MODE:	return "IWN_CMD_SET_POWER_MODE";
+	case IWN_CMD_SCAN:		return "IWN_CMD_SCAN";
+	case IWN_CMD_SCAN_RESULTS:	return "IWN_CMD_SCAN_RESULTS";
+	case IWN_CMD_TXPOWER:		return "IWN_CMD_TXPOWER";
+	case IWN_CMD_TXPOWER_DBM:	return "IWN_CMD_TXPOWER_DBM";
+	case IWN5000_CMD_TX_ANT_CONFIG:	return "IWN5000_CMD_TX_ANT_CONFIG";
+	case IWN_CMD_BT_COEX:		return "IWN_CMD_BT_COEX";
+	case IWN_CMD_SET_CRITICAL_TEMP:	return "IWN_CMD_SET_CRITICAL_TEMP";
+	case IWN_CMD_SET_SENSITIVITY:	return "IWN_CMD_SET_SENSITIVITY";
+	case IWN_CMD_PHY_CALIB:		return "IWN_CMD_PHY_CALIB";
+	}
+	return "UNKNOWN INTR NOTIF/CMD";
+}
 #else
 #define DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
 #endif
 
-struct iwn_ident {
-	uint16_t	vendor;
-	uint16_t	device;
-	const char	*name;
+static device_method_t iwn_methods[] = {
+	/* Device interface */
+	DEVMETHOD(device_probe,		iwn_probe),
+	DEVMETHOD(device_attach,	iwn_attach),
+	DEVMETHOD(device_detach,	iwn_detach),
+	DEVMETHOD(device_shutdown,	iwn_shutdown),
+	DEVMETHOD(device_suspend,	iwn_suspend),
+	DEVMETHOD(device_resume,	iwn_resume),
+	{ 0, 0 }
 };
 
-static const struct iwn_ident iwn_ident_table [] = {
-	{ 0x8086, 0x4229, "Intel(R) PRO/Wireless 4965BGN" },
-	{ 0x8086, 0x422D, "Intel(R) PRO/Wireless 4965BGN" },
-	{ 0x8086, 0x4230, "Intel(R) PRO/Wireless 4965BGN" },
-	{ 0x8086, 0x4233, "Intel(R) PRO/Wireless 4965BGN" },
-	{ 0x8086, 0x4232, "Intel(R) PRO/Wireless 5100" },
-	{ 0x8086, 0x4237, "Intel(R) PRO/Wireless 5100" },
-	{ 0x8086, 0x423C, "Intel(R) PRO/Wireless 5150" },
-	{ 0x8086, 0x423D, "Intel(R) PRO/Wireless 5150" },
-	{ 0x8086, 0x4235, "Intel(R) PRO/Wireless 5300" },
-	{ 0x8086, 0x4236, "Intel(R) PRO/Wireless 5300" },
-	{ 0x8086, 0x423A, "Intel(R) PRO/Wireless 5350" },
-	{ 0x8086, 0x423B, "Intel(R) PRO/Wireless 5350" },
-	{ 0x8086, 0x0083, "Intel(R) PRO/Wireless 1000" },
-	{ 0x8086, 0x0084, "Intel(R) PRO/Wireless 1000" },
-	{ 0x8086, 0x008D, "Intel(R) PRO/Wireless 6000" },
-	{ 0x8086, 0x008E, "Intel(R) PRO/Wireless 6000" },
-	{ 0x8086, 0x4238, "Intel(R) PRO/Wireless 6000" },
-	{ 0x8086, 0x4239, "Intel(R) PRO/Wireless 6000" },
-	{ 0x8086, 0x422B, "Intel(R) PRO/Wireless 6000" },
-	{ 0x8086, 0x422C, "Intel(R) PRO/Wireless 6000" },
-	{ 0x8086, 0x0087, "Intel(R) PRO/Wireless 6250" },
-	{ 0x8086, 0x0089, "Intel(R) PRO/Wireless 6250" },
-	{ 0x8086, 0x0082, "Intel(R) PRO/Wireless 6205a" },
-	{ 0x8086, 0x0085, "Intel(R) PRO/Wireless 6205a" },
-#ifdef notyet
-	{ 0x8086, 0x008a, "Intel(R) PRO/Wireless 6205b" },
-	{ 0x8086, 0x008b, "Intel(R) PRO/Wireless 6205b" },
-	{ 0x8086, 0x008f, "Intel(R) PRO/Wireless 6205b" },
-	{ 0x8086, 0x0090, "Intel(R) PRO/Wireless 6205b" },
-	{ 0x8086, 0x0091, "Intel(R) PRO/Wireless 6205b" },
-#endif
-	{ 0, 0, NULL }
+static driver_t iwn_driver = {
+	"iwn",
+	iwn_methods,
+	sizeof(struct iwn_softc)
 };
+static devclass_t iwn_devclass;
+
+DRIVER_MODULE(iwn, pci, iwn_driver, iwn_devclass, 0, 0);
+
+MODULE_DEPEND(iwn, firmware, 1, 1, 1);
+MODULE_DEPEND(iwn, pci, 1, 1, 1);
+MODULE_DEPEND(iwn, wlan, 1, 1, 1);
 
 static const struct iwn_hal iwn4965_hal = {
 	iwn4965_load_firmware,
@@ -422,7 +488,7 @@ iwn_attach(device_t dev)
 	struct ieee80211com *ic;
 	struct ifnet *ifp;
 	const struct iwn_hal *hal;
-	uint32_t tmp;
+	uint32_t reg;
 	int i, error, result;
 	uint8_t macaddr[IEEE80211_ADDR_LEN];
 
@@ -442,12 +508,12 @@ iwn_attach(device_t dev)
 	pci_write_config(dev, 0x41, 0, 1);
 
 	/* Hardware bug workaround. */
-	tmp = pci_read_config(dev, PCIR_COMMAND, 1);
-	if (tmp & PCIM_CMD_INTxDIS) {
+	reg = pci_read_config(dev, PCIR_COMMAND, 1);
+	if (reg & PCIM_CMD_INTxDIS) {
 		DPRINTF(sc, IWN_DEBUG_RESET, "%s: PCIe INTx Disable set\n",
 		    __func__);
-		tmp &= ~PCIM_CMD_INTxDIS;
-		pci_write_config(dev, PCIR_COMMAND, tmp, 1);
+		reg &= ~PCIM_CMD_INTxDIS;
+		pci_write_config(dev, PCIR_COMMAND, reg, 1);
 	}
 
 	/* Enable bus-mastering. */
@@ -456,30 +522,28 @@ iwn_attach(device_t dev)
 	sc->mem_rid = PCIR_BAR(0);
 	sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
 	    RF_ACTIVE);
-	if (sc->mem == NULL ) {
-		device_printf(dev, "could not allocate memory resources\n");
+	if (sc->mem == NULL) {
+		device_printf(dev, "can't map mem space\n");
 		error = ENOMEM;
 		return error;
 	}
-
 	sc->sc_st = rman_get_bustag(sc->mem);
 	sc->sc_sh = rman_get_bushandle(sc->mem);
+
 	sc->irq_rid = 0;
 	if ((result = pci_msi_count(dev)) == 1 &&
 	    pci_alloc_msi(dev, &result) == 0)
 		sc->irq_rid = 1;
+	/* Install interrupt handler. */
 	sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid,
 	    RF_ACTIVE | 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;
 	}
 
 	IWN_LOCK_INIT(sc);
-	TASK_INIT(&sc->sc_reinit_task, 0, iwn_hw_reset, sc );
-	TASK_INIT(&sc->sc_radioon_task, 0, iwn_radio_on, sc );
-	TASK_INIT(&sc->sc_radiooff_task, 0, iwn_radio_off, sc );
 
 	/* Attach Hardware Abstraction Layer. */
 	hal = iwn_hal_attach(sc);
@@ -488,15 +552,13 @@ iwn_attach(device_t dev)
 		goto fail;
 	}
 
-	error = iwn_hw_prepare(sc);
-	if (error != 0) {
+	if ((error = iwn_hw_prepare(sc)) != 0) {
 		device_printf(dev, "hardware not ready, error %d\n", error);
 		goto fail;
 	}
 
 	/* Allocate DMA memory for firmware transfers. */
-	error = iwn_alloc_fwmem(sc);
-	if (error != 0) {
+	if ((error = iwn_alloc_fwmem(sc)) != 0) {
 		device_printf(dev,
 		    "could not allocate memory for firmware, error %d\n",
 		    error);
@@ -504,47 +566,41 @@ iwn_attach(device_t dev)
 	}
 
 	/* Allocate "Keep Warm" page. */
-	error = iwn_alloc_kw(sc);
-	if (error != 0) {
+	if ((error = iwn_alloc_kw(sc)) != 0) {
 		device_printf(dev,
-		    "could not allocate \"Keep Warm\" page, error %d\n", error);
+		    "could not allocate keep warm page, error %d\n", error);
 		goto fail;
 	}
 
 	/* Allocate ICT table for 5000 Series. */
 	if (sc->hw_type != IWN_HW_REV_TYPE_4965 &&
 	    (error = iwn_alloc_ict(sc)) != 0) {
-		device_printf(dev,
-		    "%s: could not allocate ICT table, error %d\n",
-		    __func__, error);
+		device_printf(dev, "could not allocate ICT table, error %d\n",
+		    error);
 		goto fail;
 	}
 
 	/* Allocate TX scheduler "rings". */
-	error = iwn_alloc_sched(sc);
-	if (error != 0) {
+	if ((error = iwn_alloc_sched(sc)) != 0) {
 		device_printf(dev,
-		    "could not allocate TX scheduler rings, error %d\n",
-		    error);
+		    "could not allocate TX scheduler rings, error %d\n", error);
 		goto fail;
 	}
 
-	/* Allocate TX rings (16 on 4965AGN, 20 on 5000). */
+	/* Allocate TX rings (16 on 4965AGN, 20 on >=5000). */
 	for (i = 0; i < hal->ntxqs; i++) {
-		error = iwn_alloc_tx_ring(sc, &sc->txq[i], i);
-		if (error != 0) {
+		if ((error = iwn_alloc_tx_ring(sc, &sc->txq[i], i)) != 0) {
 			device_printf(dev,
-			    "could not allocate Tx ring %d, error %d\n",
-			    i, error);
+			    "could not allocate TX ring %d, error %d\n", i,
+			    error);
 			goto fail;
 		}
 	}
 
 	/* Allocate RX ring. */
-	error = iwn_alloc_rx_ring(sc, &sc->rxq);
-	if (error != 0 ){
-		device_printf(dev,
-		    "could not allocate Rx ring, error %d\n", error);
+	if ((error = iwn_alloc_rx_ring(sc, &sc->rxq)) != 0) {
+		device_printf(dev, "could not allocate RX ring, error %d\n",
+		    error);
 		goto fail;
 	}
 
@@ -560,14 +616,19 @@ iwn_attach(device_t dev)
 	    ((sc->rxchainmask >> 2) & 1) +
 	    ((sc->rxchainmask >> 1) & 1) +
 	    ((sc->rxchainmask >> 0) & 1);
+	if (bootverbose) {
+		device_printf(dev, "MIMO %dT%dR, %.4s, address %6D\n",
+		    sc->ntxchains, sc->nrxchains, sc->eeprom_domain,
+		    macaddr, ":");
+	}
 
 	ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
 	if (ifp == NULL) {
 		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 */
@@ -618,17 +679,12 @@ iwn_attach(device_t dev)
 #endif
 
 	/* Read MAC address, channels, etc from EEPROM. */
-	error = iwn_read_eeprom(sc, macaddr);
-	if (error != 0) {
+	if ((error = iwn_read_eeprom(sc, macaddr)) != 0) {
 		device_printf(dev, "could not read EEPROM, error %d\n",
 		    error);
 		goto fail;
 	}
 
-	device_printf(sc->sc_dev, "MIMO %dT%dR, %.4s, address %6D\n",
-	    sc->ntxchains, sc->nrxchains, sc->eeprom_domain,
-	    macaddr, ":");
-
 #if 0	/* HT */
 	/* Set supported HT rates. */
 	ic->ic_sup_mcs[0] = 0xff;
@@ -653,8 +709,14 @@ iwn_attach(device_t dev)
 	ic->ic_vap_delete = iwn_vap_delete;
 	ic->ic_raw_xmit = iwn_raw_xmit;
 	ic->ic_node_alloc = iwn_node_alloc;
+#if 0	/* HT */
+	ic->ic_ampdu_rx_start = iwn_ampdu_rx_start;
+	ic->ic_ampdu_rx_stop = iwn_ampdu_rx_stop;
+	ic->ic_ampdu_tx_start = iwn_ampdu_tx_start;
+	ic->ic_ampdu_tx_stop = iwn_ampdu_tx_stop;
+#endif
 	ic->ic_newassoc = iwn_newassoc;
-	ic->ic_wme.wme_update = iwn_wme_update;
+	ic->ic_wme.wme_update = iwn_updateedca;
 	ic->ic_update_mcast = iwn_update_mcast;
 	ic->ic_scan_start = iwn_scan_start;
 	ic->ic_scan_end = iwn_scan_end;
@@ -662,17 +724,14 @@ iwn_attach(device_t dev)
 	ic->ic_scan_curchan = iwn_scan_curchan;
 	ic->ic_scan_mindwell = iwn_scan_mindwell;
 	ic->ic_setregdomain = iwn_setregdomain;
-#if 0	/* HT */
-	ic->ic_ampdu_rx_start = iwn_ampdu_rx_start;
-	ic->ic_ampdu_rx_stop = iwn_ampdu_rx_stop;
-	ic->ic_ampdu_tx_start = iwn_ampdu_tx_start;
-	ic->ic_ampdu_tx_stop = iwn_ampdu_tx_stop;
-#endif
 
 	iwn_radiotap_attach(sc);
 
 	callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0);
 	callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0);
+	TASK_INIT(&sc->sc_reinit_task, 0, iwn_hw_reset, sc);
+	TASK_INIT(&sc->sc_radioon_task, 0, iwn_radio_on, sc);
+	TASK_INIT(&sc->sc_radiooff_task, 0, iwn_radio_off, sc);
 
 	iwn_sysctlattach(sc);
 
@@ -682,12 +741,13 @@ iwn_attach(device_t dev)
 	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE,
 	    NULL, iwn_intr, sc, &sc->sc_ih);
 	if (error != 0) {
-		device_printf(dev, "could not set up interrupt, error %d\n",
+		device_printf(dev, "can't establish interrupt, error %d\n",
 		    error);
 		goto fail;
 	}
 
-	ieee80211_announce(ic);
+	if (bootverbose)
+		ieee80211_announce(ic);
 	return 0;
 fail:
 	iwn_detach(dev);
@@ -791,11 +851,24 @@ iwn_radiotap_attach(struct iwn_softc *sc
 		IWN_RX_RADIOTAP_PRESENT);
 }
 
+static void
+iwn_sysctlattach(struct iwn_softc *sc)
+{
+	struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev);
+	struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev);
+
+#ifdef IWN_DEBUG
+	sc->sc_debug = 0;
+	SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO,
+	    "debug", CTLFLAG_RW, &sc->sc_debug, 0, "control debugging printfs");
+#endif
+}
+
 static struct ieee80211vap *
 iwn_vap_create(struct ieee80211com *ic,
-	const char name[IFNAMSIZ], int unit, int opmode, int flags,
-	const uint8_t bssid[IEEE80211_ADDR_LEN],
-	const uint8_t mac[IEEE80211_ADDR_LEN])
+    const char name[IFNAMSIZ], int unit, int opmode, int flags,
+    const uint8_t bssid[IEEE80211_ADDR_LEN],
+    const uint8_t mac[IEEE80211_ADDR_LEN])
 {
 	struct iwn_vap *ivp;
 	struct ieee80211vap *vap;
@@ -836,7 +909,7 @@ iwn_detach(device_t dev)
 	struct iwn_softc *sc = device_get_softc(dev);
 	struct ifnet *ifp = sc->sc_ifp;
 	struct ieee80211com *ic;
-	int i;
+	int qid;
 
 	if (ifp != NULL) {
 		ic = ifp->if_l2com;
@@ -851,24 +924,25 @@ iwn_detach(device_t dev)
 		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, sc->irq_rid, sc->irq);
+		if (sc->irq_rid == 1)
+			pci_release_msi(dev);
+	}
+
 	/* Free DMA resources. */
 	iwn_free_rx_ring(sc, &sc->rxq);
 	if (sc->sc_hal != NULL)
-		for (i = 0; i < sc->sc_hal->ntxqs; i++)
-			iwn_free_tx_ring(sc, &sc->txq[i]);
+		for (qid = 0; qid < sc->sc_hal->ntxqs; qid++)
+			iwn_free_tx_ring(sc, &sc->txq[qid]);
 	iwn_free_sched(sc);
 	iwn_free_kw(sc);
 	if (sc->ict != NULL)
 		iwn_free_ict(sc);
 	iwn_free_fwmem(sc);
 
-	if (sc->irq != NULL) {
-		bus_teardown_intr(dev, sc->irq, sc->sc_ih);
-		bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq);
-		if (sc->irq_rid == 1)
-			pci_release_msi(dev);
-	}
-
 	if (sc->mem != NULL)
 		bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
 
@@ -880,34 +954,78 @@ iwn_detach(device_t dev)
 }
 
 static int
-iwn_nic_lock(struct iwn_softc *sc)
+iwn_shutdown(device_t dev)
 {
-	int ntries;
-
-	/* Request exclusive access to NIC. */
-	IWN_SETBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_MAC_ACCESS_REQ);
+	struct iwn_softc *sc = device_get_softc(dev);
 
-	/* Spin until we actually get the lock. */
-	for (ntries = 0; ntries < 1000; ntries++) {
-		if ((IWN_READ(sc, IWN_GP_CNTRL) &
-		    (IWN_GP_CNTRL_MAC_ACCESS_ENA | IWN_GP_CNTRL_SLEEP)) ==
-		    IWN_GP_CNTRL_MAC_ACCESS_ENA)
-			return 0;
-		DELAY(10);
-	}
-	return ETIMEDOUT;
+	iwn_stop(sc);
+	return 0;
 }
 
-static __inline void
-iwn_nic_unlock(struct iwn_softc *sc)
+static int
+iwn_suspend(device_t dev)
 {
-	IWN_CLRBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_MAC_ACCESS_REQ);
+	struct iwn_softc *sc = device_get_softc(dev);
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
+	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+
+	iwn_stop(sc);
+	if (vap != NULL)
+		ieee80211_stop(vap);
+	return 0;
 }
 
-static __inline uint32_t
-iwn_prph_read(struct iwn_softc *sc, uint32_t addr)
+static int
+iwn_resume(device_t dev)
 {
-	IWN_WRITE(sc, IWN_PRPH_RADDR, IWN_PRPH_DWORD | addr);
+	struct iwn_softc *sc = device_get_softc(dev);
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = ifp->if_l2com;
+	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+
+	/* Clear device-specific "PCI retry timeout" register (41h). */
+	pci_write_config(dev, 0x41, 0, 1);
+
+	if (ifp->if_flags & IFF_UP) {
+		iwn_init(sc);
+		if (vap != NULL)
+			ieee80211_init(vap);
+		if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+			iwn_start(ifp);
+	}
+	return 0;
+}
+
+static int
+iwn_nic_lock(struct iwn_softc *sc)
+{
+	int ntries;
+
+	/* Request exclusive access to NIC. */
+	IWN_SETBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_MAC_ACCESS_REQ);
+
+	/* Spin until we actually get the lock. */
+	for (ntries = 0; ntries < 1000; ntries++) {
+		if ((IWN_READ(sc, IWN_GP_CNTRL) &
+		     (IWN_GP_CNTRL_MAC_ACCESS_ENA | IWN_GP_CNTRL_SLEEP)) ==
+		    IWN_GP_CNTRL_MAC_ACCESS_ENA)
+			return 0;
+		DELAY(10);
+	}
+	return ETIMEDOUT;
+}
+
+static __inline void
+iwn_nic_unlock(struct iwn_softc *sc)
+{
+	IWN_CLRBITS(sc, IWN_GP_CNTRL, IWN_GP_CNTRL_MAC_ACCESS_REQ);
+}
+
+static __inline uint32_t
+iwn_prph_read(struct iwn_softc *sc, uint32_t addr)
+{
+	IWN_WRITE(sc, IWN_PRPH_RADDR, IWN_PRPH_DWORD | addr);
 	IWN_BARRIER_READ_WRITE(sc);
 	return IWN_READ(sc, IWN_PRPH_RDATA);
 }
@@ -1023,12 +1141,10 @@ iwn_init_otprom(struct iwn_softc *sc)
 	int count, error;
 
 	/* Wait for clock stabilization before accessing prph. */
-	error = iwn_clock_wait(sc);
-	if (error != 0)
+	if ((error = iwn_clock_wait(sc)) != 0)
 		return error;
 
-	error = iwn_nic_lock(sc);
-	if (error != 0)
+	if ((error = iwn_nic_lock(sc)) != 0)
 		return error;
 	iwn_prph_setbits(sc, IWN_APMG_PS, IWN_APMG_PS_RESET_REQ);
 	DELAY(5);
@@ -1073,9 +1189,9 @@ iwn_init_otprom(struct iwn_softc *sc)
 static int
 iwn_read_prom_data(struct iwn_softc *sc, uint32_t addr, void *data, int count)
 {
+	uint8_t *out = data;
 	uint32_t val, tmp;
 	int ntries;
-	uint8_t *out = data;
 
 	addr += sc->prom_base;
 	for (; count > 0; count -= 2, addr++) {
@@ -1127,8 +1243,8 @@ iwn_dma_contig_alloc(struct iwn_softc *s
 {
 	int error;
 
-	dma->size = size;
 	dma->tag = NULL;
+	dma->size = size;
 
 	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), alignment,
 	    0, BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, size,
@@ -1150,9 +1266,10 @@ iwn_dma_contig_alloc(struct iwn_softc *s
 
 	if (kvap != NULL)
 		*kvap = dma->vaddr;
+
 	return 0;
-fail:
-	iwn_dma_contig_free(dma);
+
+fail:	iwn_dma_contig_free(dma);
 	return error;
 }
 
@@ -1309,11 +1426,13 @@ iwn_alloc_rx_ring(struct iwn_softc *sc, 
 		/* Set physical address of RX buffer (256-byte aligned). */
 		ring->desc[i] = htole32(paddr >> 8);
 	}
+
 	bus_dmamap_sync(ring->desc_dma.tag, ring->desc_dma.map,
 	    BUS_DMASYNC_PREWRITE);
+
 	return 0;
-fail:
-	iwn_free_rx_ring(sc, ring);
+
+fail:	iwn_free_rx_ring(sc, ring);
 	return error;
 }
 
@@ -1331,11 +1450,6 @@ iwn_reset_rx_ring(struct iwn_softc *sc, 
 			DELAY(10);
 		}
 		iwn_nic_unlock(sc);
-#ifdef IWN_DEBUG
-		if (ntries == 1000)
-			DPRINTF(sc, IWN_DEBUG_ANY, "%s\n",
-			    "timeout resetting Rx ring");
-#endif
 	}
 	ring->cur = 0;
 	sc->last_rx_valid = 0;
@@ -1371,16 +1485,16 @@ iwn_free_rx_ring(struct iwn_softc *sc, s
 static int
 iwn_alloc_tx_ring(struct iwn_softc *sc, struct iwn_tx_ring *ring, int qid)
 {
-	bus_size_t size;
 	bus_addr_t paddr;
+	bus_size_t size;
 	int i, error;
 
 	ring->qid = qid;
 	ring->queued = 0;
 	ring->cur = 0;
 
-	/* Allocate TX descriptors (256-byte aligned.) */
-	size = IWN_TX_RING_COUNT * sizeof(struct iwn_tx_desc);
+	/* Allocate TX descriptors (256-byte aligned). */
+	size = IWN_TX_RING_COUNT * sizeof (struct iwn_tx_desc);
 	error = iwn_dma_contig_alloc(sc, &ring->desc_dma, (void **)&ring->desc,
 	    size, 256);
 	if (error != 0) {
@@ -1389,15 +1503,15 @@ iwn_alloc_tx_ring(struct iwn_softc *sc, 
 		    __func__, error);
 		goto fail;
 	}
-
 	/*
 	 * We only use rings 0 through 4 (4 EDCA + cmd) so there is no need
 	 * to allocate commands space for other rings.
+	 * XXX Do we really need to allocate descriptors for other rings?
 	 */
 	if (qid > 4)
 		return 0;
 
-	size = IWN_TX_RING_COUNT * sizeof(struct iwn_tx_cmd);
+	size = IWN_TX_RING_COUNT * sizeof (struct iwn_tx_cmd);
 	error = iwn_dma_contig_alloc(sc, &ring->cmd_dma, (void **)&ring->cmd,
 	    size, 4);
 	if (error != 0) {
@@ -1408,9 +1522,9 @@ iwn_alloc_tx_ring(struct iwn_softc *sc, 
 	}
 
 	error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
-	    BUS_SPACE_MAXADDR_32BIT,
-	    BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, IWN_MAX_SCATTER - 1,
-	    MCLBYTES, BUS_DMA_NOWAIT, NULL, NULL, &ring->data_dmat);
+	    BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
+	    IWN_MAX_SCATTER - 1, MCLBYTES, BUS_DMA_NOWAIT, NULL, NULL,
+	    &ring->data_dmat);
 	if (error != 0) {
 		device_printf(sc->sc_dev,
 		    "%s: could not create TX buf DMA tag, error %d\n",
@@ -1435,8 +1549,8 @@ iwn_alloc_tx_ring(struct iwn_softc *sc, 
 		}
 	}
 	return 0;
-fail:
-	iwn_free_tx_ring(sc, ring);
+
+fail:	iwn_free_tx_ring(sc, ring);
 	return error;
 }
 
@@ -1501,7 +1615,7 @@ iwn5000_ict_reset(struct iwn_softc *sc)
 	memset(sc->ict, 0, IWN_ICT_SIZE);
 	sc->ict_cur = 0;
 
-	/* Set physical address of ICT table (4KB aligned.) */
+	/* Set physical address of ICT table (4KB aligned). */
 	DPRINTF(sc, IWN_DEBUG_RESET, "%s: enabling ICT\n", __func__);
 	IWN_WRITE(sc, IWN_DRAM_INT_TBL, IWN_DRAM_INT_TBL_ENABLE |
 	    IWN_DRAM_INT_TBL_WRAP_CHECK | sc->ict_dma.paddr >> 12);
@@ -1520,8 +1634,8 @@ static int
 iwn_read_eeprom(struct iwn_softc *sc, uint8_t macaddr[IEEE80211_ADDR_LEN])
 {
 	const struct iwn_hal *hal = sc->sc_hal;
-	int error;
 	uint16_t val;
+	int error;
 
 	/* Check whether adapter has an EEPROM or an OTPROM. */
 	if (sc->hw_type >= IWN_HW_REV_TYPE_1000 &&
@@ -1531,11 +1645,10 @@ iwn_read_eeprom(struct iwn_softc *sc, ui
 	    (sc->sc_flags & IWN_FLAG_HAS_OTPROM) ? "OTPROM" : "EEPROM");
 
 	/* Adapter has to be powered on for EEPROM access to work. */
-	error = iwn_apm_init(sc);
-	if (error != 0) {
+	if ((error = iwn_apm_init(sc)) != 0) {
 		device_printf(sc->sc_dev,
-		    "%s: could not power ON adapter, error %d\n",
-		    __func__, error);
+		    "%s: could not power ON adapter, error %d\n", __func__,
+		    error);
 		return error;
 	}
 
@@ -1543,17 +1656,13 @@ iwn_read_eeprom(struct iwn_softc *sc, ui
 		device_printf(sc->sc_dev, "%s: bad ROM signature\n", __func__);
 		return EIO;
 	}
-	error = iwn_eeprom_lock(sc);
-	if (error != 0) {
-		device_printf(sc->sc_dev,
-		    "%s: could not lock ROM, error %d\n",
+	if ((error = iwn_eeprom_lock(sc)) != 0) {
+		device_printf(sc->sc_dev, "%s: could not lock ROM, error %d\n",
 		    __func__, error);
 		return error;
 	}
-
 	if (sc->sc_flags & IWN_FLAG_HAS_OTPROM) {
-		error = iwn_init_otprom(sc);
-		if (error != 0) {
+		if ((error = iwn_init_otprom(sc)) != 0) {
 			device_printf(sc->sc_dev,
 			    "%s: could not initialize OTPROM, error %d\n",
 			    __func__, error);
@@ -1581,13 +1690,13 @@ static void
 iwn4965_read_eeprom(struct iwn_softc *sc)
 {
 	uint32_t addr;
-	int i;
 	uint16_t val;
+	int i;
 
-	/* Read regulatory domain (4 ASCII characters.) */
+	/* Read regulatory domain (4 ASCII characters). */
 	iwn_read_prom_data(sc, IWN4965_EEPROM_DOMAIN, sc->eeprom_domain, 4);
 
-	/* Read the list of authorized channels (20MHz ones only.) */
+	/* Read the list of authorized channels (20MHz ones only). */
 	for (i = 0; i < 5; i++) {
 		addr = iwn4965_regulatory_bands[i];
 		iwn_read_eeprom_channels(sc, i, addr);
@@ -1664,17 +1773,17 @@ iwn5000_read_eeprom(struct iwn_softc *sc
 {
 	struct iwn5000_eeprom_calib_hdr hdr;
 	int32_t volt;
-	uint32_t addr, base;
-	int i;
+	uint32_t base, addr;
 	uint16_t val;
+	int i;
 
-	/* Read regulatory domain (4 ASCII characters.) */
+	/* Read regulatory domain (4 ASCII characters). */
 	iwn_read_prom_data(sc, IWN5000_EEPROM_REG, &val, 2);
 	base = le16toh(val);
 	iwn_read_prom_data(sc, base + IWN5000_EEPROM_DOMAIN,
 	    sc->eeprom_domain, 4);
 
-	/* Read the list of authorized channels (20MHz ones only.) */
+	/* Read the list of authorized channels (20MHz ones only). */
 	for (i = 0; i < 5; i++) {
 		addr = base + iwn5000_regulatory_bands[i];
 		iwn_read_eeprom_channels(sc, i, addr);
@@ -1688,8 +1797,8 @@ iwn5000_read_eeprom(struct iwn_softc *sc
 	base = le16toh(val);
 	iwn_read_prom_data(sc, base, &hdr, sizeof hdr);
 	DPRINTF(sc, IWN_DEBUG_CALIBRATE,
-	    "%s: calib version=%u pa type=%u voltage=%u\n",
-	    __func__, hdr.version, hdr.pa_type, le16toh(hdr.volt));
+	    "%s: calib version=%u pa type=%u voltage=%u\n", __func__,
+	    hdr.version, hdr.pa_type, le16toh(hdr.volt));
 	sc->calib_ver = hdr.version;
 
 	if (sc->hw_type == IWN_HW_REV_TYPE_5150) {
@@ -1754,33 +1863,30 @@ iwn_read_eeprom_band(struct iwn_softc *s
 		chan = band->chan[i];
 		nflags = iwn_eeprom_channel_flags(&channels[i]);
 
-		DPRINTF(sc, IWN_DEBUG_RESET,
-		    "add chan %d flags 0x%x maxpwr %d\n",
-		    chan, channels[i].flags, channels[i].maxpwr);
-
 		c = &ic->ic_channels[ic->ic_nchans++];
 		c->ic_ieee = chan;
 		c->ic_maxregpower = channels[i].maxpwr;
 		c->ic_maxpower = 2*c->ic_maxregpower;
 
-		/* Save maximum allowed TX power for this channel. */
-		sc->maxpwr[chan] = channels[i].maxpwr;
-
 		if (n == 0) {	/* 2GHz band */
-			c->ic_freq = ieee80211_ieee2mhz(chan,
-			    IEEE80211_CHAN_G);
-
+			c->ic_freq = ieee80211_ieee2mhz(chan, IEEE80211_CHAN_G);
 			/* G =>'s B is supported */
 			c->ic_flags = IEEE80211_CHAN_B | nflags;
-
 			c = &ic->ic_channels[ic->ic_nchans++];
 			c[0] = c[-1];
 			c->ic_flags = IEEE80211_CHAN_G | nflags;
 		} else {	/* 5GHz band */
-			c->ic_freq = ieee80211_ieee2mhz(chan,
-			    IEEE80211_CHAN_A);
+			c->ic_freq = ieee80211_ieee2mhz(chan, IEEE80211_CHAN_A);
 			c->ic_flags = IEEE80211_CHAN_A | nflags;
 		}
+
+		/* Save maximum allowed TX power for this channel. */
+		sc->maxpwr[chan] = channels[i].maxpwr;
+
+		DPRINTF(sc, IWN_DEBUG_RESET,
+		    "add chan %d flags 0x%x maxpwr %d\n", chan,
+		    channels[i].flags, channels[i].maxpwr);
+
 #if 0	/* HT */
 		/* XXX no constraints on using HT20 */
 		/* add HT20, HT40 added separately */
@@ -1869,6 +1975,48 @@ iwn_read_eeprom_channels(struct iwn_soft
 	ieee80211_sort_channels(ic->ic_channels, ic->ic_nchans);
 }
 
+static struct iwn_eeprom_chan *
+iwn_find_eeprom_channel(struct iwn_softc *sc, struct ieee80211_channel *c)
+{
+	int i, j;
+
+	for (j = 0; j < 7; j++) {
+		for (i = 0; i < iwn_bands[j].nchan; i++) {
+			if (iwn_bands[j].chan[i] == c->ic_ieee)
+				return &sc->eeprom_channels[j][i];
+		}
+	}
+
+	return NULL;
+}
+
+/*
+ * Enforce flags read from EEPROM.
+ */
+static int
+iwn_setregdomain(struct ieee80211com *ic, struct ieee80211_regdomain *rd,
+    int nchan, struct ieee80211_channel chans[])
+{
+	struct iwn_softc *sc = ic->ic_ifp->if_softc;
+	int i;
+
+	for (i = 0; i < nchan; i++) {
+		struct ieee80211_channel *c = &chans[i];
+		struct iwn_eeprom_chan *channel;
+
+		channel = iwn_find_eeprom_channel(sc, c);
+		if (channel == NULL) {
+			if_printf(ic->ic_ifp,
+			    "%s: invalid channel %u freq %u/0x%x\n",
+			    __func__, c->ic_ieee, c->ic_freq, c->ic_flags);
+			return EINVAL;
+		}
+		c->ic_flags |= iwn_eeprom_channel_flags(channel);
+	}
+
+	return 0;
+}
+
 #define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
 
 static void
@@ -1929,7 +2077,9 @@ iwn_newassoc(struct ieee80211_node *ni, 
 static int
 iwn_media_change(struct ifnet *ifp)
 {
-	int error = ieee80211_media_change(ifp);
+	int error;

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



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