From owner-svn-src-stable-8@FreeBSD.ORG Sat Jun 18 12:00:49 2011 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EE0BD10657C2; Sat, 18 Jun 2011 12:00:49 +0000 (UTC) (envelope-from bschmidt@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id DBB068FC13; Sat, 18 Jun 2011 12:00:49 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p5IC0n2d039922; Sat, 18 Jun 2011 12:00:49 GMT (envelope-from bschmidt@svn.freebsd.org) Received: (from bschmidt@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p5IC0ngB039919; Sat, 18 Jun 2011 12:00:49 GMT (envelope-from bschmidt@svn.freebsd.org) Message-Id: <201106181200.p5IC0ngB039919@svn.freebsd.org> From: Bernhard Schmidt Date: Sat, 18 Jun 2011 12:00:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r223248 - stable/8/sys/dev/iwn X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 18 Jun 2011 12:00:50 -0000 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 #include +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 ***