From 8a374d5e4fae93bbf90dabe7487e22ad67f236b0 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 3 Feb 2012 13:06:57 -0800 Subject: [PATCH] --- yaml --- r: 290655 b: refs/heads/master c: 2f73d7c2b1f92e34aceee21740ec5fb9b8262ecb h: refs/heads/master i: 290653: 3d9ecb15d8fec787ac8d3347101afd57645e18a4 290651: e30f0b1e7d0cf7b14d9aa765b8d964efb0c684d9 290647: 1e080c024574ef72b3e5b7353f5cd925876c03cd 290639: d01f9b8878bd4d2613d269803993870282d63d01 290623: 4fd50bf44b784697be5842ded8f23b34d51b88aa v: v3 --- [refs] | 2 +- trunk/MAINTAINERS | 1 + trunk/drivers/net/wireless/ath/ath5k/ahb.c | 20 +- trunk/drivers/net/wireless/ath/ath5k/ath5k.h | 4 +- trunk/drivers/net/wireless/ath/ath5k/reset.c | 10 +- .../net/wireless/ath/ath6kl/cfg80211.c | 82 +- trunk/drivers/net/wireless/ath/ath9k/main.c | 10 + trunk/drivers/net/wireless/brcm80211/Kconfig | 17 +- .../net/wireless/brcm80211/brcmfmac/Makefile | 6 +- .../brcm80211/brcmfmac/bcmsdh_sdmmc.c | 14 +- .../net/wireless/brcm80211/brcmfmac/dhd_bus.h | 17 +- .../wireless/brcm80211/brcmfmac/dhd_linux.c | 59 +- .../wireless/brcm80211/brcmfmac/dhd_sdio.c | 32 +- .../net/wireless/brcm80211/brcmfmac/usb.c | 1623 ----------------- .../net/wireless/brcm80211/brcmfmac/usb.h | 84 - .../net/wireless/brcm80211/brcmfmac/usb_rdl.h | 75 - .../wireless/brcm80211/brcmfmac/wl_cfg80211.c | 13 +- .../net/wireless/brcm80211/brcmsmac/ampdu.c | 6 +- .../wireless/brcm80211/brcmsmac/mac80211_if.c | 4 +- .../net/wireless/brcm80211/brcmsmac/main.c | 1 + .../wireless/brcm80211/brcmsmac/phy/phy_n.c | 28 +- .../net/wireless/brcm80211/brcmsmac/srom.c | 14 +- .../net/wireless/iwlegacy/3945-debug.c | 6 - .../drivers/net/wireless/iwlegacy/3945-mac.c | 108 +- trunk/drivers/net/wireless/iwlegacy/3945.c | 133 +- trunk/drivers/net/wireless/iwlegacy/3945.h | 8 +- .../net/wireless/iwlegacy/4965-calib.c | 4 +- .../net/wireless/iwlegacy/4965-debug.c | 6 - .../drivers/net/wireless/iwlegacy/4965-mac.c | 589 ++---- trunk/drivers/net/wireless/iwlegacy/4965.c | 402 +++- trunk/drivers/net/wireless/iwlegacy/4965.h | 20 +- trunk/drivers/net/wireless/iwlegacy/common.c | 548 ++++-- trunk/drivers/net/wireless/iwlegacy/common.h | 224 ++- trunk/drivers/net/wireless/iwlegacy/debug.c | 260 ++- .../net/wireless/iwlwifi/iwl-testmode.c | 122 +- trunk/drivers/net/wireless/rt2x00/Kconfig | 2 +- trunk/drivers/net/wireless/rt2x00/rt2800lib.c | 4 +- trunk/drivers/net/wireless/rtlwifi/base.c | 6 +- .../wireless/rtlwifi/rtl8192c/phy_common.c | 156 +- .../net/wireless/rtlwifi/rtl8192de/phy.c | 187 +- .../net/wireless/rtlwifi/rtl8192se/fw.h | 3 +- .../net/wireless/rtlwifi/rtl8192se/phy.c | 40 +- .../net/wireless/rtlwifi/rtl8192se/sw.c | 3 +- trunk/drivers/net/wireless/wl1251/Makefile | 2 - trunk/drivers/net/wireless/wl1251/boot.c | 2 + trunk/drivers/net/wireless/wl1251/io.h | 9 +- trunk/drivers/net/wireless/wl1251/wl1251.h | 2 +- trunk/drivers/net/wireless/wl12xx/Makefile | 2 - trunk/drivers/net/wireless/wl12xx/acx.c | 17 +- trunk/drivers/net/wireless/wl12xx/acx.h | 149 +- trunk/drivers/net/wireless/wl12xx/boot.c | 105 +- trunk/drivers/net/wireless/wl12xx/boot.h | 10 + trunk/drivers/net/wireless/wl12xx/cmd.c | 143 +- trunk/drivers/net/wireless/wl12xx/cmd.h | 148 +- trunk/drivers/net/wireless/wl12xx/conf.h | 51 +- trunk/drivers/net/wireless/wl12xx/debug.h | 1 - trunk/drivers/net/wireless/wl12xx/debugfs.c | 241 +-- trunk/drivers/net/wireless/wl12xx/event.c | 154 +- trunk/drivers/net/wireless/wl12xx/event.h | 20 +- trunk/drivers/net/wireless/wl12xx/init.c | 55 +- trunk/drivers/net/wireless/wl12xx/io.c | 59 - trunk/drivers/net/wireless/wl12xx/io.h | 2 - trunk/drivers/net/wireless/wl12xx/main.c | 674 +++---- trunk/drivers/net/wireless/wl12xx/ps.c | 34 +- trunk/drivers/net/wireless/wl12xx/ps.h | 2 +- trunk/drivers/net/wireless/wl12xx/reg.h | 27 - trunk/drivers/net/wireless/wl12xx/rx.c | 2 +- trunk/drivers/net/wireless/wl12xx/scan.c | 56 +- trunk/drivers/net/wireless/wl12xx/scan.h | 2 +- trunk/drivers/net/wireless/wl12xx/sdio.c | 29 +- trunk/drivers/net/wireless/wl12xx/spi.c | 8 +- trunk/drivers/net/wireless/wl12xx/testmode.c | 50 - trunk/drivers/net/wireless/wl12xx/tx.c | 75 +- trunk/drivers/net/wireless/wl12xx/tx.h | 5 +- trunk/drivers/net/wireless/wl12xx/wl12xx.h | 46 +- .../net/wireless/wl12xx/wl12xx_80211.h | 2 +- trunk/include/linux/nl80211.h | 34 +- trunk/include/net/cfg80211.h | 70 +- trunk/net/mac80211/cfg.c | 146 +- trunk/net/mac80211/ieee80211_i.h | 2 +- trunk/net/mac80211/tx.c | 13 +- trunk/net/wireless/nl80211.c | 255 ++- 82 files changed, 2890 insertions(+), 4767 deletions(-) delete mode 100644 trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c delete mode 100644 trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.h delete mode 100644 trunk/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h diff --git a/[refs] b/[refs] index bd6374bfc3f4..b54ef7a124f5 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 0a8a721de97dce7477bfb89e7b4ca1eba425db34 +refs/heads/master: 2f73d7c2b1f92e34aceee21740ec5fb9b8262ecb diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 0b92435d9f51..48418c8475f0 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -1575,6 +1575,7 @@ F: drivers/net/ethernet/broadcom/tg3.* BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER M: Brett Rudley +M: Henry Ptasinski M: Roland Vossen M: Arend van Spriel M: Franky (Zhenhui) Lin diff --git a/trunk/drivers/net/wireless/ath/ath5k/ahb.c b/trunk/drivers/net/wireless/ath/ath5k/ahb.c index 8faa129da5a0..ee7ea572b065 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/ahb.c +++ b/trunk/drivers/net/wireless/ath/ath5k/ahb.c @@ -140,23 +140,23 @@ static int ath_ahb_probe(struct platform_device *pdev) if (bcfg->devid >= AR5K_SREV_AR2315_R6) { /* Enable WMAC AHB arbitration */ - reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL); + reg = __raw_readl((void __iomem *) AR5K_AR2315_AHB_ARB_CTL); reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN; - iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL); + __raw_writel(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL); /* Enable global WMAC swapping */ - reg = ioread32((void __iomem *) AR5K_AR2315_BYTESWAP); + reg = __raw_readl((void __iomem *) AR5K_AR2315_BYTESWAP); reg |= AR5K_AR2315_BYTESWAP_WMAC; - iowrite32(reg, (void __iomem *) AR5K_AR2315_BYTESWAP); + __raw_writel(reg, (void __iomem *) AR5K_AR2315_BYTESWAP); } else { /* Enable WMAC DMA access (assuming 5312 or 231x*/ /* TODO: check other platforms */ - reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE); + reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE); if (to_platform_device(ah->dev)->id == 0) reg |= AR5K_AR5312_ENABLE_WLAN0; else reg |= AR5K_AR5312_ENABLE_WLAN1; - iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE); + __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); /* * On a dual-band AR5312, the multiband radio is only @@ -203,17 +203,17 @@ static int ath_ahb_remove(struct platform_device *pdev) if (bcfg->devid >= AR5K_SREV_AR2315_R6) { /* Disable WMAC AHB arbitration */ - reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL); + reg = __raw_readl((void __iomem *) AR5K_AR2315_AHB_ARB_CTL); reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN; - iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL); + __raw_writel(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL); } else { /*Stop DMA access */ - reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE); + reg = __raw_readl((void __iomem *) AR5K_AR5312_ENABLE); if (to_platform_device(ah->dev)->id == 0) reg &= ~AR5K_AR5312_ENABLE_WLAN0; else reg &= ~AR5K_AR5312_ENABLE_WLAN1; - iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE); + __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); } ath5k_deinit_ah(ah); diff --git a/trunk/drivers/net/wireless/ath/ath5k/ath5k.h b/trunk/drivers/net/wireless/ath/ath5k/ath5k.h index 6640326f7005..c2b2518c2ecd 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/trunk/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1656,12 +1656,12 @@ static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg) static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) { - return ioread32(ath5k_ahb_reg(ah, reg)); + return __raw_readl(ath5k_ahb_reg(ah, reg)); } static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) { - iowrite32(val, ath5k_ahb_reg(ah, reg)); + __raw_writel(val, ath5k_ahb_reg(ah, reg)); } #else diff --git a/trunk/drivers/net/wireless/ath/ath5k/reset.c b/trunk/drivers/net/wireless/ath/ath5k/reset.c index 200f165c0c6d..250db40b751d 100644 --- a/trunk/drivers/net/wireless/ath/ath5k/reset.c +++ b/trunk/drivers/net/wireless/ath/ath5k/reset.c @@ -473,14 +473,14 @@ ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) } /* Put BB/MAC into reset */ - regval = ioread32(reg); - iowrite32(regval | val, reg); - regval = ioread32(reg); + regval = __raw_readl(reg); + __raw_writel(regval | val, reg); + regval = __raw_readl(reg); usleep_range(100, 150); /* Bring BB/MAC out of reset */ - iowrite32(regval & ~val, reg); - regval = ioread32(reg); + __raw_writel(regval & ~val, reg); + regval = __raw_readl(reg); /* * Reset configuration register (for hw byte-swap). Note that this diff --git a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c index 5370333883e4..d1922d8eb3bb 100644 --- a/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/trunk/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2269,11 +2269,25 @@ static int ath6kl_set_ap_probe_resp_ies(struct ath6kl_vif *vif, return ret; } -static int ath6kl_set_ies(struct ath6kl_vif *vif, - struct cfg80211_beacon_data *info) +static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *info, bool add) { - struct ath6kl *ar = vif->ar; + struct ath6kl *ar = ath6kl_priv(dev); + struct ath6kl_vif *vif = netdev_priv(dev); + struct ieee80211_mgmt *mgmt; + u8 *ies; + int ies_len; + struct wmi_connect_cmd p; int res; + int i, ret; + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: add=%d\n", __func__, add); + + if (!ath6kl_cfg80211_ready(vif)) + return -EIO; + + if (vif->next_mode != AP_NETWORK) + return -EOPNOTSUPP; if (info->beacon_ies) { res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, @@ -2283,14 +2297,12 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif, if (res) return res; } - if (info->proberesp_ies) { res = ath6kl_set_ap_probe_resp_ies(vif, info->proberesp_ies, info->proberesp_ies_len); if (res) return res; } - if (info->assocresp_ies) { res = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, WMI_FRAME_ASSOC_RESP, @@ -2300,30 +2312,8 @@ static int ath6kl_set_ies(struct ath6kl_vif *vif, return res; } - return 0; -} - -static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ap_settings *info) -{ - struct ath6kl *ar = ath6kl_priv(dev); - struct ath6kl_vif *vif = netdev_priv(dev); - struct ieee80211_mgmt *mgmt; - u8 *ies; - int ies_len; - struct wmi_connect_cmd p; - int res; - int i, ret; - - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__); - - if (!ath6kl_cfg80211_ready(vif)) - return -EIO; - - if (vif->next_mode != AP_NETWORK) - return -EOPNOTSUPP; - - res = ath6kl_set_ies(vif, &info->beacon); + if (!add) + return 0; ar->ap_mode_bkey.valid = false; @@ -2332,13 +2322,13 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, * info->dtim_period */ - if (info->beacon.head == NULL) + if (info->head == NULL) return -EINVAL; - mgmt = (struct ieee80211_mgmt *) info->beacon.head; + mgmt = (struct ieee80211_mgmt *) info->head; ies = mgmt->u.beacon.variable; - if (ies > info->beacon.head + info->beacon.head_len) + if (ies > info->head + info->head_len) return -EINVAL; - ies_len = info->beacon.head + info->beacon.head_len - ies; + ies_len = info->head + info->head_len - ies; if (info->ssid == NULL) return -EINVAL; @@ -2446,21 +2436,19 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, return 0; } -static int ath6kl_change_beacon(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_beacon_data *beacon) +static int ath6kl_add_beacon(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *info) { - struct ath6kl_vif *vif = netdev_priv(dev); - - if (!ath6kl_cfg80211_ready(vif)) - return -EIO; - - if (vif->next_mode != AP_NETWORK) - return -EOPNOTSUPP; + return ath6kl_ap_beacon(wiphy, dev, info, true); +} - return ath6kl_set_ies(vif, beacon); +static int ath6kl_set_beacon(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *info) +{ + return ath6kl_ap_beacon(wiphy, dev, info, false); } -static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev) +static int ath6kl_del_beacon(struct wiphy *wiphy, struct net_device *dev) { struct ath6kl *ar = ath6kl_priv(dev); struct ath6kl_vif *vif = netdev_priv(dev); @@ -2795,9 +2783,9 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { .resume = __ath6kl_cfg80211_resume, #endif .set_channel = ath6kl_set_channel, - .start_ap = ath6kl_start_ap, - .change_beacon = ath6kl_change_beacon, - .stop_ap = ath6kl_stop_ap, + .add_beacon = ath6kl_add_beacon, + .set_beacon = ath6kl_set_beacon, + .del_beacon = ath6kl_del_beacon, .del_station = ath6kl_del_station, .change_station = ath6kl_change_station, .remain_on_channel = ath6kl_remain_on_channel, diff --git a/trunk/drivers/net/wireless/ath/ath9k/main.c b/trunk/drivers/net/wireless/ath/ath9k/main.c index c81304d3ef14..ec82e926badc 100644 --- a/trunk/drivers/net/wireless/ath/ath9k/main.c +++ b/trunk/drivers/net/wireless/ath/ath9k/main.c @@ -371,8 +371,12 @@ static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, if (sc->sc_flags & SC_OP_INVALID) return -EIO; + ath9k_ps_wakeup(sc); + r = ath_reset_internal(sc, hchan, false); + ath9k_ps_restore(sc); + return r; } @@ -1583,6 +1587,12 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) ath9k_ps_wakeup(sc); mutex_lock(&sc->mutex); + /* + * Leave this as the first check because we need to turn on the + * radio if it was disabled before prior to processing the rest + * of the changes. Likewise we must only disable the radio towards + * the end. + */ if (changed & IEEE80211_CONF_CHANGE_IDLE) { sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE); if (sc->ps_idle) diff --git a/trunk/drivers/net/wireless/brcm80211/Kconfig b/trunk/drivers/net/wireless/brcm80211/Kconfig index c5104533e24e..cd6375de2a60 100644 --- a/trunk/drivers/net/wireless/brcm80211/Kconfig +++ b/trunk/drivers/net/wireless/brcm80211/Kconfig @@ -26,25 +26,16 @@ config BRCMFMAC it'll be called brcmfmac.ko. config BRCMFMAC_SDIO - bool "SDIO bus interface support for FullMAC driver" + bool "SDIO bus interface support for FullMAC" depends on MMC depends on BRCMFMAC select FW_LOADER default y ---help--- This option enables the SDIO bus interface support for Broadcom - IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to - use the driver for a SDIO wireless card. - -config BRCMFMAC_USB - bool "USB bus interface support for FullMAC driver" - depends on USB - depends on BRCMFMAC - select FW_LOADER - ---help--- - This option enables the USB bus interface support for Broadcom - IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to - use the driver for an USB wireless card. + FullMAC WLAN driver. + Say Y if you want to use brcmfmac for a compatible SDIO interface + wireless card. config BRCMDBG bool "Broadcom driver debug functions" diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/trunk/drivers/net/wireless/brcm80211/brcmfmac/Makefile index abb48032753b..9ca9ea1135ea 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/Makefile @@ -19,8 +19,6 @@ ccflags-y += \ -Idrivers/net/wireless/brcm80211/brcmfmac \ -Idrivers/net/wireless/brcm80211/include -ccflags-y += -D__CHECK_ENDIAN__ - obj-$(CONFIG_BRCMFMAC) += brcmfmac.o brcmfmac-objs += \ wl_cfg80211.o \ @@ -32,5 +30,5 @@ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ bcmsdh.o \ bcmsdh_sdmmc.o \ sdio_chip.o -brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ - usb.o + +ccflags-y += -D__CHECK_ENDIAN__ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index 83ca3cc2cccb..ac71adeece51 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c @@ -294,14 +294,13 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, struct sk_buff *pkt) { int status; - uint pkt_len; + uint pkt_len = pkt->len; bool fifo = (fix_inc == SDIOH_DATA_FIX); brcmf_dbg(TRACE, "Enter\n"); if (pkt == NULL) return -EINVAL; - pkt_len = pkt->len; brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait); if (brcmf_pm_resume_error(sdiodev)) @@ -489,7 +488,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, sdiodev->func[0] = func->card->sdio_func[0]; sdiodev->func[1] = func; sdiodev->bus_if = bus_if; - bus_if->bus_priv.sdio = sdiodev; + bus_if->bus_priv = sdiodev; bus_if->type = SDIO_BUS; bus_if->align = BRCMF_SDALIGN; dev_set_drvdata(&func->card->dev, sdiodev); @@ -530,7 +529,7 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func) if (func->num == 2) { bus_if = dev_get_drvdata(&func->dev); - sdiodev = bus_if->bus_priv.sdio; + sdiodev = bus_if->bus_priv; brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n"); brcmf_sdio_remove(sdiodev); dev_set_drvdata(&func->card->dev, NULL); @@ -597,14 +596,14 @@ static struct sdio_driver brcmf_sdmmc_driver = { #endif /* CONFIG_PM_SLEEP */ }; -void brcmf_sdio_exit(void) +static void __exit brcmf_sdio_exit(void) { brcmf_dbg(TRACE, "Enter\n"); sdio_unregister_driver(&brcmf_sdmmc_driver); } -int brcmf_sdio_init(void) +static int __init brcmf_sdio_init(void) { int ret; @@ -617,3 +616,6 @@ int brcmf_sdio_init(void) return ret; } + +module_init(brcmf_sdio_init); +module_exit(brcmf_sdio_exit); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index b7671b30692f..ad9be2410b59 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h @@ -39,11 +39,8 @@ struct dngl_stats { /* interface structure between common and bus layer */ struct brcmf_bus { u8 type; /* bus type */ - union { - struct brcmf_sdio_dev *sdio; - struct brcmf_usbdev *usb; - } bus_priv; - struct brcmf_pub *drvr; /* pointer to driver pub structure brcmf_pub */ + void *bus_priv; /* pointer to bus private structure */ + void *drvr; /* pointer to driver pub structure brcmf_pub */ enum brcmf_bus_state state; uint maxctl; /* Max size rxctl request from proto to bus */ bool drvr_up; /* Status flag of driver up/down */ @@ -105,14 +102,4 @@ extern int brcmf_bus_start(struct device *dev); extern int brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr); - -#ifdef CONFIG_BRCMFMAC_SDIO -extern void brcmf_sdio_exit(void); -extern int brcmf_sdio_init(void); -#endif -#ifdef CONFIG_BRCMFMAC_USB -extern void brcmf_usb_exit(void); -extern int brcmf_usb_init(void); -#endif - #endif /* _BRCMF_BUS_H_ */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index c4da05817443..db2df1f1e6b2 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c @@ -796,19 +796,18 @@ static int brcmf_netdev_open(struct net_device *ndev) { struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_pub *drvr = ifp->drvr; - struct brcmf_bus *bus_if = drvr->bus_if; u32 toe_ol; s32 ret = 0; brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx); if (ifp->idx == 0) { /* do it only for primary eth0 */ - /* If bus is not ready, can't continue */ - if (bus_if->state != BRCMF_BUS_DATA) { - brcmf_dbg(ERROR, "failed bus is not ready\n"); - return -EAGAIN; + /* try to bring up bus */ + ret = brcmf_bus_start(drvr->dev); + if (ret != 0) { + brcmf_dbg(ERROR, "failed with code %d\n", ret); + return -1; } - atomic_set(&drvr->pend_8021x_cnt, 0); memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN); @@ -980,6 +979,12 @@ int brcmf_bus_start(struct device *dev) return ret; } + /* If bus is not ready, can't come up */ + if (bus_if->state != BRCMF_BUS_DATA) { + brcmf_dbg(ERROR, "failed bus is not ready\n"); + return -ENODEV; + } + brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, iovbuf, @@ -1016,8 +1021,6 @@ int brcmf_bus_start(struct device *dev) if (ret < 0) return ret; - /* signal bus ready */ - bus_if->state = BRCMF_BUS_DATA; return 0; } @@ -1106,13 +1109,13 @@ void brcmf_detach(struct device *dev) if (drvr->iflist[i]) brcmf_del_if(drvr, i); + cancel_work_sync(&drvr->setmacaddr_work); + cancel_work_sync(&drvr->multicast_work); + brcmf_bus_detach(drvr); - if (drvr->prot) { - cancel_work_sync(&drvr->setmacaddr_work); - cancel_work_sync(&drvr->multicast_work); + if (drvr->prot) brcmf_proto_detach(drvr); - } bus_if->drvr = NULL; kfree(drvr); @@ -1180,35 +1183,3 @@ int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size) return ret; } #endif /* DEBUG */ - -static int __init brcmfmac_init(void) -{ - int ret = 0; - -#ifdef CONFIG_BRCMFMAC_SDIO - ret = brcmf_sdio_init(); - if (ret) - goto fail; -#endif -#ifdef CONFIG_BRCMFMAC_USB - ret = brcmf_usb_init(); - if (ret) - goto fail; -#endif - -fail: - return ret; -} - -static void __exit brcmfmac_exit(void) -{ -#ifdef CONFIG_BRCMFMAC_SDIO - brcmf_sdio_exit(); -#endif -#ifdef CONFIG_BRCMFMAC_USB - brcmf_usb_exit(); -#endif -} - -module_init(brcmfmac_init); -module_exit(brcmfmac_exit); diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 0b467b08604d..6e4b5e85a099 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -309,10 +309,10 @@ struct rte_console { /* Flags for SDH calls */ #define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED) -#define BRCMF_SDIO_FW_NAME "brcm/brcmfmac-sdio.bin" -#define BRCMF_SDIO_NV_NAME "brcm/brcmfmac-sdio.txt" -MODULE_FIRMWARE(BRCMF_SDIO_FW_NAME); -MODULE_FIRMWARE(BRCMF_SDIO_NV_NAME); +#define BRCMFMAC_FW_NAME "brcm/brcmfmac.bin" +#define BRCMFMAC_NV_NAME "brcm/brcmfmac.txt" +MODULE_FIRMWARE(BRCMFMAC_FW_NAME); +MODULE_FIRMWARE(BRCMFMAC_NV_NAME); #define BRCMF_IDLE_IMMEDIATE (-1) /* Enter idle immediately */ #define BRCMF_IDLE_ACTIVE 0 /* Do not request any SD clock change @@ -2277,7 +2277,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) uint retries; int err; struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; struct brcmf_sdio *bus = sdiodev->bus; brcmf_dbg(TRACE, "Enter\n"); @@ -2627,7 +2627,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt) int ret = -EBADE; uint datalen, prec; struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; struct brcmf_sdio *bus = sdiodev->bus; brcmf_dbg(TRACE, "Enter\n"); @@ -2869,7 +2869,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen) u8 doff = 0; int ret = -1; struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; struct brcmf_sdio *bus = sdiodev->bus; brcmf_dbg(TRACE, "Enter\n"); @@ -2978,7 +2978,7 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen) uint rxlen = 0; bool pending; struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; struct brcmf_sdio *bus = sdiodev->bus; brcmf_dbg(TRACE, "Enter\n"); @@ -3202,7 +3202,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus) brcmf_dbg(INFO, "Enter\n"); - ret = request_firmware(&bus->firmware, BRCMF_SDIO_FW_NAME, + ret = request_firmware(&bus->firmware, BRCMFMAC_FW_NAME, &bus->sdiodev->func[2]->dev); if (ret) { brcmf_dbg(ERROR, "Fail to request firmware %d\n", ret); @@ -3299,7 +3299,7 @@ static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus) char *bufp; int ret; - ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME, + ret = request_firmware(&bus->firmware, BRCMFMAC_NV_NAME, &bus->sdiodev->func[2]->dev); if (ret) { brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret); @@ -3389,7 +3389,7 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus) static int brcmf_sdbrcm_bus_init(struct device *dev) { struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv; struct brcmf_sdio *bus = sdiodev->bus; unsigned long timeout; uint retries = 0; @@ -3464,12 +3464,16 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, SBSDIO_WATERMARK, 8, &err); - } else { + + /* Set bus state according to enable result */ + bus_if->state = BRCMF_BUS_DATA; + } + + else { /* Disable F2 again */ enable = SDIO_FUNC_ENABLE_1; brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, enable, NULL); - ret = -ENODEV; } /* Restore previous clock setting */ @@ -3477,7 +3481,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); /* If we didn't come up, turn off backplane clock */ - if (!ret) + if (bus_if->state != BRCMF_BUS_DATA) brcmf_sdbrcm_clkctl(bus, CLK_NONE, false); exit: diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c deleted file mode 100644 index 934ed782620c..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ /dev/null @@ -1,1623 +0,0 @@ -/* - * Copyright (c) 2011 Broadcom Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "usb_rdl.h" -#include "usb.h" - -#define IOCTL_RESP_TIMEOUT 2000 - -#define BRCMF_USB_SYNC_TIMEOUT 300 /* ms */ -#define BRCMF_USB_DLIMAGE_SPINWAIT 100 /* in unit of ms */ -#define BRCMF_USB_DLIMAGE_LIMIT 500 /* spinwait limit (ms) */ - -#define BRCMF_POSTBOOT_ID 0xA123 /* ID to detect if dongle - has boot up */ -#define BRCMF_USB_RESETCFG_SPINWAIT 1 /* wait after resetcfg (ms) */ - -#define BRCMF_USB_NRXQ 50 -#define BRCMF_USB_NTXQ 50 - -#define CONFIGDESC(usb) (&((usb)->actconfig)->desc) -#define IFPTR(usb, idx) ((usb)->actconfig->interface[(idx)]) -#define IFALTS(usb, idx) (IFPTR((usb), (idx))->altsetting[0]) -#define IFDESC(usb, idx) IFALTS((usb), (idx)).desc -#define IFEPDESC(usb, idx, ep) (IFALTS((usb), (idx)).endpoint[(ep)]).desc - -#define CONTROL_IF 0 -#define BULK_IF 0 - -#define BRCMF_USB_CBCTL_WRITE 0 -#define BRCMF_USB_CBCTL_READ 1 -#define BRCMF_USB_MAX_PKT_SIZE 1600 - -#define BRCMF_USB_FW_NAME "brcm/brcmfmac-usb.bin" - -enum usbdev_suspend_state { - USBOS_SUSPEND_STATE_DEVICE_ACTIVE = 0, /* Device is busy, won't allow - suspend */ - USBOS_SUSPEND_STATE_SUSPEND_PENDING, /* Device is idle, can be - * suspended. Wating PM to - * suspend the device - */ - USBOS_SUSPEND_STATE_SUSPENDED /* Device suspended */ -}; - -struct brcmf_usb_probe_info { - void *usbdev_info; - struct usb_device *usb; /* USB device pointer from OS */ - uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2; - int intr_size; /* Size of interrupt message */ - int interval; /* Interrupt polling interval */ - int vid; - int pid; - enum usb_device_speed device_speed; - enum usbdev_suspend_state suspend_state; - struct usb_interface *intf; -}; -static struct brcmf_usb_probe_info usbdev_probe_info; - -struct brcmf_usb_image { - void *data; - u32 len; -}; -static struct brcmf_usb_image g_image = { NULL, 0 }; - -struct intr_transfer_buf { - u32 notification; - u32 reserved; -}; - -struct brcmf_usbdev_info { - struct brcmf_usbdev bus_pub; /* MUST BE FIRST */ - spinlock_t qlock; - struct list_head rx_freeq; - struct list_head rx_postq; - struct list_head tx_freeq; - struct list_head tx_postq; - enum usbdev_suspend_state suspend_state; - uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2; - - bool activity; - int rx_low_watermark; - int tx_low_watermark; - int tx_high_watermark; - bool txoff; - bool rxoff; - bool txoverride; - - struct brcmf_usbreq *tx_reqs; - struct brcmf_usbreq *rx_reqs; - - u8 *image; /* buffer for combine fw and nvram */ - int image_len; - - wait_queue_head_t wait; - bool waitdone; - int sync_urb_status; - - struct usb_device *usbdev; - struct device *dev; - enum usb_device_speed device_speed; - - int ctl_in_pipe, ctl_out_pipe; - struct urb *ctl_urb; /* URB for control endpoint */ - struct usb_ctrlrequest ctl_write; - struct usb_ctrlrequest ctl_read; - u32 ctl_urb_actual_length; - int ctl_urb_status; - int ctl_completed; - wait_queue_head_t ioctl_resp_wait; - wait_queue_head_t ctrl_wait; - ulong ctl_op; - - bool rxctl_deferrespok; - - struct urb *bulk_urb; /* used for FW download */ - struct urb *intr_urb; /* URB for interrupt endpoint */ - int intr_size; /* Size of interrupt message */ - int interval; /* Interrupt polling interval */ - struct intr_transfer_buf intr; /* Data buffer for interrupt endpoint */ - - struct brcmf_usb_probe_info probe_info; - -}; - -static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, - struct brcmf_usbreq *req); - -MODULE_AUTHOR("Broadcom Corporation"); -MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac usb driver."); -MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac usb cards"); -MODULE_LICENSE("Dual BSD/GPL"); - -static struct brcmf_usbdev *brcmf_usb_get_buspub(struct device *dev) -{ - struct brcmf_bus *bus_if = dev_get_drvdata(dev); - return bus_if->bus_priv.usb; -} - -static struct brcmf_usbdev_info *brcmf_usb_get_businfo(struct device *dev) -{ - return brcmf_usb_get_buspub(dev)->devinfo; -} - -#if 0 -static void -brcmf_usb_txflowcontrol(struct brcmf_usbdev_info *devinfo, bool onoff) -{ - dhd_txflowcontrol(devinfo->bus_pub.netdev, 0, onoff); -} -#endif - -static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo, - uint *condition, bool *pending) -{ - DECLARE_WAITQUEUE(wait, current); - int timeout = IOCTL_RESP_TIMEOUT; - - /* Convert timeout in millsecond to jiffies */ - timeout = msecs_to_jiffies(timeout); - /* Wait until control frame is available */ - add_wait_queue(&devinfo->ioctl_resp_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - smp_mb(); - while (!(*condition) && (!signal_pending(current) && timeout)) { - timeout = schedule_timeout(timeout); - /* Wait until control frame is available */ - smp_mb(); - } - - if (signal_pending(current)) - *pending = true; - - set_current_state(TASK_RUNNING); - remove_wait_queue(&devinfo->ioctl_resp_wait, &wait); - - return timeout; -} - -static int brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo) -{ - if (waitqueue_active(&devinfo->ioctl_resp_wait)) - wake_up_interruptible(&devinfo->ioctl_resp_wait); - - return 0; -} - -static void -brcmf_usb_ctl_complete(struct brcmf_usbdev_info *devinfo, int type, int status) -{ - - if (unlikely(devinfo == NULL)) - return; - - if (type == BRCMF_USB_CBCTL_READ) { - if (status == 0) - devinfo->bus_pub.stats.rx_ctlpkts++; - else - devinfo->bus_pub.stats.rx_ctlerrs++; - } else if (type == BRCMF_USB_CBCTL_WRITE) { - if (status == 0) - devinfo->bus_pub.stats.tx_ctlpkts++; - else - devinfo->bus_pub.stats.tx_ctlerrs++; - } - - devinfo->ctl_urb_status = status; - devinfo->ctl_completed = true; - brcmf_usb_ioctl_resp_wake(devinfo); -} - -static void -brcmf_usb_ctlread_complete(struct urb *urb) -{ - struct brcmf_usbdev_info *devinfo = - (struct brcmf_usbdev_info *)urb->context; - - devinfo->ctl_urb_actual_length = urb->actual_length; - brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_READ, - urb->status); -} - -static void -brcmf_usb_ctlwrite_complete(struct urb *urb) -{ - struct brcmf_usbdev_info *devinfo = - (struct brcmf_usbdev_info *)urb->context; - - brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_WRITE, - urb->status); -} - -static int brcmf_usb_pnp(struct brcmf_usbdev_info *devinfo, uint state) -{ - return 0; -} - -static int -brcmf_usb_send_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len) -{ - int ret; - u16 size; - - if (devinfo == NULL || buf == NULL || - len == 0 || devinfo->ctl_urb == NULL) - return -EINVAL; - - /* If the USB/HSIC bus in sleep state, wake it up */ - if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED) - if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) { - brcmf_dbg(ERROR, "Could not Resume the bus!\n"); - return -EIO; - } - - devinfo->activity = true; - size = len; - devinfo->ctl_write.wLength = cpu_to_le16p(&size); - devinfo->ctl_urb->transfer_buffer_length = size; - devinfo->ctl_urb_status = 0; - devinfo->ctl_urb_actual_length = 0; - - usb_fill_control_urb(devinfo->ctl_urb, - devinfo->usbdev, - devinfo->ctl_out_pipe, - (unsigned char *) &devinfo->ctl_write, - buf, size, - (usb_complete_t)brcmf_usb_ctlwrite_complete, - devinfo); - - ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC); - if (ret < 0) - brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret); - - return ret; -} - -static int -brcmf_usb_recv_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len) -{ - int ret; - u16 size; - - if ((devinfo == NULL) || (buf == NULL) || (len == 0) - || (devinfo->ctl_urb == NULL)) - return -EINVAL; - - size = len; - devinfo->ctl_read.wLength = cpu_to_le16p(&size); - devinfo->ctl_urb->transfer_buffer_length = size; - - if (devinfo->rxctl_deferrespok) { - /* BMAC model */ - devinfo->ctl_read.bRequestType = USB_DIR_IN - | USB_TYPE_VENDOR | USB_RECIP_INTERFACE; - devinfo->ctl_read.bRequest = DL_DEFER_RESP_OK; - } else { - /* full dongle model */ - devinfo->ctl_read.bRequestType = USB_DIR_IN - | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - devinfo->ctl_read.bRequest = 1; - } - - usb_fill_control_urb(devinfo->ctl_urb, - devinfo->usbdev, - devinfo->ctl_in_pipe, - (unsigned char *) &devinfo->ctl_read, - buf, size, - (usb_complete_t)brcmf_usb_ctlread_complete, - devinfo); - - ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC); - if (ret < 0) - brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret); - - return ret; -} - -static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len) -{ - int err = 0; - int timeout = 0; - bool pending; - struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); - - if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) { - /* TODO: handle suspend/resume */ - return -EIO; - } - - if (test_and_set_bit(0, &devinfo->ctl_op)) - return -EIO; - - err = brcmf_usb_send_ctl(devinfo, buf, len); - if (err) { - brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len); - return err; - } - - devinfo->ctl_completed = false; - timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed, - &pending); - clear_bit(0, &devinfo->ctl_op); - if (!timeout) { - brcmf_dbg(ERROR, "Txctl wait timed out\n"); - err = -EIO; - } - return err; -} - -static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len) -{ - int err = 0; - int timeout = 0; - bool pending; - struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); - - if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) { - /* TODO: handle suspend/resume */ - return -EIO; - } - if (test_and_set_bit(0, &devinfo->ctl_op)) - return -EIO; - - err = brcmf_usb_recv_ctl(devinfo, buf, len); - if (err) { - brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len); - return err; - } - devinfo->ctl_completed = false; - timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed, - &pending); - err = devinfo->ctl_urb_status; - clear_bit(0, &devinfo->ctl_op); - if (!timeout) { - brcmf_dbg(ERROR, "rxctl wait timed out\n"); - err = -EIO; - } - if (!err) - return devinfo->ctl_urb_actual_length; - else - return err; -} - -static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo, - struct list_head *q) -{ - unsigned long flags; - struct brcmf_usbreq *req; - spin_lock_irqsave(&devinfo->qlock, flags); - if (list_empty(q)) { - spin_unlock_irqrestore(&devinfo->qlock, flags); - return NULL; - } - req = list_entry(q->next, struct brcmf_usbreq, list); - list_del_init(q->next); - spin_unlock_irqrestore(&devinfo->qlock, flags); - return req; - -} - -static void brcmf_usb_enq(struct brcmf_usbdev_info *devinfo, - struct list_head *q, struct brcmf_usbreq *req) -{ - unsigned long flags; - spin_lock_irqsave(&devinfo->qlock, flags); - list_add_tail(&req->list, q); - spin_unlock_irqrestore(&devinfo->qlock, flags); -} - -static struct brcmf_usbreq * -brcmf_usbdev_qinit(struct list_head *q, int qsize) -{ - int i; - struct brcmf_usbreq *req, *reqs; - - reqs = kzalloc(sizeof(struct brcmf_usbreq) * qsize, GFP_ATOMIC); - if (reqs == NULL) { - brcmf_dbg(ERROR, "fail to allocate memory!\n"); - return NULL; - } - req = reqs; - - for (i = 0; i < qsize; i++) { - req->urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!req->urb) - goto fail; - - INIT_LIST_HEAD(&req->list); - list_add_tail(&req->list, q); - req++; - } - return reqs; -fail: - brcmf_dbg(ERROR, "fail!\n"); - while (!list_empty(q)) { - req = list_entry(q->next, struct brcmf_usbreq, list); - if (req && req->urb) - usb_free_urb(req->urb); - list_del(q->next); - } - return NULL; - -} - -static void brcmf_usb_free_q(struct list_head *q, bool pending) -{ - struct brcmf_usbreq *req, *next; - int i = 0; - list_for_each_entry_safe(req, next, q, list) { - if (!req || !req->urb) { - brcmf_dbg(ERROR, "bad req\n"); - break; - } - i++; - if (pending) { - usb_kill_urb(req->urb); - } else { - usb_free_urb(req->urb); - list_del_init(&req->list); - } - } -} - -static void brcmf_usb_del_fromq(struct brcmf_usbdev_info *devinfo, - struct brcmf_usbreq *req) -{ - unsigned long flags; - - spin_lock_irqsave(&devinfo->qlock, flags); - list_del_init(&req->list); - spin_unlock_irqrestore(&devinfo->qlock, flags); -} - - -static void brcmf_usb_tx_complete(struct urb *urb) -{ - struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context; - struct brcmf_usbdev_info *devinfo = req->devinfo; - - brcmf_usb_del_fromq(devinfo, req); - if (urb->status == 0) - devinfo->bus_pub.stats.tx_packets++; - else - devinfo->bus_pub.stats.tx_errors++; - - dev_kfree_skb(req->skb); - req->skb = NULL; - brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); - -} - -static void brcmf_usb_rx_complete(struct urb *urb) -{ - struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context; - struct brcmf_usbdev_info *devinfo = req->devinfo; - struct sk_buff *skb; - int ifidx = 0; - - brcmf_usb_del_fromq(devinfo, req); - skb = req->skb; - req->skb = NULL; - - if (urb->status == 0) { - devinfo->bus_pub.stats.rx_packets++; - } else { - devinfo->bus_pub.stats.rx_errors++; - dev_kfree_skb(skb); - brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); - return; - } - - if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) { - skb_put(skb, urb->actual_length); - if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) { - brcmf_dbg(ERROR, "rx protocol error\n"); - brcmu_pkt_buf_free_skb(skb); - devinfo->bus_pub.bus->dstats.rx_errors++; - } else { - brcmf_rx_packet(devinfo->dev, ifidx, skb); - brcmf_usb_rx_refill(devinfo, req); - } - } else { - dev_kfree_skb(skb); - } - return; - -} - -static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, - struct brcmf_usbreq *req) -{ - struct sk_buff *skb; - int ret; - - if (!req || !devinfo) - return; - - skb = dev_alloc_skb(devinfo->bus_pub.bus_mtu); - if (!skb) { - brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); - return; - } - req->skb = skb; - - usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe, - skb->data, skb_tailroom(skb), brcmf_usb_rx_complete, - req); - req->urb->transfer_flags |= URB_ZERO_PACKET; - req->devinfo = devinfo; - - ret = usb_submit_urb(req->urb, GFP_ATOMIC); - if (ret == 0) { - brcmf_usb_enq(devinfo, &devinfo->rx_postq, req); - } else { - dev_kfree_skb(req->skb); - req->skb = NULL; - brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req); - } - return; -} - -static void brcmf_usb_rx_fill_all(struct brcmf_usbdev_info *devinfo) -{ - struct brcmf_usbreq *req; - - if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) { - brcmf_dbg(ERROR, "bus is not up\n"); - return; - } - while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq)) != NULL) - brcmf_usb_rx_refill(devinfo, req); -} - -static void -brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state) -{ - struct brcmf_bus *bcmf_bus = devinfo->bus_pub.bus; - int old_state; - - - if (devinfo->bus_pub.state == state) - return; - - old_state = devinfo->bus_pub.state; - brcmf_dbg(TRACE, "dbus state change from %d to to %d\n", - old_state, state); - - /* Don't update state if it's PnP firmware re-download */ - if (state != BCMFMAC_USB_STATE_PNP_FWDL) /* TODO */ - devinfo->bus_pub.state = state; - - if ((old_state == BCMFMAC_USB_STATE_SLEEP) - && (state == BCMFMAC_USB_STATE_UP)) { - brcmf_usb_rx_fill_all(devinfo); - } - - /* update state of upper layer */ - if (state == BCMFMAC_USB_STATE_DOWN) { - brcmf_dbg(INFO, "DBUS is down\n"); - bcmf_bus->state = BRCMF_BUS_DOWN; - } else { - brcmf_dbg(INFO, "DBUS current state=%d\n", state); - } -} - -static void -brcmf_usb_intr_complete(struct urb *urb) -{ - struct brcmf_usbdev_info *devinfo = - (struct brcmf_usbdev_info *)urb->context; - bool killed; - - if (devinfo == NULL) - return; - - if (unlikely(urb->status)) { - if (devinfo->suspend_state == - USBOS_SUSPEND_STATE_SUSPEND_PENDING) - killed = true; - - if ((urb->status == -ENOENT && (!killed)) - || urb->status == -ESHUTDOWN || - urb->status == -ENODEV) { - brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN); - } - } - - if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN) { - brcmf_dbg(ERROR, "intr cb when DBUS down, ignoring\n"); - return; - } - - if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) - usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC); -} - -static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb) -{ - struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); - struct brcmf_usbreq *req; - int ret; - - if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) { - /* TODO: handle suspend/resume */ - return -EIO; - } - - req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq); - if (!req) { - brcmf_dbg(ERROR, "no req to send\n"); - return -ENOMEM; - } - if (!req->urb) { - brcmf_dbg(ERROR, "no urb for req %p\n", req); - return -ENOBUFS; - } - - req->skb = skb; - req->devinfo = devinfo; - usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe, - skb->data, skb->len, brcmf_usb_tx_complete, req); - req->urb->transfer_flags |= URB_ZERO_PACKET; - ret = usb_submit_urb(req->urb, GFP_ATOMIC); - if (!ret) { - brcmf_usb_enq(devinfo, &devinfo->tx_postq, req); - } else { - req->skb = NULL; - brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req); - } - - return ret; -} - - -static int brcmf_usb_up(struct device *dev) -{ - struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); - u16 ifnum; - - if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) - return 0; - - if (devinfo == NULL) - return -EINVAL; - - /* If the USB/HSIC bus in sleep state, wake it up */ - if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED) { - if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) { - brcmf_dbg(ERROR, "Could not Resume the bus!\n"); - return -EIO; - } - } - devinfo->activity = true; - - /* Success, indicate devinfo is fully up */ - brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_UP); - - if (devinfo->intr_urb) { - int ret; - - usb_fill_int_urb(devinfo->intr_urb, devinfo->usbdev, - devinfo->intr_pipe, - &devinfo->intr, - devinfo->intr_size, - (usb_complete_t)brcmf_usb_intr_complete, - devinfo, - devinfo->interval); - - ret = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC); - if (ret) { - brcmf_dbg(ERROR, "USB_SUBMIT_URB failed with status %d\n", - ret); - return -EINVAL; - } - } - - if (devinfo->ctl_urb) { - devinfo->ctl_in_pipe = usb_rcvctrlpipe(devinfo->usbdev, 0); - devinfo->ctl_out_pipe = usb_sndctrlpipe(devinfo->usbdev, 0); - - ifnum = IFDESC(devinfo->usbdev, CONTROL_IF).bInterfaceNumber; - - /* CTL Write */ - devinfo->ctl_write.bRequestType = - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - devinfo->ctl_write.bRequest = 0; - devinfo->ctl_write.wValue = cpu_to_le16(0); - devinfo->ctl_write.wIndex = cpu_to_le16p(&ifnum); - - /* CTL Read */ - devinfo->ctl_read.bRequestType = - USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - devinfo->ctl_read.bRequest = 1; - devinfo->ctl_read.wValue = cpu_to_le16(0); - devinfo->ctl_read.wIndex = cpu_to_le16p(&ifnum); - } - brcmf_usb_rx_fill_all(devinfo); - return 0; -} - -static void brcmf_usb_down(struct device *dev) -{ - struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); - - if (devinfo == NULL) - return; - - brcmf_dbg(TRACE, "enter\n"); - if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN) - return; - - brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN); - if (devinfo->intr_urb) - usb_kill_urb(devinfo->intr_urb); - - if (devinfo->ctl_urb) - usb_kill_urb(devinfo->ctl_urb); - - if (devinfo->bulk_urb) - usb_kill_urb(devinfo->bulk_urb); - brcmf_usb_free_q(&devinfo->tx_postq, true); - - brcmf_usb_free_q(&devinfo->rx_postq, true); -} - -static int -brcmf_usb_sync_wait(struct brcmf_usbdev_info *devinfo, u16 time) -{ - int ret; - int err = 0; - int ms = time; - - ret = wait_event_interruptible_timeout(devinfo->wait, - devinfo->waitdone == true, (ms * HZ / 1000)); - - if ((devinfo->waitdone == false) || (devinfo->sync_urb_status)) { - brcmf_dbg(ERROR, "timeout(%d) or urb err=%d\n", - ret, devinfo->sync_urb_status); - err = -EINVAL; - } - devinfo->waitdone = false; - return err; -} - -static void -brcmf_usb_sync_complete(struct urb *urb) -{ - struct brcmf_usbdev_info *devinfo = - (struct brcmf_usbdev_info *)urb->context; - - devinfo->waitdone = true; - wake_up_interruptible(&devinfo->wait); - devinfo->sync_urb_status = urb->status; -} - -static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd, - void *buffer, int buflen) -{ - int ret = 0; - char *tmpbuf; - u16 size; - - if ((!devinfo) || (devinfo->ctl_urb == NULL)) - return false; - - tmpbuf = kmalloc(buflen, GFP_ATOMIC); - if (!tmpbuf) - return false; - - size = buflen; - devinfo->ctl_urb->transfer_buffer_length = size; - - devinfo->ctl_read.wLength = cpu_to_le16p(&size); - devinfo->ctl_read.bRequestType = USB_DIR_IN | USB_TYPE_VENDOR | - USB_RECIP_INTERFACE; - devinfo->ctl_read.bRequest = cmd; - - usb_fill_control_urb(devinfo->ctl_urb, - devinfo->usbdev, - usb_rcvctrlpipe(devinfo->usbdev, 0), - (unsigned char *) &devinfo->ctl_read, - (void *) tmpbuf, size, - (usb_complete_t)brcmf_usb_sync_complete, devinfo); - - ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC); - if (ret < 0) { - brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret); - kfree(tmpbuf); - return false; - } - - ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT); - memcpy(buffer, tmpbuf, buflen); - kfree(tmpbuf); - - return (ret == 0); -} - -static bool -brcmf_usb_dlneeded(struct brcmf_usbdev_info *devinfo) -{ - struct bootrom_id_le id; - u32 chipid, chiprev; - - brcmf_dbg(TRACE, "enter\n"); - - if (devinfo == NULL) - return false; - - /* Check if firmware downloaded already by querying runtime ID */ - id.chip = cpu_to_le32(0xDEAD); - brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, - sizeof(struct bootrom_id_le)); - - chipid = le32_to_cpu(id.chip); - chiprev = le32_to_cpu(id.chiprev); - - if ((chipid & 0x4300) == 0x4300) - brcmf_dbg(INFO, "chip %x rev 0x%x\n", chipid, chiprev); - else - brcmf_dbg(INFO, "chip %d rev 0x%x\n", chipid, chiprev); - if (chipid == BRCMF_POSTBOOT_ID) { - brcmf_dbg(INFO, "firmware already downloaded\n"); - brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id, - sizeof(struct bootrom_id_le)); - return false; - } else { - devinfo->bus_pub.attrib.devid = chipid; - devinfo->bus_pub.attrib.chiprev = chiprev; - } - return true; -} - -static int -brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo) -{ - struct bootrom_id_le id; - u16 wait = 0, wait_time; - - brcmf_dbg(TRACE, "enter\n"); - - if (devinfo == NULL) - return -EINVAL; - - /* Give dongle chance to boot */ - wait_time = BRCMF_USB_DLIMAGE_SPINWAIT; - while (wait < BRCMF_USB_DLIMAGE_LIMIT) { - mdelay(wait_time); - wait += wait_time; - id.chip = cpu_to_le32(0xDEAD); /* Get the ID */ - brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id, - sizeof(struct bootrom_id_le)); - if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) - break; - } - - if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) { - brcmf_dbg(INFO, "download done %d ms postboot chip 0x%x/rev 0x%x\n", - wait, le32_to_cpu(id.chip), le32_to_cpu(id.chiprev)); - - brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id, - sizeof(struct bootrom_id_le)); - - /* XXX this wait may not be necessary */ - mdelay(BRCMF_USB_RESETCFG_SPINWAIT); - return 0; - } else { - brcmf_dbg(ERROR, "Cannot talk to Dongle. Firmware is not UP, %d ms\n", - wait); - return -EINVAL; - } -} - - -static int -brcmf_usb_dl_send_bulk(struct brcmf_usbdev_info *devinfo, void *buffer, int len) -{ - int ret; - - if ((devinfo == NULL) || (devinfo->bulk_urb == NULL)) - return -EINVAL; - - /* Prepare the URB */ - usb_fill_bulk_urb(devinfo->bulk_urb, devinfo->usbdev, - devinfo->tx_pipe, buffer, len, - (usb_complete_t)brcmf_usb_sync_complete, devinfo); - - devinfo->bulk_urb->transfer_flags |= URB_ZERO_PACKET; - - ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC); - if (ret) { - brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret); - return ret; - } - ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT); - return ret; -} - -static int -brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen) -{ - unsigned int sendlen, sent, dllen; - char *bulkchunk = NULL, *dlpos; - struct rdl_state_le state; - u32 rdlstate, rdlbytes; - int err = 0; - brcmf_dbg(TRACE, "fw %p, len %d\n", fw, fwlen); - - bulkchunk = kmalloc(RDL_CHUNK, GFP_ATOMIC); - if (bulkchunk == NULL) { - err = -ENOMEM; - goto fail; - } - - /* 1) Prepare USB boot loader for runtime image */ - brcmf_usb_dl_cmd(devinfo, DL_START, &state, - sizeof(struct rdl_state_le)); - - rdlstate = le32_to_cpu(state.state); - rdlbytes = le32_to_cpu(state.bytes); - - /* 2) Check we are in the Waiting state */ - if (rdlstate != DL_WAITING) { - brcmf_dbg(ERROR, "Failed to DL_START\n"); - err = -EINVAL; - goto fail; - } - sent = 0; - dlpos = fw; - dllen = fwlen; - - /* Get chip id and rev */ - while (rdlbytes != dllen) { - /* Wait until the usb device reports it received all - * the bytes we sent */ - if ((rdlbytes == sent) && (rdlbytes != dllen)) { - if ((dllen-sent) < RDL_CHUNK) - sendlen = dllen-sent; - else - sendlen = RDL_CHUNK; - - /* simply avoid having to send a ZLP by ensuring we - * never have an even - * multiple of 64 - */ - if (!(sendlen % 64)) - sendlen -= 4; - - /* send data */ - memcpy(bulkchunk, dlpos, sendlen); - if (brcmf_usb_dl_send_bulk(devinfo, bulkchunk, - sendlen)) { - brcmf_dbg(ERROR, "send_bulk failed\n"); - err = -EINVAL; - goto fail; - } - - dlpos += sendlen; - sent += sendlen; - } - if (!brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state, - sizeof(struct rdl_state_le))) { - brcmf_dbg(ERROR, "DL_GETSTATE Failed xxxx\n"); - err = -EINVAL; - goto fail; - } - - rdlstate = le32_to_cpu(state.state); - rdlbytes = le32_to_cpu(state.bytes); - - /* restart if an error is reported */ - if (rdlstate == DL_BAD_HDR || rdlstate == DL_BAD_CRC) { - brcmf_dbg(ERROR, "Bad Hdr or Bad CRC state %d\n", - rdlstate); - err = -EINVAL; - goto fail; - } - } - -fail: - kfree(bulkchunk); - brcmf_dbg(TRACE, "err=%d\n", err); - return err; -} - -static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len) -{ - int err; - - brcmf_dbg(TRACE, "enter\n"); - - if (devinfo == NULL) - return -EINVAL; - - if (devinfo->bus_pub.attrib.devid == 0xDEAD) - return -EINVAL; - - err = brcmf_usb_dl_writeimage(devinfo, fw, len); - if (err == 0) - devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_DONE; - else - devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_PENDING; - brcmf_dbg(TRACE, "exit: err=%d\n", err); - - return err; -} - -static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo) -{ - struct rdl_state_le state; - - brcmf_dbg(TRACE, "enter\n"); - if (!devinfo) - return -EINVAL; - - if (devinfo->bus_pub.attrib.devid == 0xDEAD) - return -EINVAL; - - /* Check we are runnable */ - brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state, - sizeof(struct rdl_state_le)); - - /* Start the image */ - if (state.state == cpu_to_le32(DL_RUNNABLE)) { - if (!brcmf_usb_dl_cmd(devinfo, DL_GO, &state, - sizeof(struct rdl_state_le))) - return -ENODEV; - if (brcmf_usb_resetcfg(devinfo)) - return -ENODEV; - /* The Dongle may go for re-enumeration. */ - } else { - brcmf_dbg(ERROR, "Dongle not runnable\n"); - return -EINVAL; - } - brcmf_dbg(TRACE, "exit\n"); - return 0; -} - -static bool brcmf_usb_chip_support(int chipid, int chiprev) -{ - switch(chipid) { - case 43235: - case 43236: - case 43238: - return (chiprev == 3); - default: - break; - } - return false; -} - -static int -brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo) -{ - struct brcmf_usb_attrib *attr; - int err; - - brcmf_dbg(TRACE, "enter\n"); - if (devinfo == NULL) - return -ENODEV; - - attr = &devinfo->bus_pub.attrib; - - if (!brcmf_usb_chip_support(attr->devid, attr->chiprev)) { - brcmf_dbg(ERROR, "unsupported chip %d rev %d\n", - attr->devid, attr->chiprev); - return -EINVAL; - } - - if (!devinfo->image) { - brcmf_dbg(ERROR, "No firmware!\n"); - return -ENOENT; - } - - err = brcmf_usb_dlstart(devinfo, - devinfo->image, devinfo->image_len); - if (err == 0) - err = brcmf_usb_dlrun(devinfo); - return err; -} - - -static void brcmf_usb_detach(const struct brcmf_usbdev *bus_pub) -{ - struct brcmf_usbdev_info *devinfo = - (struct brcmf_usbdev_info *)bus_pub; - - brcmf_dbg(TRACE, "devinfo %p\n", devinfo); - - /* store the image globally */ - g_image.data = devinfo->image; - g_image.len = devinfo->image_len; - - /* free the URBS */ - brcmf_usb_free_q(&devinfo->rx_freeq, false); - brcmf_usb_free_q(&devinfo->tx_freeq, false); - - usb_free_urb(devinfo->intr_urb); - usb_free_urb(devinfo->ctl_urb); - usb_free_urb(devinfo->bulk_urb); - - kfree(devinfo->tx_reqs); - kfree(devinfo->rx_reqs); - kfree(devinfo); -} - -#define TRX_MAGIC 0x30524448 /* "HDR0" */ -#define TRX_VERSION 1 /* Version 1 */ -#define TRX_MAX_LEN 0x3B0000 /* Max length */ -#define TRX_NO_HEADER 1 /* Do not write TRX header */ -#define TRX_MAX_OFFSET 3 /* Max number of individual files */ -#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed image */ - -struct trx_header_le { - __le32 magic; /* "HDR0" */ - __le32 len; /* Length of file including header */ - __le32 crc32; /* CRC from flag_version to end of file */ - __le32 flag_version; /* 0:15 flags, 16:31 version */ - __le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of - * header */ -}; - -static int check_file(const u8 *headers) -{ - struct trx_header_le *trx; - int actual_len = -1; - - /* Extract trx header */ - trx = (struct trx_header_le *) headers; - if (trx->magic != cpu_to_le32(TRX_MAGIC)) - return -1; - - headers += sizeof(struct trx_header_le); - - if (le32_to_cpu(trx->flag_version) & TRX_UNCOMP_IMAGE) { - actual_len = le32_to_cpu(trx->offsets[TRX_OFFSETS_DLFWLEN_IDX]); - return actual_len + sizeof(struct trx_header_le); - } - return -1; -} - -static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo) -{ - s8 *fwname; - const struct firmware *fw; - int err; - - devinfo->image = g_image.data; - devinfo->image_len = g_image.len; - - /* - * if we have an image we can leave here. - */ - if (devinfo->image) - return 0; - - fwname = BRCMF_USB_FW_NAME; - - err = request_firmware(&fw, fwname, devinfo->dev); - if (!fw) { - brcmf_dbg(ERROR, "fail to request firmware %s\n", fwname); - return err; - } - if (check_file(fw->data) < 0) { - brcmf_dbg(ERROR, "invalid firmware %s\n", fwname); - return -EINVAL; - } - - devinfo->image = kmalloc(fw->size, GFP_ATOMIC); /* plus nvram */ - if (!devinfo->image) - return -ENOMEM; - - memcpy(devinfo->image, fw->data, fw->size); - devinfo->image_len = fw->size; - - release_firmware(fw); - return 0; -} - - -static -struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev) -{ - struct brcmf_usbdev_info *devinfo; - - devinfo = kzalloc(sizeof(struct brcmf_usbdev_info), GFP_ATOMIC); - if (devinfo == NULL) - return NULL; - - devinfo->bus_pub.nrxq = nrxq; - devinfo->rx_low_watermark = nrxq / 2; - devinfo->bus_pub.devinfo = devinfo; - devinfo->bus_pub.ntxq = ntxq; - - /* flow control when too many tx urbs posted */ - devinfo->tx_low_watermark = ntxq / 4; - devinfo->tx_high_watermark = devinfo->tx_low_watermark * 3; - devinfo->dev = dev; - devinfo->usbdev = usbdev_probe_info.usb; - devinfo->tx_pipe = usbdev_probe_info.tx_pipe; - devinfo->rx_pipe = usbdev_probe_info.rx_pipe; - devinfo->rx_pipe2 = usbdev_probe_info.rx_pipe2; - devinfo->intr_pipe = usbdev_probe_info.intr_pipe; - - devinfo->interval = usbdev_probe_info.interval; - devinfo->intr_size = usbdev_probe_info.intr_size; - - memcpy(&devinfo->probe_info, &usbdev_probe_info, - sizeof(struct brcmf_usb_probe_info)); - devinfo->bus_pub.bus_mtu = BRCMF_USB_MAX_PKT_SIZE; - - /* Initialize other structure content */ - init_waitqueue_head(&devinfo->ioctl_resp_wait); - - /* Initialize the spinlocks */ - spin_lock_init(&devinfo->qlock); - - INIT_LIST_HEAD(&devinfo->rx_freeq); - INIT_LIST_HEAD(&devinfo->rx_postq); - - INIT_LIST_HEAD(&devinfo->tx_freeq); - INIT_LIST_HEAD(&devinfo->tx_postq); - - devinfo->rx_reqs = brcmf_usbdev_qinit(&devinfo->rx_freeq, nrxq); - if (!devinfo->rx_reqs) - goto error; - - devinfo->tx_reqs = brcmf_usbdev_qinit(&devinfo->tx_freeq, ntxq); - if (!devinfo->tx_reqs) - goto error; - - devinfo->intr_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!devinfo->intr_urb) { - brcmf_dbg(ERROR, "usb_alloc_urb (intr) failed\n"); - goto error; - } - devinfo->ctl_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!devinfo->ctl_urb) { - brcmf_dbg(ERROR, "usb_alloc_urb (ctl) failed\n"); - goto error; - } - devinfo->rxctl_deferrespok = 0; - - devinfo->bulk_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!devinfo->bulk_urb) { - brcmf_dbg(ERROR, "usb_alloc_urb (bulk) failed\n"); - goto error; - } - - init_waitqueue_head(&devinfo->wait); - if (!brcmf_usb_dlneeded(devinfo)) - return &devinfo->bus_pub; - - brcmf_dbg(TRACE, "start fw downloading\n"); - if (brcmf_usb_get_fw(devinfo)) - goto error; - - if (brcmf_usb_fw_download(devinfo)) - goto error; - - return &devinfo->bus_pub; - -error: - brcmf_dbg(ERROR, "failed!\n"); - brcmf_usb_detach(&devinfo->bus_pub); - return NULL; -} - -static int brcmf_usb_probe_cb(struct device *dev, const char *desc, - u32 bustype, u32 hdrlen) -{ - struct brcmf_bus *bus = NULL; - struct brcmf_usbdev *bus_pub = NULL; - int ret; - - - bus_pub = brcmf_usb_attach(BRCMF_USB_NRXQ, BRCMF_USB_NTXQ, dev); - if (!bus_pub) { - ret = -ENODEV; - goto fail; - } - - bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC); - if (!bus) { - ret = -ENOMEM; - goto fail; - } - - bus_pub->bus = bus; - bus->brcmf_bus_txdata = brcmf_usb_tx; - bus->brcmf_bus_init = brcmf_usb_up; - bus->brcmf_bus_stop = brcmf_usb_down; - bus->brcmf_bus_txctl = brcmf_usb_tx_ctlpkt; - bus->brcmf_bus_rxctl = brcmf_usb_rx_ctlpkt; - bus->type = bustype; - bus->bus_priv.usb = bus_pub; - dev_set_drvdata(dev, bus); - - /* Attach to the common driver interface */ - ret = brcmf_attach(hdrlen, dev); - if (ret) { - brcmf_dbg(ERROR, "dhd_attach failed\n"); - goto fail; - } - - ret = brcmf_bus_start(dev); - if (ret == -ENOLINK) { - brcmf_dbg(ERROR, "dongle is not responding\n"); - brcmf_detach(dev); - goto fail; - } - - /* add interface and open for business */ - ret = brcmf_add_if(dev, 0, "wlan%d", NULL); - if (ret) { - brcmf_dbg(ERROR, "Add primary net device interface failed!!\n"); - brcmf_detach(dev); - goto fail; - } - - return 0; -fail: - /* Release resources in reverse order */ - if (bus_pub) - brcmf_usb_detach(bus_pub); - kfree(bus); - return ret; -} - -static void -brcmf_usb_disconnect_cb(struct brcmf_usbdev *bus_pub) -{ - if (!bus_pub) - return; - brcmf_dbg(TRACE, "enter: bus_pub %p\n", bus_pub); - - brcmf_detach(bus_pub->devinfo->dev); - kfree(bus_pub->bus); - brcmf_usb_detach(bus_pub); - -} - -static int -brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - int ep; - struct usb_endpoint_descriptor *endpoint; - int ret = 0; - struct usb_device *usb = interface_to_usbdev(intf); - int num_of_eps; - u8 endpoint_num; - - brcmf_dbg(TRACE, "enter\n"); - - usbdev_probe_info.usb = usb; - usbdev_probe_info.intf = intf; - - if (id != NULL) { - usbdev_probe_info.vid = id->idVendor; - usbdev_probe_info.pid = id->idProduct; - } - - usb_set_intfdata(intf, &usbdev_probe_info); - - /* Check that the device supports only one configuration */ - if (usb->descriptor.bNumConfigurations != 1) { - ret = -1; - goto fail; - } - - if (usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) { - ret = -1; - goto fail; - } - - /* - * Only the BDC interface configuration is supported: - * Device class: USB_CLASS_VENDOR_SPEC - * if0 class: USB_CLASS_VENDOR_SPEC - * if0/ep0: control - * if0/ep1: bulk in - * if0/ep2: bulk out (ok if swapped with bulk in) - */ - if (CONFIGDESC(usb)->bNumInterfaces != 1) { - ret = -1; - goto fail; - } - - /* Check interface */ - if (IFDESC(usb, CONTROL_IF).bInterfaceClass != USB_CLASS_VENDOR_SPEC || - IFDESC(usb, CONTROL_IF).bInterfaceSubClass != 2 || - IFDESC(usb, CONTROL_IF).bInterfaceProtocol != 0xff) { - brcmf_dbg(ERROR, "invalid control interface: class %d, subclass %d, proto %d\n", - IFDESC(usb, CONTROL_IF).bInterfaceClass, - IFDESC(usb, CONTROL_IF).bInterfaceSubClass, - IFDESC(usb, CONTROL_IF).bInterfaceProtocol); - ret = -1; - goto fail; - } - - /* Check control endpoint */ - endpoint = &IFEPDESC(usb, CONTROL_IF, 0); - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - != USB_ENDPOINT_XFER_INT) { - brcmf_dbg(ERROR, "invalid control endpoint %d\n", - endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); - ret = -1; - goto fail; - } - - endpoint_num = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - usbdev_probe_info.intr_pipe = usb_rcvintpipe(usb, endpoint_num); - - usbdev_probe_info.rx_pipe = 0; - usbdev_probe_info.rx_pipe2 = 0; - usbdev_probe_info.tx_pipe = 0; - num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1; - - /* Check data endpoints and get pipes */ - for (ep = 1; ep <= num_of_eps; ep++) { - endpoint = &IFEPDESC(usb, BULK_IF, ep); - if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != - USB_ENDPOINT_XFER_BULK) { - brcmf_dbg(ERROR, "invalid data endpoint %d\n", ep); - ret = -1; - goto fail; - } - - endpoint_num = endpoint->bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK; - if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - == USB_DIR_IN) { - if (!usbdev_probe_info.rx_pipe) { - usbdev_probe_info.rx_pipe = - usb_rcvbulkpipe(usb, endpoint_num); - } else { - usbdev_probe_info.rx_pipe2 = - usb_rcvbulkpipe(usb, endpoint_num); - } - } else { - usbdev_probe_info.tx_pipe = - usb_sndbulkpipe(usb, endpoint_num); - } - } - - /* Allocate interrupt URB and data buffer */ - /* RNDIS says 8-byte intr, our old drivers used 4-byte */ - if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16)) - usbdev_probe_info.intr_size = 8; - else - usbdev_probe_info.intr_size = 4; - - usbdev_probe_info.interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval; - - usbdev_probe_info.device_speed = usb->speed; - if (usb->speed == USB_SPEED_HIGH) - brcmf_dbg(INFO, "Broadcom high speed USB wireless device detected\n"); - else - brcmf_dbg(INFO, "Broadcom full speed USB wireless device detected\n"); - - ret = brcmf_usb_probe_cb(&usb->dev, "", USB_BUS, 0); - if (ret) - goto fail; - - /* Success */ - return 0; - -fail: - brcmf_dbg(ERROR, "failed with errno %d\n", ret); - usb_set_intfdata(intf, NULL); - return ret; - -} - -static void -brcmf_usb_disconnect(struct usb_interface *intf) -{ - struct usb_device *usb = interface_to_usbdev(intf); - - brcmf_dbg(TRACE, "enter\n"); - brcmf_usb_disconnect_cb(brcmf_usb_get_buspub(&usb->dev)); - usb_set_intfdata(intf, NULL); -} - -/* - * only need to signal the bus being down and update the suspend state. - */ -static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state) -{ - struct usb_device *usb = interface_to_usbdev(intf); - struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); - - brcmf_dbg(TRACE, "enter\n"); - devinfo->bus_pub.state = BCMFMAC_USB_STATE_DOWN; - devinfo->suspend_state = USBOS_SUSPEND_STATE_SUSPENDED; - return 0; -} - -/* - * mark suspend state active and crank up the bus. - */ -static int brcmf_usb_resume(struct usb_interface *intf) -{ - struct usb_device *usb = interface_to_usbdev(intf); - struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); - - brcmf_dbg(TRACE, "enter\n"); - devinfo->suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE; - brcmf_bus_start(&usb->dev); - return 0; -} - -#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c -#define BRCMF_USB_DEVICE_ID_43236 0xbd17 -#define BRCMF_USB_DEVICE_ID_BCMFW 0x0bdc - -static struct usb_device_id brcmf_usb_devid_table[] = { - { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) }, - /* special entry for device with firmware loaded and running */ - { USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) }, - { } -}; -MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); -MODULE_FIRMWARE(BRCMF_USB_FW_NAME); - -/* TODO: suspend and resume entries */ -static struct usb_driver brcmf_usbdrvr = { - .name = KBUILD_MODNAME, - .probe = brcmf_usb_probe, - .disconnect = brcmf_usb_disconnect, - .id_table = brcmf_usb_devid_table, - .suspend = brcmf_usb_suspend, - .resume = brcmf_usb_resume, - .supports_autosuspend = 1 -}; - -void brcmf_usb_exit(void) -{ - usb_deregister(&brcmf_usbdrvr); - kfree(g_image.data); - g_image.data = NULL; - g_image.len = 0; -} - -int brcmf_usb_init(void) -{ - return usb_register(&brcmf_usbdrvr); -} diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.h deleted file mode 100644 index b31da7b83ff7..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2011 Broadcom Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef BRCMFMAC_USB_H -#define BRCMFMAC_USB_H - -enum brcmf_usb_state { - BCMFMAC_USB_STATE_DL_PENDING, - BCMFMAC_USB_STATE_DL_DONE, - BCMFMAC_USB_STATE_UP, - BCMFMAC_USB_STATE_DOWN, - BCMFMAC_USB_STATE_PNP_FWDL, - BCMFMAC_USB_STATE_DISCONNECT, - BCMFMAC_USB_STATE_SLEEP -}; - -enum brcmf_usb_pnp_state { - BCMFMAC_USB_PNP_DISCONNECT, - BCMFMAC_USB_PNP_SLEEP, - BCMFMAC_USB_PNP_RESUME, -}; - -struct brcmf_stats { - u32 tx_errors; - u32 tx_packets; - u32 tx_multicast; - u32 tx_ctlpkts; - u32 tx_ctlerrs; - u32 tx_dropped; - u32 tx_flushed; - u32 rx_errors; - u32 rx_packets; - u32 rx_multicast; - u32 rx_ctlpkts; - u32 rx_ctlerrs; - u32 rx_dropped; - u32 rx_flushed; - -}; - -struct brcmf_usb_attrib { - int bustype; - int vid; - int pid; - int devid; - int chiprev; /* chip revsion number */ - int mtu; - int nchan; /* Data Channels */ - int has_2nd_bulk_in_ep; -}; - -struct brcmf_usbdev_info; - -struct brcmf_usbdev { - struct brcmf_bus *bus; - struct brcmf_usbdev_info *devinfo; - enum brcmf_usb_state state; - struct brcmf_stats stats; - int ntxq, nrxq, rxsize; - u32 bus_mtu; - struct brcmf_usb_attrib attrib; -}; - -/* IO Request Block (IRB) */ -struct brcmf_usbreq { - struct list_head list; - struct brcmf_usbdev_info *devinfo; - struct urb *urb; - struct sk_buff *skb; -}; - -#endif /* BRCMFMAC_USB_H */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h b/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h deleted file mode 100644 index 0a35c51c3da2..000000000000 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2011 Broadcom Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY - * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION - * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _USB_RDL_H -#define _USB_RDL_H - -/* Control messages: bRequest values */ -#define DL_GETSTATE 0 /* returns the rdl_state_t struct */ -#define DL_CHECK_CRC 1 /* currently unused */ -#define DL_GO 2 /* execute downloaded image */ -#define DL_START 3 /* initialize dl state */ -#define DL_REBOOT 4 /* reboot the device in 2 seconds */ -#define DL_GETVER 5 /* returns the bootrom_id_t struct */ -#define DL_GO_PROTECTED 6 /* execute the downloaded code and set reset - * event to occur in 2 seconds. It is the - * responsibility of the downloaded code to - * clear this event - */ -#define DL_EXEC 7 /* jump to a supplied address */ -#define DL_RESETCFG 8 /* To support single enum on dongle - * - Not used by bootloader - */ -#define DL_DEFER_RESP_OK 9 /* Potentially defer the response to setup - * if resp unavailable - */ - -/* states */ -#define DL_WAITING 0 /* waiting to rx first pkt */ -#define DL_READY 1 /* hdr was good, waiting for more of the - * compressed image */ -#define DL_BAD_HDR 2 /* hdr was corrupted */ -#define DL_BAD_CRC 3 /* compressed image was corrupted */ -#define DL_RUNNABLE 4 /* download was successful,waiting for go cmd */ -#define DL_START_FAIL 5 /* failed to initialize correctly */ -#define DL_NVRAM_TOOBIG 6 /* host specified nvram data exceeds DL_NVRAM - * value */ -#define DL_IMAGE_TOOBIG 7 /* download image too big (exceeds DATA_START - * for rdl) */ - -struct rdl_state_le { - __le32 state; - __le32 bytes; -}; - -struct bootrom_id_le { - __le32 chip; /* Chip id */ - __le32 chiprev; /* Chip rev */ - __le32 ramsize; /* Size of RAM */ - __le32 remapbase; /* Current remap base address */ - __le32 boardtype; /* Type of board */ - __le32 boardrev; /* Board revision */ -}; - -#define RDL_CHUNK 1500 /* size of each dl transfer */ - -#define TRX_OFFSETS_DLFWLEN_IDX 0 -#define TRX_OFFSETS_JUMPTO_IDX 1 -#define TRX_OFFSETS_NVM_LEN_IDX 2 - -#define TRX_OFFSETS_DLBASE_IDX 0 - -#endif /* _USB_RDL_H */ diff --git a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 15d7f00513be..74c95a597950 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -1376,7 +1376,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, memset(&join_params, 0, sizeof(join_params)); join_params_size = sizeof(join_params.ssid_le); - ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), (u32)sme->ssid_len); + ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), sme->ssid_len); memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len); memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len); join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); @@ -3297,9 +3297,7 @@ static struct brcmf_cfg80211_event_q *brcmf_deq_event( } /* -* push event to tail of the queue -* -* remark: this function may not sleep as it is called in atomic context. +** push event to tail of the queue */ static s32 @@ -3308,18 +3306,17 @@ brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event, { struct brcmf_cfg80211_event_q *e; s32 err = 0; - ulong flags; - e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_ATOMIC); + e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL); if (!e) return -ENOMEM; e->etype = event; memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg)); - spin_lock_irqsave(&cfg_priv->evt_q_lock, flags); + spin_lock_irq(&cfg_priv->evt_q_lock); list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list); - spin_unlock_irqrestore(&cfg_priv->evt_q_lock, flags); + spin_unlock_irq(&cfg_priv->evt_q_lock); return err; } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c index c1ce831b9bf4..d89dcb14cb6d 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c @@ -1051,13 +1051,17 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, } /* either retransmit or send bar if ack not recd */ if (!ack_recd) { - if (retry && (ini->txretry[index] < (int)retry_limit)) { + struct ieee80211_tx_rate *txrate = + tx_info->status.rates; + if (retry && (txrate[0].count < (int)retry_limit)) { ini->txretry[index]++; ini->tx_in_transit--; /* * Use high prededence for retransmit to * give some punch */ + /* brcms_c_txq_enq(wlc, scb, p, + * BRCMS_PRIO_TO_PREC(tid)); */ brcms_c_txq_enq(wlc, scb, p, BRCMS_PRIO_TO_HI_PREC(tid)); } else { diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index fec0f10773e5..c8427978d09e 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -1136,8 +1136,8 @@ static int brcms_suspend(struct bcma_device *pdev) hw = bcma_get_drvdata(pdev); wl = hw->priv; if (!wl) { - pr_err("%s: %s: no driver private struct!\n", KBUILD_MODNAME, - __func__); + wiphy_err(wl->wiphy, + "brcms_suspend: bcma_get_drvdata failed\n"); return -ENODEV; } diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c index 86186fa82946..fb712cac9157 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/main.c @@ -2901,6 +2901,7 @@ brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel) objoff += 2; return bcma_read16(core, objoff); +; } static void diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c index 9595ecd38c1f..ec7450d2fbd6 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c @@ -17824,6 +17824,8 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) if (pi->sh->sromrev < 4) { idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; + target_pwr_qtrdbm[0] = 13 * 4; + target_pwr_qtrdbm[1] = 13 * 4; a1[0] = -424; a1[1] = -424; b0[0] = 5612; @@ -17837,6 +17839,10 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) case WL_CHAN_FREQ_RANGE_2G: idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; + target_pwr_qtrdbm[0] = + pi->nphy_pwrctrl_info[0].max_pwr_2g; + target_pwr_qtrdbm[1] = + pi->nphy_pwrctrl_info[1].max_pwr_2g; a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1; a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1; b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0; @@ -17847,6 +17853,10 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) case WL_CHAN_FREQ_RANGE_5GL: idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; + target_pwr_qtrdbm[0] = + pi->nphy_pwrctrl_info[0].max_pwr_5gl; + target_pwr_qtrdbm[1] = + pi->nphy_pwrctrl_info[1].max_pwr_5gl; a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1; a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1; b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0; @@ -17857,6 +17867,10 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) case WL_CHAN_FREQ_RANGE_5GM: idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; + target_pwr_qtrdbm[0] = + pi->nphy_pwrctrl_info[0].max_pwr_5gm; + target_pwr_qtrdbm[1] = + pi->nphy_pwrctrl_info[1].max_pwr_5gm; a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1; a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1; b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0; @@ -17867,6 +17881,10 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) case WL_CHAN_FREQ_RANGE_5GH: idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g; + target_pwr_qtrdbm[0] = + pi->nphy_pwrctrl_info[0].max_pwr_5gh; + target_pwr_qtrdbm[1] = + pi->nphy_pwrctrl_info[1].max_pwr_5gh; a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1; a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1; b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0; @@ -17877,6 +17895,8 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) default: idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g; idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g; + target_pwr_qtrdbm[0] = 13 * 4; + target_pwr_qtrdbm[1] = 13 * 4; a1[0] = -424; a1[1] = -424; b0[0] = 5612; @@ -17887,7 +17907,6 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi) } } - /* use the provided transmit power */ target_pwr_qtrdbm[0] = (s8) pi->tx_power_max; target_pwr_qtrdbm[1] = (s8) pi->tx_power_max; @@ -19970,11 +19989,12 @@ static void wlc_phy_radio_init_2057(struct brcms_phy *pi) switch (pi->pubpi.radiorev) { case 5: - if (NREV_IS(pi->pubpi.phy_rev, 8)) + if (pi->pubpi.radiover == 0x0) regs_2057_ptr = regs_2057_rev5; - else if (NREV_IS(pi->pubpi.phy_rev, 9)) + else if (pi->pubpi.radiover == 0x1) regs_2057_ptr = regs_2057_rev5v1; - break; + else + break; case 7: diff --git a/trunk/drivers/net/wireless/brcm80211/brcmsmac/srom.c b/trunk/drivers/net/wireless/brcm80211/brcmsmac/srom.c index b96f4b9d74bd..563743643038 100644 --- a/trunk/drivers/net/wireless/brcm80211/brcmsmac/srom.c +++ b/trunk/drivers/net/wireless/brcm80211/brcmsmac/srom.c @@ -621,7 +621,7 @@ static inline void cpu_to_le16_buf(u16 *buf, uint nwords) /* * convert binary srom data into linked list of srom variable items. */ -static int +static void _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) { struct brcms_srom_list_head *entry; @@ -638,9 +638,6 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) /* first store the srom revision */ entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL); - if (!entry) - return -ENOMEM; - entry->varid = BRCMS_SROM_REV; entry->var_type = BRCMS_SROM_UNUMBER; entry->uval = sromrev; @@ -718,8 +715,6 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) entry = kzalloc(sizeof(struct brcms_srom_list_head) + extra_space, GFP_KERNEL); - if (!entry) - return -ENOMEM; entry->varid = id; entry->var_type = type; if (flags & SRFL_ETHADDR) { @@ -759,8 +754,6 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL); - if (!entry) - return -ENOMEM; entry->varid = srv->varid+p; entry->var_type = BRCMS_SROM_UNUMBER; entry->uval = val; @@ -768,7 +761,6 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) } pb += psz; } - return 0; } /* @@ -914,9 +906,7 @@ int srom_var_init(struct si_pub *sih) INIT_LIST_HEAD(&sii->var_list); /* parse SROM into name=value pairs. */ - err = _initvars_srom_pci(sromrev, srom, &sii->var_list); - if (err) - srom_free_vars(sih); + _initvars_srom_pci(sromrev, srom, &sii->var_list); } errout: diff --git a/trunk/drivers/net/wireless/iwlegacy/3945-debug.c b/trunk/drivers/net/wireless/iwlegacy/3945-debug.c index f767dd106b09..5e1a19fd354d 100644 --- a/trunk/drivers/net/wireless/iwlegacy/3945-debug.c +++ b/trunk/drivers/net/wireless/iwlegacy/3945-debug.c @@ -503,9 +503,3 @@ il3945_ucode_general_stats_read(struct file *file, char __user *user_buf, kfree(buf); return ret; } - -const struct il_debugfs_ops il3945_debugfs_ops = { - .rx_stats_read = il3945_ucode_rx_stats_read, - .tx_stats_read = il3945_ucode_tx_stats_read, - .general_stats_read = il3945_ucode_general_stats_read, -}; diff --git a/trunk/drivers/net/wireless/iwlegacy/3945-mac.c b/trunk/drivers/net/wireless/iwlegacy/3945-mac.c index 0ccc934a35bb..aa8f5c0bd642 100644 --- a/trunk/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/trunk/drivers/net/wireless/iwlegacy/3945-mac.c @@ -573,6 +573,7 @@ il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) len = (u16) skb->len; tx_cmd->len = cpu_to_le16(len); + il_dbg_log_tx_data_frame(il, len, hdr); il_update_stats(il, true, fc, len); tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK; tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; @@ -615,7 +616,7 @@ il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ - il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0); + il->ops->lib->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0); /* Set up TFD's 2nd entry to point directly to remainder of skb, * if any (802.11 null frames have no payload). */ @@ -624,8 +625,8 @@ il3945_tx_skb(struct il_priv *il, struct sk_buff *skb) phys_addr = pci_map_single(il->pci_dev, skb->data + hdr_len, len, PCI_DMA_TODEVICE); - il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, len, 0, - U32_PAD(len)); + il->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, len, 0, + U32_PAD(len)); } /* Tell device the write idx *just past* this latest filled TFD */ @@ -809,16 +810,16 @@ il3945_hdl_card_state(struct il_priv *il, struct il_rx_buf *rxb) _il_wr(il, CSR_UCODE_DRV_GP1_SET, CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); if (flags & HW_CARD_DISABLED) - set_bit(S_RFKILL, &il->status); + set_bit(S_RF_KILL_HW, &il->status); else - clear_bit(S_RFKILL, &il->status); + clear_bit(S_RF_KILL_HW, &il->status); il_scan_cancel(il); - if ((test_bit(S_RFKILL, &status) != - test_bit(S_RFKILL, &il->status))) + if ((test_bit(S_RF_KILL_HW, &status) != + test_bit(S_RF_KILL_HW, &il->status))) wiphy_rfkill_set_hw_state(il->hw->wiphy, - test_bit(S_RFKILL, &il->status)); + test_bit(S_RF_KILL_HW, &il->status)); else wake_up(&il->wait_command_queue); } @@ -2166,7 +2167,7 @@ il3945_alive_start(struct il_priv *il) D_INFO("RFKILL status: 0x%x\n", rfkill); if (rfkill & 0x1) { - clear_bit(S_RFKILL, &il->status); + clear_bit(S_RF_KILL_HW, &il->status); /* if RFKILL is not on, then wait for thermal * sensor in adapter to kick in */ while (il3945_hw_get_temperature(il) == 0) { @@ -2178,7 +2179,7 @@ il3945_alive_start(struct il_priv *il) D_INFO("Thermal calibration took %dus\n", thermal_spin * 10); } else - set_bit(S_RFKILL, &il->status); + set_bit(S_RF_KILL_HW, &il->status); /* After the ALIVE response, we can send commands to 3945 uCode */ set_bit(S_ALIVE, &il->status); @@ -2272,8 +2273,12 @@ __il3945_down(struct il_priv *il) * clear all bits but the RF Kill bits and return */ if (!il_is_init(il)) { il->status = - test_bit(S_RFKILL, &il->status) << S_RFKILL | - test_bit(S_GEO_CONFIGURED, &il->status) << S_GEO_CONFIGURED | + test_bit(S_RF_KILL_HW, + &il-> + status) << S_RF_KILL_HW | + test_bit(S_GEO_CONFIGURED, + &il-> + status) << S_GEO_CONFIGURED | test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING; goto exit; } @@ -2281,30 +2286,25 @@ __il3945_down(struct il_priv *il) /* ...otherwise clear out all the status bits but the RF Kill * bit and continue taking the NIC down. */ il->status &= - test_bit(S_RFKILL, &il->status) << S_RFKILL | - test_bit(S_GEO_CONFIGURED, &il->status) << S_GEO_CONFIGURED | - test_bit(S_FW_ERROR, &il->status) << S_FW_ERROR | + test_bit(S_RF_KILL_HW, + &il->status) << S_RF_KILL_HW | test_bit(S_GEO_CONFIGURED, + &il-> + status) << + S_GEO_CONFIGURED | test_bit(S_FW_ERROR, + &il-> + status) << S_FW_ERROR | test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING; - /* - * We disabled and synchronized interrupt, and priv->mutex is taken, so - * here is the only thread which will program device registers, but - * still have lockdep assertions, so we are taking reg_lock. - */ - spin_lock_irq(&il->reg_lock); - /* FIXME: il_grab_nic_access if rfkill is off ? */ - il3945_hw_txq_ctx_stop(il); il3945_hw_rxq_stop(il); + /* Power-down device's busmaster DMA clocks */ - _il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); + il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); udelay(5); - /* Stop the device, and put it in low power state */ - _il_apm_stop(il); - spin_unlock_irq(&il->reg_lock); + /* Stop the device, and put it in low power state */ + il_apm_stop(il); - il3945_hw_txq_ctx_free(il); exit: memset(&il->card_alive, 0, sizeof(struct il_alive_resp)); @@ -2371,9 +2371,9 @@ __il3945_up(struct il_priv *il) /* If platform's RF_KILL switch is NOT set to KILL */ if (_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(S_RFKILL, &il->status); + clear_bit(S_RF_KILL_HW, &il->status); else { - set_bit(S_RFKILL, &il->status); + set_bit(S_RF_KILL_HW, &il->status); IL_WARN("Radio disabled by HW RF Kill switch\n"); return -ENODEV; } @@ -2405,7 +2405,7 @@ __il3945_up(struct il_priv *il) il->ucode_data.len); /* We return success when we resume from suspend and rf_kill is on. */ - if (test_bit(S_RFKILL, &il->status)) + if (test_bit(S_RF_KILL_HW, &il->status)) return 0; for (i = 0; i < MAX_HW_RESTARTS; i++) { @@ -2413,7 +2413,7 @@ __il3945_up(struct il_priv *il) /* load bootstrap state machine, * load bootstrap program into processor's memory, * prepare to load the "initialize" uCode */ - rc = il->ops->load_ucode(il); + rc = il->ops->lib->load_ucode(il); if (rc) { IL_ERR("Unable to set up bootstrap uCode: %d\n", rc); @@ -2485,15 +2485,15 @@ il3945_rfkill_poll(struct work_struct *data) { struct il_priv *il = container_of(data, struct il_priv, _3945.rfkill_poll.work); - bool old_rfkill = test_bit(S_RFKILL, &il->status); + bool old_rfkill = test_bit(S_RF_KILL_HW, &il->status); bool new_rfkill = !(_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW); if (new_rfkill != old_rfkill) { if (new_rfkill) - set_bit(S_RFKILL, &il->status); + set_bit(S_RF_KILL_HW, &il->status); else - clear_bit(S_RFKILL, &il->status); + clear_bit(S_RF_KILL_HW, &il->status); wiphy_rfkill_set_hw_state(il->hw->wiphy, new_rfkill); @@ -2782,9 +2782,10 @@ il3945_mac_start(struct ieee80211_hw *hw) struct il_priv *il = hw->priv; int ret; + D_MAC80211("enter\n"); + /* we should be verifying the device is ready to be opened */ mutex_lock(&il->mutex); - D_MAC80211("enter\n"); /* fetch ucode file from disk, alloc and copy to bus-master buffers ... * ucode filename and max sizes are card-specific. */ @@ -2940,19 +2941,15 @@ il3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, * hardware will then not attempt to decrypt the frames. */ if (vif->type == NL80211_IFTYPE_ADHOC && - !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { - D_MAC80211("leave - IBSS RSN\n"); + !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) return -EOPNOTSUPP; - } static_key = !il_is_associated(il); if (!static_key) { sta_id = il_sta_id_or_broadcast(il, sta); - if (sta_id == IL_INVALID_STATION) { - D_MAC80211("leave - station not found\n"); + if (sta_id == IL_INVALID_STATION) return -EINVAL; - } } mutex_lock(&il->mutex); @@ -2977,8 +2974,8 @@ il3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ret = -EINVAL; } - D_MAC80211("leave ret %d\n", ret); mutex_unlock(&il->mutex); + D_MAC80211("leave\n"); return ret; } @@ -2993,8 +2990,9 @@ il3945_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, bool is_ap = vif->type == NL80211_IFTYPE_STATION; u8 sta_id; + D_INFO("received request to add station %pM\n", sta->addr); mutex_lock(&il->mutex); - D_INFO("station %pM\n", sta->addr); + D_INFO("proceeding to add station %pM\n", sta->addr); sta_priv->common.sta_id = IL_INVALID_STATION; ret = il_add_station_common(il, sta->addr, is_ap, sta, &sta_id); @@ -3100,9 +3098,11 @@ il3945_store_debug_level(struct device *d, struct device_attribute *attr, ret = strict_strtoul(buf, 0, &val); if (ret) IL_INFO("%s is not in hex or decimal form.\n", buf); - else + else { il->debug_level = val; - + if (il_alloc_traffic_mem(il)) + IL_ERR("Not enough memory to generate traffic log\n"); + } return strnlen(buf, count); } @@ -3619,12 +3619,12 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) D_INFO("*** LOAD DRIVER ***\n"); il->cfg = cfg; il->ops = &il3945_ops; -#ifdef CONFIG_IWLEGACY_DEBUGFS - il->debugfs_ops = &il3945_debugfs_ops; -#endif il->pci_dev = pdev; il->inta_mask = CSR_INI_SET_MASK; + if (il_alloc_traffic_mem(il)) + IL_ERR("Not enough memory to generate traffic log\n"); + /*************************** * 2. Initializing PCI bus * *************************/ @@ -3655,7 +3655,7 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /*********************** * 3. Read REV Register * ********************/ - il->hw_base = pci_ioremap_bar(pdev, 0); + il->hw_base = pci_iomap(pdev, 0, 0); if (!il->hw_base) { err = -ENODEV; goto out_pci_release_regions; @@ -3669,7 +3669,7 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * PCI Tx retries from interfering with C3 CPU state */ pci_write_config_byte(pdev, 0x41, 0x00); - /* these spin locks will be used in apm_init and EEPROM access + /* these spin locks will be used in apm_ops.init and EEPROM access * we should init now */ spin_lock_init(&il->reg_lock); @@ -3780,13 +3780,14 @@ il3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) out_eeprom_free: il_eeprom_free(il); out_iounmap: - iounmap(il->hw_base); + pci_iounmap(pdev, il->hw_base); out_pci_release_regions: pci_release_regions(pdev); out_pci_disable_device: pci_set_drvdata(pdev, NULL); pci_disable_device(pdev); out_ieee80211_free_hw: + il_free_traffic_mem(il); ieee80211_free_hw(il->hw); out: return err; @@ -3854,11 +3855,12 @@ il3945_pci_remove(struct pci_dev *pdev) * until now... */ destroy_workqueue(il->workqueue); il->workqueue = NULL; + il_free_traffic_mem(il); free_irq(pdev->irq, il); pci_disable_msi(pdev); - iounmap(il->hw_base); + pci_iounmap(pdev, il->hw_base); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); diff --git a/trunk/drivers/net/wireless/iwlegacy/3945.c b/trunk/drivers/net/wireless/iwlegacy/3945.c index 456f32da6b26..6c1ae5fab899 100644 --- a/trunk/drivers/net/wireless/iwlegacy/3945.c +++ b/trunk/drivers/net/wireless/iwlegacy/3945.c @@ -57,6 +57,10 @@ il3945_send_led_cmd(struct il_priv *il, struct il_led_cmd *led_cmd) return il_send_cmd(il, &cmd); } +const struct il_led_ops il3945_led_ops = { + .cmd = il3945_send_led_cmd, +}; + #define IL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ [RATE_##r##M_IDX] = { RATE_##r##M_PLCP, \ RATE_##r##M_IEEE, \ @@ -299,7 +303,7 @@ il3945_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx) skb = txq->skbs[txq->q.read_ptr]; ieee80211_tx_status_irqsafe(il->hw, skb); txq->skbs[txq->q.read_ptr] = NULL; - il->ops->txq_free_tfd(il, txq); + il->ops->lib->txq_free_tfd(il, txq); } if (il_queue_space(q) > q->low_mark && txq_id >= 0 && @@ -573,6 +577,8 @@ il3945_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) network_packet ? '*' : ' ', le16_to_cpu(rx_hdr->channel), rx_status.signal, rx_status.signal, rx_status.rate_idx); + il_dbg_log_rx_data_frame(il, le16_to_cpu(rx_hdr->len), header); + if (network_packet) { il->_3945.last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp); @@ -790,6 +796,7 @@ il3945_rx_init(struct il_priv *il, struct il_rx_queue *rxq) static int il3945_tx_reset(struct il_priv *il) { + /* bypass mode */ il_wr_prph(il, ALM_SCD_MODE_REG, 0x2); @@ -826,7 +833,8 @@ il3945_tx_reset(struct il_priv *il) static int il3945_txq_ctx_reset(struct il_priv *il) { - int rc, txq_id; + int rc; + int txq_id, slots_num; il3945_hw_txq_ctx_free(il); @@ -842,7 +850,10 @@ il3945_txq_ctx_reset(struct il_priv *il) /* Tx queue(s) */ for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) { - rc = il_tx_queue_init(il, txq_id); + slots_num = + (txq_id == + IL39_CMD_QUEUE_NUM) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; + rc = il_tx_queue_init(il, &il->txq[txq_id], slots_num, txq_id); if (rc) { IL_ERR("Tx %d queue init failed\n", txq_id); goto error; @@ -947,11 +958,12 @@ il3945_hw_nic_init(struct il_priv *il) struct il_rx_queue *rxq = &il->rxq; spin_lock_irqsave(&il->lock, flags); - il3945_apm_init(il); + il->ops->lib->apm_ops.init(il); spin_unlock_irqrestore(&il->lock, flags); il3945_set_pwr_vmain(il); - il3945_nic_config(il); + + il->ops->lib->apm_ops.config(il); /* Allocate the RX queue, or reset if it is already allocated */ if (!rxq->bd) { @@ -1002,7 +1014,7 @@ il3945_hw_txq_ctx_free(struct il_priv *il) il_tx_queue_free(il, txq_id); /* free tx queue structure */ - il_free_txq_mem(il); + il_txq_mem(il); } void @@ -1011,17 +1023,18 @@ il3945_hw_txq_ctx_stop(struct il_priv *il) int txq_id; /* stop SCD */ - _il_wr_prph(il, ALM_SCD_MODE_REG, 0); - _il_wr_prph(il, ALM_SCD_TXFACT_REG, 0); + il_wr_prph(il, ALM_SCD_MODE_REG, 0); + il_wr_prph(il, ALM_SCD_TXFACT_REG, 0); /* reset TFD queues */ for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) { - _il_wr(il, FH39_TCSR_CONFIG(txq_id), 0x0); - _il_poll_bit(il, FH39_TSSR_TX_STATUS, - FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id), - FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id), - 1000); + il_wr(il, FH39_TCSR_CONFIG(txq_id), 0x0); + il_poll_bit(il, FH39_TSSR_TX_STATUS, + FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id), + 1000); } + + il3945_hw_txq_ctx_free(il); } /** @@ -1600,7 +1613,7 @@ il3945_hw_reg_comp_txpower_temp(struct il_priv *il) } /* send Txpower command for current channel to ucode */ - return il->ops->send_tx_power(il); + return il->ops->lib->send_tx_power(il); } int @@ -2170,14 +2183,12 @@ il3945_txpower_set_from_eeprom(struct il_priv *il) int il3945_hw_rxq_stop(struct il_priv *il) { - int ret; + int rc; - _il_wr(il, FH39_RCSR_CONFIG(0), 0); - ret = _il_poll_bit(il, FH39_RSSR_STATUS, - FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, - FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, - 1000); - if (ret < 0) + il_wr(il, FH39_RCSR_CONFIG(0), 0); + rc = il_poll_bit(il, FH39_RSSR_STATUS, + FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); + if (rc < 0) IL_ERR("Can't stop Rx DMA.\n"); return 0; @@ -2619,31 +2630,65 @@ il3945_load_bsm(struct il_priv *il) return 0; } -const struct il_ops il3945_ops = { +static struct il_hcmd_ops il3945_hcmd = { + .rxon_assoc = il3945_send_rxon_assoc, + .commit_rxon = il3945_commit_rxon, +}; + +static struct il_lib_ops il3945_lib = { .txq_attach_buf_to_tfd = il3945_hw_txq_attach_buf_to_tfd, .txq_free_tfd = il3945_hw_txq_free_tfd, .txq_init = il3945_hw_tx_queue_init, .load_ucode = il3945_load_bsm, .dump_nic_error_log = il3945_dump_nic_error_log, - .apm_init = il3945_apm_init, + .apm_ops = { + .init = il3945_apm_init, + .config = il3945_nic_config, + }, + .eeprom_ops = { + .regulatory_bands = { + EEPROM_REGULATORY_BAND_1_CHANNELS, + EEPROM_REGULATORY_BAND_2_CHANNELS, + EEPROM_REGULATORY_BAND_3_CHANNELS, + EEPROM_REGULATORY_BAND_4_CHANNELS, + EEPROM_REGULATORY_BAND_5_CHANNELS, + EEPROM_REGULATORY_BAND_NO_HT40, + EEPROM_REGULATORY_BAND_NO_HT40, + }, + .acquire_semaphore = il3945_eeprom_acquire_semaphore, + .release_semaphore = il3945_eeprom_release_semaphore, + }, .send_tx_power = il3945_send_tx_power, .is_valid_rtc_data_addr = il3945_hw_valid_rtc_data_addr, - .eeprom_acquire_semaphore = il3945_eeprom_acquire_semaphore, - .eeprom_release_semaphore = il3945_eeprom_release_semaphore, - .rxon_assoc = il3945_send_rxon_assoc, - .commit_rxon = il3945_commit_rxon, +#ifdef CONFIG_IWLEGACY_DEBUGFS + .debugfs_ops = { + .rx_stats_read = il3945_ucode_rx_stats_read, + .tx_stats_read = il3945_ucode_tx_stats_read, + .general_stats_read = il3945_ucode_general_stats_read, + }, +#endif +}; + +static const struct il_legacy_ops il3945_legacy_ops = { + .post_associate = il3945_post_associate, + .config_ap = il3945_config_ap, + .manage_ibss_station = il3945_manage_ibss_station, +}; +static struct il_hcmd_utils_ops il3945_hcmd_utils = { .get_hcmd_size = il3945_get_hcmd_size, .build_addsta_hcmd = il3945_build_addsta_hcmd, .request_scan = il3945_request_scan, .post_scan = il3945_post_scan, +}; - .post_associate = il3945_post_associate, - .config_ap = il3945_config_ap, - .manage_ibss_station = il3945_manage_ibss_station, - - .send_led_cmd = il3945_send_led_cmd, +const struct il_ops il3945_ops = { + .lib = &il3945_lib, + .hcmd = &il3945_hcmd, + .utils = &il3945_hcmd_utils, + .led = &il3945_led_ops, + .legacy = &il3945_legacy_ops, }; static struct il_cfg il3945_bg_cfg = { @@ -2662,17 +2707,7 @@ static struct il_cfg il3945_bg_cfg = { .set_l0s = false, .use_bsm = true, .led_compensation = 64, - .wd_timeout = IL_DEF_WD_TIMEOUT, - - .regulatory_bands = { - EEPROM_REGULATORY_BAND_1_CHANNELS, - EEPROM_REGULATORY_BAND_2_CHANNELS, - EEPROM_REGULATORY_BAND_3_CHANNELS, - EEPROM_REGULATORY_BAND_4_CHANNELS, - EEPROM_REGULATORY_BAND_5_CHANNELS, - EEPROM_REGULATORY_BAND_NO_HT40, - EEPROM_REGULATORY_BAND_NO_HT40, - }, + .wd_timeout = IL_DEF_WD_TIMEOUT }; static struct il_cfg il3945_abg_cfg = { @@ -2691,17 +2726,7 @@ static struct il_cfg il3945_abg_cfg = { .set_l0s = false, .use_bsm = true, .led_compensation = 64, - .wd_timeout = IL_DEF_WD_TIMEOUT, - - .regulatory_bands = { - EEPROM_REGULATORY_BAND_1_CHANNELS, - EEPROM_REGULATORY_BAND_2_CHANNELS, - EEPROM_REGULATORY_BAND_3_CHANNELS, - EEPROM_REGULATORY_BAND_4_CHANNELS, - EEPROM_REGULATORY_BAND_5_CHANNELS, - EEPROM_REGULATORY_BAND_NO_HT40, - EEPROM_REGULATORY_BAND_NO_HT40, - }, + .wd_timeout = IL_DEF_WD_TIMEOUT }; DEFINE_PCI_DEVICE_TABLE(il3945_hw_card_ids) = { diff --git a/trunk/drivers/net/wireless/iwlegacy/3945.h b/trunk/drivers/net/wireless/iwlegacy/3945.h index 1d45075e0d5b..c00a8d30b6fe 100644 --- a/trunk/drivers/net/wireless/iwlegacy/3945.h +++ b/trunk/drivers/net/wireless/iwlegacy/3945.h @@ -595,7 +595,13 @@ struct il3945_tfd { } __packed; #ifdef CONFIG_IWLEGACY_DEBUGFS -extern const struct il_debugfs_ops il3945_debugfs_ops; +ssize_t il3945_ucode_rx_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); +ssize_t il3945_ucode_tx_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); +ssize_t il3945_ucode_general_stats_read(struct file *file, + char __user *user_buf, size_t count, + loff_t *ppos); #endif #endif diff --git a/trunk/drivers/net/wireless/iwlegacy/4965-calib.c b/trunk/drivers/net/wireless/iwlegacy/4965-calib.c index 47c20e3d5605..fe9171506a91 100644 --- a/trunk/drivers/net/wireless/iwlegacy/4965-calib.c +++ b/trunk/drivers/net/wireless/iwlegacy/4965-calib.c @@ -923,8 +923,8 @@ il4965_chain_noise_calibration(struct il_priv *il, void *stat_resp) /* Some power changes may have been made during the calibration. * Update and commit the RXON */ - if (il->ops->update_chain_flags) - il->ops->update_chain_flags(il); + if (il->ops->lib->update_chain_flags) + il->ops->lib->update_chain_flags(il); data->state = IL_CHAIN_NOISE_DONE; il_power_update_mode(il, false); diff --git a/trunk/drivers/net/wireless/iwlegacy/4965-debug.c b/trunk/drivers/net/wireless/iwlegacy/4965-debug.c index c8153fc64f74..98ec39f56ba3 100644 --- a/trunk/drivers/net/wireless/iwlegacy/4965-debug.c +++ b/trunk/drivers/net/wireless/iwlegacy/4965-debug.c @@ -744,9 +744,3 @@ il4965_ucode_general_stats_read(struct file *file, char __user *user_buf, kfree(buf); return ret; } - -const struct il_debugfs_ops il4965_debugfs_ops = { - .rx_stats_read = il4965_ucode_rx_stats_read, - .tx_stats_read = il4965_ucode_tx_stats_read, - .general_stats_read = il4965_ucode_general_stats_read, -}; diff --git a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c index 2d01db0f08e0..235812ac6a0d 100644 --- a/trunk/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/trunk/drivers/net/wireless/iwlegacy/4965-mac.c @@ -199,14 +199,18 @@ il4965_hw_nic_init(struct il_priv *il) struct il_rx_queue *rxq = &il->rxq; int ret; + /* nic_init */ spin_lock_irqsave(&il->lock, flags); - il_apm_init(il); + il->ops->lib->apm_ops.init(il); + /* Set interrupt coalescing calibration timer to default (512 usecs) */ il_write8(il, CSR_INT_COALESCING, IL_HOST_INT_CALIB_TIMEOUT_DEF); + spin_unlock_irqrestore(&il->lock, flags); il4965_set_pwr_vmain(il); - il4965_nic_config(il); + + il->ops->lib->apm_ops.config(il); /* Allocate the RX queue, or reset if it is already allocated */ if (!rxq->bd) { @@ -441,15 +445,11 @@ il4965_rx_queue_free(struct il_priv *il, struct il_rx_queue *rxq) int il4965_rxq_stop(struct il_priv *il) { - int ret; - _il_wr(il, FH49_MEM_RCSR_CHNL0_CONFIG_REG, 0); - ret = _il_poll_bit(il, FH49_MEM_RSSR_RX_STATUS_REG, - FH49_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, - FH49_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, - 1000); - if (ret < 0) - IL_ERR("Can't stop Rx DMA.\n"); + /* stop Rx DMA */ + il_wr(il, FH49_MEM_RCSR_CHNL0_CONFIG_REG, 0); + il_poll_bit(il, FH49_MEM_RSSR_RX_STATUS_REG, + FH49_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); return 0; } @@ -692,6 +692,7 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb) /* Find max signal strength (dBm) among 3 antenna/receiver chains */ rx_status.signal = il4965_calc_rssi(il, phy_res); + il_dbg_log_rx_data_frame(il, len, header); D_STATS("Rssi %d, TSF %llu\n", rx_status.signal, (unsigned long long)rx_status.mactime); @@ -1342,11 +1343,12 @@ il4965_accumulative_stats(struct il_priv *il, __le32 * stats) } #endif +#define REG_RECALIB_PERIOD (60) + void il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb) { - const int recalib_seconds = 60; - bool change; + int change; struct il_rx_pkt *pkt = rxb_addr(rxb); D_RX("Statistics notification received (%d vs %d).\n", @@ -1367,21 +1369,20 @@ il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb) set_bit(S_STATS, &il->status); - /* - * Reschedule the stats timer to occur in recalib_seconds to ensure - * we get a thermal update even if the uCode doesn't give us one - */ + /* Reschedule the stats timer to occur in + * REG_RECALIB_PERIOD seconds to ensure we get a + * thermal update even if the uCode doesn't give + * us one */ mod_timer(&il->stats_periodic, - jiffies + msecs_to_jiffies(recalib_seconds * 1000)); + jiffies + msecs_to_jiffies(REG_RECALIB_PERIOD * 1000)); if (unlikely(!test_bit(S_SCANNING, &il->status)) && (pkt->hdr.cmd == N_STATS)) { il4965_rx_calc_noise(il); queue_work(il->workqueue, &il->run_time_calib_work); } - - if (change) - il4965_temperature_calib(il); + if (il->ops->lib->temp_ops.temperature && change) + il->ops->lib->temp_ops.temperature(il); } void @@ -1784,6 +1785,7 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) /* TODO need this for burst mode later on */ il4965_tx_cmd_build_basic(il, skb, tx_cmd, info, hdr, sta_id); + il_dbg_log_tx_data_frame(il, len, hdr); il4965_tx_cmd_build_rate(il, tx_cmd, info, fc); @@ -1813,7 +1815,7 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) dma_unmap_len_set(out_meta, len, firstlen); /* Add buffer containing Tx command and MAC(!) header to TFD's * first entry */ - il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0); + il->ops->lib->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0); if (!ieee80211_has_morefrags(hdr->frame_control)) { txq->need_update = 1; @@ -1829,8 +1831,8 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) phys_addr = pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen, PCI_DMA_TODEVICE); - il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, secondlen, - 0, 0); + il->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, + secondlen, 0, 0); } scratch_phys = @@ -1850,7 +1852,8 @@ il4965_tx_skb(struct il_priv *il, struct sk_buff *skb) /* Set up entry for this TFD in Tx byte-count array */ if (info->flags & IEEE80211_TX_CTL_AMPDU) - il->ops->txq_update_byte_cnt_tbl(il, txq, le16_to_cpu(tx_cmd->len)); + il->ops->lib->txq_update_byte_cnt_tbl(il, txq, + le16_to_cpu(tx_cmd->len)); pci_dma_sync_single_for_device(il->pci_dev, txcmd_phys, firstlen, PCI_DMA_BIDIRECTIONAL); @@ -1939,7 +1942,7 @@ il4965_hw_txq_ctx_free(struct il_priv *il) il4965_free_dma_ptr(il, &il->scd_bc_tbls); /* free tx queue structure */ - il_free_txq_mem(il); + il_txq_mem(il); } /** @@ -1952,7 +1955,8 @@ il4965_hw_txq_ctx_free(struct il_priv *il) int il4965_txq_ctx_alloc(struct il_priv *il) { - int ret, txq_id; + int ret; + int txq_id, slots_num; unsigned long flags; /* Free all tx/cmd queues and keep-warm buffer */ @@ -1989,7 +1993,10 @@ il4965_txq_ctx_alloc(struct il_priv *il) /* Alloc and init all Tx queues, including the command queue (#4/#9) */ for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) { - ret = il_tx_queue_init(il, txq_id); + slots_num = + (txq_id == + il->cmd_queue) ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; + ret = il_tx_queue_init(il, &il->txq[txq_id], slots_num, txq_id); if (ret) { IL_ERR("Tx %d queue init failed\n", txq_id); goto error; @@ -2010,27 +2017,52 @@ il4965_txq_ctx_alloc(struct il_priv *il) void il4965_txq_ctx_reset(struct il_priv *il) { - int txq_id; + int txq_id, slots_num; unsigned long flags; spin_lock_irqsave(&il->lock, flags); /* Turn off all Tx DMA fifos */ il4965_txq_set_sched(il, 0); + /* Tell NIC where to find the "keep warm" buffer */ il_wr(il, FH49_KW_MEM_ADDR_REG, il->kw.dma >> 4); spin_unlock_irqrestore(&il->lock, flags); /* Alloc and init all Tx queues, including the command queue (#4) */ - for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) - il_tx_queue_reset(il, txq_id); + for (txq_id = 0; txq_id < il->hw_params.max_txq_num; txq_id++) { + slots_num = + txq_id == il->cmd_queue ? TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; + il_tx_queue_reset(il, &il->txq[txq_id], slots_num, txq_id); + } } +/** + * il4965_txq_ctx_stop - Stop all Tx DMA channels + */ void -il4965_txq_ctx_unmap(struct il_priv *il) +il4965_txq_ctx_stop(struct il_priv *il) { - int txq_id; + int ch, txq_id; + unsigned long flags; + + /* Turn off all Tx DMA fifos */ + spin_lock_irqsave(&il->lock, flags); + + il4965_txq_set_sched(il, 0); + + /* Stop each Tx DMA channel, and wait for it to be idle */ + for (ch = 0; ch < il->hw_params.dma_chnl_num; ch++) { + il_wr(il, FH49_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); + if (il_poll_bit + (il, FH49_TSSR_TX_STATUS_REG, + FH49_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 1000)) + IL_ERR("Failing on timeout while stopping" + " DMA channel %d [0x%08x]", ch, + il_rd(il, FH49_TSSR_TX_STATUS_REG)); + } + spin_unlock_irqrestore(&il->lock, flags); if (!il->txq) return; @@ -2043,30 +2075,6 @@ il4965_txq_ctx_unmap(struct il_priv *il) il_tx_queue_unmap(il, txq_id); } -/** - * il4965_txq_ctx_stop - Stop all Tx DMA channels - */ -void -il4965_txq_ctx_stop(struct il_priv *il) -{ - int ch, ret; - - _il_wr_prph(il, IL49_SCD_TXFACT, 0); - - /* Stop each Tx DMA channel, and wait for it to be idle */ - for (ch = 0; ch < il->hw_params.dma_chnl_num; ch++) { - _il_wr(il, FH49_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); - ret = - _il_poll_bit(il, FH49_TSSR_TX_STATUS_REG, - FH49_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), - FH49_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), - 1000); - if (ret < 0) - IL_ERR("Timeout stopping DMA channel %d [0x%08x]", - ch, _il_rd(il, FH49_TSSR_TX_STATUS_REG)); - } -} - /* * Find first available (lowest unused) Tx Queue, mark it "active". * Called only when finding queue for aggregation. @@ -2466,7 +2474,7 @@ il4965_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx) il4965_tx_status(il, skb, txq_id >= IL4965_FIRST_AMPDU_QUEUE); txq->skbs[txq->q.read_ptr] = NULL; - il->ops->txq_free_tfd(il, txq); + il->ops->lib->txq_free_tfd(il, txq); } return nfreed; } @@ -2540,308 +2548,6 @@ il4965_tx_status_reply_compressed_ba(struct il_priv *il, struct il_ht_agg *agg, return 0; } -static inline bool -il4965_is_tx_success(u32 status) -{ - status &= TX_STATUS_MSK; - return (status == TX_STATUS_SUCCESS || status == TX_STATUS_DIRECT_DONE); -} - -static u8 -il4965_find_station(struct il_priv *il, const u8 *addr) -{ - int i; - int start = 0; - int ret = IL_INVALID_STATION; - unsigned long flags; - - if (il->iw_mode == NL80211_IFTYPE_ADHOC) - start = IL_STA_ID; - - if (is_broadcast_ether_addr(addr)) - return il->hw_params.bcast_id; - - spin_lock_irqsave(&il->sta_lock, flags); - for (i = start; i < il->hw_params.max_stations; i++) - if (il->stations[i].used && - (!compare_ether_addr(il->stations[i].sta.sta.addr, addr))) { - ret = i; - goto out; - } - - D_ASSOC("can not find STA %pM total %d\n", addr, il->num_stations); - -out: - /* - * It may be possible that more commands interacting with stations - * arrive before we completed processing the adding of - * station - */ - if (ret != IL_INVALID_STATION && - (!(il->stations[ret].used & IL_STA_UCODE_ACTIVE) || - ((il->stations[ret].used & IL_STA_UCODE_ACTIVE) && - (il->stations[ret].used & IL_STA_UCODE_INPROGRESS)))) { - IL_ERR("Requested station info for sta %d before ready.\n", - ret); - ret = IL_INVALID_STATION; - } - spin_unlock_irqrestore(&il->sta_lock, flags); - return ret; -} - -static int -il4965_get_ra_sta_id(struct il_priv *il, struct ieee80211_hdr *hdr) -{ - if (il->iw_mode == NL80211_IFTYPE_STATION) - return IL_AP_ID; - else { - u8 *da = ieee80211_get_DA(hdr); - - return il4965_find_station(il, da); - } -} - -static inline u32 -il4965_get_scd_ssn(struct il4965_tx_resp *tx_resp) -{ - return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN; -} - -static inline u32 -il4965_tx_status_to_mac80211(u32 status) -{ - status &= TX_STATUS_MSK; - - switch (status) { - case TX_STATUS_SUCCESS: - case TX_STATUS_DIRECT_DONE: - return IEEE80211_TX_STAT_ACK; - case TX_STATUS_FAIL_DEST_PS: - return IEEE80211_TX_STAT_TX_FILTERED; - default: - return 0; - } -} - -/** - * il4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue - */ -static int -il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg, - struct il4965_tx_resp *tx_resp, int txq_id, - u16 start_idx) -{ - u16 status; - struct agg_tx_status *frame_status = tx_resp->u.agg_status; - struct ieee80211_tx_info *info = NULL; - struct ieee80211_hdr *hdr = NULL; - u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); - int i, sh, idx; - u16 seq; - if (agg->wait_for_ba) - D_TX_REPLY("got tx response w/o block-ack\n"); - - agg->frame_count = tx_resp->frame_count; - agg->start_idx = start_idx; - agg->rate_n_flags = rate_n_flags; - agg->bitmap = 0; - - /* num frames attempted by Tx command */ - if (agg->frame_count == 1) { - /* Only one frame was attempted; no block-ack will arrive */ - status = le16_to_cpu(frame_status[0].status); - idx = start_idx; - - D_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n", - agg->frame_count, agg->start_idx, idx); - - info = IEEE80211_SKB_CB(il->txq[txq_id].skbs[idx]); - info->status.rates[0].count = tx_resp->failure_frame + 1; - info->flags &= ~IEEE80211_TX_CTL_AMPDU; - info->flags |= il4965_tx_status_to_mac80211(status); - il4965_hwrate_to_tx_control(il, rate_n_flags, info); - - D_TX_REPLY("1 Frame 0x%x failure :%d\n", status & 0xff, - tx_resp->failure_frame); - D_TX_REPLY("Rate Info rate_n_flags=%x\n", rate_n_flags); - - agg->wait_for_ba = 0; - } else { - /* Two or more frames were attempted; expect block-ack */ - u64 bitmap = 0; - int start = agg->start_idx; - struct sk_buff *skb; - - /* Construct bit-map of pending frames within Tx win */ - for (i = 0; i < agg->frame_count; i++) { - u16 sc; - status = le16_to_cpu(frame_status[i].status); - seq = le16_to_cpu(frame_status[i].sequence); - idx = SEQ_TO_IDX(seq); - txq_id = SEQ_TO_QUEUE(seq); - - if (status & - (AGG_TX_STATE_FEW_BYTES_MSK | - AGG_TX_STATE_ABORT_MSK)) - continue; - - D_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n", - agg->frame_count, txq_id, idx); - - skb = il->txq[txq_id].skbs[idx]; - if (WARN_ON_ONCE(skb == NULL)) - return -1; - hdr = (struct ieee80211_hdr *) skb->data; - - sc = le16_to_cpu(hdr->seq_ctrl); - if (idx != (SEQ_TO_SN(sc) & 0xff)) { - IL_ERR("BUG_ON idx doesn't match seq control" - " idx=%d, seq_idx=%d, seq=%d\n", idx, - SEQ_TO_SN(sc), hdr->seq_ctrl); - return -1; - } - - D_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n", i, idx, - SEQ_TO_SN(sc)); - - sh = idx - start; - if (sh > 64) { - sh = (start - idx) + 0xff; - bitmap = bitmap << sh; - sh = 0; - start = idx; - } else if (sh < -64) - sh = 0xff - (start - idx); - else if (sh < 0) { - sh = start - idx; - start = idx; - bitmap = bitmap << sh; - sh = 0; - } - bitmap |= 1ULL << sh; - D_TX_REPLY("start=%d bitmap=0x%llx\n", start, - (unsigned long long)bitmap); - } - - agg->bitmap = bitmap; - agg->start_idx = start; - D_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n", - agg->frame_count, agg->start_idx, - (unsigned long long)agg->bitmap); - - if (bitmap) - agg->wait_for_ba = 1; - } - return 0; -} - -/** - * il4965_hdl_tx - Handle standard (non-aggregation) Tx response - */ -static void -il4965_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb) -{ - struct il_rx_pkt *pkt = rxb_addr(rxb); - u16 sequence = le16_to_cpu(pkt->hdr.sequence); - int txq_id = SEQ_TO_QUEUE(sequence); - int idx = SEQ_TO_IDX(sequence); - struct il_tx_queue *txq = &il->txq[txq_id]; - struct sk_buff *skb; - struct ieee80211_hdr *hdr; - struct ieee80211_tx_info *info; - struct il4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - u32 status = le32_to_cpu(tx_resp->u.status); - int uninitialized_var(tid); - int sta_id; - int freed; - u8 *qc = NULL; - unsigned long flags; - - if (idx >= txq->q.n_bd || il_queue_used(&txq->q, idx) == 0) { - IL_ERR("Read idx for DMA queue txq_id (%d) idx %d " - "is out of range [0-%d] %d %d\n", txq_id, idx, - txq->q.n_bd, txq->q.write_ptr, txq->q.read_ptr); - return; - } - - txq->time_stamp = jiffies; - - skb = txq->skbs[txq->q.read_ptr]; - info = IEEE80211_SKB_CB(skb); - memset(&info->status, 0, sizeof(info->status)); - - hdr = (struct ieee80211_hdr *) skb->data; - if (ieee80211_is_data_qos(hdr->frame_control)) { - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; - } - - sta_id = il4965_get_ra_sta_id(il, hdr); - if (txq->sched_retry && unlikely(sta_id == IL_INVALID_STATION)) { - IL_ERR("Station not known\n"); - return; - } - - spin_lock_irqsave(&il->sta_lock, flags); - if (txq->sched_retry) { - const u32 scd_ssn = il4965_get_scd_ssn(tx_resp); - struct il_ht_agg *agg = NULL; - WARN_ON(!qc); - - agg = &il->stations[sta_id].tid[tid].agg; - - il4965_tx_status_reply_tx(il, agg, tx_resp, txq_id, idx); - - /* check if BAR is needed */ - if (tx_resp->frame_count == 1 && - !il4965_is_tx_success(status)) - info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - - if (txq->q.read_ptr != (scd_ssn & 0xff)) { - idx = il_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); - D_TX_REPLY("Retry scheduler reclaim scd_ssn " - "%d idx %d\n", scd_ssn, idx); - freed = il4965_tx_queue_reclaim(il, txq_id, idx); - if (qc) - il4965_free_tfds_in_queue(il, sta_id, tid, - freed); - - if (il->mac80211_registered && - il_queue_space(&txq->q) > txq->q.low_mark && - agg->state != IL_EMPTYING_HW_QUEUE_DELBA) - il_wake_queue(il, txq); - } - } else { - info->status.rates[0].count = tx_resp->failure_frame + 1; - info->flags |= il4965_tx_status_to_mac80211(status); - il4965_hwrate_to_tx_control(il, - le32_to_cpu(tx_resp->rate_n_flags), - info); - - D_TX_REPLY("TXQ %d status %s (0x%08x) " - "rate_n_flags 0x%x retries %d\n", txq_id, - il4965_get_tx_fail_reason(status), status, - le32_to_cpu(tx_resp->rate_n_flags), - tx_resp->failure_frame); - - freed = il4965_tx_queue_reclaim(il, txq_id, idx); - if (qc && likely(sta_id != IL_INVALID_STATION)) - il4965_free_tfds_in_queue(il, sta_id, tid, freed); - else if (sta_id == IL_INVALID_STATION) - D_TX_REPLY("Station not known\n"); - - if (il->mac80211_registered && - il_queue_space(&txq->q) > txq->q.low_mark) - il_wake_queue(il, txq); - } - if (qc && likely(sta_id != IL_INVALID_STATION)) - il4965_txq_check_empty(il, sta_id, tid, txq_id); - - il4965_check_abort_status(il, tx_resp->frame_count, status); - - spin_unlock_irqrestore(&il->sta_lock, flags); -} - /** * translate ucode response to mac80211 tx status control values */ @@ -3646,8 +3352,8 @@ il4965_sta_modify_sleep_tx_count(struct il_priv *il, int sta_id, int cnt) void il4965_update_chain_flags(struct il_priv *il) { - if (il->ops->set_rxon_chain) { - il->ops->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) { + il->ops->hcmd->set_rxon_chain(il); if (il->active.rx_chain != il->staging.rx_chain) il_commit_rxon(il); } @@ -4020,9 +3726,9 @@ il4965_hdl_alive(struct il_priv *il, struct il_rx_buf *rxb) * This callback is provided in order to send a stats request. * * This timer function is continually reset to execute within - * 60 seconds since the last N_STATS was received. We need to - * ensure we receive the stats in order to update the temperature - * used for calibrating the TXPOWER. + * REG_RECALIB_PERIOD seconds since the last N_STATS + * was received. We need to ensure we receive the stats in order + * to update the temperature used for calibrating the TXPOWER. */ static void il4965_bg_stats_periodic(unsigned long data) @@ -4072,7 +3778,7 @@ il4965_perform_ct_kill_task(struct il_priv *il) _il_rd(il, CSR_UCODE_DRV_GP1); spin_lock_irqsave(&il->reg_lock, flags); - if (likely(_il_grab_nic_access(il))) + if (!_il_grab_nic_access(il)) _il_release_nic_access(il); spin_unlock_irqrestore(&il->reg_lock, flags); } @@ -4110,17 +3816,17 @@ il4965_hdl_card_state(struct il_priv *il, struct il_rx_buf *rxb) il4965_perform_ct_kill_task(il); if (flags & HW_CARD_DISABLED) - set_bit(S_RFKILL, &il->status); + set_bit(S_RF_KILL_HW, &il->status); else - clear_bit(S_RFKILL, &il->status); + clear_bit(S_RF_KILL_HW, &il->status); if (!(flags & RXON_CARD_DISABLED)) il_scan_cancel(il); - if ((test_bit(S_RFKILL, &status) != - test_bit(S_RFKILL, &il->status))) + if ((test_bit(S_RF_KILL_HW, &status) != + test_bit(S_RF_KILL_HW, &il->status))) wiphy_rfkill_set_hw_state(il->hw->wiphy, - test_bit(S_RFKILL, &il->status)); + test_bit(S_RF_KILL_HW, &il->status)); else wake_up(&il->wait_command_queue); } @@ -4162,11 +3868,10 @@ il4965_setup_handlers(struct il_priv *il) /* Rx handlers */ il->handlers[N_RX_PHY] = il4965_hdl_rx_phy; il->handlers[N_RX_MPDU] = il4965_hdl_rx; - il->handlers[N_RX] = il4965_hdl_rx; /* block ack */ il->handlers[N_COMPRESSED_BA] = il4965_hdl_compressed_ba; - /* Tx response */ - il->handlers[C_TX] = il4965_hdl_tx; + /* Set up hardware specific Rx handlers */ + il->ops->lib->handler_setup(il); } /** @@ -4396,8 +4101,9 @@ il4965_irq_tasklet(struct il_priv *il) /* HW RF KILL switch toggled */ if (inta & CSR_INT_BIT_RF_KILL) { int hw_rf_kill = 0; - - if (!(_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) + if (! + (_il_rd(il, CSR_GP_CNTRL) & + CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) hw_rf_kill = 1; IL_WARN("RF_KILL bit toggled to %s.\n", @@ -4412,9 +4118,9 @@ il4965_irq_tasklet(struct il_priv *il) */ if (!test_bit(S_ALIVE, &il->status)) { if (hw_rf_kill) - set_bit(S_RFKILL, &il->status); + set_bit(S_RF_KILL_HW, &il->status); else - clear_bit(S_RFKILL, &il->status); + clear_bit(S_RF_KILL_HW, &il->status); wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill); } @@ -4538,9 +4244,11 @@ il4965_store_debug_level(struct device *d, struct device_attribute *attr, ret = strict_strtoul(buf, 0, &val); if (ret) IL_ERR("%s is not in hex or decimal form.\n", buf); - else + else { il->debug_level = val; - + if (il_alloc_traffic_mem(il)) + IL_ERR("Not enough memory to generate traffic log\n"); + } return strnlen(buf, count); } @@ -5065,7 +4773,7 @@ il4965_dump_nic_error_log(struct il_priv *il) else base = le32_to_cpu(il->card_alive.error_event_table_ptr); - if (!il->ops->is_valid_rtc_data_addr(base)) { + if (!il->ops->lib->is_valid_rtc_data_addr(base)) { IL_ERR("Not valid error log pointer 0x%08X for %s uCode\n", base, (il->ucode_type == UCODE_INIT) ? "Init" : "RT"); return; @@ -5294,8 +5002,8 @@ il4965_alive_start(struct il_priv *il) /* Initialize our rx_config data */ il_connection_init_rx_config(il); - if (il->ops->set_rxon_chain) - il->ops->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); } /* Configure bluetooth coexistence if enabled */ @@ -5383,8 +5091,12 @@ __il4965_down(struct il_priv *il) * clear all bits but the RF Kill bit and return */ if (!il_is_init(il)) { il->status = - test_bit(S_RFKILL, &il->status) << S_RFKILL | - test_bit(S_GEO_CONFIGURED, &il->status) << S_GEO_CONFIGURED | + test_bit(S_RF_KILL_HW, + &il-> + status) << S_RF_KILL_HW | + test_bit(S_GEO_CONFIGURED, + &il-> + status) << S_GEO_CONFIGURED | test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING; goto exit; } @@ -5392,32 +5104,28 @@ __il4965_down(struct il_priv *il) /* ...otherwise clear out all the status bits but the RF Kill * bit and continue taking the NIC down. */ il->status &= - test_bit(S_RFKILL, &il->status) << S_RFKILL | - test_bit(S_GEO_CONFIGURED, &il->status) << S_GEO_CONFIGURED | - test_bit(S_FW_ERROR, &il->status) << S_FW_ERROR | + test_bit(S_RF_KILL_HW, + &il->status) << S_RF_KILL_HW | test_bit(S_GEO_CONFIGURED, + &il-> + status) << + S_GEO_CONFIGURED | test_bit(S_FW_ERROR, + &il-> + status) << S_FW_ERROR | test_bit(S_EXIT_PENDING, &il->status) << S_EXIT_PENDING; - /* - * We disabled and synchronized interrupt, and priv->mutex is taken, so - * here is the only thread which will program device registers, but - * still have lockdep assertions, so we are taking reg_lock. - */ - spin_lock_irq(&il->reg_lock); - /* FIXME: il_grab_nic_access if rfkill is off ? */ - il4965_txq_ctx_stop(il); il4965_rxq_stop(il); + /* Power-down device's busmaster DMA clocks */ - _il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); + il_wr_prph(il, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT); udelay(5); + /* Make sure (redundant) we've released our request to stay awake */ - _il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - /* Stop the device, and put it in low power state */ - _il_apm_stop(il); + il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - spin_unlock_irq(&il->reg_lock); + /* Stop the device, and put it in low power state */ + il_apm_stop(il); - il4965_txq_ctx_unmap(il); exit: memset(&il->card_alive, 0, sizeof(struct il_alive_resp)); @@ -5438,36 +5146,40 @@ il4965_down(struct il_priv *il) il4965_cancel_deferred_work(il); } +#define HW_READY_TIMEOUT (50) -static void +static int il4965_set_hw_ready(struct il_priv *il) { - int ret; + int ret = 0; il_set_bit(il, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); /* See if we got it */ - ret = _il_poll_bit(il, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, - 100); - if (ret >= 0) + ret = + _il_poll_bit(il, CSR_HW_IF_CONFIG_REG, + CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, + CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, HW_READY_TIMEOUT); + if (ret != -ETIMEDOUT) il->hw_ready = true; + else + il->hw_ready = false; - D_INFO("hardware %s ready\n", (il->hw_ready) ? "" : "not"); + D_INFO("hardware %s\n", (il->hw_ready == 1) ? "ready" : "not ready"); + return ret; } -static void +static int il4965_prepare_card_hw(struct il_priv *il) { - int ret; + int ret = 0; - il->hw_ready = false; + D_INFO("il4965_prepare_card_hw enter\n"); - il4965_set_hw_ready(il); + ret = il4965_set_hw_ready(il); if (il->hw_ready) - return; + return ret; /* If HW is not ready, prepare the conditions to check again */ il_set_bit(il, CSR_HW_IF_CONFIG_REG, CSR_HW_IF_CONFIG_REG_PREPARE); @@ -5480,6 +5192,8 @@ il4965_prepare_card_hw(struct il_priv *il) /* HW should be ready by now, check again. */ if (ret != -ETIMEDOUT) il4965_set_hw_ready(il); + + return ret; } #define MAX_HW_RESTARTS 5 @@ -5507,19 +5221,22 @@ __il4965_up(struct il_priv *il) } il4965_prepare_card_hw(il); + if (!il->hw_ready) { - IL_ERR("HW not ready\n"); + IL_WARN("Exit HW not ready\n"); return -EIO; } /* If platform's RF_KILL switch is NOT set to KILL */ if (_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(S_RFKILL, &il->status); - else { - set_bit(S_RFKILL, &il->status); + clear_bit(S_RF_KILL_HW, &il->status); + else + set_bit(S_RF_KILL_HW, &il->status); + + if (il_is_rfkill(il)) { wiphy_rfkill_set_hw_state(il->hw->wiphy, true); - il_enable_rfkill_int(il); + il_enable_interrupts(il); IL_WARN("Radio disabled by HW RF Kill switch\n"); return 0; } @@ -5558,7 +5275,7 @@ __il4965_up(struct il_priv *il) /* load bootstrap state machine, * load bootstrap program into processor's memory, * prepare to load the "initialize" uCode */ - ret = il->ops->load_ucode(il); + ret = il->ops->lib->load_ucode(il); if (ret) { IL_ERR("Unable to set up bootstrap uCode: %d\n", ret); @@ -5599,7 +5316,7 @@ il4965_bg_init_alive_start(struct work_struct *data) if (test_bit(S_EXIT_PENDING, &il->status)) goto out; - il->ops->init_alive_start(il); + il->ops->lib->init_alive_start(il); out: mutex_unlock(&il->mutex); } @@ -6031,7 +5748,7 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, if (!il_is_associated(il)) goto out; - if (!il->ops->set_channel_switch) + if (!il->ops->lib->set_channel_switch) goto out; ch = channel->hw_value; @@ -6083,7 +5800,7 @@ il4965_mac_channel_switch(struct ieee80211_hw *hw, */ set_bit(S_CHANNEL_SWITCH_PENDING, &il->status); il->switch_channel = cpu_to_le16(ch); - if (il->ops->set_channel_switch(il, ch_switch)) { + if (il->ops->lib->set_channel_switch(il, ch_switch)) { clear_bit(S_CHANNEL_SWITCH_PENDING, &il->status); il->switch_channel = 0; ieee80211_chswitch_done(il->vif, false); @@ -6166,7 +5883,7 @@ il4965_bg_txpower_work(struct work_struct *work) /* Regardless of if we are associated, we must reconfigure the * TX power since frames can be sent on non-radar channels while * not associated */ - il->ops->send_tx_power(il); + il->ops->lib->send_tx_power(il); /* Update last_temperature to keep is_calib_needed from running * when it isn't needed... */ @@ -6318,8 +6035,8 @@ il4965_init_drv(struct il_priv *il) il->force_reset.reset_duration = IL_DELAY_NEXT_FORCE_FW_RELOAD; /* Choose which receivers/antennas to use */ - if (il->ops->set_rxon_chain) - il->ops->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); il_init_scan_params(il); @@ -6463,12 +6180,12 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) D_INFO("*** LOAD DRIVER ***\n"); il->cfg = cfg; il->ops = &il4965_ops; -#ifdef CONFIG_IWLEGACY_DEBUGFS - il->debugfs_ops = &il4965_debugfs_ops; -#endif il->pci_dev = pdev; il->inta_mask = CSR_INI_SET_MASK; + if (il_alloc_traffic_mem(il)) + IL_ERR("Not enough memory to generate traffic log\n"); + /************************** * 2. Initializing PCI bus **************************/ @@ -6507,7 +6224,7 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /*********************** * 3. Read REV register ***********************/ - il->hw_base = pci_ioremap_bar(pdev, 0); + il->hw_base = pci_iomap(pdev, 0, 0); if (!il->hw_base) { err = -ENODEV; goto out_pci_release_regions; @@ -6612,12 +6329,12 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* If platform's RF_KILL switch is NOT set to KILL */ if (_il_rd(il, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(S_RFKILL, &il->status); + clear_bit(S_RF_KILL_HW, &il->status); else - set_bit(S_RFKILL, &il->status); + set_bit(S_RF_KILL_HW, &il->status); wiphy_rfkill_set_hw_state(il->hw->wiphy, - test_bit(S_RFKILL, &il->status)); + test_bit(S_RF_KILL_HW, &il->status)); il_power_initialize(il); @@ -6639,13 +6356,14 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) out_free_eeprom: il_eeprom_free(il); out_iounmap: - iounmap(il->hw_base); + pci_iounmap(pdev, il->hw_base); out_pci_release_regions: pci_set_drvdata(pdev, NULL); pci_release_regions(pdev); out_pci_disable_device: pci_disable_device(pdev); out_ieee80211_free_hw: + il_free_traffic_mem(il); ieee80211_free_hw(il->hw); out: return err; @@ -6716,10 +6434,11 @@ il4965_pci_remove(struct pci_dev *pdev) * until now... */ destroy_workqueue(il->workqueue); il->workqueue = NULL; + il_free_traffic_mem(il); free_irq(il->pci_dev->irq, il); pci_disable_msi(il->pci_dev); - iounmap(il->hw_base); + pci_iounmap(pdev, il->hw_base); pci_release_regions(pdev); pci_disable_device(pdev); pci_set_drvdata(pdev, NULL); diff --git a/trunk/drivers/net/wireless/iwlegacy/4965.c b/trunk/drivers/net/wireless/iwlegacy/4965.c index 5db11714e047..79e4e7971338 100644 --- a/trunk/drivers/net/wireless/iwlegacy/4965.c +++ b/trunk/drivers/net/wireless/iwlegacy/4965.c @@ -264,6 +264,10 @@ il4965_led_enable(struct il_priv *il) _il_wr(il, CSR_LED_REG, CSR_LED_REG_TRUN_ON); } +const struct il_led_ops il4965_led_ops = { + .cmd = il4965_send_led_cmd, +}; + static int il4965_send_tx_power(struct il_priv *il); static int il4965_hw_get_temperature(struct il_priv *il); @@ -504,7 +508,7 @@ iw4965_is_ht40_channel(__le32 rxon_flags) chan_mod == CHANNEL_MODE_MIXED); } -void +static void il4965_nic_config(struct il_priv *il) { unsigned long flags; @@ -1674,7 +1678,7 @@ il4965_is_temp_calib_needed(struct il_priv *il) return 1; } -void +static void il4965_temperature_calib(struct il_priv *il) { s32 temp; @@ -1733,6 +1737,323 @@ il4965_build_addsta_hcmd(const struct il_addsta_cmd *cmd, u8 * data) return (u16) sizeof(struct il4965_addsta_cmd); } +static inline u32 +il4965_get_scd_ssn(struct il4965_tx_resp *tx_resp) +{ + return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN; +} + +static inline u32 +il4965_tx_status_to_mac80211(u32 status) +{ + status &= TX_STATUS_MSK; + + switch (status) { + case TX_STATUS_SUCCESS: + case TX_STATUS_DIRECT_DONE: + return IEEE80211_TX_STAT_ACK; + case TX_STATUS_FAIL_DEST_PS: + return IEEE80211_TX_STAT_TX_FILTERED; + default: + return 0; + } +} + +static inline bool +il4965_is_tx_success(u32 status) +{ + status &= TX_STATUS_MSK; + return (status == TX_STATUS_SUCCESS || status == TX_STATUS_DIRECT_DONE); +} + +/** + * il4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue + */ +static int +il4965_tx_status_reply_tx(struct il_priv *il, struct il_ht_agg *agg, + struct il4965_tx_resp *tx_resp, int txq_id, + u16 start_idx) +{ + u16 status; + struct agg_tx_status *frame_status = tx_resp->u.agg_status; + struct ieee80211_tx_info *info = NULL; + struct ieee80211_hdr *hdr = NULL; + u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); + int i, sh, idx; + u16 seq; + if (agg->wait_for_ba) + D_TX_REPLY("got tx response w/o block-ack\n"); + + agg->frame_count = tx_resp->frame_count; + agg->start_idx = start_idx; + agg->rate_n_flags = rate_n_flags; + agg->bitmap = 0; + + /* num frames attempted by Tx command */ + if (agg->frame_count == 1) { + /* Only one frame was attempted; no block-ack will arrive */ + status = le16_to_cpu(frame_status[0].status); + idx = start_idx; + + D_TX_REPLY("FrameCnt = %d, StartIdx=%d idx=%d\n", + agg->frame_count, agg->start_idx, idx); + + info = IEEE80211_SKB_CB(il->txq[txq_id].skbs[idx]); + info->status.rates[0].count = tx_resp->failure_frame + 1; + info->flags &= ~IEEE80211_TX_CTL_AMPDU; + info->flags |= il4965_tx_status_to_mac80211(status); + il4965_hwrate_to_tx_control(il, rate_n_flags, info); + + D_TX_REPLY("1 Frame 0x%x failure :%d\n", status & 0xff, + tx_resp->failure_frame); + D_TX_REPLY("Rate Info rate_n_flags=%x\n", rate_n_flags); + + agg->wait_for_ba = 0; + } else { + /* Two or more frames were attempted; expect block-ack */ + u64 bitmap = 0; + int start = agg->start_idx; + struct sk_buff *skb; + + /* Construct bit-map of pending frames within Tx win */ + for (i = 0; i < agg->frame_count; i++) { + u16 sc; + status = le16_to_cpu(frame_status[i].status); + seq = le16_to_cpu(frame_status[i].sequence); + idx = SEQ_TO_IDX(seq); + txq_id = SEQ_TO_QUEUE(seq); + + if (status & + (AGG_TX_STATE_FEW_BYTES_MSK | + AGG_TX_STATE_ABORT_MSK)) + continue; + + D_TX_REPLY("FrameCnt = %d, txq_id=%d idx=%d\n", + agg->frame_count, txq_id, idx); + + skb = il->txq[txq_id].skbs[idx]; + if (WARN_ON_ONCE(skb == NULL)) + return -1; + hdr = (struct ieee80211_hdr *) skb->data; + + sc = le16_to_cpu(hdr->seq_ctrl); + if (idx != (SEQ_TO_SN(sc) & 0xff)) { + IL_ERR("BUG_ON idx doesn't match seq control" + " idx=%d, seq_idx=%d, seq=%d\n", idx, + SEQ_TO_SN(sc), hdr->seq_ctrl); + return -1; + } + + D_TX_REPLY("AGG Frame i=%d idx %d seq=%d\n", i, idx, + SEQ_TO_SN(sc)); + + sh = idx - start; + if (sh > 64) { + sh = (start - idx) + 0xff; + bitmap = bitmap << sh; + sh = 0; + start = idx; + } else if (sh < -64) + sh = 0xff - (start - idx); + else if (sh < 0) { + sh = start - idx; + start = idx; + bitmap = bitmap << sh; + sh = 0; + } + bitmap |= 1ULL << sh; + D_TX_REPLY("start=%d bitmap=0x%llx\n", start, + (unsigned long long)bitmap); + } + + agg->bitmap = bitmap; + agg->start_idx = start; + D_TX_REPLY("Frames %d start_idx=%d bitmap=0x%llx\n", + agg->frame_count, agg->start_idx, + (unsigned long long)agg->bitmap); + + if (bitmap) + agg->wait_for_ba = 1; + } + return 0; +} + +static u8 +il4965_find_station(struct il_priv *il, const u8 * addr) +{ + int i; + int start = 0; + int ret = IL_INVALID_STATION; + unsigned long flags; + + if ((il->iw_mode == NL80211_IFTYPE_ADHOC)) + start = IL_STA_ID; + + if (is_broadcast_ether_addr(addr)) + return il->hw_params.bcast_id; + + spin_lock_irqsave(&il->sta_lock, flags); + for (i = start; i < il->hw_params.max_stations; i++) + if (il->stations[i].used && + (!compare_ether_addr(il->stations[i].sta.sta.addr, addr))) { + ret = i; + goto out; + } + + D_ASSOC("can not find STA %pM total %d\n", addr, il->num_stations); + +out: + /* + * It may be possible that more commands interacting with stations + * arrive before we completed processing the adding of + * station + */ + if (ret != IL_INVALID_STATION && + (!(il->stations[ret].used & IL_STA_UCODE_ACTIVE) || + ((il->stations[ret].used & IL_STA_UCODE_ACTIVE) && + (il->stations[ret].used & IL_STA_UCODE_INPROGRESS)))) { + IL_ERR("Requested station info for sta %d before ready.\n", + ret); + ret = IL_INVALID_STATION; + } + spin_unlock_irqrestore(&il->sta_lock, flags); + return ret; +} + +static int +il4965_get_ra_sta_id(struct il_priv *il, struct ieee80211_hdr *hdr) +{ + if (il->iw_mode == NL80211_IFTYPE_STATION) { + return IL_AP_ID; + } else { + u8 *da = ieee80211_get_DA(hdr); + return il4965_find_station(il, da); + } +} + +/** + * il4965_hdl_tx - Handle standard (non-aggregation) Tx response + */ +static void +il4965_hdl_tx(struct il_priv *il, struct il_rx_buf *rxb) +{ + struct il_rx_pkt *pkt = rxb_addr(rxb); + u16 sequence = le16_to_cpu(pkt->hdr.sequence); + int txq_id = SEQ_TO_QUEUE(sequence); + int idx = SEQ_TO_IDX(sequence); + struct il_tx_queue *txq = &il->txq[txq_id]; + struct sk_buff *skb; + struct ieee80211_hdr *hdr; + struct ieee80211_tx_info *info; + struct il4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; + u32 status = le32_to_cpu(tx_resp->u.status); + int uninitialized_var(tid); + int sta_id; + int freed; + u8 *qc = NULL; + unsigned long flags; + + if (idx >= txq->q.n_bd || il_queue_used(&txq->q, idx) == 0) { + IL_ERR("Read idx for DMA queue txq_id (%d) idx %d " + "is out of range [0-%d] %d %d\n", txq_id, idx, + txq->q.n_bd, txq->q.write_ptr, txq->q.read_ptr); + return; + } + + txq->time_stamp = jiffies; + + skb = txq->skbs[txq->q.read_ptr]; + info = IEEE80211_SKB_CB(skb); + memset(&info->status, 0, sizeof(info->status)); + + hdr = (struct ieee80211_hdr *) skb->data; + if (ieee80211_is_data_qos(hdr->frame_control)) { + qc = ieee80211_get_qos_ctl(hdr); + tid = qc[0] & 0xf; + } + + sta_id = il4965_get_ra_sta_id(il, hdr); + if (txq->sched_retry && unlikely(sta_id == IL_INVALID_STATION)) { + IL_ERR("Station not known\n"); + return; + } + + spin_lock_irqsave(&il->sta_lock, flags); + if (txq->sched_retry) { + const u32 scd_ssn = il4965_get_scd_ssn(tx_resp); + struct il_ht_agg *agg = NULL; + WARN_ON(!qc); + + agg = &il->stations[sta_id].tid[tid].agg; + + il4965_tx_status_reply_tx(il, agg, tx_resp, txq_id, idx); + + /* check if BAR is needed */ + if ((tx_resp->frame_count == 1) && + !il4965_is_tx_success(status)) + info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + + if (txq->q.read_ptr != (scd_ssn & 0xff)) { + idx = il_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); + D_TX_REPLY("Retry scheduler reclaim scd_ssn " + "%d idx %d\n", scd_ssn, idx); + freed = il4965_tx_queue_reclaim(il, txq_id, idx); + if (qc) + il4965_free_tfds_in_queue(il, sta_id, tid, + freed); + + if (il->mac80211_registered && + il_queue_space(&txq->q) > txq->q.low_mark && + agg->state != IL_EMPTYING_HW_QUEUE_DELBA) + il_wake_queue(il, txq); + } + } else { + info->status.rates[0].count = tx_resp->failure_frame + 1; + info->flags |= il4965_tx_status_to_mac80211(status); + il4965_hwrate_to_tx_control(il, + le32_to_cpu(tx_resp->rate_n_flags), + info); + + D_TX_REPLY("TXQ %d status %s (0x%08x) " + "rate_n_flags 0x%x retries %d\n", txq_id, + il4965_get_tx_fail_reason(status), status, + le32_to_cpu(tx_resp->rate_n_flags), + tx_resp->failure_frame); + + freed = il4965_tx_queue_reclaim(il, txq_id, idx); + if (qc && likely(sta_id != IL_INVALID_STATION)) + il4965_free_tfds_in_queue(il, sta_id, tid, freed); + else if (sta_id == IL_INVALID_STATION) + D_TX_REPLY("Station not known\n"); + + if (il->mac80211_registered && + il_queue_space(&txq->q) > txq->q.low_mark) + il_wake_queue(il, txq); + } + if (qc && likely(sta_id != IL_INVALID_STATION)) + il4965_txq_check_empty(il, sta_id, tid, txq_id); + + il4965_check_abort_status(il, tx_resp->frame_count, status); + + spin_unlock_irqrestore(&il->sta_lock, flags); +} + +/* Set up 4965-specific Rx frame reply handlers */ +static void +il4965_handler_setup(struct il_priv *il) +{ + /* Legacy Rx frames */ + il->handlers[N_RX] = il4965_hdl_rx; + /* Tx response */ + il->handlers[C_TX] = il4965_hdl_tx; +} + +static struct il_hcmd_ops il4965_hcmd = { + .rxon_assoc = il4965_send_rxon_assoc, + .commit_rxon = il4965_commit_rxon, + .set_rxon_chain = il4965_set_rxon_chain, +}; + static void il4965_post_scan(struct il_priv *il) { @@ -1772,8 +2093,8 @@ il4965_post_associate(struct il_priv *il) il_set_rxon_ht(il, &il->current_ht_config); - if (il->ops->set_rxon_chain) - il->ops->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); il->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid); @@ -1847,8 +2168,8 @@ il4965_config_ap(struct il_priv *il) /* AP has all antennas */ il->chain_noise_data.active_chains = il->hw_params.valid_rx_ant; il_set_rxon_ht(il, &il->current_ht_config); - if (il->ops->set_rxon_chain) - il->ops->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); il->staging.assoc_id = 0; @@ -1872,38 +2193,68 @@ il4965_config_ap(struct il_priv *il) il4965_send_beacon_cmd(il); } -const struct il_ops il4965_ops = { +static struct il_hcmd_utils_ops il4965_hcmd_utils = { + .get_hcmd_size = il4965_get_hcmd_size, + .build_addsta_hcmd = il4965_build_addsta_hcmd, + .request_scan = il4965_request_scan, + .post_scan = il4965_post_scan, +}; + +static struct il_lib_ops il4965_lib = { .txq_update_byte_cnt_tbl = il4965_txq_update_byte_cnt_tbl, .txq_attach_buf_to_tfd = il4965_hw_txq_attach_buf_to_tfd, .txq_free_tfd = il4965_hw_txq_free_tfd, .txq_init = il4965_hw_tx_queue_init, + .handler_setup = il4965_handler_setup, .is_valid_rtc_data_addr = il4965_hw_valid_rtc_data_addr, .init_alive_start = il4965_init_alive_start, .load_ucode = il4965_load_bsm, .dump_nic_error_log = il4965_dump_nic_error_log, .dump_fh = il4965_dump_fh, .set_channel_switch = il4965_hw_channel_switch, - .apm_init = il_apm_init, + .apm_ops = { + .init = il_apm_init, + .config = il4965_nic_config, + }, + .eeprom_ops = { + .regulatory_bands = { + EEPROM_REGULATORY_BAND_1_CHANNELS, + EEPROM_REGULATORY_BAND_2_CHANNELS, + EEPROM_REGULATORY_BAND_3_CHANNELS, + EEPROM_REGULATORY_BAND_4_CHANNELS, + EEPROM_REGULATORY_BAND_5_CHANNELS, + EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS, + EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS}, + .acquire_semaphore = il4965_eeprom_acquire_semaphore, + .release_semaphore = il4965_eeprom_release_semaphore, + }, .send_tx_power = il4965_send_tx_power, .update_chain_flags = il4965_update_chain_flags, - .eeprom_acquire_semaphore = il4965_eeprom_acquire_semaphore, - .eeprom_release_semaphore = il4965_eeprom_release_semaphore, - - .rxon_assoc = il4965_send_rxon_assoc, - .commit_rxon = il4965_commit_rxon, - .set_rxon_chain = il4965_set_rxon_chain, - - .get_hcmd_size = il4965_get_hcmd_size, - .build_addsta_hcmd = il4965_build_addsta_hcmd, - .request_scan = il4965_request_scan, - .post_scan = il4965_post_scan, + .temp_ops = { + .temperature = il4965_temperature_calib, + }, +#ifdef CONFIG_IWLEGACY_DEBUGFS + .debugfs_ops = { + .rx_stats_read = il4965_ucode_rx_stats_read, + .tx_stats_read = il4965_ucode_tx_stats_read, + .general_stats_read = il4965_ucode_general_stats_read, + }, +#endif +}; +static const struct il_legacy_ops il4965_legacy_ops = { .post_associate = il4965_post_associate, .config_ap = il4965_config_ap, .manage_ibss_station = il4965_manage_ibss_station, .update_bcast_stations = il4965_update_bcast_stations, +}; - .send_led_cmd = il4965_send_led_cmd, +const struct il_ops il4965_ops = { + .lib = &il4965_lib, + .hcmd = &il4965_hcmd, + .utils = &il4965_hcmd_utils, + .led = &il4965_led_ops, + .legacy = &il4965_legacy_ops, }; struct il_cfg il4965_cfg = { @@ -1937,17 +2288,6 @@ struct il_cfg il4965_cfg = { .ucode_tracing = true, .sensitivity_calib_by_driver = true, .chain_noise_calib_by_driver = true, - - .regulatory_bands = { - EEPROM_REGULATORY_BAND_1_CHANNELS, - EEPROM_REGULATORY_BAND_2_CHANNELS, - EEPROM_REGULATORY_BAND_3_CHANNELS, - EEPROM_REGULATORY_BAND_4_CHANNELS, - EEPROM_REGULATORY_BAND_5_CHANNELS, - EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS, - EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS - }, - }; /* Module firmware */ diff --git a/trunk/drivers/net/wireless/iwlegacy/4965.h b/trunk/drivers/net/wireless/iwlegacy/4965.h index 208a4564d063..83ab60496388 100644 --- a/trunk/drivers/net/wireless/iwlegacy/4965.h +++ b/trunk/drivers/net/wireless/iwlegacy/4965.h @@ -60,8 +60,6 @@ int il4965_rx_init(struct il_priv *il, struct il_rx_queue *rxq); int il4965_hw_nic_init(struct il_priv *il); int il4965_dump_fh(struct il_priv *il, char **buf, bool display); -void il4965_nic_config(struct il_priv *il); - /* rx */ void il4965_rx_queue_restock(struct il_priv *il); void il4965_rx_replenish(struct il_priv *il); @@ -69,6 +67,8 @@ void il4965_rx_replenish_now(struct il_priv *il); void il4965_rx_queue_free(struct il_priv *il, struct il_rx_queue *rxq); int il4965_rxq_stop(struct il_priv *il); int il4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); +void il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb); +void il4965_hdl_rx_phy(struct il_priv *il, struct il_rx_buf *rxb); void il4965_rx_handle(struct il_priv *il); /* tx */ @@ -84,6 +84,7 @@ int il4965_tx_agg_start(struct il_priv *il, struct ieee80211_vif *vif, int il4965_tx_agg_stop(struct il_priv *il, struct ieee80211_vif *vif, struct ieee80211_sta *sta, u16 tid); int il4965_txq_check_empty(struct il_priv *il, int sta_id, u8 tid, int txq_id); +void il4965_hdl_compressed_ba(struct il_priv *il, struct il_rx_buf *rxb); int il4965_tx_queue_reclaim(struct il_priv *il, int txq_id, int idx); void il4965_hw_txq_ctx_free(struct il_priv *il); int il4965_txq_ctx_alloc(struct il_priv *il); @@ -105,6 +106,12 @@ void il4965_set_wr_ptrs(struct il_priv *il, int txq_id, u32 idx); void il4965_tx_queue_set_status(struct il_priv *il, struct il_tx_queue *txq, int tx_fifo_id, int scd_retry); +/* rx */ +void il4965_hdl_missed_beacon(struct il_priv *il, struct il_rx_buf *rxb); +bool il4965_good_plcp_health(struct il_priv *il, struct il_rx_pkt *pkt); +void il4965_hdl_stats(struct il_priv *il, struct il_rx_buf *rxb); +void il4965_hdl_c_stats(struct il_priv *il, struct il_rx_buf *rxb); + /* scan */ int il4965_request_scan(struct il_priv *il, struct ieee80211_vif *vif); @@ -268,7 +275,6 @@ il4965_hw_valid_rtc_data_addr(u32 addr) ((t) < IL_TX_POWER_TEMPERATURE_MIN || \ (t) > IL_TX_POWER_TEMPERATURE_MAX) -extern void il4965_temperature_calib(struct il_priv *il); /********************* END TEMPERATURE ***************************************/ /********************* START TXPOWER *****************************************/ @@ -931,7 +937,13 @@ void il4965_calib_free_results(struct il_priv *il); /* Debug */ #ifdef CONFIG_IWLEGACY_DEBUGFS -extern const struct il_debugfs_ops il4965_debugfs_ops; +ssize_t il4965_ucode_rx_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); +ssize_t il4965_ucode_tx_stats_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); +ssize_t il4965_ucode_general_stats_read(struct file *file, + char __user *user_buf, size_t count, + loff_t *ppos); #endif /****************************/ diff --git a/trunk/drivers/net/wireless/iwlegacy/common.c b/trunk/drivers/net/wireless/iwlegacy/common.c index b42052b47d8e..04ec38e5eaaf 100644 --- a/trunk/drivers/net/wireless/iwlegacy/common.c +++ b/trunk/drivers/net/wireless/iwlegacy/common.c @@ -81,7 +81,7 @@ il_clear_bit(struct il_priv *p, u32 r, u32 m) } EXPORT_SYMBOL(il_clear_bit); -bool +int _il_grab_nic_access(struct il_priv *il) { int ret; @@ -111,15 +111,14 @@ _il_grab_nic_access(struct il_priv *il) _il_poll_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); - if (unlikely(ret < 0)) { + if (ret < 0) { val = _il_rd(il, CSR_GP_CNTRL); - WARN_ONCE(1, "Timeout waiting for ucode processor access " - "(CSR_GP_CNTRL 0x%08x)\n", val); + IL_ERR("MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); _il_wr(il, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); - return false; + return -EIO; } - return true; + return 0; } EXPORT_SYMBOL_GPL(_il_grab_nic_access); @@ -161,7 +160,7 @@ il_wr_prph(struct il_priv *il, u32 addr, u32 val) unsigned long reg_flags; spin_lock_irqsave(&il->reg_lock, reg_flags); - if (likely(_il_grab_nic_access(il))) { + if (!_il_grab_nic_access(il)) { _il_wr_prph(il, addr, val); _il_release_nic_access(il); } @@ -179,6 +178,7 @@ il_read_targ_mem(struct il_priv *il, u32 addr) _il_grab_nic_access(il); _il_wr(il, HBUS_TARG_MEM_RADDR, addr); + rmb(); value = _il_rd(il, HBUS_TARG_MEM_RDAT); _il_release_nic_access(il); @@ -193,8 +193,9 @@ il_write_targ_mem(struct il_priv *il, u32 addr, u32 val) unsigned long reg_flags; spin_lock_irqsave(&il->reg_lock, reg_flags); - if (likely(_il_grab_nic_access(il))) { + if (!_il_grab_nic_access(il)) { _il_wr(il, HBUS_TARG_MEM_WADDR, addr); + wmb(); _il_wr(il, HBUS_TARG_MEM_WDAT, val); _il_release_nic_access(il); } @@ -350,7 +351,7 @@ il_send_cmd_sync(struct il_priv *il, struct il_host_cmd *cmd) } } - if (test_bit(S_RFKILL, &il->status)) { + if (test_bit(S_RF_KILL_HW, &il->status)) { IL_ERR("Command %s aborted: RF KILL Switch\n", il_get_cmd_string(cmd->id)); ret = -ECANCELED; @@ -519,7 +520,7 @@ il_led_cmd(struct il_priv *il, unsigned long on, unsigned long off) il_blink_compensation(il, off, il->cfg->led_compensation); - ret = il->ops->send_led_cmd(il, &led_cmd); + ret = il->ops->led->cmd(il, &led_cmd); if (!ret) { il->blink_on = on; il->blink_off = off; @@ -730,7 +731,7 @@ il_eeprom_init(struct il_priv *il) } e = (__le16 *) il->eeprom; - il->ops->apm_init(il); + il->ops->lib->apm_ops.init(il); ret = il_eeprom_verify_signature(il); if (ret < 0) { @@ -740,7 +741,7 @@ il_eeprom_init(struct il_priv *il) } /* Make sure driver (instead of uCode) is allowed to read EEPROM */ - ret = il->ops->eeprom_acquire_semaphore(il); + ret = il->ops->lib->eeprom_ops.acquire_semaphore(il); if (ret < 0) { IL_ERR("Failed to acquire EEPROM semaphore.\n"); ret = -ENOENT; @@ -772,7 +773,7 @@ il_eeprom_init(struct il_priv *il) ret = 0; done: - il->ops->eeprom_release_semaphore(il); + il->ops->lib->eeprom_ops.release_semaphore(il); err: if (ret) @@ -798,8 +799,8 @@ il_init_band_reference(const struct il_priv *il, int eep_band, const struct il_eeprom_channel **eeprom_ch_info, const u8 **eeprom_ch_idx) { - u32 offset = il->cfg->regulatory_bands[eep_band - 1]; - + u32 offset = + il->ops->lib->eeprom_ops.regulatory_bands[eep_band - 1]; switch (eep_band) { case 1: /* 2.4GHz band */ *eeprom_ch_count = ARRAY_SIZE(il_eeprom_band_1); @@ -1000,8 +1001,10 @@ il_init_channel_map(struct il_priv *il) } /* Check if we do have HT40 channels */ - if (il->cfg->regulatory_bands[5] == EEPROM_REGULATORY_BAND_NO_HT40 && - il->cfg->regulatory_bands[6] == EEPROM_REGULATORY_BAND_NO_HT40) + if (il->ops->lib->eeprom_ops.regulatory_bands[5] == + EEPROM_REGULATORY_BAND_NO_HT40 && + il->ops->lib->eeprom_ops.regulatory_bands[6] == + EEPROM_REGULATORY_BAND_NO_HT40) return 0; /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ @@ -1155,9 +1158,9 @@ il_power_set_mode(struct il_priv *il, struct il_powertable_cmd *cmd, bool force) if (!(cmd->flags & IL_POWER_DRIVER_ALLOW_SLEEP_MSK)) clear_bit(S_POWER_PMI, &il->status); - if (il->ops->update_chain_flags && update_chains) - il->ops->update_chain_flags(il); - else if (il->ops->update_chain_flags) + if (il->ops->lib->update_chain_flags && update_chains) + il->ops->lib->update_chain_flags(il); + else if (il->ops->lib->update_chain_flags) D_POWER("Cannot update the power, chain noise " "calibration running: %d\n", il->chain_noise_data.state); @@ -1482,6 +1485,9 @@ il_scan_initiate(struct il_priv *il, struct ieee80211_vif *vif) lockdep_assert_held(&il->mutex); + if (WARN_ON(!il->ops->utils->request_scan)) + return -EOPNOTSUPP; + cancel_delayed_work(&il->scan_check); if (!il_is_ready_rf(il)) { @@ -1504,7 +1510,7 @@ il_scan_initiate(struct il_priv *il, struct ieee80211_vif *vif) set_bit(S_SCANNING, &il->status); il->scan_start = jiffies; - ret = il->ops->request_scan(il, vif); + ret = il->ops->utils->request_scan(il, vif); if (ret) { clear_bit(S_SCANNING, &il->status); return ret; @@ -1523,13 +1529,12 @@ il_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct il_priv *il = hw->priv; int ret; - if (req->n_channels == 0) { - IL_ERR("Can not scan on no channels.\n"); + D_MAC80211("enter\n"); + + if (req->n_channels == 0) return -EINVAL; - } mutex_lock(&il->mutex); - D_MAC80211("enter\n"); if (test_bit(S_SCANNING, &il->status)) { D_SCAN("Scan already in progress.\n"); @@ -1544,8 +1549,9 @@ il_mac_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ret = il_scan_initiate(il, vif); + D_MAC80211("leave\n"); + out_unlock: - D_MAC80211("leave ret %d\n", ret); mutex_unlock(&il->mutex); return ret; @@ -1666,7 +1672,7 @@ il_bg_scan_completed(struct work_struct *work) il_power_set_mode(il, &il->power_data.sleep_cmd_next, false); il_set_tx_power(il, il->tx_power_next, false); - il->ops->post_scan(il); + il->ops->utils->post_scan(il); out: mutex_unlock(&il->mutex); @@ -1808,7 +1814,7 @@ il_send_add_sta(struct il_priv *il, struct il_addsta_cmd *sta, u8 flags) might_sleep(); } - cmd.len = il->ops->build_addsta_hcmd(sta, data); + cmd.len = il->ops->utils->build_addsta_hcmd(sta, data); ret = il_send_cmd(il, &cmd); if (ret || (flags & CMD_ASYNC)) @@ -2413,16 +2419,13 @@ il_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct il_station_priv_common *sta_common = (void *)sta->drv_priv; int ret; + D_INFO("received request to remove station %pM\n", sta->addr); mutex_lock(&il->mutex); - D_MAC80211("enter station %pM\n", sta->addr); - + D_INFO("proceeding to remove station %pM\n", sta->addr); ret = il_remove_station(il, sta_common->sta_id, sta->addr); if (ret) IL_ERR("Error removing station %pM\n", sta->addr); - - D_MAC80211("leave ret %d\n", ret); mutex_unlock(&il->mutex); - return ret; } EXPORT_SYMBOL(il_mac_sta_remove); @@ -2719,7 +2722,7 @@ il_tx_queue_unmap(struct il_priv *il, int txq_id) return; while (q->write_ptr != q->read_ptr) { - il->ops->txq_free_tfd(il, txq); + il->ops->lib->txq_free_tfd(il, txq); q->read_ptr = il_queue_inc_wrap(q->read_ptr, q->n_bd); } } @@ -2887,22 +2890,20 @@ EXPORT_SYMBOL(il_queue_space); * il_queue_init - Initialize queue's high/low-water and read/write idxes */ static int -il_queue_init(struct il_priv *il, struct il_queue *q, int slots, u32 id) +il_queue_init(struct il_priv *il, struct il_queue *q, int count, int slots_num, + u32 id) { - /* - * TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise - * il_queue_inc_wrap and il_queue_dec_wrap are broken. - */ - BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); - /* FIXME: remove q->n_bd */ - q->n_bd = TFD_QUEUE_SIZE_MAX; - - q->n_win = slots; + q->n_bd = count; + q->n_win = slots_num; q->id = id; - /* slots_must be power-of-two size, otherwise + /* count must be power-of-two size, otherwise il_queue_inc_wrap + * and il_queue_dec_wrap are broken. */ + BUG_ON(!is_power_of_2(count)); + + /* slots_num must be power-of-two size, otherwise * il_get_cmd_idx is broken. */ - BUG_ON(!is_power_of_2(slots)); + BUG_ON(!is_power_of_2(slots_num)); q->low_mark = q->n_win / 4; if (q->low_mark < 4) @@ -2961,11 +2962,12 @@ il_tx_queue_alloc(struct il_priv *il, struct il_tx_queue *txq, u32 id) * il_tx_queue_init - Allocate and initialize one tx/cmd queue */ int -il_tx_queue_init(struct il_priv *il, u32 txq_id) +il_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq, int slots_num, + u32 txq_id) { - int i, len, ret; - int slots, actual_slots; - struct il_tx_queue *txq = &il->txq[txq_id]; + int i, len; + int ret; + int actual_slots = slots_num; /* * Alloc buffer array for commands (Tx or other types of commands). @@ -2975,13 +2977,8 @@ il_tx_queue_init(struct il_priv *il, u32 txq_id) * For normal Tx queues (all other queues), no super-size command * space is needed. */ - if (txq_id == il->cmd_queue) { - slots = TFD_CMD_SLOTS; - actual_slots = slots + 1; - } else { - slots = TFD_TX_CMD_SLOTS; - actual_slots = slots; - } + if (txq_id == il->cmd_queue) + actual_slots++; txq->meta = kzalloc(sizeof(struct il_cmd_meta) * actual_slots, GFP_KERNEL); @@ -2994,7 +2991,7 @@ il_tx_queue_init(struct il_priv *il, u32 txq_id) len = sizeof(struct il_device_cmd); for (i = 0; i < actual_slots; i++) { /* only happens for cmd queue */ - if (i == slots) + if (i == slots_num) len = IL_MAX_CMD_SIZE; txq->cmd[i] = kmalloc(len, GFP_KERNEL); @@ -3017,11 +3014,15 @@ il_tx_queue_init(struct il_priv *il, u32 txq_id) if (txq_id < 4) il_set_swq_id(txq, txq_id, txq_id); + /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise + * il_queue_inc_wrap and il_queue_dec_wrap are broken. */ + BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); + /* Initialize queue's high/low-water marks, and head/tail idxes */ - il_queue_init(il, &txq->q, slots, txq_id); + il_queue_init(il, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); /* Tell device where to find queue */ - il->ops->txq_init(il, txq); + il->ops->lib->txq_init(il, txq); return 0; err: @@ -3036,27 +3037,23 @@ il_tx_queue_init(struct il_priv *il, u32 txq_id) EXPORT_SYMBOL(il_tx_queue_init); void -il_tx_queue_reset(struct il_priv *il, u32 txq_id) +il_tx_queue_reset(struct il_priv *il, struct il_tx_queue *txq, int slots_num, + u32 txq_id) { - int slots, actual_slots; - struct il_tx_queue *txq = &il->txq[txq_id]; + int actual_slots = slots_num; - if (txq_id == il->cmd_queue) { - slots = TFD_CMD_SLOTS; - actual_slots = TFD_CMD_SLOTS + 1; - } else { - slots = TFD_TX_CMD_SLOTS; - actual_slots = TFD_TX_CMD_SLOTS; - } + if (txq_id == il->cmd_queue) + actual_slots++; memset(txq->meta, 0, sizeof(struct il_cmd_meta) * actual_slots); + txq->need_update = 0; /* Initialize queue's high/low-water marks, and head/tail idxes */ - il_queue_init(il, &txq->q, slots, txq_id); + il_queue_init(il, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); /* Tell device where to find queue */ - il->ops->txq_init(il, txq); + il->ops->lib->txq_init(il, txq); } EXPORT_SYMBOL(il_tx_queue_reset); @@ -3084,7 +3081,7 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd) u32 idx; u16 fix_size; - cmd->len = il->ops->get_hcmd_size(cmd->id, cmd->len); + cmd->len = il->ops->utils->get_hcmd_size(cmd->id, cmd->len); fix_size = (u16) (cmd->len + sizeof(out_cmd->hdr)); /* If any of the command structures end up being larger than @@ -3163,9 +3160,9 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd) #endif txq->need_update = 1; - if (il->ops->txq_update_byte_cnt_tbl) + if (il->ops->lib->txq_update_byte_cnt_tbl) /* Set up entry in queue's byte count circular buffer */ - il->ops->txq_update_byte_cnt_tbl(il, txq, 0); + il->ops->lib->txq_update_byte_cnt_tbl(il, txq, 0); phys_addr = pci_map_single(il->pci_dev, &out_cmd->hdr, fix_size, @@ -3173,7 +3170,7 @@ il_enqueue_hcmd(struct il_priv *il, struct il_host_cmd *cmd) dma_unmap_addr_set(out_meta, mapping, phys_addr); dma_unmap_len_set(out_meta, len, fix_size); - il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, fix_size, 1, + il->ops->lib->txq_attach_buf_to_tfd(il, txq, phys_addr, fix_size, 1, U32_PAD(cmd->len)); /* Increment and update queue's write idx */ @@ -3848,8 +3845,8 @@ _il_set_rxon_ht(struct il_priv *il, struct il_ht_config *ht_conf) rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY; } - if (il->ops->set_rxon_chain) - il->ops->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); D_ASSOC("rxon flags 0x%X operation mode :0x%X " "extension channel offset 0x%x\n", le32_to_cpu(rxon->flags), @@ -4107,9 +4104,9 @@ il_irq_handle_error(struct il_priv *il) IL_ERR("Loaded firmware version: %s\n", il->hw->wiphy->fw_version); - il->ops->dump_nic_error_log(il); - if (il->ops->dump_fh) - il->ops->dump_fh(il, NULL, false); + il->ops->lib->dump_nic_error_log(il); + if (il->ops->lib->dump_fh) + il->ops->lib->dump_fh(il, NULL, false); #ifdef CONFIG_IWLEGACY_DEBUG if (il_get_debug_level(il) & IL_DL_FW_ERRORS) il_print_rx_config_cmd(il); @@ -4132,17 +4129,17 @@ il_irq_handle_error(struct il_priv *il) EXPORT_SYMBOL(il_irq_handle_error); static int -_il_apm_stop_master(struct il_priv *il) +il_apm_stop_master(struct il_priv *il) { int ret = 0; /* stop device's busmaster DMA activity */ - _il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); + il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); ret = _il_poll_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED, CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); - if (ret < 0) + if (ret) IL_WARN("Master Disable Timed Out, 100 usec\n"); D_INFO("stop master\n"); @@ -4151,17 +4148,15 @@ _il_apm_stop_master(struct il_priv *il) } void -_il_apm_stop(struct il_priv *il) +il_apm_stop(struct il_priv *il) { - lockdep_assert_held(&il->reg_lock); - D_INFO("Stop card, put in low power state\n"); /* Stop device's DMA activity */ - _il_apm_stop_master(il); + il_apm_stop_master(il); /* Reset the entire device */ - _il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); + il_set_bit(il, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); udelay(10); @@ -4169,18 +4164,7 @@ _il_apm_stop(struct il_priv *il) * Clear "initialization complete" bit to move adapter from * D0A* (powered-up Active) --> D0U* (Uninitialized) state. */ - _il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); -} -EXPORT_SYMBOL(_il_apm_stop); - -void -il_apm_stop(struct il_priv *il) -{ - unsigned long flags; - - spin_lock_irqsave(&il->reg_lock, flags); - _il_apm_stop(il); - spin_unlock_irqrestore(&il->reg_lock, flags); + il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); } EXPORT_SYMBOL(il_apm_stop); @@ -4309,7 +4293,7 @@ il_set_tx_power(struct il_priv *il, s8 tx_power, bool force) if (il->tx_power_user_lmt == tx_power && !force) return 0; - if (!il->ops->send_tx_power) + if (!il->ops->lib->send_tx_power) return -EOPNOTSUPP; /* 0 dBm mean 1 milliwatt */ @@ -4342,7 +4326,7 @@ il_set_tx_power(struct il_priv *il, s8 tx_power, bool force) prev_tx_power = il->tx_power_user_lmt; il->tx_power_user_lmt = tx_power; - ret = il->ops->send_tx_power(il); + ret = il->ops->lib->send_tx_power(il); /* if fail to set tx_power, restore the orig. tx power */ if (ret) { @@ -4481,14 +4465,8 @@ int il_mac_tx_last_beacon(struct ieee80211_hw *hw) { struct il_priv *il = hw->priv; - int ret; - D_MAC80211("enter\n"); - - ret = (il->ibss_manager == IL_IBSS_MANAGER); - - D_MAC80211("leave ret %d\n", ret); - return ret; + return il->ibss_manager == IL_IBSS_MANAGER; } EXPORT_SYMBOL_GPL(il_mac_tx_last_beacon); @@ -4497,8 +4475,8 @@ il_set_mode(struct il_priv *il) { il_connection_init_rx_config(il); - if (il->ops->set_rxon_chain) - il->ops->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); return il_commit_rxon(il); } @@ -4509,9 +4487,10 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct il_priv *il = hw->priv; int err; - mutex_lock(&il->mutex); D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr); + mutex_lock(&il->mutex); + if (!il_is_ready_rf(il)) { IL_WARN("Try to add interface when device not ready\n"); err = -EINVAL; @@ -4533,9 +4512,9 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) } out: - D_MAC80211("leave err %d\n", err); mutex_unlock(&il->mutex); + D_MAC80211("leave\n"); return err; } EXPORT_SYMBOL(il_mac_add_interface); @@ -4561,17 +4540,20 @@ il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct il_priv *il = hw->priv; + D_MAC80211("enter\n"); + mutex_lock(&il->mutex); - D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr); WARN_ON(il->vif != vif); il->vif = NULL; il_teardown_interface(il, vif, false); + memset(il->bssid, 0, ETH_ALEN); + mutex_unlock(&il->mutex); D_MAC80211("leave\n"); - mutex_unlock(&il->mutex); + } EXPORT_SYMBOL(il_mac_remove_interface); @@ -4591,12 +4573,259 @@ il_alloc_txq_mem(struct il_priv *il) EXPORT_SYMBOL(il_alloc_txq_mem); void -il_free_txq_mem(struct il_priv *il) +il_txq_mem(struct il_priv *il) { kfree(il->txq); il->txq = NULL; } -EXPORT_SYMBOL(il_free_txq_mem); +EXPORT_SYMBOL(il_txq_mem); + +#ifdef CONFIG_IWLEGACY_DEBUGFS + +#define IL_TRAFFIC_DUMP_SIZE (IL_TRAFFIC_ENTRY_SIZE * IL_TRAFFIC_ENTRIES) + +void +il_reset_traffic_log(struct il_priv *il) +{ + il->tx_traffic_idx = 0; + il->rx_traffic_idx = 0; + if (il->tx_traffic) + memset(il->tx_traffic, 0, IL_TRAFFIC_DUMP_SIZE); + if (il->rx_traffic) + memset(il->rx_traffic, 0, IL_TRAFFIC_DUMP_SIZE); +} + +int +il_alloc_traffic_mem(struct il_priv *il) +{ + u32 traffic_size = IL_TRAFFIC_DUMP_SIZE; + + if (il_debug_level & IL_DL_TX) { + if (!il->tx_traffic) { + il->tx_traffic = kzalloc(traffic_size, GFP_KERNEL); + if (!il->tx_traffic) + return -ENOMEM; + } + } + if (il_debug_level & IL_DL_RX) { + if (!il->rx_traffic) { + il->rx_traffic = kzalloc(traffic_size, GFP_KERNEL); + if (!il->rx_traffic) + return -ENOMEM; + } + } + il_reset_traffic_log(il); + return 0; +} +EXPORT_SYMBOL(il_alloc_traffic_mem); + +void +il_free_traffic_mem(struct il_priv *il) +{ + kfree(il->tx_traffic); + il->tx_traffic = NULL; + + kfree(il->rx_traffic); + il->rx_traffic = NULL; +} +EXPORT_SYMBOL(il_free_traffic_mem); + +void +il_dbg_log_tx_data_frame(struct il_priv *il, u16 length, + struct ieee80211_hdr *header) +{ + __le16 fc; + u16 len; + + if (likely(!(il_debug_level & IL_DL_TX))) + return; + + if (!il->tx_traffic) + return; + + fc = header->frame_control; + if (ieee80211_is_data(fc)) { + len = + (length > + IL_TRAFFIC_ENTRY_SIZE) ? IL_TRAFFIC_ENTRY_SIZE : length; + memcpy((il->tx_traffic + + (il->tx_traffic_idx * IL_TRAFFIC_ENTRY_SIZE)), header, + len); + il->tx_traffic_idx = + (il->tx_traffic_idx + 1) % IL_TRAFFIC_ENTRIES; + } +} +EXPORT_SYMBOL(il_dbg_log_tx_data_frame); + +void +il_dbg_log_rx_data_frame(struct il_priv *il, u16 length, + struct ieee80211_hdr *header) +{ + __le16 fc; + u16 len; + + if (likely(!(il_debug_level & IL_DL_RX))) + return; + + if (!il->rx_traffic) + return; + + fc = header->frame_control; + if (ieee80211_is_data(fc)) { + len = + (length > + IL_TRAFFIC_ENTRY_SIZE) ? IL_TRAFFIC_ENTRY_SIZE : length; + memcpy((il->rx_traffic + + (il->rx_traffic_idx * IL_TRAFFIC_ENTRY_SIZE)), header, + len); + il->rx_traffic_idx = + (il->rx_traffic_idx + 1) % IL_TRAFFIC_ENTRIES; + } +} +EXPORT_SYMBOL(il_dbg_log_rx_data_frame); + +const char * +il_get_mgmt_string(int cmd) +{ + switch (cmd) { + IL_CMD(MANAGEMENT_ASSOC_REQ); + IL_CMD(MANAGEMENT_ASSOC_RESP); + IL_CMD(MANAGEMENT_REASSOC_REQ); + IL_CMD(MANAGEMENT_REASSOC_RESP); + IL_CMD(MANAGEMENT_PROBE_REQ); + IL_CMD(MANAGEMENT_PROBE_RESP); + IL_CMD(MANAGEMENT_BEACON); + IL_CMD(MANAGEMENT_ATIM); + IL_CMD(MANAGEMENT_DISASSOC); + IL_CMD(MANAGEMENT_AUTH); + IL_CMD(MANAGEMENT_DEAUTH); + IL_CMD(MANAGEMENT_ACTION); + default: + return "UNKNOWN"; + + } +} + +const char * +il_get_ctrl_string(int cmd) +{ + switch (cmd) { + IL_CMD(CONTROL_BACK_REQ); + IL_CMD(CONTROL_BACK); + IL_CMD(CONTROL_PSPOLL); + IL_CMD(CONTROL_RTS); + IL_CMD(CONTROL_CTS); + IL_CMD(CONTROL_ACK); + IL_CMD(CONTROL_CFEND); + IL_CMD(CONTROL_CFENDACK); + default: + return "UNKNOWN"; + + } +} + +void +il_clear_traffic_stats(struct il_priv *il) +{ + memset(&il->tx_stats, 0, sizeof(struct traffic_stats)); + memset(&il->rx_stats, 0, sizeof(struct traffic_stats)); +} + +/* + * if CONFIG_IWLEGACY_DEBUGFS defined, + * il_update_stats function will + * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass + * Use debugFs to display the rx/rx_stats + * if CONFIG_IWLEGACY_DEBUGFS not being defined, then no MGMT and CTRL + * information will be recorded, but DATA pkt still will be recorded + * for the reason of il_led.c need to control the led blinking based on + * number of tx and rx data. + * + */ +void +il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len) +{ + struct traffic_stats *stats; + + if (is_tx) + stats = &il->tx_stats; + else + stats = &il->rx_stats; + + if (ieee80211_is_mgmt(fc)) { + switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { + case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): + stats->mgmt[MANAGEMENT_ASSOC_REQ]++; + break; + case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): + stats->mgmt[MANAGEMENT_ASSOC_RESP]++; + break; + case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): + stats->mgmt[MANAGEMENT_REASSOC_REQ]++; + break; + case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): + stats->mgmt[MANAGEMENT_REASSOC_RESP]++; + break; + case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): + stats->mgmt[MANAGEMENT_PROBE_REQ]++; + break; + case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): + stats->mgmt[MANAGEMENT_PROBE_RESP]++; + break; + case cpu_to_le16(IEEE80211_STYPE_BEACON): + stats->mgmt[MANAGEMENT_BEACON]++; + break; + case cpu_to_le16(IEEE80211_STYPE_ATIM): + stats->mgmt[MANAGEMENT_ATIM]++; + break; + case cpu_to_le16(IEEE80211_STYPE_DISASSOC): + stats->mgmt[MANAGEMENT_DISASSOC]++; + break; + case cpu_to_le16(IEEE80211_STYPE_AUTH): + stats->mgmt[MANAGEMENT_AUTH]++; + break; + case cpu_to_le16(IEEE80211_STYPE_DEAUTH): + stats->mgmt[MANAGEMENT_DEAUTH]++; + break; + case cpu_to_le16(IEEE80211_STYPE_ACTION): + stats->mgmt[MANAGEMENT_ACTION]++; + break; + } + } else if (ieee80211_is_ctl(fc)) { + switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { + case cpu_to_le16(IEEE80211_STYPE_BACK_REQ): + stats->ctrl[CONTROL_BACK_REQ]++; + break; + case cpu_to_le16(IEEE80211_STYPE_BACK): + stats->ctrl[CONTROL_BACK]++; + break; + case cpu_to_le16(IEEE80211_STYPE_PSPOLL): + stats->ctrl[CONTROL_PSPOLL]++; + break; + case cpu_to_le16(IEEE80211_STYPE_RTS): + stats->ctrl[CONTROL_RTS]++; + break; + case cpu_to_le16(IEEE80211_STYPE_CTS): + stats->ctrl[CONTROL_CTS]++; + break; + case cpu_to_le16(IEEE80211_STYPE_ACK): + stats->ctrl[CONTROL_ACK]++; + break; + case cpu_to_le16(IEEE80211_STYPE_CFEND): + stats->ctrl[CONTROL_CFEND]++; + break; + case cpu_to_le16(IEEE80211_STYPE_CFENDACK): + stats->ctrl[CONTROL_CFENDACK]++; + break; + } + } else { + /* data */ + stats->data_cnt++; + stats->data_bytes += len; + } +} +EXPORT_SYMBOL(il_update_stats); +#endif int il_force_reset(struct il_priv *il, bool external) @@ -4657,14 +4886,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct il_priv *il = hw->priv; int err; - mutex_lock(&il->mutex); - D_MAC80211("enter: type %d, addr %pM newtype %d newp2p %d\n", - vif->type, vif->addr, newtype, newp2p); + if (newp2p) + return -EOPNOTSUPP; - if (newp2p) { - err = -EOPNOTSUPP; - goto out; - } + mutex_lock(&il->mutex); if (!il->vif || !il_is_ready_rf(il)) { /* @@ -4691,9 +4916,7 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, err = 0; out: - D_MAC80211("leave err %d\n", err); mutex_unlock(&il->mutex); - return err; } EXPORT_SYMBOL(il_mac_change_interface); @@ -4890,9 +5113,9 @@ il_pci_resume(struct device *device) hw_rfkill = true; if (hw_rfkill) - set_bit(S_RFKILL, &il->status); + set_bit(S_RF_KILL_HW, &il->status); else - clear_bit(S_RFKILL, &il->status); + clear_bit(S_RF_KILL_HW, &il->status); wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rfkill); @@ -4951,8 +5174,12 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) int scan_active = 0; bool ht_changed = false; + if (WARN_ON(!il->ops->legacy)) + return -EOPNOTSUPP; + mutex_lock(&il->mutex); - D_MAC80211("enter: channel %d changed 0x%X\n", channel->hw_value, + + D_MAC80211("enter to channel %d changed 0x%X\n", channel->hw_value, changed); if (unlikely(test_bit(S_SCANNING, &il->status))) { @@ -4972,8 +5199,8 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) * set up the SM PS mode to OFF if an HT channel is * configured. */ - if (il->ops->set_rxon_chain) - il->ops->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); } /* during scanning mac80211 will delay channel setting until @@ -5042,8 +5269,8 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) spin_unlock_irqrestore(&il->lock, flags); - if (il->ops->update_bcast_stations) - ret = il->ops->update_bcast_stations(il); + if (il->ops->legacy->update_bcast_stations) + ret = il->ops->legacy->update_bcast_stations(il); set_ch_out: /* The list of supported rates and rate mask can be different @@ -5081,9 +5308,8 @@ il_mac_config(struct ieee80211_hw *hw, u32 changed) il_update_qos(il); out: - D_MAC80211("leave ret %d\n", ret); + D_MAC80211("leave\n"); mutex_unlock(&il->mutex); - return ret; } EXPORT_SYMBOL(il_mac_config); @@ -5094,17 +5320,24 @@ il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) struct il_priv *il = hw->priv; unsigned long flags; + if (WARN_ON(!il->ops->legacy)) + return; + mutex_lock(&il->mutex); - D_MAC80211("enter: type %d, addr %pM\n", vif->type, vif->addr); + D_MAC80211("enter\n"); spin_lock_irqsave(&il->lock, flags); - memset(&il->current_ht_config, 0, sizeof(struct il_ht_config)); + spin_unlock_irqrestore(&il->lock, flags); + + spin_lock_irqsave(&il->lock, flags); /* new association get rid of ibss beacon skb */ if (il->beacon_skb) dev_kfree_skb(il->beacon_skb); + il->beacon_skb = NULL; + il->timestamp = 0; spin_unlock_irqrestore(&il->lock, flags); @@ -5116,14 +5349,17 @@ il_mac_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) return; } - /* we are restarting association process */ + /* we are restarting association process + * clear RXON_FILTER_ASSOC_MSK bit + */ il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; il_commit_rxon(il); il_set_rate(il); - D_MAC80211("leave\n"); mutex_unlock(&il->mutex); + + D_MAC80211("leave\n"); } EXPORT_SYMBOL(il_mac_reset_tsf); @@ -5239,7 +5475,7 @@ il_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) return; } - il->ops->post_associate(il); + il->ops->legacy->post_associate(il); } void @@ -5249,11 +5485,14 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct il_priv *il = hw->priv; int ret; + if (WARN_ON(!il->ops->legacy)) + return; + + D_MAC80211("changes = 0x%X\n", changes); + mutex_lock(&il->mutex); - D_MAC80211("enter: changes 0x%x\n", changes); if (!il_is_alive(il)) { - D_MAC80211("leave - not alive\n"); mutex_unlock(&il->mutex); return; } @@ -5284,7 +5523,8 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, * below/in post_associate will fail. */ if (il_scan_cancel_timeout(il, 100)) { - D_MAC80211("leave - scan abort failed\n"); + IL_WARN("Aborted scan still in progress after 100ms\n"); + D_MAC80211("leaving - scan abort failed.\n"); mutex_unlock(&il->mutex); return; } @@ -5296,8 +5536,10 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, /* currently needed in a few places */ memcpy(il->bssid, bss_conf->bssid, ETH_ALEN); - } else + } else { il->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; + } + } /* @@ -5348,8 +5590,8 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, if (changes & BSS_CHANGED_HT) { il_ht_conf(il, vif); - if (il->ops->set_rxon_chain) - il->ops->set_rxon_chain(il); + if (il->ops->hcmd->set_rxon_chain) + il->ops->hcmd->set_rxon_chain(il); } if (changes & BSS_CHANGED_ASSOC) { @@ -5358,7 +5600,7 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, il->timestamp = bss_conf->timestamp; if (!il_is_rfkill(il)) - il->ops->post_associate(il); + il->ops->legacy->post_associate(il); } else il_set_no_assoc(il, vif); } @@ -5378,22 +5620,24 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif, memcpy(il->staging.bssid_addr, bss_conf->bssid, ETH_ALEN); memcpy(il->bssid, bss_conf->bssid, ETH_ALEN); - il->ops->config_ap(il); + il->ops->legacy->config_ap(il); } else il_set_no_assoc(il, vif); } if (changes & BSS_CHANGED_IBSS) { - ret = il->ops->manage_ibss_station(il, vif, - bss_conf->ibss_joined); + ret = + il->ops->legacy->manage_ibss_station(il, vif, + bss_conf->ibss_joined); if (ret) IL_ERR("failed to %s IBSS station %pM\n", bss_conf->ibss_joined ? "add" : "remove", bss_conf->bssid); } - D_MAC80211("leave\n"); mutex_unlock(&il->mutex); + + D_MAC80211("leave\n"); } EXPORT_SYMBOL(il_mac_bss_info_changed); diff --git a/trunk/drivers/net/wireless/iwlegacy/common.h b/trunk/drivers/net/wireless/iwlegacy/common.h index 6ed9871f1c4b..708095644f17 100644 --- a/trunk/drivers/net/wireless/iwlegacy/common.h +++ b/trunk/drivers/net/wireless/iwlegacy/common.h @@ -425,6 +425,12 @@ struct il_eeprom_calib_info { #define EEPROM_REGULATORY_BAND_NO_HT40 (0) +struct il_eeprom_ops { + const u32 regulatory_bands[7]; + int (*acquire_semaphore) (struct il_priv *il); + void (*release_semaphore) (struct il_priv *il); +}; + int il_eeprom_init(struct il_priv *il); void il_eeprom_free(struct il_priv *il); const u8 *il_eeprom_query_addr(const struct il_priv *il, size_t offset); @@ -1150,15 +1156,13 @@ struct il_power_mgr { }; struct il_priv { + + /* ieee device used by generic ieee processing code */ struct ieee80211_hw *hw; struct ieee80211_channel *ieee_channels; struct ieee80211_rate *ieee_rates; - struct il_cfg *cfg; const struct il_ops *ops; -#ifdef CONFIG_IWLEGACY_DEBUGFS - const struct il_debugfs_ops *debugfs_ops; -#endif /* temporary frame storage list */ struct list_head free_frames; @@ -1553,6 +1557,24 @@ il_free_pages(struct il_priv *il, unsigned long page) #define IL_RX_BUF_SIZE_4K (4 * 1024) #define IL_RX_BUF_SIZE_8K (8 * 1024) +struct il_hcmd_ops { + int (*rxon_assoc) (struct il_priv *il); + int (*commit_rxon) (struct il_priv *il); + void (*set_rxon_chain) (struct il_priv *il); +}; + +struct il_hcmd_utils_ops { + u16(*get_hcmd_size) (u8 cmd_id, u16 len); + u16(*build_addsta_hcmd) (const struct il_addsta_cmd *cmd, u8 *data); + int (*request_scan) (struct il_priv *il, struct ieee80211_vif *vif); + void (*post_scan) (struct il_priv *il); +}; + +struct il_apm_ops { + int (*init) (struct il_priv *il); + void (*config) (struct il_priv *il); +}; + #ifdef CONFIG_IWLEGACY_DEBUGFS struct il_debugfs_ops { ssize_t(*rx_stats_read) (struct file *file, char __user *user_buf, @@ -1565,7 +1587,11 @@ struct il_debugfs_ops { }; #endif -struct il_ops { +struct il_temp_ops { + void (*temperature) (struct il_priv *il); +}; + +struct il_lib_ops { /* Handling TX */ void (*txq_update_byte_cnt_tbl) (struct il_priv *il, struct il_tx_queue *txq, @@ -1575,6 +1601,8 @@ struct il_ops { u16 len, u8 reset, u8 pad); void (*txq_free_tfd) (struct il_priv *il, struct il_tx_queue *txq); int (*txq_init) (struct il_priv *il, struct il_tx_queue *txq); + /* setup Rx handler */ + void (*handler_setup) (struct il_priv *il); /* alive notification after init uCode load */ void (*init_alive_start) (struct il_priv *il); /* check validity of rtc data address */ @@ -1587,33 +1615,44 @@ struct il_ops { int (*set_channel_switch) (struct il_priv *il, struct ieee80211_channel_switch *ch_switch); /* power management */ - int (*apm_init) (struct il_priv *il); + struct il_apm_ops apm_ops; - /* tx power */ + /* power */ int (*send_tx_power) (struct il_priv *il); void (*update_chain_flags) (struct il_priv *il); /* eeprom operations */ - int (*eeprom_acquire_semaphore) (struct il_priv *il); - void (*eeprom_release_semaphore) (struct il_priv *il); + struct il_eeprom_ops eeprom_ops; - int (*rxon_assoc) (struct il_priv *il); - int (*commit_rxon) (struct il_priv *il); - void (*set_rxon_chain) (struct il_priv *il); + /* temperature */ + struct il_temp_ops temp_ops; - u16(*get_hcmd_size) (u8 cmd_id, u16 len); - u16(*build_addsta_hcmd) (const struct il_addsta_cmd *cmd, u8 *data); +#ifdef CONFIG_IWLEGACY_DEBUGFS + struct il_debugfs_ops debugfs_ops; +#endif - int (*request_scan) (struct il_priv *il, struct ieee80211_vif *vif); - void (*post_scan) (struct il_priv *il); +}; + +struct il_led_ops { + int (*cmd) (struct il_priv *il, struct il_led_cmd *led_cmd); +}; + +struct il_legacy_ops { void (*post_associate) (struct il_priv *il); void (*config_ap) (struct il_priv *il); /* station management */ int (*update_bcast_stations) (struct il_priv *il); int (*manage_ibss_station) (struct il_priv *il, struct ieee80211_vif *vif, bool add); +}; - int (*send_led_cmd) (struct il_priv *il, struct il_led_cmd *led_cmd); +struct il_ops { + const struct il_lib_ops *lib; + const struct il_hcmd_ops *hcmd; + const struct il_hcmd_utils_ops *utils; + const struct il_led_ops *led; + const struct il_nic_ops *nic; + const struct il_legacy_ops *legacy; }; struct il_mod_params { @@ -1626,6 +1665,22 @@ struct il_mod_params { int restart_fw; /* def: 1 = restart firmware */ }; +/* + * @led_compensation: compensate on the led on/off time per HW according + * to the deviation to achieve the desired led frequency. + * The detail algorithm is described in common.c + * @chain_noise_num_beacons: number of beacons used to compute chain noise + * @wd_timeout: TX queues watchdog timeout + * @temperature_kelvin: temperature report by uCode in kelvin + * @ucode_tracing: support ucode continuous tracing + * @sensitivity_calib_by_driver: driver has the capability to perform + * sensitivity calibration operation + * @chain_noise_calib_by_driver: driver has the capability to perform + * chain noise calibration operation + */ +struct il_base_params { +}; + #define IL_LED_SOLID 11 #define IL_DEF_LED_INTRVL cpu_to_le32(1000) @@ -1714,8 +1769,6 @@ struct il_cfg { const bool ucode_tracing; const bool sensitivity_calib_by_driver; const bool chain_noise_calib_by_driver; - - const u32 regulatory_bands[7]; }; /*************************** @@ -1747,24 +1800,60 @@ void il_mac_remove_interface(struct ieee80211_hw *hw, int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum nl80211_iftype newtype, bool newp2p); int il_alloc_txq_mem(struct il_priv *il); -void il_free_txq_mem(struct il_priv *il); +void il_txq_mem(struct il_priv *il); #ifdef CONFIG_IWLEGACY_DEBUGFS -extern void il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len); +int il_alloc_traffic_mem(struct il_priv *il); +void il_free_traffic_mem(struct il_priv *il); +void il_reset_traffic_log(struct il_priv *il); +void il_dbg_log_tx_data_frame(struct il_priv *il, u16 length, + struct ieee80211_hdr *header); +void il_dbg_log_rx_data_frame(struct il_priv *il, u16 length, + struct ieee80211_hdr *header); +const char *il_get_mgmt_string(int cmd); +const char *il_get_ctrl_string(int cmd); +void il_clear_traffic_stats(struct il_priv *il); +void il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len); #else +static inline int +il_alloc_traffic_mem(struct il_priv *il) +{ + return 0; +} + +static inline void +il_free_traffic_mem(struct il_priv *il) +{ +} + +static inline void +il_reset_traffic_log(struct il_priv *il) +{ +} + +static inline void +il_dbg_log_tx_data_frame(struct il_priv *il, u16 length, + struct ieee80211_hdr *header) +{ +} + +static inline void +il_dbg_log_rx_data_frame(struct il_priv *il, u16 length, + struct ieee80211_hdr *header) +{ +} + static inline void il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len) { } #endif - /***************************************************** - * Handlers - ***************************************************/ + * RX handlers. + * **************************************************/ void il_hdl_pm_sleep(struct il_priv *il, struct il_rx_buf *rxb); void il_hdl_pm_debug_stats(struct il_priv *il, struct il_rx_buf *rxb); void il_hdl_error(struct il_priv *il, struct il_rx_buf *rxb); -void il_hdl_csa(struct il_priv *il, struct il_rx_buf *rxb); /***************************************************** * RX @@ -1775,20 +1864,25 @@ int il_rx_queue_alloc(struct il_priv *il); void il_rx_queue_update_write_ptr(struct il_priv *il, struct il_rx_queue *q); int il_rx_queue_space(const struct il_rx_queue *q); void il_tx_cmd_complete(struct il_priv *il, struct il_rx_buf *rxb); - +/* Handlers */ void il_hdl_spectrum_measurement(struct il_priv *il, struct il_rx_buf *rxb); void il_recover_from_stats(struct il_priv *il, struct il_rx_pkt *pkt); void il_chswitch_done(struct il_priv *il, bool is_success); +void il_hdl_csa(struct il_priv *il, struct il_rx_buf *rxb); + +/* TX helpers */ /***************************************************** * TX ******************************************************/ -extern void il_txq_update_write_ptr(struct il_priv *il, struct il_tx_queue *txq); -extern int il_tx_queue_init(struct il_priv *il, u32 txq_id); -extern void il_tx_queue_reset(struct il_priv *il, u32 txq_id); -extern void il_tx_queue_unmap(struct il_priv *il, int txq_id); -extern void il_tx_queue_free(struct il_priv *il, int txq_id); -extern void il_setup_watchdog(struct il_priv *il); +void il_txq_update_write_ptr(struct il_priv *il, struct il_tx_queue *txq); +int il_tx_queue_init(struct il_priv *il, struct il_tx_queue *txq, int slots_num, + u32 txq_id); +void il_tx_queue_reset(struct il_priv *il, struct il_tx_queue *txq, + int slots_num, u32 txq_id); +void il_tx_queue_unmap(struct il_priv *il, int txq_id); +void il_tx_queue_free(struct il_priv *il, int txq_id); +void il_setup_watchdog(struct il_priv *il); /***************************************************** * TX power ****************************************************/ @@ -1906,7 +2000,7 @@ void il_free_geos(struct il_priv *il); #define S_HCMD_ACTIVE 0 /* host command in progress */ /* 1 is unused (used to be S_HCMD_SYNC_ACTIVE) */ #define S_INT_ENABLED 2 -#define S_RFKILL 3 +#define S_RF_KILL_HW 3 #define S_CT_KILL 4 #define S_INIT 5 #define S_ALIVE 6 @@ -1944,10 +2038,16 @@ il_is_init(struct il_priv *il) return test_bit(S_INIT, &il->status); } +static inline int +il_is_rfkill_hw(struct il_priv *il) +{ + return test_bit(S_RF_KILL_HW, &il->status); +} + static inline int il_is_rfkill(struct il_priv *il) { - return test_bit(S_RFKILL, &il->status); + return il_is_rfkill_hw(il); } static inline int @@ -1968,9 +2068,7 @@ il_is_ready_rf(struct il_priv *il) extern void il_send_bt_config(struct il_priv *il); extern int il_send_stats_request(struct il_priv *il, u8 flags, bool clear); -extern void il_apm_stop(struct il_priv *il); -extern void _il_apm_stop(struct il_priv *il); - +void il_apm_stop(struct il_priv *il); int il_apm_init(struct il_priv *il); int il_send_rxon_timing(struct il_priv *il); @@ -1978,13 +2076,13 @@ int il_send_rxon_timing(struct il_priv *il); static inline int il_send_rxon_assoc(struct il_priv *il) { - return il->ops->rxon_assoc(il); + return il->ops->hcmd->rxon_assoc(il); } static inline int il_commit_rxon(struct il_priv *il) { - return il->ops->commit_rxon(il); + return il->ops->hcmd->commit_rxon(il); } static inline const struct ieee80211_supported_band * @@ -2005,7 +2103,7 @@ irqreturn_t il_isr(int irq, void *data); extern void il_set_bit(struct il_priv *p, u32 r, u32 m); extern void il_clear_bit(struct il_priv *p, u32 r, u32 m); -extern bool _il_grab_nic_access(struct il_priv *il); +extern int _il_grab_nic_access(struct il_priv *il); extern int _il_poll_bit(struct il_priv *il, u32 addr, u32 bits, u32 mask, int timeout); extern int il_poll_bit(struct il_priv *il, u32 addr, u32 mask, int timeout); extern u32 il_rd_prph(struct il_priv *il, u32 reg); @@ -2016,20 +2114,20 @@ extern void il_write_targ_mem(struct il_priv *il, u32 addr, u32 val); static inline void _il_write8(struct il_priv *il, u32 ofs, u8 val) { - writeb(val, il->hw_base + ofs); + iowrite8(val, il->hw_base + ofs); } #define il_write8(il, ofs, val) _il_write8(il, ofs, val) static inline void _il_wr(struct il_priv *il, u32 ofs, u32 val) { - writel(val, il->hw_base + ofs); + iowrite32(val, il->hw_base + ofs); } static inline u32 _il_rd(struct il_priv *il, u32 ofs) { - return readl(il->hw_base + ofs); + return ioread32(il->hw_base + ofs); } static inline void @@ -2048,13 +2146,6 @@ static inline void _il_release_nic_access(struct il_priv *il) { _il_clear_bit(il, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - /* - * In above we are reading CSR_GP_CNTRL register, what will flush any - * previous writes, but still want write, which clear MAC_ACCESS_REQ - * bit, be performed on PCI bus before any other writes scheduled on - * different CPUs (after we drop reg_lock). - */ - mmiowb(); } static inline u32 @@ -2077,7 +2168,7 @@ il_wr(struct il_priv *il, u32 reg, u32 value) unsigned long reg_flags; spin_lock_irqsave(&il->reg_lock, reg_flags); - if (likely(_il_grab_nic_access(il))) { + if (!_il_grab_nic_access(il)) { _il_wr(il, reg, value); _il_release_nic_access(il); } @@ -2088,6 +2179,7 @@ static inline u32 _il_rd_prph(struct il_priv *il, u32 reg) { _il_wr(il, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); + rmb(); return _il_rd(il, HBUS_TARG_PRPH_RDAT); } @@ -2095,6 +2187,7 @@ static inline void _il_wr_prph(struct il_priv *il, u32 addr, u32 val) { _il_wr(il, HBUS_TARG_PRPH_WADDR, ((addr & 0x0000FFFF) | (3 << 24))); + wmb(); _il_wr(il, HBUS_TARG_PRPH_WDAT, val); } @@ -2104,10 +2197,9 @@ il_set_bits_prph(struct il_priv *il, u32 reg, u32 mask) unsigned long reg_flags; spin_lock_irqsave(&il->reg_lock, reg_flags); - if (likely(_il_grab_nic_access(il))) { - _il_wr_prph(il, reg, (_il_rd_prph(il, reg) | mask)); - _il_release_nic_access(il); - } + _il_grab_nic_access(il); + _il_wr_prph(il, reg, (_il_rd_prph(il, reg) | mask)); + _il_release_nic_access(il); spin_unlock_irqrestore(&il->reg_lock, reg_flags); } @@ -2117,10 +2209,9 @@ il_set_bits_mask_prph(struct il_priv *il, u32 reg, u32 bits, u32 mask) unsigned long reg_flags; spin_lock_irqsave(&il->reg_lock, reg_flags); - if (likely(_il_grab_nic_access(il))) { - _il_wr_prph(il, reg, ((_il_rd_prph(il, reg) & mask) | bits)); - _il_release_nic_access(il); - } + _il_grab_nic_access(il); + _il_wr_prph(il, reg, ((_il_rd_prph(il, reg) & mask) | bits)); + _il_release_nic_access(il); spin_unlock_irqrestore(&il->reg_lock, reg_flags); } @@ -2131,11 +2222,10 @@ il_clear_bits_prph(struct il_priv *il, u32 reg, u32 mask) u32 val; spin_lock_irqsave(&il->reg_lock, reg_flags); - if (likely(_il_grab_nic_access(il))) { - val = _il_rd_prph(il, reg); - _il_wr_prph(il, reg, (val & ~mask)); - _il_release_nic_access(il); - } + _il_grab_nic_access(il); + val = _il_rd_prph(il, reg); + _il_wr_prph(il, reg, (val & ~mask)); + _il_release_nic_access(il); spin_unlock_irqrestore(&il->reg_lock, reg_flags); } @@ -2397,10 +2487,10 @@ struct il_rb_status { __le32 __unused; /* 3945 only */ } __packed; -#define TFD_QUEUE_SIZE_MAX 256 -#define TFD_QUEUE_SIZE_BC_DUP 64 +#define TFD_QUEUE_SIZE_MAX (256) +#define TFD_QUEUE_SIZE_BC_DUP (64) #define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP) -#define IL_TX_DMA_MASK DMA_BIT_MASK(36) +#define IL_TX_DMA_MASK DMA_BIT_MASK(36) #define IL_NUM_OF_TBS 20 static inline u8 diff --git a/trunk/drivers/net/wireless/iwlegacy/debug.c b/trunk/drivers/net/wireless/iwlegacy/debug.c index 229849150aac..bb7c95607a69 100644 --- a/trunk/drivers/net/wireless/iwlegacy/debug.c +++ b/trunk/drivers/net/wireless/iwlegacy/debug.c @@ -31,101 +31,6 @@ #include "common.h" -void -il_clear_traffic_stats(struct il_priv *il) -{ - memset(&il->tx_stats, 0, sizeof(struct traffic_stats)); - memset(&il->rx_stats, 0, sizeof(struct traffic_stats)); -} - -/* - * il_update_stats function record all the MGMT, CTRL and DATA pkt for - * both TX and Rx . Use debugfs to display the rx/rx_stats - */ -void -il_update_stats(struct il_priv *il, bool is_tx, __le16 fc, u16 len) -{ - struct traffic_stats *stats; - - if (is_tx) - stats = &il->tx_stats; - else - stats = &il->rx_stats; - - if (ieee80211_is_mgmt(fc)) { - switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { - case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): - stats->mgmt[MANAGEMENT_ASSOC_REQ]++; - break; - case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): - stats->mgmt[MANAGEMENT_ASSOC_RESP]++; - break; - case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): - stats->mgmt[MANAGEMENT_REASSOC_REQ]++; - break; - case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): - stats->mgmt[MANAGEMENT_REASSOC_RESP]++; - break; - case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): - stats->mgmt[MANAGEMENT_PROBE_REQ]++; - break; - case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): - stats->mgmt[MANAGEMENT_PROBE_RESP]++; - break; - case cpu_to_le16(IEEE80211_STYPE_BEACON): - stats->mgmt[MANAGEMENT_BEACON]++; - break; - case cpu_to_le16(IEEE80211_STYPE_ATIM): - stats->mgmt[MANAGEMENT_ATIM]++; - break; - case cpu_to_le16(IEEE80211_STYPE_DISASSOC): - stats->mgmt[MANAGEMENT_DISASSOC]++; - break; - case cpu_to_le16(IEEE80211_STYPE_AUTH): - stats->mgmt[MANAGEMENT_AUTH]++; - break; - case cpu_to_le16(IEEE80211_STYPE_DEAUTH): - stats->mgmt[MANAGEMENT_DEAUTH]++; - break; - case cpu_to_le16(IEEE80211_STYPE_ACTION): - stats->mgmt[MANAGEMENT_ACTION]++; - break; - } - } else if (ieee80211_is_ctl(fc)) { - switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { - case cpu_to_le16(IEEE80211_STYPE_BACK_REQ): - stats->ctrl[CONTROL_BACK_REQ]++; - break; - case cpu_to_le16(IEEE80211_STYPE_BACK): - stats->ctrl[CONTROL_BACK]++; - break; - case cpu_to_le16(IEEE80211_STYPE_PSPOLL): - stats->ctrl[CONTROL_PSPOLL]++; - break; - case cpu_to_le16(IEEE80211_STYPE_RTS): - stats->ctrl[CONTROL_RTS]++; - break; - case cpu_to_le16(IEEE80211_STYPE_CTS): - stats->ctrl[CONTROL_CTS]++; - break; - case cpu_to_le16(IEEE80211_STYPE_ACK): - stats->ctrl[CONTROL_ACK]++; - break; - case cpu_to_le16(IEEE80211_STYPE_CFEND): - stats->ctrl[CONTROL_CFEND]++; - break; - case cpu_to_le16(IEEE80211_STYPE_CFENDACK): - stats->ctrl[CONTROL_CFENDACK]++; - break; - } - } else { - /* data */ - stats->data_cnt++; - stats->data_bytes += len; - } -} -EXPORT_SYMBOL(il_update_stats); - /* create and remove of files */ #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ if (!debugfs_create_file(#name, mode, parent, il, \ @@ -193,46 +98,6 @@ static const struct file_operations il_dbgfs_##name##_ops = { \ .llseek = generic_file_llseek, \ }; -static const char * -il_get_mgmt_string(int cmd) -{ - switch (cmd) { - IL_CMD(MANAGEMENT_ASSOC_REQ); - IL_CMD(MANAGEMENT_ASSOC_RESP); - IL_CMD(MANAGEMENT_REASSOC_REQ); - IL_CMD(MANAGEMENT_REASSOC_RESP); - IL_CMD(MANAGEMENT_PROBE_REQ); - IL_CMD(MANAGEMENT_PROBE_RESP); - IL_CMD(MANAGEMENT_BEACON); - IL_CMD(MANAGEMENT_ATIM); - IL_CMD(MANAGEMENT_DISASSOC); - IL_CMD(MANAGEMENT_AUTH); - IL_CMD(MANAGEMENT_DEAUTH); - IL_CMD(MANAGEMENT_ACTION); - default: - return "UNKNOWN"; - - } -} - -static const char * -il_get_ctrl_string(int cmd) -{ - switch (cmd) { - IL_CMD(CONTROL_BACK_REQ); - IL_CMD(CONTROL_BACK); - IL_CMD(CONTROL_PSPOLL); - IL_CMD(CONTROL_RTS); - IL_CMD(CONTROL_CTS); - IL_CMD(CONTROL_ACK); - IL_CMD(CONTROL_CFEND); - IL_CMD(CONTROL_CFENDACK); - default: - return "UNKNOWN"; - - } -} - static ssize_t il_dbgfs_tx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -630,8 +495,8 @@ il_dbgfs_status_read(struct file *file, char __user *user_buf, size_t count, scnprintf(buf + pos, bufsz - pos, "S_INT_ENABLED:\t %d\n", test_bit(S_INT_ENABLED, &il->status)); pos += - scnprintf(buf + pos, bufsz - pos, "S_RFKILL:\t %d\n", - test_bit(S_RFKILL, &il->status)); + scnprintf(buf + pos, bufsz - pos, "S_RF_KILL_HW:\t %d\n", + test_bit(S_RF_KILL_HW, &il->status)); pos += scnprintf(buf + pos, bufsz - pos, "S_CT_KILL:\t\t %d\n", test_bit(S_CT_KILL, &il->status)); @@ -849,6 +714,112 @@ DEBUGFS_READ_WRITE_FILE_OPS(interrupt); DEBUGFS_READ_FILE_OPS(qos); DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); +static ssize_t +il_dbgfs_traffic_log_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct il_priv *il = file->private_data; + int pos = 0, ofs = 0; + int cnt = 0, entry; + struct il_tx_queue *txq; + struct il_queue *q; + struct il_rx_queue *rxq = &il->rxq; + char *buf; + int bufsz = + ((IL_TRAFFIC_ENTRIES * IL_TRAFFIC_ENTRY_SIZE * 64) * 2) + + (il->cfg->num_of_queues * 32 * 8) + 400; + const u8 *ptr; + ssize_t ret; + + if (!il->txq) { + IL_ERR("txq not ready\n"); + return -EAGAIN; + } + buf = kzalloc(bufsz, GFP_KERNEL); + if (!buf) { + IL_ERR("Can not allocate buffer\n"); + return -ENOMEM; + } + pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); + for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { + txq = &il->txq[cnt]; + q = &txq->q; + pos += + scnprintf(buf + pos, bufsz - pos, + "q[%d]: read_ptr: %u, write_ptr: %u\n", cnt, + q->read_ptr, q->write_ptr); + } + if (il->tx_traffic && (il_debug_level & IL_DL_TX)) { + ptr = il->tx_traffic; + pos += + scnprintf(buf + pos, bufsz - pos, "Tx Traffic idx: %u\n", + il->tx_traffic_idx); + for (cnt = 0, ofs = 0; cnt < IL_TRAFFIC_ENTRIES; cnt++) { + for (entry = 0; entry < IL_TRAFFIC_ENTRY_SIZE / 16; + entry++, ofs += 16) { + pos += + scnprintf(buf + pos, bufsz - pos, "0x%.4x ", + ofs); + hex_dump_to_buffer(ptr + ofs, 16, 16, 2, + buf + pos, bufsz - pos, 0); + pos += strlen(buf + pos); + if (bufsz - pos > 0) + buf[pos++] = '\n'; + } + } + } + + pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); + pos += + scnprintf(buf + pos, bufsz - pos, "read: %u, write: %u\n", + rxq->read, rxq->write); + + if (il->rx_traffic && (il_debug_level & IL_DL_RX)) { + ptr = il->rx_traffic; + pos += + scnprintf(buf + pos, bufsz - pos, "Rx Traffic idx: %u\n", + il->rx_traffic_idx); + for (cnt = 0, ofs = 0; cnt < IL_TRAFFIC_ENTRIES; cnt++) { + for (entry = 0; entry < IL_TRAFFIC_ENTRY_SIZE / 16; + entry++, ofs += 16) { + pos += + scnprintf(buf + pos, bufsz - pos, "0x%.4x ", + ofs); + hex_dump_to_buffer(ptr + ofs, 16, 16, 2, + buf + pos, bufsz - pos, 0); + pos += strlen(buf + pos); + if (bufsz - pos > 0) + buf[pos++] = '\n'; + } + } + } + + ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); + kfree(buf); + return ret; +} + +static ssize_t +il_dbgfs_traffic_log_write(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct il_priv *il = file->private_data; + char buf[8]; + int buf_size; + int traffic_log; + + memset(buf, 0, sizeof(buf)); + buf_size = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, buf_size)) + return -EFAULT; + if (sscanf(buf, "%d", &traffic_log) != 1) + return -EFAULT; + if (traffic_log == 0) + il_reset_traffic_log(il); + + return count; +} + static ssize_t il_dbgfs_tx_queue_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -930,8 +901,7 @@ il_dbgfs_ucode_rx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct il_priv *il = file->private_data; - - return il->debugfs_ops->rx_stats_read(file, user_buf, count, ppos); + return il->ops->lib->debugfs_ops.rx_stats_read(file, user_buf, count, ppos); } static ssize_t @@ -939,8 +909,7 @@ il_dbgfs_ucode_tx_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct il_priv *il = file->private_data; - - return il->debugfs_ops->tx_stats_read(file, user_buf, count, ppos); + return il->ops->lib->debugfs_ops.tx_stats_read(file, user_buf, count, ppos); } static ssize_t @@ -948,8 +917,7 @@ il_dbgfs_ucode_general_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct il_priv *il = file->private_data; - - return il->debugfs_ops->general_stats_read(file, user_buf, count, ppos); + return il->ops->lib->debugfs_ops.general_stats_read(file, user_buf, count, ppos); } static ssize_t @@ -1207,8 +1175,8 @@ il_dbgfs_fh_reg_read(struct file *file, char __user *user_buf, size_t count, int pos = 0; ssize_t ret = -EFAULT; - if (il->ops->dump_fh) { - ret = pos = il->ops->dump_fh(il, &buf, true); + if (il->ops->lib->dump_fh) { + ret = pos = il->ops->lib->dump_fh(il, &buf, true); if (buf) { ret = simple_read_from_buffer(user_buf, count, ppos, buf, @@ -1332,6 +1300,7 @@ il_dbgfs_wd_timeout_write(struct file *file, const char __user *user_buf, DEBUGFS_READ_FILE_OPS(rx_stats); DEBUGFS_READ_FILE_OPS(tx_stats); +DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); DEBUGFS_READ_FILE_OPS(rx_queue); DEBUGFS_READ_FILE_OPS(tx_queue); DEBUGFS_READ_FILE_OPS(ucode_rx_stats); @@ -1385,6 +1354,7 @@ il_dbgfs_register(struct il_priv *il, const char *name) DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rx_stats, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(tx_stats, dir_debug, S_IRUSR); + DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR); DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR); diff --git a/trunk/drivers/net/wireless/iwlwifi/iwl-testmode.c b/trunk/drivers/net/wireless/iwlwifi/iwl-testmode.c index df7ab332c833..e42e0768880b 100644 --- a/trunk/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/trunk/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -172,7 +172,7 @@ static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv, skb = cfg80211_testmode_alloc_event_skb(hw->wiphy, 20 + length, GFP_ATOMIC); if (skb == NULL) { - IWL_DEBUG_INFO(priv, + IWL_ERR(priv, "Run out of memory for messages to user space ?\n"); return; } @@ -183,7 +183,7 @@ static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv, nla_put_failure: kfree_skb(skb); - IWL_DEBUG_INFO(priv, "Ouch, overran buffer, check allocation!\n"); + IWL_ERR(priv, "Ouch, overran buffer, check allocation!\n"); } void iwl_testmode_init(struct iwl_priv *priv) @@ -252,8 +252,7 @@ static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] || !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) { - IWL_DEBUG_INFO(priv, - "Error finding ucode command mandatory fields\n"); + IWL_ERR(priv, "Missing ucode command mandatory fields\n"); return -ENOMSG; } @@ -295,7 +294,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) int status = 0; if (!tb[IWL_TM_ATTR_REG_OFFSET]) { - IWL_DEBUG_INFO(priv, "Error finding register offset\n"); + IWL_ERR(priv, "Missing register offset\n"); return -ENOMSG; } ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]); @@ -309,7 +308,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32 || cmd == IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8) && (ofs >= FH_MEM_UPPER_BOUND)) { - IWL_DEBUG_INFO(priv, "offset out of segment (0x0 - 0x%x)\n", + IWL_ERR(priv, "offset out of segment (0x0 - 0x%x)\n", FH_MEM_UPPER_BOUND); return -EINVAL; } @@ -321,19 +320,17 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); if (!skb) { - IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + IWL_ERR(priv, "Memory allocation fail\n"); return -ENOMEM; } NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32); status = cfg80211_testmode_reply(skb); if (status < 0) - IWL_DEBUG_INFO(priv, - "Error sending msg : %d\n", status); + IWL_ERR(priv, "Error sending msg : %d\n", status); break; case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE32: if (!tb[IWL_TM_ATTR_REG_VALUE32]) { - IWL_DEBUG_INFO(priv, - "Error finding value to write\n"); + IWL_ERR(priv, "Missing value to write\n"); return -ENOMSG; } else { val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); @@ -343,7 +340,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) break; case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: if (!tb[IWL_TM_ATTR_REG_VALUE8]) { - IWL_DEBUG_INFO(priv, "Error finding value to write\n"); + IWL_ERR(priv, "Missing value to write\n"); return -ENOMSG; } else { val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); @@ -357,19 +354,17 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); if (!skb) { - IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + IWL_ERR(priv, "Memory allocation fail\n"); return -ENOMEM; } NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32); status = cfg80211_testmode_reply(skb); if (status < 0) - IWL_DEBUG_INFO(priv, - "Error sending msg : %d\n", status); + IWL_ERR(priv, "Error sending msg : %d\n", status); break; case IWL_TM_CMD_APP2DEV_INDIRECT_REG_WRITE32: if (!tb[IWL_TM_ATTR_REG_VALUE32]) { - IWL_DEBUG_INFO(priv, - "Error finding value to write\n"); + IWL_ERR(priv, "Missing value to write\n"); return -ENOMSG; } else { val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); @@ -378,7 +373,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) } break; default: - IWL_DEBUG_INFO(priv, "Unknown testmode register command ID\n"); + IWL_ERR(priv, "Unknown testmode register command ID\n"); return -ENOSYS; } @@ -400,14 +395,13 @@ static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) NULL, NULL); ret = iwl_init_alive_start(trans(priv)); if (ret) { - IWL_DEBUG_INFO(priv, - "Error configuring init calibration: %d\n", ret); + IWL_ERR(priv, "Fail init calibration: %d\n", ret); goto cfg_init_calib_error; } ret = iwl_wait_notification(priv->shrd, &calib_wait, 2 * HZ); if (ret) - IWL_DEBUG_INFO(priv, "Error detecting" + IWL_ERR(priv, "Error detecting" " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); return ret; @@ -448,8 +442,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, rsp_data_len + 20); if (!skb) { - IWL_DEBUG_INFO(priv, - "Error allocating memory\n"); + IWL_ERR(priv, "Memory allocation fail\n"); return -ENOMEM; } NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, @@ -458,15 +451,13 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) rsp_data_len, rsp_data_ptr); status = cfg80211_testmode_reply(skb); if (status < 0) - IWL_DEBUG_INFO(priv, "Error sending msg : %d\n", - status); + IWL_ERR(priv, "Error sending msg : %d\n", status); break; case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT); if (status) - IWL_DEBUG_INFO(priv, - "Error loading init ucode: %d\n", status); + IWL_ERR(priv, "Error loading init ucode: %d\n", status); break; case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: @@ -477,13 +468,13 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_REGULAR); if (status) { - IWL_DEBUG_INFO(priv, + IWL_ERR(priv, "Error loading runtime ucode: %d\n", status); break; } status = iwl_alive_start(priv); if (status) - IWL_DEBUG_INFO(priv, + IWL_ERR(priv, "Error starting the device: %d\n", status); break; @@ -492,13 +483,13 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) iwl_trans_stop_device(trans); status = iwl_load_ucode_wait_alive(trans, IWL_UCODE_WOWLAN); if (status) { - IWL_DEBUG_INFO(priv, + IWL_ERR(priv, "Error loading WOWLAN ucode: %d\n", status); break; } status = iwl_alive_start(priv); if (status) - IWL_DEBUG_INFO(priv, + IWL_ERR(priv, "Error starting the device: %d\n", status); break; @@ -507,8 +498,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, cfg(priv)->base_params->eeprom_size + 20); if (!skb) { - IWL_DEBUG_INFO(priv, - "Error allocating memory\n"); + IWL_ERR(priv, "Memory allocation fail\n"); return -ENOMEM; } NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, @@ -518,17 +508,15 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) priv->shrd->eeprom); status = cfg80211_testmode_reply(skb); if (status < 0) - IWL_DEBUG_INFO(priv, - "Error sending msg : %d\n", - status); + IWL_ERR(priv, "Error sending msg : %d\n", + status); } else return -EFAULT; break; case IWL_TM_CMD_APP2DEV_FIXRATE_REQ: if (!tb[IWL_TM_ATTR_FIXRATE]) { - IWL_DEBUG_INFO(priv, - "Error finding fixrate setting\n"); + IWL_ERR(priv, "Missing fixrate setting\n"); return -ENOMSG; } priv->tm_fixed_rate = nla_get_u32(tb[IWL_TM_ATTR_FIXRATE]); @@ -539,14 +527,13 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); if (!skb) { - IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + IWL_ERR(priv, "Memory allocation fail\n"); return -ENOMEM; } NLA_PUT_U32(skb, IWL_TM_ATTR_FW_VERSION, priv->ucode_ver); status = cfg80211_testmode_reply(skb); if (status < 0) - IWL_DEBUG_INFO(priv, - "Error sending msg : %d\n", status); + IWL_ERR(priv, "Error sending msg : %d\n", status); break; case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: @@ -555,20 +542,19 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); if (!skb) { - IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + IWL_ERR(priv, "Memory allocation fail\n"); return -ENOMEM; } NLA_PUT_U32(skb, IWL_TM_ATTR_DEVICE_ID, devid); status = cfg80211_testmode_reply(skb); if (status < 0) - IWL_DEBUG_INFO(priv, - "Error sending msg : %d\n", status); + IWL_ERR(priv, "Error sending msg : %d\n", status); break; case IWL_TM_CMD_APP2DEV_GET_FW_INFO: skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20 + 8); if (!skb) { - IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + IWL_ERR(priv, "Memory allocation fail\n"); return -ENOMEM; } switch (priv->shrd->ucode_type) { @@ -585,10 +571,10 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) data_size = trans(priv)->ucode_wowlan.data.len; break; case IWL_UCODE_NONE: - IWL_DEBUG_INFO(priv, "The uCode has not been loaded\n"); + IWL_ERR(priv, "No uCode has not been loaded\n"); break; default: - IWL_DEBUG_INFO(priv, "Unsupported uCode type\n"); + IWL_ERR(priv, "Unsupported uCode type\n"); break; } NLA_PUT_U32(skb, IWL_TM_ATTR_FW_TYPE, priv->shrd->ucode_type); @@ -596,12 +582,11 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) NLA_PUT_U32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size); status = cfg80211_testmode_reply(skb); if (status < 0) - IWL_DEBUG_INFO(priv, - "Error sending msg : %d\n", status); + IWL_ERR(priv, "Error sending msg : %d\n", status); break; default: - IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); + IWL_ERR(priv, "Unknown testmode driver command ID\n"); return -ENOSYS; } return status; @@ -664,8 +649,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, sizeof(priv->testmode_trace.dma_addr) + 20); if (!skb) { - IWL_DEBUG_INFO(priv, - "Error allocating memory\n"); + IWL_ERR(priv, "Memory allocation fail\n"); iwl_trace_cleanup(priv); return -ENOMEM; } @@ -674,9 +658,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) (u64 *)&priv->testmode_trace.dma_addr); status = cfg80211_testmode_reply(skb); if (status < 0) { - IWL_DEBUG_INFO(priv, - "Error sending msg : %d\n", - status); + IWL_ERR(priv, "Error sending msg : %d\n", status); } priv->testmode_trace.num_chunks = DIV_ROUND_UP(priv->testmode_trace.buff_size, @@ -687,7 +669,7 @@ static int iwl_testmode_trace(struct ieee80211_hw *hw, struct nlattr **tb) iwl_trace_cleanup(priv); break; default: - IWL_DEBUG_INFO(priv, "Unknown testmode mem command ID\n"); + IWL_ERR(priv, "Unknown testmode mem command ID\n"); return -ENOSYS; } return status; @@ -752,7 +734,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) u8 owner; if (!tb[IWL_TM_ATTR_UCODE_OWNER]) { - IWL_DEBUG_INFO(priv, "Error finding ucode owner\n"); + IWL_ERR(priv, "Missing ucode owner\n"); return -ENOMSG; } @@ -760,7 +742,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) if ((owner == IWL_OWNERSHIP_DRIVER) || (owner == IWL_OWNERSHIP_TM)) priv->shrd->ucode_owner = owner; else { - IWL_DEBUG_INFO(priv, "Invalid owner\n"); + IWL_ERR(priv, "Invalid owner\n"); return -EINVAL; } return 0; @@ -791,12 +773,12 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) return -EBUSY; if (!tb[IWL_TM_ATTR_SRAM_ADDR]) { - IWL_DEBUG_INFO(priv, "Error finding SRAM offset address\n"); + IWL_ERR(priv, "Missing SRAM offset address\n"); return -ENOMSG; } ofs = nla_get_u32(tb[IWL_TM_ATTR_SRAM_ADDR]); if (!tb[IWL_TM_ATTR_SRAM_SIZE]) { - IWL_DEBUG_INFO(priv, "Error finding size for SRAM reading\n"); + IWL_ERR(priv, "Missing size for SRAM reading\n"); return -ENOMSG; } size = nla_get_u32(tb[IWL_TM_ATTR_SRAM_SIZE]); @@ -811,10 +793,10 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) maxsize = trans(priv)->ucode_wowlan.data.len; break; case IWL_UCODE_NONE: - IWL_ERR(priv, "Error, uCode does not been loaded\n"); + IWL_ERR(priv, "uCode does not been loaded\n"); return -ENOSYS; default: - IWL_ERR(priv, "Error, unsupported uCode type\n"); + IWL_ERR(priv, "unsupported uCode type\n"); return -ENOSYS; } if ((ofs + size) > (maxsize + SRAM_DATA_SEG_OFFSET)) { @@ -825,7 +807,7 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) priv->testmode_sram.buff_addr = kmalloc(priv->testmode_sram.buff_size, GFP_KERNEL); if (priv->testmode_sram.buff_addr == NULL) { - IWL_ERR(priv, "Error allocating memory\n"); + IWL_ERR(priv, "Memory allocation fail\n"); return -ENOMEM; } _iwl_read_targ_mem_words(trans(priv), ofs, @@ -898,14 +880,13 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, iwl_testmode_gnl_msg_policy); if (result != 0) { - IWL_DEBUG_INFO(priv, - "Error parsing the gnl message : %d\n", result); + IWL_ERR(priv, "Error parsing the gnl message : %d\n", result); return result; } /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ if (!tb[IWL_TM_ATTR_COMMAND]) { - IWL_DEBUG_INFO(priv, "Error finding testmode command type\n"); + IWL_ERR(priv, "Missing testmode command type\n"); return -ENOMSG; } /* in case multiple accesses to the device happens */ @@ -956,7 +937,7 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) break; default: - IWL_DEBUG_INFO(priv, "Unknown testmode command\n"); + IWL_ERR(priv, "Unknown testmode command\n"); result = -ENOSYS; break; } @@ -981,15 +962,14 @@ int iwlagn_mac_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb, result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, iwl_testmode_gnl_msg_policy); if (result) { - IWL_DEBUG_INFO(priv, - "Error parsing the gnl message : %d\n", result); + IWL_ERR(priv, + "Error parsing the gnl message : %d\n", result); return result; } /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ if (!tb[IWL_TM_ATTR_COMMAND]) { - IWL_DEBUG_INFO(priv, - "Error finding testmode command type\n"); + IWL_ERR(priv, "Missing testmode command type\n"); return -ENOMSG; } cmd = nla_get_u32(tb[IWL_TM_ATTR_COMMAND]); diff --git a/trunk/drivers/net/wireless/rt2x00/Kconfig b/trunk/drivers/net/wireless/rt2x00/Kconfig index 299c3879582d..a0a7854facc0 100644 --- a/trunk/drivers/net/wireless/rt2x00/Kconfig +++ b/trunk/drivers/net/wireless/rt2x00/Kconfig @@ -163,7 +163,7 @@ config RT2800USB_RT53XX depends on EXPERIMENTAL ---help--- This adds support for rt53xx wireless chipset family to the - rt2800usb driver. + rt2800pci driver. Supported chips: RT5370 config RT2800USB_UNKNOWN diff --git a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c index f1df929e97a7..772d4aec303a 100644 --- a/trunk/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/trunk/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4053,7 +4053,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) case RT5390: break; default: - ERROR(rt2x00dev, "Invalid RT chipset 0x%04x detected.\n", rt2x00dev->chip.rt); + ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); return -ENODEV; } @@ -4072,7 +4072,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) case RF5390: break; default: - ERROR(rt2x00dev, "Invalid RF chipset 0x%04x detected.\n", + ERROR(rt2x00dev, "Invalid RF chipset 0x%x detected.\n", rt2x00dev->chip.rf); return -ENODEV; } diff --git a/trunk/drivers/net/wireless/rtlwifi/base.c b/trunk/drivers/net/wireless/rtlwifi/base.c index 510023554e5f..df5655cc55c0 100644 --- a/trunk/drivers/net/wireless/rtlwifi/base.c +++ b/trunk/drivers/net/wireless/rtlwifi/base.c @@ -39,10 +39,10 @@ #include /* - *NOTICE!!!: This file will be very big, we should - *keep it clear under following roles: + *NOTICE!!!: This file will be very big, we hsould + *keep it clear under follwing roles: * - *This file include following parts, so, if you add new + *This file include follwing part, so, if you add new *functions into this file, please check which part it *should includes. or check if you should add new part *for this file: diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index cdd71f5e77ac..22e998dd2f32 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c @@ -177,7 +177,7 @@ u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask) u32 i; for (i = 0; i <= 31; i++) { - if ((bitmask >> i) & 0x1) + if (((bitmask >> i) & 0x1) == 1) break; } return i; @@ -253,51 +253,121 @@ void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); - int index; - - if (regaddr == RTXAGC_A_RATE18_06) - index = 0; - else if (regaddr == RTXAGC_A_RATE54_24) - index = 1; - else if (regaddr == RTXAGC_A_CCK1_MCS32) - index = 6; - else if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) - index = 7; - else if (regaddr == RTXAGC_A_MCS03_MCS00) - index = 2; - else if (regaddr == RTXAGC_A_MCS07_MCS04) - index = 3; - else if (regaddr == RTXAGC_A_MCS11_MCS08) - index = 4; - else if (regaddr == RTXAGC_A_MCS15_MCS12) - index = 5; - else if (regaddr == RTXAGC_B_RATE18_06) - index = 8; - else if (regaddr == RTXAGC_B_RATE54_24) - index = 9; - else if (regaddr == RTXAGC_B_CCK1_55_MCS32) - index = 14; - else if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) - index = 15; - else if (regaddr == RTXAGC_B_MCS03_MCS00) - index = 10; - else if (regaddr == RTXAGC_B_MCS07_MCS04) - index = 11; - else if (regaddr == RTXAGC_B_MCS11_MCS08) - index = 12; - else if (regaddr == RTXAGC_B_MCS15_MCS12) - index = 13; - else - return; - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][index] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%x\n", - rtlphy->pwrgroup_cnt, index, - rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][index]); + if (regaddr == RTXAGC_A_RATE18_06) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][0] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][0]); + } + if (regaddr == RTXAGC_A_RATE54_24) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][1] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][1]); + } + if (regaddr == RTXAGC_A_CCK1_MCS32) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][6] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][6]); + } + if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][7] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][7]); + } + if (regaddr == RTXAGC_A_MCS03_MCS00) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][2] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][2]); + } + if (regaddr == RTXAGC_A_MCS07_MCS04) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][3] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][3]); + } + if (regaddr == RTXAGC_A_MCS11_MCS08) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][4] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][4]); + } + if (regaddr == RTXAGC_A_MCS15_MCS12) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][5] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][5]); + } + if (regaddr == RTXAGC_B_RATE18_06) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][8] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][8]); + } + if (regaddr == RTXAGC_B_RATE54_24) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9]); + } + if (regaddr == RTXAGC_B_CCK1_55_MCS32) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14]); + } + if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15]); + } + if (regaddr == RTXAGC_B_MCS03_MCS00) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10]); + } + if (regaddr == RTXAGC_B_MCS07_MCS04) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11]); + } + if (regaddr == RTXAGC_B_MCS11_MCS08) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12]); + } + if (regaddr == RTXAGC_B_MCS15_MCS12) { + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][13] = data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n", + rtlphy->pwrgroup_cnt, + rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][13]); - if (index == 13) rtlphy->pwrgroup_cnt++; + } } EXPORT_SYMBOL(_rtl92c_store_pwrIndex_diffrate_offset); diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/phy.c index 96dc71746eaa..9581a19c2548 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192de/phy.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192de/phy.c @@ -665,51 +665,152 @@ static void _rtl92d_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); - int index; - - if (regaddr == RTXAGC_A_RATE18_06) - index = 0; - else if (regaddr == RTXAGC_A_RATE54_24) - index = 1; - else if (regaddr == RTXAGC_A_CCK1_MCS32) - index = 6; - else if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) - index = 7; - else if (regaddr == RTXAGC_A_MCS03_MCS00) - index = 2; - else if (regaddr == RTXAGC_A_MCS07_MCS04) - index = 3; - else if (regaddr == RTXAGC_A_MCS11_MCS08) - index = 4; - else if (regaddr == RTXAGC_A_MCS15_MCS12) - index = 5; - else if (regaddr == RTXAGC_B_RATE18_06) - index = 8; - else if (regaddr == RTXAGC_B_RATE54_24) - index = 9; - else if (regaddr == RTXAGC_B_CCK1_55_MCS32) - index = 14; - else if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) - index = 15; - else if (regaddr == RTXAGC_B_MCS03_MCS00) - index = 10; - else if (regaddr == RTXAGC_B_MCS07_MCS04) - index = 11; - else if (regaddr == RTXAGC_B_MCS11_MCS08) - index = 12; - else if (regaddr == RTXAGC_B_MCS15_MCS12) - index = 13; - else - return; - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][index] = data; - RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, - "MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%ulx\n", - rtlphy->pwrgroup_cnt, index, - rtlphy->mcs_txpwrlevel_origoffset - [rtlphy->pwrgroup_cnt][index]); - if (index == 13) + if (regaddr == RTXAGC_A_RATE18_06) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][0] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][0]); + } + if (regaddr == RTXAGC_A_RATE54_24) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][1] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][1]); + } + if (regaddr == RTXAGC_A_CCK1_MCS32) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][6] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][6]); + } + if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][7] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][7]); + } + if (regaddr == RTXAGC_A_MCS03_MCS00) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][2] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][2]); + } + if (regaddr == RTXAGC_A_MCS07_MCS04) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][3] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][3]); + } + if (regaddr == RTXAGC_A_MCS11_MCS08) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][4] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][4]); + } + if (regaddr == RTXAGC_A_MCS15_MCS12) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][5] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][5]); + } + if (regaddr == RTXAGC_B_RATE18_06) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][8] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][8]); + } + if (regaddr == RTXAGC_B_RATE54_24) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][9] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][9]); + } + if (regaddr == RTXAGC_B_CCK1_55_MCS32) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][14] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][14]); + } + if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][15] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][15]); + } + if (regaddr == RTXAGC_B_MCS03_MCS00) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][10] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][10]); + } + if (regaddr == RTXAGC_B_MCS07_MCS04) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][11] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][11]); + } + if (regaddr == RTXAGC_B_MCS11_MCS08) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][12] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][12]); + } + if (regaddr == RTXAGC_B_MCS15_MCS12) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] = + data; + RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, + "MCSTxPowerLevelOriginalOffset[%d][13] = 0x%ulx\n", + rtlphy->pwrgroup_cnt, + rtlphy->mcs_txpwrlevel_origoffset + [rtlphy->pwrgroup_cnt][13]); rtlphy->pwrgroup_cnt++; + } } static bool _rtl92d_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw, diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/fw.h b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/fw.h index b4afff626437..babe85d4b694 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/fw.h +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/fw.h @@ -30,7 +30,6 @@ #define __REALTEK_FIRMWARE92S_H__ #define RTL8190_MAX_FIRMWARE_CODE_SIZE 64000 -#define RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE 90000 #define RTL8190_CPU_START_OFFSET 0x80 /* Firmware Local buffer size. 64k */ #define MAX_FIRMWARE_CODE_SIZE 0xFF00 @@ -218,7 +217,7 @@ struct rt_firmware { u8 fw_emem[RTL8190_MAX_FIRMWARE_CODE_SIZE]; u32 fw_imem_len; u32 fw_emem_len; - u8 sz_fw_tmpbuffer[RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE]; + u8 sz_fw_tmpbuffer[164000]; u32 sz_fw_tmpbufferlen; u16 cmdpacket_fragthresold; }; diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/phy.c index 6d5bbd0e4d38..05b4e2790e99 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/phy.c @@ -678,28 +678,30 @@ static void _rtl92s_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, { struct rtl_priv *rtlpriv = rtl_priv(hw); struct rtl_phy *rtlphy = &(rtlpriv->phy); - int index; if (reg_addr == RTXAGC_RATE18_06) - index = 0; - else if (reg_addr == RTXAGC_RATE54_24) - index = 1; - else if (reg_addr == RTXAGC_CCK_MCS32) - index = 6; - else if (reg_addr == RTXAGC_MCS03_MCS00) - index = 2; - else if (reg_addr == RTXAGC_MCS07_MCS04) - index = 3; - else if (reg_addr == RTXAGC_MCS11_MCS08) - index = 4; - else if (reg_addr == RTXAGC_MCS15_MCS12) - index = 5; - else - return; - - rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][index] = data; - if (index == 5) + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] = + data; + if (reg_addr == RTXAGC_RATE54_24) + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] = + data; + if (reg_addr == RTXAGC_CCK_MCS32) + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] = + data; + if (reg_addr == RTXAGC_MCS03_MCS00) + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] = + data; + if (reg_addr == RTXAGC_MCS07_MCS04) + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] = + data; + if (reg_addr == RTXAGC_MCS11_MCS08) + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] = + data; + if (reg_addr == RTXAGC_MCS15_MCS12) { + rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] = + data; rtlphy->pwrgroup_cnt++; + } } static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw) diff --git a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index 345d752137fa..ca38dd9f3564 100644 --- a/trunk/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/trunk/drivers/net/wireless/rtlwifi/rtl8192se/sw.c @@ -108,7 +108,6 @@ static void rtl92se_fw_cb(const struct firmware *firmware, void *context) if (firmware->size > rtlpriv->max_fw_size) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Firmware is too big!\n"); - rtlpriv->max_fw_size = 0; release_firmware(firmware); return; } @@ -233,7 +232,7 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) return 1; } - rtlpriv->max_fw_size = RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE; + rtlpriv->max_fw_size = sizeof(struct rt_firmware); pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n" "Loading firmware %s\n", rtlpriv->cfg->fw_name); diff --git a/trunk/drivers/net/wireless/wl1251/Makefile b/trunk/drivers/net/wireless/wl1251/Makefile index a5c6328b5f72..58b4f935a3f6 100644 --- a/trunk/drivers/net/wireless/wl1251/Makefile +++ b/trunk/drivers/net/wireless/wl1251/Makefile @@ -6,5 +6,3 @@ wl1251_sdio-objs += sdio.o obj-$(CONFIG_WL1251) += wl1251.o obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/trunk/drivers/net/wireless/wl1251/boot.c b/trunk/drivers/net/wireless/wl1251/boot.c index a2e5241382da..d729daf8e841 100644 --- a/trunk/drivers/net/wireless/wl1251/boot.c +++ b/trunk/drivers/net/wireless/wl1251/boot.c @@ -464,6 +464,8 @@ static int wl1251_boot_upload_nvs(struct wl1251 *wl) val = (nvs_ptr[0] | (nvs_ptr[1] << 8) | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); + val = cpu_to_le32(val); + wl1251_debug(DEBUG_BOOT, "nvs write table 0x%x: 0x%x", nvs_start, val); diff --git a/trunk/drivers/net/wireless/wl1251/io.h b/trunk/drivers/net/wireless/wl1251/io.h index d382877c34cc..c545e9d5f512 100644 --- a/trunk/drivers/net/wireless/wl1251/io.h +++ b/trunk/drivers/net/wireless/wl1251/io.h @@ -36,15 +36,16 @@ static inline u32 wl1251_read32(struct wl1251 *wl, int addr) { - wl->if_ops->read(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32)); + u32 response; + + wl->if_ops->read(wl, addr, &response, sizeof(u32)); - return le32_to_cpu(wl->buffer_32); + return response; } static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val) { - wl->buffer_32 = cpu_to_le32(val); - wl->if_ops->write(wl, addr, &wl->buffer_32, sizeof(wl->buffer_32)); + wl->if_ops->write(wl, addr, &val, sizeof(u32)); } static inline u32 wl1251_read_elp(struct wl1251 *wl, int addr) diff --git a/trunk/drivers/net/wireless/wl1251/wl1251.h b/trunk/drivers/net/wireless/wl1251/wl1251.h index 9d8f5816c6f9..a77f1bbbed0a 100644 --- a/trunk/drivers/net/wireless/wl1251/wl1251.h +++ b/trunk/drivers/net/wireless/wl1251/wl1251.h @@ -380,7 +380,7 @@ struct wl1251 { struct wl1251_stats stats; struct wl1251_debugfs debugfs; - __le32 buffer_32; + u32 buffer_32; u32 buffer_cmd; u8 buffer_busyword[WL1251_BUSY_WORD_LEN]; struct wl1251_rx_descriptor *rx_descriptor; diff --git a/trunk/drivers/net/wireless/wl12xx/Makefile b/trunk/drivers/net/wireless/wl12xx/Makefile index 98f289c907a9..fe67262ba19f 100644 --- a/trunk/drivers/net/wireless/wl12xx/Makefile +++ b/trunk/drivers/net/wireless/wl12xx/Makefile @@ -11,5 +11,3 @@ obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o # small builtin driver bit obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o - -ccflags-y += -D__CHECK_ENDIAN__ diff --git a/trunk/drivers/net/wireless/wl12xx/acx.c b/trunk/drivers/net/wireless/wl12xx/acx.c index bc96db0683a5..7537c401a448 100644 --- a/trunk/drivers/net/wireless/wl12xx/acx.c +++ b/trunk/drivers/net/wireless/wl12xx/acx.c @@ -34,14 +34,12 @@ #include "reg.h" #include "ps.h" -int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 wake_up_event, u8 listen_interval) +int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif) { struct acx_wake_up_condition *wake_up; int ret; - wl1271_debug(DEBUG_ACX, "acx wake up conditions (wake_up_event %d listen_interval %d)", - wake_up_event, listen_interval); + wl1271_debug(DEBUG_ACX, "acx wake up conditions"); wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL); if (!wake_up) { @@ -50,8 +48,8 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl, struct wl12xx_vif *wlvif, } wake_up->role_id = wlvif->role_id; - wake_up->wake_up_event = wake_up_event; - wake_up->listen_interval = listen_interval; + wake_up->wake_up_event = wl->conf.conn.wake_up_event; + wake_up->listen_interval = wl->conf.conn.listen_interval; ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS, wake_up, sizeof(*wake_up)); @@ -1461,10 +1459,9 @@ int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, return ret; } -int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u64 *mactime) +int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime) { - struct wl12xx_acx_fw_tsf_information *tsf_info; + struct wl1271_acx_fw_tsf_information *tsf_info; int ret; tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL); @@ -1473,8 +1470,6 @@ int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; } - tsf_info->role_id = wlvif->role_id; - ret = wl1271_cmd_interrogate(wl, ACX_TSF_INFO, tsf_info, sizeof(*tsf_info)); if (ret < 0) { diff --git a/trunk/drivers/net/wireless/wl12xx/acx.h b/trunk/drivers/net/wireless/wl12xx/acx.h index a28fc044034c..69892b40c2df 100644 --- a/trunk/drivers/net/wireless/wl12xx/acx.h +++ b/trunk/drivers/net/wireless/wl12xx/acx.h @@ -995,17 +995,15 @@ struct wl1271_acx_ba_receiver_setup { u8 padding[2]; } __packed; -struct wl12xx_acx_fw_tsf_information { +struct wl1271_acx_fw_tsf_information { struct acx_header header; - u8 role_id; - u8 padding1[3]; __le32 current_tsf_high; __le32 current_tsf_low; __le32 last_bttt_high; __le32 last_tbtt_low; u8 last_dtim_count; - u8 padding2[3]; + u8 padding[3]; } __packed; struct wl1271_acx_ps_rx_streaming { @@ -1153,81 +1151,79 @@ struct wl12xx_acx_config_hangover { } __packed; enum { - ACX_WAKE_UP_CONDITIONS = 0x0000, - ACX_MEM_CFG = 0x0001, - ACX_SLOT = 0x0002, - ACX_AC_CFG = 0x0003, - ACX_MEM_MAP = 0x0004, - ACX_AID = 0x0005, - ACX_MEDIUM_USAGE = 0x0006, - ACX_STATISTICS = 0x0007, - ACX_PWR_CONSUMPTION_STATISTICS = 0x0008, - ACX_TID_CFG = 0x0009, - ACX_PS_RX_STREAMING = 0x000A, - ACX_BEACON_FILTER_OPT = 0x000B, - ACX_NOISE_HIST = 0x000C, - ACX_HDK_VERSION = 0x000D, - ACX_PD_THRESHOLD = 0x000E, - ACX_TX_CONFIG_OPT = 0x000F, - ACX_CCA_THRESHOLD = 0x0010, - ACX_EVENT_MBOX_MASK = 0x0011, - ACX_CONN_MONIT_PARAMS = 0x0012, - ACX_DISABLE_BROADCASTS = 0x0013, - ACX_BCN_DTIM_OPTIONS = 0x0014, - ACX_SG_ENABLE = 0x0015, - ACX_SG_CFG = 0x0016, - ACX_FM_COEX_CFG = 0x0017, - ACX_BEACON_FILTER_TABLE = 0x0018, - ACX_ARP_IP_FILTER = 0x0019, - ACX_ROAMING_STATISTICS_TBL = 0x001A, - ACX_RATE_POLICY = 0x001B, - ACX_CTS_PROTECTION = 0x001C, - ACX_SLEEP_AUTH = 0x001D, - ACX_PREAMBLE_TYPE = 0x001E, - ACX_ERROR_CNT = 0x001F, - ACX_IBSS_FILTER = 0x0020, - ACX_SERVICE_PERIOD_TIMEOUT = 0x0021, - ACX_TSF_INFO = 0x0022, - ACX_CONFIG_PS_WMM = 0x0023, - ACX_ENABLE_RX_DATA_FILTER = 0x0024, - ACX_SET_RX_DATA_FILTER = 0x0025, - ACX_GET_DATA_FILTER_STATISTICS = 0x0026, - ACX_RX_CONFIG_OPT = 0x0027, - ACX_FRAG_CFG = 0x0028, - ACX_BET_ENABLE = 0x0029, - ACX_RSSI_SNR_TRIGGER = 0x002A, - ACX_RSSI_SNR_WEIGHTS = 0x002B, - ACX_KEEP_ALIVE_MODE = 0x002C, - ACX_SET_KEEP_ALIVE_CONFIG = 0x002D, - ACX_BA_SESSION_INIT_POLICY = 0x002E, - ACX_BA_SESSION_RX_SETUP = 0x002F, - ACX_PEER_HT_CAP = 0x0030, - ACX_HT_BSS_OPERATION = 0x0031, - ACX_COEX_ACTIVITY = 0x0032, - ACX_BURST_MODE = 0x0033, - ACX_SET_RATE_MGMT_PARAMS = 0x0034, - ACX_GET_RATE_MGMT_PARAMS = 0x0035, - ACX_SET_RATE_ADAPT_PARAMS = 0x0036, - ACX_SET_DCO_ITRIM_PARAMS = 0x0037, - ACX_GEN_FW_CMD = 0x0038, - ACX_HOST_IF_CFG_BITMAP = 0x0039, - ACX_MAX_TX_FAILURE = 0x003A, - ACX_UPDATE_INCONNECTION_STA_LIST = 0x003B, - DOT11_RX_MSDU_LIFE_TIME = 0x003C, - DOT11_CUR_TX_PWR = 0x003D, - DOT11_RTS_THRESHOLD = 0x003E, - DOT11_GROUP_ADDRESS_TBL = 0x003F, - ACX_PM_CONFIG = 0x0040, - ACX_CONFIG_PS = 0x0041, - ACX_CONFIG_HANGOVER = 0x0042, - ACX_FEATURE_CFG = 0x0043, - ACX_PROTECTION_CFG = 0x0044, + ACX_WAKE_UP_CONDITIONS = 0x0002, + ACX_MEM_CFG = 0x0003, + ACX_SLOT = 0x0004, + ACX_AC_CFG = 0x0007, + ACX_MEM_MAP = 0x0008, + ACX_AID = 0x000A, + ACX_MEDIUM_USAGE = 0x000F, + ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */ + ACX_STATISTICS = 0x0013, /* Debug API */ + ACX_PWR_CONSUMPTION_STATISTICS = 0x0014, + ACX_FEATURE_CFG = 0x0015, + ACX_TID_CFG = 0x001A, + ACX_PS_RX_STREAMING = 0x001B, + ACX_BEACON_FILTER_OPT = 0x001F, + ACX_NOISE_HIST = 0x0021, + ACX_HDK_VERSION = 0x0022, /* ??? */ + ACX_PD_THRESHOLD = 0x0023, + ACX_TX_CONFIG_OPT = 0x0024, + ACX_CCA_THRESHOLD = 0x0025, + ACX_EVENT_MBOX_MASK = 0x0026, + ACX_CONN_MONIT_PARAMS = 0x002D, + ACX_BCN_DTIM_OPTIONS = 0x0031, + ACX_SG_ENABLE = 0x0032, + ACX_SG_CFG = 0x0033, + ACX_FM_COEX_CFG = 0x0034, + ACX_BEACON_FILTER_TABLE = 0x0038, + ACX_ARP_IP_FILTER = 0x0039, + ACX_ROAMING_STATISTICS_TBL = 0x003B, + ACX_RATE_POLICY = 0x003D, + ACX_CTS_PROTECTION = 0x003E, + ACX_SLEEP_AUTH = 0x003F, + ACX_PREAMBLE_TYPE = 0x0040, + ACX_ERROR_CNT = 0x0041, + ACX_IBSS_FILTER = 0x0044, + ACX_SERVICE_PERIOD_TIMEOUT = 0x0045, + ACX_TSF_INFO = 0x0046, + ACX_CONFIG_PS_WMM = 0x0049, + ACX_ENABLE_RX_DATA_FILTER = 0x004A, + ACX_SET_RX_DATA_FILTER = 0x004B, + ACX_GET_DATA_FILTER_STATISTICS = 0x004C, + ACX_RX_CONFIG_OPT = 0x004E, + ACX_FRAG_CFG = 0x004F, + ACX_BET_ENABLE = 0x0050, + ACX_RSSI_SNR_TRIGGER = 0x0051, + ACX_RSSI_SNR_WEIGHTS = 0x0052, + ACX_KEEP_ALIVE_MODE = 0x0053, + ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, + ACX_BA_SESSION_INIT_POLICY = 0x0055, + ACX_BA_SESSION_RX_SETUP = 0x0056, + ACX_PEER_HT_CAP = 0x0057, + ACX_HT_BSS_OPERATION = 0x0058, + ACX_COEX_ACTIVITY = 0x0059, + ACX_BURST_MODE = 0x005C, + ACX_SET_RATE_MGMT_PARAMS = 0x005D, + ACX_SET_RATE_ADAPT_PARAMS = 0x0060, + ACX_SET_DCO_ITRIM_PARAMS = 0x0061, + ACX_GEN_FW_CMD = 0x0070, + ACX_HOST_IF_CFG_BITMAP = 0x0071, + ACX_MAX_TX_FAILURE = 0x0072, + ACX_UPDATE_INCONNECTION_STA_LIST = 0x0073, + DOT11_RX_MSDU_LIFE_TIME = 0x1004, + DOT11_CUR_TX_PWR = 0x100D, + DOT11_RX_DOT11_MODE = 0x1012, + DOT11_RTS_THRESHOLD = 0x1013, + DOT11_GROUP_ADDRESS_TBL = 0x1014, + ACX_PM_CONFIG = 0x1016, + ACX_CONFIG_PS = 0x1017, + ACX_CONFIG_HANGOVER = 0x1018, }; int wl1271_acx_wake_up_conditions(struct wl1271 *wl, - struct wl12xx_vif *wlvif, - u8 wake_up_event, u8 listen_interval); + struct wl12xx_vif *wlvif); int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth); int wl1271_acx_tx_power(struct wl1271 *wl, struct wl12xx_vif *wlvif, int power); @@ -1300,8 +1296,7 @@ int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, bool enable, u8 peer_hlid); -int wl12xx_acx_tsf_info(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u64 *mactime); +int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, bool enable); int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl, struct wl12xx_vif *wlvif); diff --git a/trunk/drivers/net/wireless/wl12xx/boot.c b/trunk/drivers/net/wireless/wl12xx/boot.c index 954101d03f06..8f9cf5a816ea 100644 --- a/trunk/drivers/net/wireless/wl12xx/boot.c +++ b/trunk/drivers/net/wireless/wl12xx/boot.c @@ -33,6 +33,65 @@ #include "event.h" #include "rx.h" +static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { + [PART_DOWN] = { + .mem = { + .start = 0x00000000, + .size = 0x000177c0 + }, + .reg = { + .start = REGISTERS_BASE, + .size = 0x00008800 + }, + .mem2 = { + .start = 0x00000000, + .size = 0x00000000 + }, + .mem3 = { + .start = 0x00000000, + .size = 0x00000000 + }, + }, + + [PART_WORK] = { + .mem = { + .start = 0x00040000, + .size = 0x00014fc0 + }, + .reg = { + .start = REGISTERS_BASE, + .size = 0x0000a000 + }, + .mem2 = { + .start = 0x003004f8, + .size = 0x00000004 + }, + .mem3 = { + .start = 0x00040404, + .size = 0x00000000 + }, + }, + + [PART_DRPW] = { + .mem = { + .start = 0x00040000, + .size = 0x00014fc0 + }, + .reg = { + .start = DRPW_BASE, + .size = 0x00006000 + }, + .mem2 = { + .start = 0x00000000, + .size = 0x00000000 + }, + .mem3 = { + .start = 0x00000000, + .size = 0x00000000 + } + } +}; + static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) { u32 cpu_ctrl; @@ -122,13 +181,13 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, return -ENOMEM; } - memcpy(&partition, &wl12xx_part_table[PART_DOWN], sizeof(partition)); + memcpy(&partition, &part_table[PART_DOWN], sizeof(partition)); partition.mem.start = dest; wl1271_set_partition(wl, &partition); /* 10.1 set partition limit and chunk num */ chunk_num = 0; - partition_limit = wl12xx_part_table[PART_DOWN].mem.size; + partition_limit = part_table[PART_DOWN].mem.size; while (chunk_num < fw_data_len / CHUNK_SIZE) { /* 10.2 update partition, if needed */ @@ -136,7 +195,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, if (addr > partition_limit) { addr = dest + chunk_num * CHUNK_SIZE; partition_limit = chunk_num * CHUNK_SIZE + - wl12xx_part_table[PART_DOWN].mem.size; + part_table[PART_DOWN].mem.size; partition.mem.start = addr; wl1271_set_partition(wl, &partition); } @@ -258,12 +317,12 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) } /* update current MAC address to NVS */ - nvs_ptr[11] = wl->addresses[0].addr[0]; - nvs_ptr[10] = wl->addresses[0].addr[1]; - nvs_ptr[6] = wl->addresses[0].addr[2]; - nvs_ptr[5] = wl->addresses[0].addr[3]; - nvs_ptr[4] = wl->addresses[0].addr[4]; - nvs_ptr[3] = wl->addresses[0].addr[5]; + nvs_ptr[11] = wl->mac_addr[0]; + nvs_ptr[10] = wl->mac_addr[1]; + nvs_ptr[6] = wl->mac_addr[2]; + nvs_ptr[5] = wl->mac_addr[3]; + nvs_ptr[4] = wl->mac_addr[4]; + nvs_ptr[3] = wl->mac_addr[5]; /* * Layout before the actual NVS tables: @@ -324,7 +383,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) nvs_len -= nvs_ptr - (u8 *)wl->nvs; /* Now we must set the partition correctly */ - wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]); + wl1271_set_partition(wl, &part_table[PART_WORK]); /* Copy the NVS tables to a new block to ensure alignment */ nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); @@ -433,7 +492,7 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) wl->event_box_addr = wl1271_read32(wl, REG_EVENT_MAILBOX_PTR); /* set the working partition to its "running" mode offset */ - wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]); + wl1271_set_partition(wl, &part_table[PART_WORK]); wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", wl->cmd_box_addr, wl->event_box_addr); @@ -448,7 +507,8 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) /* unmask required mbox events */ wl->event_mask = BSS_LOSE_EVENT_ID | SCAN_COMPLETE_EVENT_ID | - ROLE_STOP_COMPLETE_EVENT_ID | + PS_REPORT_EVENT_ID | + DISCONNECT_EVENT_COMPLETE_ID | RSSI_SNR_TRIGGER_0_EVENT_ID | PSPOLL_DELIVERY_FAILURE_EVENT_ID | SOFT_GEMINI_SENSE_EVENT_ID | @@ -487,6 +547,19 @@ static int wl1271_boot_write_irq_polarity(struct wl1271 *wl) return 0; } +static void wl1271_boot_hw_version(struct wl1271 *wl) +{ + u32 fuse; + + if (wl->chip.id == CHIP_ID_1283_PG20) + fuse = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1); + else + fuse = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1); + fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET; + + wl->hw_pg_ver = (s8)fuse; +} + static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) { u16 spare_reg; @@ -625,7 +698,7 @@ static int wl127x_boot_clk(struct wl1271 *wl) u32 pause; u32 clk; - if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) + if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3) wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; if (wl->ref_clock == CONF_REF_CLK_19_2_E || @@ -680,6 +753,8 @@ int wl1271_load_firmware(struct wl1271 *wl) u32 tmp, clk; int selected_clock = -1; + wl1271_boot_hw_version(wl); + if (wl->chip.id == CHIP_ID_1283_PG20) { ret = wl128x_boot_clk(wl, &selected_clock); if (ret < 0) @@ -694,7 +769,7 @@ int wl1271_load_firmware(struct wl1271 *wl) wl1271_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); udelay(500); - wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]); + wl1271_set_partition(wl, &part_table[PART_DRPW]); /* Read-modify-write DRPW_SCRATCH_START register (see next state) to be used by DRPw FW. The RTRIM value will be added by the FW @@ -713,7 +788,7 @@ int wl1271_load_firmware(struct wl1271 *wl) wl1271_write32(wl, DRPW_SCRATCH_START, clk); - wl1271_set_partition(wl, &wl12xx_part_table[PART_WORK]); + wl1271_set_partition(wl, &part_table[PART_WORK]); /* Disable interrupts */ wl1271_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); diff --git a/trunk/drivers/net/wireless/wl12xx/boot.h b/trunk/drivers/net/wireless/wl12xx/boot.h index c3adc09f403d..06dad9380fa7 100644 --- a/trunk/drivers/net/wireless/wl12xx/boot.h +++ b/trunk/drivers/net/wireless/wl12xx/boot.h @@ -55,6 +55,16 @@ struct wl1271_static_data { #define OCP_REG_CLK_POLARITY 0x0cb2 #define OCP_REG_CLK_PULL 0x0cb4 +#define WL127X_REG_FUSE_DATA_2_1 0x050a +#define WL128X_REG_FUSE_DATA_2_1 0x2152 +#define PG_VER_MASK 0x3c +#define PG_VER_OFFSET 2 + +#define PG_MAJOR_VER_MASK 0x3 +#define PG_MAJOR_VER_OFFSET 0x0 +#define PG_MINOR_VER_MASK 0xc +#define PG_MINOR_VER_OFFSET 0x2 + #define CMD_MBOX_ADDRESS 0x407B4 #define POLARITY_LOW BIT(1) diff --git a/trunk/drivers/net/wireless/wl12xx/cmd.c b/trunk/drivers/net/wireless/wl12xx/cmd.c index b776d9d5efe8..25990bd38be6 100644 --- a/trunk/drivers/net/wireless/wl12xx/cmd.c +++ b/trunk/drivers/net/wireless/wl12xx/cmd.c @@ -566,7 +566,7 @@ static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, goto out_free; } - ret = wl1271_cmd_wait_for_event(wl, ROLE_STOP_COMPLETE_EVENT_ID); + ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); if (ret < 0) { wl1271_error("cmd role stop dev event completion error"); goto out_free; @@ -715,8 +715,6 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif) cmd->ap.beacon_interval = cpu_to_le16(wlvif->beacon_int); cmd->ap.dtim_interval = bss_conf->dtim_period; cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; - /* FIXME: Change when adding DFS */ - cmd->ap.reset_tsf = 1; /* By default reset AP TSF */ cmd->channel = wlvif->channel; if (!bss_conf->hidden_ssid) { @@ -996,7 +994,7 @@ int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) } int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 ps_mode, u16 auto_ps_timeout) + u8 ps_mode) { struct wl1271_cmd_ps_params *ps_params = NULL; int ret = 0; @@ -1011,7 +1009,6 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, ps_params->role_id = wlvif->role_id; ps_params->ps_mode = ps_mode; - ps_params->auto_ps_timeout = auto_ps_timeout; ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, sizeof(*ps_params), 0); @@ -1025,15 +1022,13 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl1271_cmd_template_set(struct wl1271 *wl, u8 role_id, - u16 template_id, void *buf, size_t buf_len, - int index, u32 rates) +int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, + void *buf, size_t buf_len, int index, u32 rates) { struct wl1271_cmd_template_set *cmd; int ret = 0; - wl1271_debug(DEBUG_CMD, "cmd template_set %d (role %d)", - template_id, role_id); + wl1271_debug(DEBUG_CMD, "cmd template_set %d", template_id); WARN_ON(buf_len > WL1271_CMD_TEMPL_MAX_SIZE); buf_len = min_t(size_t, buf_len, WL1271_CMD_TEMPL_MAX_SIZE); @@ -1044,8 +1039,6 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u8 role_id, goto out; } - /* during initialization wlvif is NULL */ - cmd->role_id = role_id; cmd->len = cpu_to_le16(buf_len); cmd->template_type = template_id; cmd->enabled_rates = cpu_to_le32(rates); @@ -1089,8 +1082,7 @@ int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif) ptr = skb->data; } - ret = wl1271_cmd_template_set(wl, wlvif->role_id, - CMD_TEMPL_NULL_DATA, ptr, size, 0, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, wlvif->basic_rate); out: @@ -1113,7 +1105,7 @@ int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, if (!skb) goto out; - ret = wl1271_cmd_template_set(wl, wlvif->role_id, CMD_TEMPL_KLV, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, skb->data, skb->len, CMD_TEMPL_KLV_IDX_NULL_DATA, wlvif->basic_rate); @@ -1138,8 +1130,7 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (!skb) goto out; - ret = wl1271_cmd_template_set(wl, wlvif->role_id, - CMD_TEMPL_PS_POLL, skb->data, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, skb->len, 0, wlvif->basic_rate_set); out: @@ -1147,10 +1138,9 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } -int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 role_id, u8 band, +int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, const u8 *ssid, size_t ssid_len, - const u8 *ie, size_t ie_len) + const u8 *ie, size_t ie_len, u8 band) { struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); struct sk_buff *skb; @@ -1168,12 +1158,10 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]); if (band == IEEE80211_BAND_2GHZ) - ret = wl1271_cmd_template_set(wl, role_id, - CMD_TEMPL_CFG_PROBE_REQ_2_4, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, skb->data, skb->len, 0, rate); else - ret = wl1271_cmd_template_set(wl, role_id, - CMD_TEMPL_CFG_PROBE_REQ_5, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, skb->data, skb->len, 0, rate); out: @@ -1198,12 +1186,10 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]); if (wlvif->band == IEEE80211_BAND_2GHZ) - ret = wl1271_cmd_template_set(wl, wlvif->role_id, - CMD_TEMPL_CFG_PROBE_REQ_2_4, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, skb->data, skb->len, 0, rate); else - ret = wl1271_cmd_template_set(wl, wlvif->role_id, - CMD_TEMPL_CFG_PROBE_REQ_5, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, skb->data, skb->len, 0, rate); if (ret < 0) @@ -1213,34 +1199,32 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, return skb; } -int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif) +int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, + __be32 ip_addr) { - int ret, extra; - u16 fc; + int ret; struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); - struct sk_buff *skb; - struct wl12xx_arp_rsp_template *tmpl; + struct wl12xx_arp_rsp_template tmpl; struct ieee80211_hdr_3addr *hdr; struct arphdr *arp_hdr; - skb = dev_alloc_skb(sizeof(*hdr) + sizeof(__le16) + sizeof(*tmpl) + - WL1271_EXTRA_SPACE_MAX); - if (!skb) { - wl1271_error("failed to allocate buffer for arp rsp template"); - return -ENOMEM; - } - - skb_reserve(skb, sizeof(*hdr) + WL1271_EXTRA_SPACE_MAX); + memset(&tmpl, 0, sizeof(tmpl)); - tmpl = (struct wl12xx_arp_rsp_template *)skb_put(skb, sizeof(*tmpl)); - memset(tmpl, 0, sizeof(tmpl)); + /* mac80211 header */ + hdr = &tmpl.hdr; + hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | + IEEE80211_STYPE_DATA | + IEEE80211_FCTL_TODS); + memcpy(hdr->addr1, vif->bss_conf.bssid, ETH_ALEN); + memcpy(hdr->addr2, vif->addr, ETH_ALEN); + memset(hdr->addr3, 0xff, ETH_ALEN); /* llc layer */ - memcpy(tmpl->llc_hdr, rfc1042_header, sizeof(rfc1042_header)); - tmpl->llc_type = cpu_to_be16(ETH_P_ARP); + memcpy(tmpl.llc_hdr, rfc1042_header, sizeof(rfc1042_header)); + tmpl.llc_type = cpu_to_be16(ETH_P_ARP); /* arp header */ - arp_hdr = &tmpl->arp_hdr; + arp_hdr = &tmpl.arp_hdr; arp_hdr->ar_hrd = cpu_to_be16(ARPHRD_ETHER); arp_hdr->ar_pro = cpu_to_be16(ETH_P_IP); arp_hdr->ar_hln = ETH_ALEN; @@ -1248,59 +1232,13 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif) arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY); /* arp payload */ - memcpy(tmpl->sender_hw, vif->addr, ETH_ALEN); - tmpl->sender_ip = wlvif->ip_addr; - - /* encryption space */ - switch (wlvif->encryption_type) { - case KEY_TKIP: - extra = WL1271_EXTRA_SPACE_TKIP; - break; - case KEY_AES: - extra = WL1271_EXTRA_SPACE_AES; - break; - case KEY_NONE: - case KEY_WEP: - case KEY_GEM: - extra = 0; - break; - default: - wl1271_warning("Unknown encryption type: %d", - wlvif->encryption_type); - ret = -EINVAL; - goto out; - } - - if (extra) { - u8 *space = skb_push(skb, extra); - memset(space, 0, extra); - } - - /* QoS header - BE */ - if (wlvif->sta.qos) - memset(skb_push(skb, sizeof(__le16)), 0, sizeof(__le16)); + memcpy(tmpl.sender_hw, vif->addr, ETH_ALEN); + tmpl.sender_ip = ip_addr; - /* mac80211 header */ - hdr = (struct ieee80211_hdr_3addr *)skb_push(skb, sizeof(*hdr)); - memset(hdr, 0, sizeof(hdr)); - fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS; - if (wlvif->sta.qos) - fc |= IEEE80211_STYPE_QOS_DATA; - else - fc |= IEEE80211_STYPE_DATA; - if (wlvif->encryption_type != KEY_NONE) - fc |= IEEE80211_FCTL_PROTECTED; - - hdr->frame_control = cpu_to_le16(fc); - memcpy(hdr->addr1, vif->bss_conf.bssid, ETH_ALEN); - memcpy(hdr->addr2, vif->addr, ETH_ALEN); - memset(hdr->addr3, 0xff, ETH_ALEN); - - ret = wl1271_cmd_template_set(wl, wlvif->role_id, CMD_TEMPL_ARP_RSP, - skb->data, skb->len, 0, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, + &tmpl, sizeof(tmpl), 0, wlvif->basic_rate); -out: - dev_kfree_skb(skb); + return ret; } @@ -1322,8 +1260,7 @@ int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif) /* FIXME: not sure what priority to use here */ template.qos_ctrl = cpu_to_le16(0); - return wl1271_cmd_template_set(wl, wlvif->role_id, - CMD_TEMPL_QOS_NULL_DATA, &template, + return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, sizeof(template), 0, wlvif->basic_rate); } @@ -1807,7 +1744,6 @@ int wl12xx_croc(struct wl1271 *wl, u8 role_id) } int wl12xx_cmd_channel_switch(struct wl1271 *wl, - struct wl12xx_vif *wlvif, struct ieee80211_channel_switch *ch_switch) { struct wl12xx_cmd_channel_switch *cmd; @@ -1821,13 +1757,10 @@ int wl12xx_cmd_channel_switch(struct wl1271 *wl, goto out; } - cmd->role_id = wlvif->role_id; cmd->channel = ch_switch->channel->hw_value; cmd->switch_time = ch_switch->count; - cmd->stop_tx = ch_switch->block_tx; - - /* FIXME: control from mac80211 in the future */ - cmd->post_switch_tx_disable = 0; /* Enable TX on the target channel */ + cmd->tx_suspend = ch_switch->block_tx; + cmd->flush = 0; /* this value is ignored by the FW */ ret = wl1271_cmd_send(wl, CMD_CHANNEL_SWITCH, cmd, sizeof(*cmd), 0); if (ret < 0) { diff --git a/trunk/drivers/net/wireless/wl12xx/cmd.h b/trunk/drivers/net/wireless/wl12xx/cmd.h index de217d92516b..3f7d0b93c24d 100644 --- a/trunk/drivers/net/wireless/wl12xx/cmd.h +++ b/trunk/drivers/net/wireless/wl12xx/cmd.h @@ -51,23 +51,22 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 ps_mode, u16 auto_ps_timeout); + u8 ps_mode); int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, size_t len); -int wl1271_cmd_template_set(struct wl1271 *wl, u8 role_id, - u16 template_id, void *buf, size_t buf_len, - int index, u32 rates); +int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, + void *buf, size_t buf_len, int index, u32 rates); int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif); int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif, u16 aid); -int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, - u8 role_id, u8 band, +int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, const u8 *ssid, size_t ssid_len, - const u8 *ie, size_t ie_len); + const u8 *ie, size_t ie_len, u8 band); struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct sk_buff *skb); -int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif); +int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif, + __be32 ip_addr); int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif); int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif); @@ -90,7 +89,6 @@ int wl12xx_cmd_config_fwlog(struct wl1271 *wl); int wl12xx_cmd_start_fwlog(struct wl1271 *wl); int wl12xx_cmd_stop_fwlog(struct wl1271 *wl); int wl12xx_cmd_channel_switch(struct wl1271 *wl, - struct wl12xx_vif *wlvif, struct ieee80211_channel_switch *ch_switch); int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl); int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, @@ -98,65 +96,62 @@ int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid); enum wl1271_commands { - CMD_INTERROGATE = 1, /* use this to read information elements */ - CMD_CONFIGURE = 2, /* use this to write information elements */ - CMD_ENABLE_RX = 3, - CMD_ENABLE_TX = 4, - CMD_DISABLE_RX = 5, - CMD_DISABLE_TX = 6, - CMD_SCAN = 7, - CMD_STOP_SCAN = 8, - CMD_SET_KEYS = 9, - CMD_READ_MEMORY = 10, - CMD_WRITE_MEMORY = 11, - CMD_SET_TEMPLATE = 12, - CMD_TEST = 13, - CMD_NOISE_HIST = 14, - CMD_QUIET_ELEMENT_SET_STATE = 15, - CMD_SET_BCN_MODE = 16, - - CMD_MEASUREMENT = 17, - CMD_STOP_MEASUREMENT = 18, - CMD_SET_PS_MODE = 19, - CMD_CHANNEL_SWITCH = 20, - CMD_STOP_CHANNEL_SWICTH = 21, - CMD_AP_DISCOVERY = 22, - CMD_STOP_AP_DISCOVERY = 23, - CMD_HEALTH_CHECK = 24, - CMD_DEBUG = 25, - CMD_TRIGGER_SCAN_TO = 26, - CMD_CONNECTION_SCAN_CFG = 27, - CMD_CONNECTION_SCAN_SSID_CFG = 28, - CMD_START_PERIODIC_SCAN = 29, - CMD_STOP_PERIODIC_SCAN = 30, - CMD_SET_PEER_STATE = 31, - CMD_REMAIN_ON_CHANNEL = 32, - CMD_CANCEL_REMAIN_ON_CHANNEL = 33, - CMD_CONFIG_FWLOGGER = 34, - CMD_START_FWLOGGER = 35, - CMD_STOP_FWLOGGER = 36, - - /* Access point commands */ - CMD_ADD_PEER = 37, - CMD_REMOVE_PEER = 38, + CMD_INTERROGATE = 1, /*use this to read information elements*/ + CMD_CONFIGURE = 2, /*use this to write information elements*/ + CMD_ENABLE_RX = 3, + CMD_ENABLE_TX = 4, + CMD_DISABLE_RX = 5, + CMD_DISABLE_TX = 6, + CMD_SCAN = 8, + CMD_STOP_SCAN = 9, + CMD_SET_KEYS = 12, + CMD_READ_MEMORY = 13, + CMD_WRITE_MEMORY = 14, + CMD_SET_TEMPLATE = 19, + CMD_TEST = 23, + CMD_NOISE_HIST = 28, + CMD_QUIET_ELEMENT_SET_STATE = 29, + CMD_SET_BCN_MODE = 33, + CMD_MEASUREMENT = 34, + CMD_STOP_MEASUREMENT = 35, + CMD_SET_PS_MODE = 37, + CMD_CHANNEL_SWITCH = 38, + CMD_STOP_CHANNEL_SWICTH = 39, + CMD_AP_DISCOVERY = 40, + CMD_STOP_AP_DISCOVERY = 41, + CMD_HEALTH_CHECK = 45, + CMD_DEBUG = 46, + CMD_TRIGGER_SCAN_TO = 47, + CMD_CONNECTION_SCAN_CFG = 48, + CMD_CONNECTION_SCAN_SSID_CFG = 49, + CMD_START_PERIODIC_SCAN = 50, + CMD_STOP_PERIODIC_SCAN = 51, + CMD_SET_PEER_STATE = 52, + CMD_REMAIN_ON_CHANNEL = 53, + CMD_CANCEL_REMAIN_ON_CHANNEL = 54, + + CMD_CONFIG_FWLOGGER = 55, + CMD_START_FWLOGGER = 56, + CMD_STOP_FWLOGGER = 57, + + /* AP commands */ + CMD_ADD_PEER = 62, + CMD_REMOVE_PEER = 63, /* Role API */ - CMD_ROLE_ENABLE = 39, - CMD_ROLE_DISABLE = 40, - CMD_ROLE_START = 41, - CMD_ROLE_STOP = 42, - - /* DFS */ - CMD_START_RADAR_DETECTION = 43, - CMD_STOP_RADAR_DETECTION = 44, + CMD_ROLE_ENABLE = 70, + CMD_ROLE_DISABLE = 71, + CMD_ROLE_START = 72, + CMD_ROLE_STOP = 73, /* WIFI Direct */ - CMD_WFD_START_DISCOVERY = 45, - CMD_WFD_STOP_DISCOVERY = 46, - CMD_WFD_ATTRIBUTE_CONFIG = 47, - CMD_NOP = 48, - CMD_LAST_COMMAND, + CMD_WFD_START_DISCOVERY = 80, + CMD_WFD_STOP_DISCOVERY = 81, + CMD_WFD_ATTRIBUTE_CONFIG = 82, + + CMD_NOP = 100, + NUM_COMMANDS, MAX_COMMAND_ID = 0xFFFF, }; @@ -196,7 +191,7 @@ enum cmd_templ { /* unit ms */ #define WL1271_COMMAND_TIMEOUT 2000 #define WL1271_CMD_TEMPL_DFLT_SIZE 252 -#define WL1271_CMD_TEMPL_MAX_SIZE 512 +#define WL1271_CMD_TEMPL_MAX_SIZE 548 #define WL1271_EVENT_TIMEOUT 750 struct wl1271_cmd_header { @@ -344,9 +339,7 @@ struct wl12xx_cmd_role_start { u8 ssid_len; u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 reset_tsf; - - u8 padding_1[4]; + u8 padding_1[5]; } __packed ap; }; } __packed; @@ -371,18 +364,14 @@ struct cmd_enabledisable_path { struct wl1271_cmd_template_set { struct wl1271_cmd_header header; - u8 role_id; - u8 template_type; __le16 len; + u8 template_type; u8 index; /* relevant only for KLV_TEMPLATE type */ - u8 padding[3]; - __le32 enabled_rates; u8 short_retry_limit; u8 long_retry_limit; u8 aflags; u8 reserved; - u8 template_data[WL1271_CMD_TEMPL_MAX_SIZE]; } __packed; @@ -399,7 +388,6 @@ struct wl1271_tim { } __packed; enum wl1271_cmd_ps_mode { - STATION_AUTO_PS_MODE, /* Dynamic Power Save */ STATION_ACTIVE_MODE, STATION_POWER_SAVE_MODE }; @@ -409,7 +397,7 @@ struct wl1271_cmd_ps_params { u8 role_id; u8 ps_mode; /* STATION_* */ - u16 auto_ps_timeout; + u8 padding[2]; } __packed; /* HW encryption keys */ @@ -707,18 +695,14 @@ struct wl12xx_cmd_stop_fwlog { struct wl12xx_cmd_channel_switch { struct wl1271_cmd_header header; - u8 role_id; - /* The new serving channel */ u8 channel; /* Relative time of the serving channel switch in TBTT units */ u8 switch_time; - /* Stop the role TX, should expect it after radar detection */ - u8 stop_tx; - /* The target channel tx status 1-stopped 0-open*/ - u8 post_switch_tx_disable; - - u8 padding[3]; + /* 1: Suspend TX till switch time; 0: Do not suspend TX */ + u8 tx_suspend; + /* 1: Flush TX at switch time; 0: Do not flush */ + u8 flush; } __packed; struct wl12xx_cmd_stop_channel_switch { diff --git a/trunk/drivers/net/wireless/wl12xx/conf.h b/trunk/drivers/net/wireless/wl12xx/conf.h index cc50faaf03d1..1bcfb017058d 100644 --- a/trunk/drivers/net/wireless/wl12xx/conf.h +++ b/trunk/drivers/net/wireless/wl12xx/conf.h @@ -66,8 +66,7 @@ enum { }; enum { - CONF_HW_RXTX_RATE_MCS7_SGI = 0, - CONF_HW_RXTX_RATE_MCS7, + CONF_HW_RXTX_RATE_MCS7 = 0, CONF_HW_RXTX_RATE_MCS6, CONF_HW_RXTX_RATE_MCS5, CONF_HW_RXTX_RATE_MCS4, @@ -92,10 +91,6 @@ enum { CONF_HW_RXTX_RATE_UNSUPPORTED = 0xff }; -/* Rates between and including these are MCS rates */ -#define CONF_HW_RXTX_RATE_MCS_MIN CONF_HW_RXTX_RATE_MCS7_SGI -#define CONF_HW_RXTX_RATE_MCS_MAX CONF_HW_RXTX_RATE_MCS0 - enum { CONF_SG_DISABLE = 0, CONF_SG_PROTECTIVE, @@ -317,10 +312,6 @@ enum { CONF_AP_BT_ACL_VAL_BT_SERVE_TIME, CONF_AP_BT_ACL_VAL_WL_SERVE_TIME, - /* CTS Diluting params */ - CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH, - CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER, - CONF_SG_TEMP_PARAM_1, CONF_SG_TEMP_PARAM_2, CONF_SG_TEMP_PARAM_3, @@ -818,19 +809,6 @@ struct conf_conn_settings { */ u8 listen_interval; - /* - * Firmware wakeup conditions during suspend - * Range: CONF_WAKE_UP_EVENT_* - */ - u8 suspend_wake_up_event; - - /* - * Listen interval during suspend. - * Currently will be in DTIMs (1-10) - * - */ - u8 suspend_listen_interval; - /* * Enable or disable the beacon filtering. * @@ -889,6 +867,13 @@ struct conf_conn_settings { */ u8 ps_poll_threshold; + /* + * PS Poll failure recovery ACTIVE period length + * + * Range: u32 (ms) + */ + u32 ps_poll_recovery_period; + /* * Configuration of signal average weights. */ @@ -936,18 +921,6 @@ struct conf_conn_settings { */ u8 psm_entry_nullfunc_retries; - /* - * Specifies the dynamic PS timeout in ms that will be used - * by the FW when in AUTO_PS mode - */ - u16 dynamic_ps_timeout; - - /* - * Specifies whether dynamic PS should be disabled and PSM forced. - * This is required for certain WiFi certification tests. - */ - u8 forced_ps; - /* * * Specifies the interval of the connection keep-alive null-func @@ -1082,14 +1055,6 @@ struct conf_scan_settings { */ u16 num_probe_reqs; - /* - * Scan trigger (split scan) timeout. The FW will split the scan - * operation into slices of the given time and allow the FW to schedule - * other tasks in between. - * - * Range: u32 Microsecs - */ - u32 split_scan_timeout; }; struct conf_sched_scan_settings { diff --git a/trunk/drivers/net/wireless/wl12xx/debug.h b/trunk/drivers/net/wireless/wl12xx/debug.h index ec0fdc25b280..b85fd8c41e8f 100644 --- a/trunk/drivers/net/wireless/wl12xx/debug.h +++ b/trunk/drivers/net/wireless/wl12xx/debug.h @@ -51,7 +51,6 @@ enum { DEBUG_FILTERS = BIT(15), DEBUG_ADHOC = BIT(16), DEBUG_AP = BIT(17), - DEBUG_PROBE = BIT(18), DEBUG_MASTER = (DEBUG_ADHOC | DEBUG_AP), DEBUG_ALL = ~0, }; diff --git a/trunk/drivers/net/wireless/wl12xx/debugfs.c b/trunk/drivers/net/wireless/wl12xx/debugfs.c index e1cf72765965..15eb3a9c30ca 100644 --- a/trunk/drivers/net/wireless/wl12xx/debugfs.c +++ b/trunk/drivers/net/wireless/wl12xx/debugfs.c @@ -113,7 +113,7 @@ static void wl1271_debugfs_update_stats(struct wl1271 *wl) if (ret < 0) goto out; - if (wl->state == WL1271_STATE_ON && !wl->plt && + if (wl->state == WL1271_STATE_ON && time_after(jiffies, wl->stats.fw_stats_update + msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) { wl1271_acx_statistics(wl, wl->stats.fw_stats); @@ -312,181 +312,6 @@ static const struct file_operations start_recovery_ops = { .llseek = default_llseek, }; -static ssize_t dynamic_ps_timeout_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - - return wl1271_format_buffer(user_buf, count, - ppos, "%d\n", - wl->conf.conn.dynamic_ps_timeout); -} - -static ssize_t dynamic_ps_timeout_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - struct wl12xx_vif *wlvif; - unsigned long value; - int ret; - - ret = kstrtoul_from_user(user_buf, count, 10, &value); - if (ret < 0) { - wl1271_warning("illegal value in dynamic_ps"); - return -EINVAL; - } - - if (value < 1 || value > 65535) { - wl1271_warning("dyanmic_ps_timeout is not in valid range"); - return -ERANGE; - } - - mutex_lock(&wl->mutex); - - wl->conf.conn.dynamic_ps_timeout = value; - - if (wl->state == WL1271_STATE_OFF) - goto out; - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - /* In case we're already in PSM, trigger it again to set new timeout - * immediately without waiting for re-association - */ - - wl12xx_for_each_wlvif_sta(wl, wlvif) { - if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) - wl1271_ps_set_mode(wl, wlvif, STATION_AUTO_PS_MODE); - } - - wl1271_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); - return count; -} - -static const struct file_operations dynamic_ps_timeout_ops = { - .read = dynamic_ps_timeout_read, - .write = dynamic_ps_timeout_write, - .open = wl1271_open_file_generic, - .llseek = default_llseek, -}; - -static ssize_t forced_ps_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - - return wl1271_format_buffer(user_buf, count, - ppos, "%d\n", - wl->conf.conn.forced_ps); -} - -static ssize_t forced_ps_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - struct wl12xx_vif *wlvif; - unsigned long value; - int ret, ps_mode; - - ret = kstrtoul_from_user(user_buf, count, 10, &value); - if (ret < 0) { - wl1271_warning("illegal value in forced_ps"); - return -EINVAL; - } - - if (value != 1 && value != 0) { - wl1271_warning("forced_ps should be either 0 or 1"); - return -ERANGE; - } - - mutex_lock(&wl->mutex); - - if (wl->conf.conn.forced_ps == value) - goto out; - - wl->conf.conn.forced_ps = value; - - if (wl->state == WL1271_STATE_OFF) - goto out; - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - /* In case we're already in PSM, trigger it again to switch mode - * immediately without waiting for re-association - */ - - ps_mode = value ? STATION_POWER_SAVE_MODE : STATION_AUTO_PS_MODE; - - wl12xx_for_each_wlvif_sta(wl, wlvif) { - if (test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) - wl1271_ps_set_mode(wl, wlvif, ps_mode); - } - - wl1271_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); - return count; -} - -static const struct file_operations forced_ps_ops = { - .read = forced_ps_read, - .write = forced_ps_write, - .open = wl1271_open_file_generic, - .llseek = default_llseek, -}; - -static ssize_t split_scan_timeout_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - - return wl1271_format_buffer(user_buf, count, - ppos, "%d\n", - wl->conf.scan.split_scan_timeout / 1000); -} - -static ssize_t split_scan_timeout_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - unsigned long value; - int ret; - - ret = kstrtoul_from_user(user_buf, count, 10, &value); - if (ret < 0) { - wl1271_warning("illegal value in split_scan_timeout"); - return -EINVAL; - } - - if (value == 0) - wl1271_info("split scan will be disabled"); - - mutex_lock(&wl->mutex); - - wl->conf.scan.split_scan_timeout = value * 1000; - - mutex_unlock(&wl->mutex); - return count; -} - -static const struct file_operations split_scan_timeout_ops = { - .read = split_scan_timeout_read, - .write = split_scan_timeout_write, - .open = wl1271_open_file_generic, - .llseek = default_llseek, -}; - static ssize_t driver_state_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -621,7 +446,6 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, VIF_STATE_PRINT_INT(sta.basic_rate_idx); VIF_STATE_PRINT_INT(sta.ap_rate_idx); VIF_STATE_PRINT_INT(sta.p2p_rate_idx); - VIF_STATE_PRINT_INT(sta.qos); } else { VIF_STATE_PRINT_INT(ap.global_hlid); VIF_STATE_PRINT_INT(ap.bcast_hlid); @@ -647,6 +471,7 @@ static ssize_t vifs_state_read(struct file *file, char __user *user_buf, VIF_STATE_PRINT_INT(default_key); VIF_STATE_PRINT_INT(aid); VIF_STATE_PRINT_INT(session_counter); + VIF_STATE_PRINT_INT(ps_poll_failures); VIF_STATE_PRINT_INT(psm_entry_retry); VIF_STATE_PRINT_INT(power_level); VIF_STATE_PRINT_INT(rssi_thold); @@ -737,64 +562,6 @@ static const struct file_operations dtim_interval_ops = { .llseek = default_llseek, }; - - -static ssize_t suspend_dtim_interval_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - u8 value; - - if (wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_DTIM || - wl->conf.conn.suspend_wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM) - value = wl->conf.conn.suspend_listen_interval; - else - value = 0; - - return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); -} - -static ssize_t suspend_dtim_interval_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - unsigned long value; - int ret; - - ret = kstrtoul_from_user(user_buf, count, 10, &value); - if (ret < 0) { - wl1271_warning("illegal value for suspend_dtim_interval"); - return -EINVAL; - } - - if (value < 1 || value > 10) { - wl1271_warning("suspend_dtim value is not in valid range"); - return -ERANGE; - } - - mutex_lock(&wl->mutex); - - wl->conf.conn.suspend_listen_interval = value; - /* for some reason there are different event types for 1 and >1 */ - if (value == 1) - wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_DTIM; - else - wl->conf.conn.suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM; - - mutex_unlock(&wl->mutex); - return count; -} - - -static const struct file_operations suspend_dtim_interval_ops = { - .read = suspend_dtim_interval_read, - .write = suspend_dtim_interval_write, - .open = wl1271_open_file_generic, - .llseek = default_llseek, -}; - static ssize_t beacon_interval_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -1119,12 +886,8 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, DEBUGFS_ADD(driver_state, rootdir); DEBUGFS_ADD(vifs_state, rootdir); DEBUGFS_ADD(dtim_interval, rootdir); - DEBUGFS_ADD(suspend_dtim_interval, rootdir); DEBUGFS_ADD(beacon_interval, rootdir); DEBUGFS_ADD(beacon_filtering, rootdir); - DEBUGFS_ADD(dynamic_ps_timeout, rootdir); - DEBUGFS_ADD(forced_ps, rootdir); - DEBUGFS_ADD(split_scan_timeout, rootdir); streaming = debugfs_create_dir("rx_streaming", rootdir); if (!streaming || IS_ERR(streaming)) diff --git a/trunk/drivers/net/wireless/wl12xx/event.c b/trunk/drivers/net/wireless/wl12xx/event.c index c953717f38eb..d3280df68f5d 100644 --- a/trunk/drivers/net/wireless/wl12xx/event.c +++ b/trunk/drivers/net/wireless/wl12xx/event.c @@ -30,6 +30,133 @@ #include "scan.h" #include "wl12xx_80211.h" +void wl1271_pspoll_work(struct work_struct *work) +{ + struct ieee80211_vif *vif; + struct wl12xx_vif *wlvif; + struct delayed_work *dwork; + struct wl1271 *wl; + int ret; + + dwork = container_of(work, struct delayed_work, work); + wlvif = container_of(dwork, struct wl12xx_vif, pspoll_work); + vif = container_of((void *)wlvif, struct ieee80211_vif, drv_priv); + wl = wlvif->wl; + + wl1271_debug(DEBUG_EVENT, "pspoll work"); + + mutex_lock(&wl->mutex); + + if (unlikely(wl->state == WL1271_STATE_OFF)) + goto out; + + if (!test_and_clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags)) + goto out; + + if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + goto out; + + /* + * if we end up here, then we were in powersave when the pspoll + * delivery failure occurred, and no-one changed state since, so + * we should go back to powersave. + */ + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out; + + wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE, + wlvif->basic_rate, true); + + wl1271_ps_elp_sleep(wl); +out: + mutex_unlock(&wl->mutex); +}; + +static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl, + struct wl12xx_vif *wlvif) +{ + int delay = wl->conf.conn.ps_poll_recovery_period; + int ret; + + wlvif->ps_poll_failures++; + if (wlvif->ps_poll_failures == 1) + wl1271_info("AP with dysfunctional ps-poll, " + "trying to work around it."); + + /* force active mode receive data from the AP */ + if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { + ret = wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE, + wlvif->basic_rate, true); + if (ret < 0) + return; + set_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags); + ieee80211_queue_delayed_work(wl->hw, &wlvif->pspoll_work, + msecs_to_jiffies(delay)); + } + + /* + * If already in active mode, lets we should be getting data from + * the AP right away. If we enter PSM too fast after this, and data + * remains on the AP, we will get another event like this, and we'll + * go into active once more. + */ +} + +static int wl1271_event_ps_report(struct wl1271 *wl, + struct wl12xx_vif *wlvif, + struct event_mailbox *mbox, + bool *beacon_loss) +{ + int ret = 0; + u32 total_retries = wl->conf.conn.psm_entry_retries; + + wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status); + + switch (mbox->ps_status) { + case EVENT_ENTER_POWER_SAVE_FAIL: + wl1271_debug(DEBUG_PSM, "PSM entry failed"); + + if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { + /* remain in active mode */ + wlvif->psm_entry_retry = 0; + break; + } + + if (wlvif->psm_entry_retry < total_retries) { + wlvif->psm_entry_retry++; + ret = wl1271_ps_set_mode(wl, wlvif, + STATION_POWER_SAVE_MODE, + wlvif->basic_rate, true); + } else { + wl1271_info("No ack to nullfunc from AP."); + wlvif->psm_entry_retry = 0; + *beacon_loss = true; + } + break; + case EVENT_ENTER_POWER_SAVE_SUCCESS: + wlvif->psm_entry_retry = 0; + + /* + * BET has only a minor effect in 5GHz and masks + * channel switch IEs, so we only enable BET on 2.4GHz + */ + if (wlvif->band == IEEE80211_BAND_2GHZ) + /* enable beacon early termination */ + ret = wl1271_acx_bet_enable(wl, wlvif, true); + + if (wlvif->ps_compl) { + complete(wlvif->ps_compl); + wlvif->ps_compl = NULL; + } + break; + default: + break; + } + + return ret; +} + static void wl1271_event_rssi_trigger(struct wl1271 *wl, struct wl12xx_vif *wlvif, struct event_mailbox *mbox) @@ -78,13 +205,21 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif) static void wl12xx_event_soft_gemini_sense(struct wl1271 *wl, u8 enable) { + struct ieee80211_vif *vif; struct wl12xx_vif *wlvif; if (enable) { + /* disable dynamic PS when requested by the firmware */ + wl12xx_for_each_wlvif_sta(wl, wlvif) { + vif = wl12xx_wlvif_to_vif(wlvif); + ieee80211_disable_dyn_ps(vif); + } set_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); } else { clear_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags); wl12xx_for_each_wlvif_sta(wl, wlvif) { + vif = wl12xx_wlvif_to_vif(wlvif); + ieee80211_enable_dyn_ps(vif); wl1271_recalc_rx_streaming(wl, wlvif); } } @@ -102,6 +237,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) { struct ieee80211_vif *vif; struct wl12xx_vif *wlvif; + int ret; u32 vector; bool beacon_loss = false; bool disconnect_sta = false; @@ -157,6 +293,21 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) beacon_loss = true; } + if (vector & PS_REPORT_EVENT_ID) { + wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT"); + wl12xx_for_each_wlvif_sta(wl, wlvif) { + ret = wl1271_event_ps_report(wl, wlvif, + mbox, &beacon_loss); + if (ret < 0) + return ret; + } + } + + if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) + wl12xx_for_each_wlvif_sta(wl, wlvif) { + wl1271_event_pspoll_delivery_fail(wl, wlvif); + } + if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { /* TODO: check actual multi-role support */ wl1271_debug(DEBUG_EVENT, "RSSI_SNR_TRIGGER_0_EVENT"); @@ -193,6 +344,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) /* TODO: configure only the relevant vif */ wl12xx_for_each_wlvif_sta(wl, wlvif) { + struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); bool success; if (!test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, @@ -200,8 +352,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) continue; success = mbox->channel_switch_status ? false : true; - vif = wl12xx_wlvif_to_vif(wlvif); - ieee80211_chswitch_done(vif, success); } } diff --git a/trunk/drivers/net/wireless/wl12xx/event.h b/trunk/drivers/net/wireless/wl12xx/event.h index 057d193d3525..1d878ba47bf4 100644 --- a/trunk/drivers/net/wireless/wl12xx/event.h +++ b/trunk/drivers/net/wireless/wl12xx/event.h @@ -51,10 +51,10 @@ enum { SCAN_COMPLETE_EVENT_ID = BIT(10), WFD_DISCOVERY_COMPLETE_EVENT_ID = BIT(11), AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12), - RESERVED1 = BIT(13), + PS_REPORT_EVENT_ID = BIT(13), PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14), - ROLE_STOP_COMPLETE_EVENT_ID = BIT(15), - RADAR_DETECTED_EVENT_ID = BIT(16), + DISCONNECT_EVENT_COMPLETE_ID = BIT(15), + /* BIT(16) is reserved */ CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), BSS_LOSE_EVENT_ID = BIT(18), REGAINED_BSS_EVENT_ID = BIT(19), @@ -94,9 +94,9 @@ struct event_mailbox { u8 soft_gemini_sense_info; u8 soft_gemini_protective_info; s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS]; - u8 change_auto_mode_timeout; + u8 channel_switch_status; u8 scheduled_scan_status; - u8 reserved4; + u8 ps_status; /* tuned channel (roc) */ u8 roc_channel; @@ -119,21 +119,17 @@ struct event_mailbox { u8 rx_ba_allowed; u8 reserved_6[2]; - /* Channel switch results */ - - u8 channel_switch_role_id; - u8 channel_switch_status; - u8 reserved_7[2]; - u8 ps_poll_delivery_failure_role_ids; u8 stopped_role_ids; u8 started_role_ids; + u8 change_auto_mode_timeout; - u8 reserved_8[9]; + u8 reserved_7[12]; } __packed; int wl1271_event_unmask(struct wl1271 *wl); void wl1271_event_mbox_config(struct wl1271 *wl); int wl1271_event_handle(struct wl1271 *wl, u8 mbox); +void wl1271_pspoll_work(struct work_struct *work); #endif diff --git a/trunk/drivers/net/wireless/wl12xx/init.c b/trunk/drivers/net/wireless/wl12xx/init.c index 203fbebf09eb..ca7ee59e4505 100644 --- a/trunk/drivers/net/wireless/wl12xx/init.c +++ b/trunk/drivers/net/wireless/wl12xx/init.c @@ -37,64 +37,54 @@ int wl1271_init_templates_config(struct wl1271 *wl) { int ret, i; - size_t max_size; /* send empty templates for fw memory reservation */ - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, - WL1271_CMD_TEMPL_MAX_SIZE, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, + WL1271_CMD_TEMPL_DFLT_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_CFG_PROBE_REQ_5, - NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, + NULL, WL1271_CMD_TEMPL_DFLT_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_NULL_DATA, NULL, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, sizeof(struct wl12xx_null_data_template), 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_PS_POLL, NULL, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, sizeof(struct wl12xx_ps_poll_template), 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_QOS_NULL_DATA, NULL, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, sizeof (struct ieee80211_qos_hdr), 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_PROBE_RESPONSE, NULL, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, WL1271_CMD_TEMPL_DFLT_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_BEACON, NULL, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, WL1271_CMD_TEMPL_DFLT_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; - max_size = sizeof(struct wl12xx_arp_rsp_template) + - WL1271_EXTRA_SPACE_MAX; - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_ARP_RSP, NULL, - max_size, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, NULL, + sizeof + (struct wl12xx_arp_rsp_template), 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; @@ -103,22 +93,19 @@ int wl1271_init_templates_config(struct wl1271 *wl) * Put very large empty placeholders for all templates. These * reserve memory for later. */ - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_AP_PROBE_RESPONSE, NULL, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_AP_BEACON, NULL, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0, WL1271_RATE_AUTOMATIC); if (ret < 0) return ret; - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_DEAUTH_AP, NULL, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL, sizeof (struct wl12xx_disconn_template), 0, WL1271_RATE_AUTOMATIC); @@ -126,8 +113,7 @@ int wl1271_init_templates_config(struct wl1271 *wl) return ret; for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { - ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, - CMD_TEMPL_KLV, NULL, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL, sizeof(struct ieee80211_qos_hdr), i, WL1271_RATE_AUTOMATIC); if (ret < 0) @@ -154,8 +140,7 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl, IEEE80211_STYPE_DEAUTH); rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); - ret = wl1271_cmd_template_set(wl, wlvif->role_id, - CMD_TEMPL_DEAUTH_AP, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, tmpl, sizeof(*tmpl), 0, rate); out: @@ -187,8 +172,7 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl, memcpy(nullfunc->addr3, vif->addr, ETH_ALEN); rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); - ret = wl1271_cmd_template_set(wl, wlvif->role_id, - CMD_TEMPL_NULL_DATA, nullfunc, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc, sizeof(*nullfunc), 0, rate); out: @@ -220,8 +204,7 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl, memcpy(qosnull->addr3, vif->addr, ETH_ALEN); rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); - ret = wl1271_cmd_template_set(wl, wlvif->role_id, - CMD_TEMPL_QOS_NULL_DATA, qosnull, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull, sizeof(*qosnull), 0, rate); out: diff --git a/trunk/drivers/net/wireless/wl12xx/io.c b/trunk/drivers/net/wireless/wl12xx/io.c index c574a3b31e31..079ad380e8ff 100644 --- a/trunk/drivers/net/wireless/wl12xx/io.c +++ b/trunk/drivers/net/wireless/wl12xx/io.c @@ -45,65 +45,6 @@ #define OCP_STATUS_REQ_FAILED 0x20000 #define OCP_STATUS_RESP_ERROR 0x30000 -struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN] = { - [PART_DOWN] = { - .mem = { - .start = 0x00000000, - .size = 0x000177c0 - }, - .reg = { - .start = REGISTERS_BASE, - .size = 0x00008800 - }, - .mem2 = { - .start = 0x00000000, - .size = 0x00000000 - }, - .mem3 = { - .start = 0x00000000, - .size = 0x00000000 - }, - }, - - [PART_WORK] = { - .mem = { - .start = 0x00040000, - .size = 0x00014fc0 - }, - .reg = { - .start = REGISTERS_BASE, - .size = 0x0000a000 - }, - .mem2 = { - .start = 0x003004f8, - .size = 0x00000004 - }, - .mem3 = { - .start = 0x00040404, - .size = 0x00000000 - }, - }, - - [PART_DRPW] = { - .mem = { - .start = 0x00040000, - .size = 0x00014fc0 - }, - .reg = { - .start = DRPW_BASE, - .size = 0x00006000 - }, - .mem2 = { - .start = 0x00000000, - .size = 0x00000000 - }, - .mem3 = { - .start = 0x00000000, - .size = 0x00000000 - } - } -}; - bool wl1271_set_block_size(struct wl1271 *wl) { if (wl->if_ops->set_block_size) { diff --git a/trunk/drivers/net/wireless/wl12xx/io.h b/trunk/drivers/net/wireless/wl12xx/io.h index 4fb3dab8c3b2..d398cbcea986 100644 --- a/trunk/drivers/net/wireless/wl12xx/io.h +++ b/trunk/drivers/net/wireless/wl12xx/io.h @@ -43,8 +43,6 @@ #define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 -extern struct wl1271_partition_set wl12xx_part_table[PART_TABLE_LEN]; - struct wl1271; void wl1271_disable_interrupts(struct wl1271 *wl); diff --git a/trunk/drivers/net/wireless/wl12xx/main.c b/trunk/drivers/net/wireless/wl12xx/main.c index adf9bbcf88fd..f8748cedbae1 100644 --- a/trunk/drivers/net/wireless/wl12xx/main.c +++ b/trunk/drivers/net/wireless/wl12xx/main.c @@ -1,4 +1,3 @@ - /* * This file is part of wl1271 * @@ -116,9 +115,6 @@ static struct conf_drv_settings default_conf = { [CONF_AP_CONNECTION_PROTECTION_TIME] = 0, [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25, [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25, - /* CTS Diluting params */ - [CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0, - [CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0, }, .state = CONF_SG_PROTECTIVE, }, @@ -221,8 +217,6 @@ static struct conf_drv_settings default_conf = { .conn = { .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, .listen_interval = 1, - .suspend_wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM, - .suspend_listen_interval = 3, .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, .bcn_filt_ie_count = 2, .bcn_filt_ie = { @@ -241,13 +235,12 @@ static struct conf_drv_settings default_conf = { .broadcast_timeout = 20000, .rx_broadcast_in_ps = 1, .ps_poll_threshold = 10, + .ps_poll_recovery_period = 700, .bet_enable = CONF_BET_MODE_ENABLE, .bet_max_consecutive = 50, .psm_entry_retries = 8, .psm_exit_retries = 16, .psm_entry_nullfunc_retries = 3, - .dynamic_ps_timeout = 100, - .forced_ps = false, .keep_alive_interval = 55000, .max_listen_interval = 20, }, @@ -272,7 +265,6 @@ static struct conf_drv_settings default_conf = { .min_dwell_time_passive = 100000, .max_dwell_time_passive = 100000, .num_probe_reqs = 2, - .split_scan_timeout = 50000, }, .sched_scan = { /* sched_scan requires dwell times in TU instead of TU/1000 */ @@ -680,6 +672,8 @@ static int wl1271_plt_init(struct wl1271 *wl) if (ret < 0) return ret; } + if (ret < 0) + return ret; /* Chip-specific initializations */ ret = wl1271_chip_specific_init(wl); @@ -991,70 +985,16 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) return IRQ_HANDLED; } -struct vif_counter_data { - u8 counter; - - struct ieee80211_vif *cur_vif; - bool cur_vif_running; -}; - -static void wl12xx_vif_count_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) -{ - struct vif_counter_data *counter = data; - - counter->counter++; - if (counter->cur_vif == vif) - counter->cur_vif_running = true; -} - -/* caller must not hold wl->mutex, as it might deadlock */ -static void wl12xx_get_vif_count(struct ieee80211_hw *hw, - struct ieee80211_vif *cur_vif, - struct vif_counter_data *data) -{ - memset(data, 0, sizeof(*data)); - data->cur_vif = cur_vif; - - ieee80211_iterate_active_interfaces(hw, - wl12xx_vif_count_iter, data); -} - -static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt) +static int wl1271_fetch_firmware(struct wl1271 *wl) { const struct firmware *fw; const char *fw_name; - enum wl12xx_fw_type fw_type; int ret; - if (plt) { - fw_type = WL12XX_FW_TYPE_PLT; - if (wl->chip.id == CHIP_ID_1283_PG20) - fw_name = WL128X_PLT_FW_NAME; - else - fw_name = WL127X_PLT_FW_NAME; - } else { - /* - * we can't call wl12xx_get_vif_count() here because - * wl->mutex is taken, so use the cached last_vif_count value - */ - if (wl->last_vif_count > 1) { - fw_type = WL12XX_FW_TYPE_MULTI; - if (wl->chip.id == CHIP_ID_1283_PG20) - fw_name = WL128X_FW_NAME_MULTI; - else - fw_name = WL127X_FW_NAME_MULTI; - } else { - fw_type = WL12XX_FW_TYPE_NORMAL; - if (wl->chip.id == CHIP_ID_1283_PG20) - fw_name = WL128X_FW_NAME_SINGLE; - else - fw_name = WL127X_FW_NAME_SINGLE; - } - } - - if (wl->fw_type == fw_type) - return 0; + if (wl->chip.id == CHIP_ID_1283_PG20) + fw_name = WL128X_FW_NAME; + else + fw_name = WL127X_FW_NAME; wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name); @@ -1073,7 +1013,6 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt) } vfree(wl->fw); - wl->fw_type = WL12XX_FW_TYPE_NONE; wl->fw_len = fw->size; wl->fw = vmalloc(wl->fw_len); @@ -1085,7 +1024,7 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt) memcpy(wl->fw, fw->data, wl->fw_len); ret = 0; - wl->fw_type = fw_type; + out: release_firmware(fw); @@ -1213,7 +1152,7 @@ static void wl1271_recovery_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (wl->state != WL1271_STATE_ON || wl->plt) + if (wl->state != WL1271_STATE_ON) goto out_unlock; /* Avoid a recursive recovery */ @@ -1293,9 +1232,10 @@ static int wl1271_setup(struct wl1271 *wl) return 0; } -static int wl12xx_set_power_on(struct wl1271 *wl) +static int wl1271_chip_wakeup(struct wl1271 *wl) { - int ret; + struct wl1271_partition_set partition; + int ret = 0; msleep(WL1271_PRE_POWER_ON_SLEEP); ret = wl1271_power_on(wl); @@ -1305,22 +1245,20 @@ static int wl12xx_set_power_on(struct wl1271 *wl) wl1271_io_reset(wl); wl1271_io_init(wl); - wl1271_set_partition(wl, &wl12xx_part_table[PART_DOWN]); + /* We don't need a real memory partition here, because we only want + * to use the registers at this point. */ + memset(&partition, 0, sizeof(partition)); + partition.reg.start = REGISTERS_BASE; + partition.reg.size = REGISTERS_DOWN_SIZE; + wl1271_set_partition(wl, &partition); /* ELP module wake up */ wl1271_fw_wakeup(wl); -out: - return ret; -} + /* whal_FwCtrl_BootSm() */ -static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) -{ - int ret = 0; - - ret = wl12xx_set_power_on(wl); - if (ret < 0) - goto out; + /* 0. read chip id from CHIP_ID */ + wl->chip.id = wl1271_read32(wl, CHIP_ID_B); /* * For wl127x based devices we could use the default block @@ -1369,9 +1307,11 @@ static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) goto out; } - ret = wl12xx_fetch_firmware(wl, plt); - if (ret < 0) - goto out; + if (wl->fw == NULL) { + ret = wl1271_fetch_firmware(wl); + if (ret < 0) + goto out; + } /* No NVS from netlink, try to get it from the filesystem */ if (wl->nvs == NULL) { @@ -1403,7 +1343,7 @@ int wl1271_plt_start(struct wl1271 *wl) while (retries) { retries--; - ret = wl12xx_chip_wakeup(wl, true); + ret = wl1271_chip_wakeup(wl); if (ret < 0) goto power_off; @@ -1415,8 +1355,7 @@ int wl1271_plt_start(struct wl1271 *wl) if (ret < 0) goto irq_disable; - wl->plt = true; - wl->state = WL1271_STATE_ON; + wl->state = WL1271_STATE_PLT; wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver_str); @@ -1452,51 +1391,41 @@ int wl1271_plt_start(struct wl1271 *wl) return ret; } -int wl1271_plt_stop(struct wl1271 *wl) +static int __wl1271_plt_stop(struct wl1271 *wl) { int ret = 0; wl1271_notice("power down"); - /* - * Interrupts must be disabled before setting the state to OFF. - * Otherwise, the interrupt handler might be called and exit without - * reading the interrupt status. - */ - wl1271_disable_interrupts(wl); - mutex_lock(&wl->mutex); - if (!wl->plt) { - mutex_unlock(&wl->mutex); - - /* - * This will not necessarily enable interrupts as interrupts - * may have been disabled when op_stop was called. It will, - * however, balance the above call to disable_interrupts(). - */ - wl1271_enable_interrupts(wl); - + if (wl->state != WL1271_STATE_PLT) { wl1271_error("cannot power down because not in PLT " "state: %d", wl->state); ret = -EBUSY; goto out; } - mutex_unlock(&wl->mutex); + wl1271_power_off(wl); + + wl->state = WL1271_STATE_OFF; + wl->rx_counter = 0; + mutex_unlock(&wl->mutex); + wl1271_disable_interrupts(wl); wl1271_flush_deferred_work(wl); cancel_work_sync(&wl->netstack_work); cancel_work_sync(&wl->recovery_work); - cancel_delayed_work_sync(&wl->elp_work); + mutex_lock(&wl->mutex); +out: + return ret; +} + +int wl1271_plt_stop(struct wl1271 *wl) +{ + int ret; mutex_lock(&wl->mutex); - wl1271_power_off(wl); - wl->flags = 0; - wl->state = WL1271_STATE_OFF; - wl->plt = false; - wl->rx_counter = 0; + ret = __wl1271_plt_stop(wl); mutex_unlock(&wl->mutex); - -out: return ret; } @@ -1645,16 +1574,38 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, if (ret < 0) goto out_unlock; - ret = wl1271_acx_wake_up_conditions(wl, wlvif, - wl->conf.conn.suspend_wake_up_event, - wl->conf.conn.suspend_listen_interval); + /* enter psm if needed*/ + if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { + DECLARE_COMPLETION_ONSTACK(compl); - if (ret < 0) - wl1271_error("suspend: set wake up conditions failed: %d", ret); + wlvif->ps_compl = &compl; + ret = wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE, + wlvif->basic_rate, true); + if (ret < 0) + goto out_sleep; + + /* we must unlock here so we will be able to get events */ + wl1271_ps_elp_sleep(wl); + mutex_unlock(&wl->mutex); + ret = wait_for_completion_timeout( + &compl, msecs_to_jiffies(WL1271_PS_COMPLETE_TIMEOUT)); - wl1271_ps_elp_sleep(wl); + mutex_lock(&wl->mutex); + if (ret <= 0) { + wl1271_warning("couldn't enter ps mode!"); + ret = -EBUSY; + goto out_cleanup; + } + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out_cleanup; + } +out_sleep: + wl1271_ps_elp_sleep(wl); +out_cleanup: + wlvif->ps_compl = NULL; out_unlock: mutex_unlock(&wl->mutex); return ret; @@ -1697,11 +1648,11 @@ static int wl1271_configure_suspend(struct wl1271 *wl, static void wl1271_configure_resume(struct wl1271 *wl, struct wl12xx_vif *wlvif) { - int ret = 0; - bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; + int ret; bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS; + bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; - if ((!is_ap) && (!is_sta)) + if (!is_sta && !is_ap) return; mutex_lock(&wl->mutex); @@ -1710,16 +1661,12 @@ static void wl1271_configure_resume(struct wl1271 *wl, goto out; if (is_sta) { - ret = wl1271_acx_wake_up_conditions(wl, wlvif, - wl->conf.conn.wake_up_event, - wl->conf.conn.listen_interval); - - if (ret < 0) - wl1271_error("resume: wake up conditions failed: %d", - ret); - + /* exit psm if it wasn't configured */ + if (!test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) + wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE, + wlvif->basic_rate, true); } else if (is_ap) { - ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); + wl1271_acx_beacon_filter_opt(wl, wlvif, false); } wl1271_ps_elp_sleep(wl); @@ -1762,6 +1709,9 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, wl1271_enable_interrupts(wl); flush_work(&wl->tx_work); + wl12xx_for_each_wlvif(wl, wlvif) { + flush_delayed_work(&wlvif->pspoll_work); + } flush_delayed_work(&wl->elp_work); return 0; @@ -1828,25 +1778,11 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); - /* - * Interrupts must be disabled before setting the state to OFF. - * Otherwise, the interrupt handler might be called and exit without - * reading the interrupt status. - */ - wl1271_disable_interrupts(wl); mutex_lock(&wl->mutex); if (wl->state == WL1271_STATE_OFF) { mutex_unlock(&wl->mutex); - - /* - * This will not necessarily enable interrupts as interrupts - * may have been disabled when op_stop was called. It will, - * however, balance the above call to disable_interrupts(). - */ - wl1271_enable_interrupts(wl); return; } - /* * this must be before the cancel_work calls below, so that the work * functions don't perform further work. @@ -1858,6 +1794,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) list_del(&wl->list); mutex_unlock(&wl_list_mutex); + wl1271_disable_interrupts(wl); wl1271_flush_deferred_work(wl); cancel_delayed_work_sync(&wl->scan_complete_work); cancel_work_sync(&wl->netstack_work); @@ -2032,6 +1969,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) wl1271_rx_streaming_enable_work); INIT_WORK(&wlvif->rx_streaming_disable_work, wl1271_rx_streaming_disable_work); + INIT_DELAYED_WORK(&wlvif->pspoll_work, wl1271_pspoll_work); INIT_LIST_HEAD(&wlvif->list); setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer, @@ -2048,7 +1986,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl) while (retries) { retries--; - ret = wl12xx_chip_wakeup(wl, false); + ret = wl1271_chip_wakeup(wl); if (ret < 0) goto power_off; @@ -2113,60 +2051,11 @@ static bool wl12xx_dev_role_started(struct wl12xx_vif *wlvif) return wlvif->dev_hlid != WL12XX_INVALID_LINK_ID; } -/* - * Check whether a fw switch (i.e. moving from one loaded - * fw to another) is needed. This function is also responsible - * for updating wl->last_vif_count, so it must be called before - * loading a non-plt fw (so the correct fw (single-role/multi-role) - * will be used). - */ -static bool wl12xx_need_fw_change(struct wl1271 *wl, - struct vif_counter_data vif_counter_data, - bool add) -{ - enum wl12xx_fw_type current_fw = wl->fw_type; - u8 vif_count = vif_counter_data.counter; - - if (test_bit(WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, &wl->flags)) - return false; - - /* increase the vif count if this is a new vif */ - if (add && !vif_counter_data.cur_vif_running) - vif_count++; - - wl->last_vif_count = vif_count; - - /* no need for fw change if the device is OFF */ - if (wl->state == WL1271_STATE_OFF) - return false; - - if (vif_count > 1 && current_fw == WL12XX_FW_TYPE_NORMAL) - return true; - if (vif_count <= 1 && current_fw == WL12XX_FW_TYPE_MULTI) - return true; - - return false; -} - -/* - * Enter "forced psm". Make sure the sta is in psm against the ap, - * to make the fw switch a bit more disconnection-persistent. - */ -static void wl12xx_force_active_psm(struct wl1271 *wl) -{ - struct wl12xx_vif *wlvif; - - wl12xx_for_each_wlvif_sta(wl, wlvif) { - wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE); - } -} - static int wl1271_op_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct wl1271 *wl = hw->priv; struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - struct vif_counter_data vif_count; int ret = 0; u8 role_type; bool booted = false; @@ -2177,13 +2066,18 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", ieee80211_vif_type_p2p(vif), vif->addr); - wl12xx_get_vif_count(hw, vif, &vif_count); - mutex_lock(&wl->mutex); ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out_unlock; + if (wl->vif) { + wl1271_debug(DEBUG_MAC80211, + "multiple vifs are not supported yet"); + ret = -EBUSY; + goto out; + } + /* * in some very corner case HW recovery scenarios its possible to * get here before __wl1271_op_remove_interface is complete, so @@ -2195,7 +2089,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, goto out; } - ret = wl12xx_init_vif_data(wl, vif); if (ret < 0) goto out; @@ -2207,13 +2100,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, goto out; } - if (wl12xx_need_fw_change(wl, vif_count, true)) { - wl12xx_force_active_psm(wl); - mutex_unlock(&wl->mutex); - wl1271_recovery_work(&wl->recovery_work); - return 0; - } - /* * TODO: after the nvs issue will be solved, move this block * to start(), and make sure here the driver is ON. @@ -2223,7 +2109,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, * we still need this in order to configure the fw * while uploading the nvs */ - memcpy(wl->addresses[0].addr, vif->addr, ETH_ALEN); + memcpy(wl->mac_addr, vif->addr, ETH_ALEN); booted = wl12xx_init_fw(wl); if (!booted) { @@ -2256,6 +2142,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, if (ret < 0) goto out; + wl->vif = vif; list_add(&wlvif->list, &wl->wlvif_list); set_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags); @@ -2288,12 +2175,18 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, if (!test_and_clear_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) return; + wl->vif = NULL; + /* because of hardware recovery, we may get here twice */ if (wl->state != WL1271_STATE_ON) return; wl1271_info("down"); + /* enable dyn ps just in case (if left on due to fw crash etc) */ + if (wlvif->bss_type == BSS_TYPE_STA_BSS) + ieee80211_enable_dyn_ps(vif); + if (wl->scan.state != WL1271_SCAN_STATE_IDLE && wl->scan_vif == vif) { wl->scan.state = WL1271_SCAN_STATE_IDLE; @@ -2360,10 +2253,10 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wl->sta_count--; mutex_unlock(&wl->mutex); - del_timer_sync(&wlvif->rx_streaming_timer); cancel_work_sync(&wlvif->rx_streaming_enable_work); cancel_work_sync(&wlvif->rx_streaming_disable_work); + cancel_delayed_work_sync(&wlvif->pspoll_work); mutex_lock(&wl->mutex); } @@ -2374,10 +2267,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, struct wl1271 *wl = hw->priv; struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl12xx_vif *iter; - struct vif_counter_data vif_count; - bool cancel_recovery = true; - wl12xx_get_vif_count(hw, vif, &vif_count); mutex_lock(&wl->mutex); if (wl->state == WL1271_STATE_OFF || @@ -2396,33 +2286,20 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, break; } WARN_ON(iter != wlvif); - if (wl12xx_need_fw_change(wl, vif_count, false)) { - wl12xx_force_active_psm(wl); - wl12xx_queue_recovery_work(wl); - cancel_recovery = false; - } out: mutex_unlock(&wl->mutex); - if (cancel_recovery) - cancel_work_sync(&wl->recovery_work); + cancel_work_sync(&wl->recovery_work); } static int wl12xx_op_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, enum nl80211_iftype new_type, bool p2p) { - struct wl1271 *wl = hw->priv; - int ret; - - set_bit(WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, &wl->flags); wl1271_op_remove_interface(hw, vif); vif->type = ieee80211_iftype_p2p(new_type, p2p); vif->p2p = p2p; - ret = wl1271_op_add_interface(hw, vif); - - clear_bit(WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, &wl->flags); - return ret; + return wl1271_op_add_interface(hw, vif); } static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, @@ -2443,9 +2320,6 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) wl1271_info("JOIN while associated."); - /* clear encryption type */ - wlvif->encryption_type = KEY_NONE; - if (set_assoc) set_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags); @@ -2629,41 +2503,38 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, } } - if ((changed & IEEE80211_CONF_CHANGE_PS) && !is_ap) { - - if ((conf->flags & IEEE80211_CONF_PS) && - test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) && - !test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) { - - int ps_mode; - char *ps_mode_str; - - if (wl->conf.conn.forced_ps) { - ps_mode = STATION_POWER_SAVE_MODE; - ps_mode_str = "forced"; - } else { - ps_mode = STATION_AUTO_PS_MODE; - ps_mode_str = "auto"; - } - - wl1271_debug(DEBUG_PSM, "%s ps enabled", ps_mode_str); - - ret = wl1271_ps_set_mode(wl, wlvif, ps_mode); + /* + * if mac80211 changes the PSM mode, make sure the mode is not + * incorrectly changed after the pspoll failure active window. + */ + if (changed & IEEE80211_CONF_CHANGE_PS) + clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags); - if (ret < 0) - wl1271_warning("enter %s ps failed %d", - ps_mode_str, ret); + if (conf->flags & IEEE80211_CONF_PS && + !test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) { + set_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags); - } else if (!(conf->flags & IEEE80211_CONF_PS) && - test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) { + /* + * We enter PSM only if we're already associated. + * If we're not, we'll enter it when joining an SSID, + * through the bss_info_changed() hook. + */ + if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { + wl1271_debug(DEBUG_PSM, "psm enabled"); + ret = wl1271_ps_set_mode(wl, wlvif, + STATION_POWER_SAVE_MODE, + wlvif->basic_rate, true); + } + } else if (!(conf->flags & IEEE80211_CONF_PS) && + test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) { + wl1271_debug(DEBUG_PSM, "psm disabled"); - wl1271_debug(DEBUG_PSM, "auto ps disabled"); + clear_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags); + if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) ret = wl1271_ps_set_mode(wl, wlvif, - STATION_ACTIVE_MODE); - if (ret < 0) - wl1271_warning("exit auto ps failed %d", ret); - } + STATION_ACTIVE_MODE, + wlvif->basic_rate, true); } if (conf->power_level != wlvif->power_level) { @@ -3103,21 +2974,6 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, wl1271_error("Could not add or replace key"); goto out_sleep; } - - /* - * reconfiguring arp response if the unicast (or common) - * encryption key type was changed - */ - if (wlvif->bss_type == BSS_TYPE_STA_BSS && - (sta || key_type == KEY_WEP) && - wlvif->encryption_type != key_type) { - wlvif->encryption_type = key_type; - ret = wl1271_cmd_build_arp_rsp(wl, wlvif); - if (ret < 0) { - wl1271_warning("build arp rsp failed: %d", ret); - goto out_sleep; - } - } break; case DISABLE_KEY: @@ -3187,6 +3043,10 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, goto out_sleep; } + /* cancel ROC before scanning */ + if (wl12xx_dev_role_started(wlvif)) + wl12xx_stop_dev(wl, wlvif); + ret = wl1271_scan(hw->priv, vif, ssid, len, req); out_sleep: wl1271_ps_elp_sleep(wl); @@ -3248,11 +3108,6 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) { - ret = -EAGAIN; - goto out; - } - ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; @@ -3284,9 +3139,6 @@ static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) - goto out; - ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; @@ -3414,7 +3266,6 @@ static void wl12xx_remove_vendor_ie(struct sk_buff *skb, static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates, struct ieee80211_vif *vif) { - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct sk_buff *skb; int ret; @@ -3422,7 +3273,7 @@ static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates, if (!skb) return -EOPNOTSUPP; - ret = wl1271_cmd_template_set(wl, wlvif->role_id, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, skb->data, skb->len, 0, @@ -3446,7 +3297,7 @@ static int wl1271_ap_set_probe_resp_tmpl_legacy(struct wl1271 *wl, /* no need to change probe response if the SSID is set correctly */ if (wlvif->ssid_len > 0) - return wl1271_cmd_template_set(wl, wlvif->role_id, + return wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, probe_rsp_data, probe_rsp_len, 0, @@ -3483,7 +3334,7 @@ static int wl1271_ap_set_probe_resp_tmpl_legacy(struct wl1271 *wl, ptr, probe_rsp_len - (ptr - probe_rsp_data)); templ_len += probe_rsp_len - (ptr - probe_rsp_data); - return wl1271_cmd_template_set(wl, wlvif->role_id, + return wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, probe_rsp_templ, templ_len, 0, @@ -3580,7 +3431,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : CMD_TEMPL_BEACON; - ret = wl1271_cmd_template_set(wl, wlvif->role_id, tmpl_id, + ret = wl1271_cmd_template_set(wl, tmpl_id, beacon->data, beacon->len, 0, min_rate); @@ -3619,7 +3470,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, beacon->len, min_rate); else - ret = wl1271_cmd_template_set(wl, wlvif->role_id, + ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, beacon->data, beacon->len, 0, @@ -3783,8 +3634,7 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, wlvif->rssi_thold = bss_conf->cqm_rssi_thold; } - if (changed & BSS_CHANGED_BSSID && - (is_ibss || bss_conf->assoc)) + if (changed & BSS_CHANGED_BSSID) if (!is_zero_ether_addr(bss_conf->bssid)) { ret = wl12xx_cmd_build_null_data(wl, wlvif); if (ret < 0) @@ -3823,6 +3673,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, wlvif->aid = bss_conf->aid; set_assoc = true; + wlvif->ps_poll_failures = 0; + /* * use basic rates from AP, and determine lowest rate * to use with control frames. @@ -3882,6 +3734,9 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, dev_kfree_skb(wlvif->probereq); wlvif->probereq = NULL; + /* re-enable dynamic ps - just in case */ + ieee80211_enable_dyn_ps(vif); + /* revert back to minimum rates for the current band */ wl1271_set_band_rate(wl, wlvif); wlvif->basic_rate = @@ -3955,6 +3810,34 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, if (ret < 0) goto out; + if (changed & BSS_CHANGED_ARP_FILTER) { + __be32 addr = bss_conf->arp_addr_list[0]; + WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS); + + if (bss_conf->arp_addr_cnt == 1 && + bss_conf->arp_filter_enabled) { + /* + * The template should have been configured only upon + * association. however, it seems that the correct ip + * isn't being set (when sending), so we have to + * reconfigure the template upon every ip change. + */ + ret = wl1271_cmd_build_arp_rsp(wl, wlvif, addr); + if (ret < 0) { + wl1271_warning("build arp rsp failed: %d", ret); + goto out; + } + + ret = wl1271_acx_arp_ip_filter(wl, wlvif, + ACX_ARP_FILTER_ARP_FILTERING, + addr); + } else + ret = wl1271_acx_arp_ip_filter(wl, wlvif, 0, addr); + + if (ret < 0) + goto out; + } + if (do_join) { ret = wl1271_join(wl, wlvif, set_assoc); if (ret < 0) { @@ -3980,6 +3863,19 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, if (ret < 0) goto out; } + + /* If we want to go in PSM but we're not there yet */ + if (test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags) && + !test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { + enum wl1271_cmd_ps_mode mode; + + mode = STATION_POWER_SAVE_MODE; + ret = wl1271_ps_set_mode(wl, wlvif, mode, + wlvif->basic_rate, + true); + if (ret < 0) + goto out; + } } /* Handle new association with HT. Do this after join. */ @@ -4021,41 +3917,6 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, } } - /* Handle arp filtering. Done after join. */ - if ((changed & BSS_CHANGED_ARP_FILTER) || - (!is_ibss && (changed & BSS_CHANGED_QOS))) { - __be32 addr = bss_conf->arp_addr_list[0]; - wlvif->sta.qos = bss_conf->qos; - WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS); - - if (bss_conf->arp_addr_cnt == 1 && - bss_conf->arp_filter_enabled) { - wlvif->ip_addr = addr; - /* - * The template should have been configured only upon - * association. however, it seems that the correct ip - * isn't being set (when sending), so we have to - * reconfigure the template upon every ip change. - */ - ret = wl1271_cmd_build_arp_rsp(wl, wlvif); - if (ret < 0) { - wl1271_warning("build arp rsp failed: %d", ret); - goto out; - } - - ret = wl1271_acx_arp_ip_filter(wl, wlvif, - (ACX_ARP_FILTER_ARP_FILTERING | - ACX_ARP_FILTER_AUTO_ARP), - addr); - } else { - wlvif->ip_addr = 0; - ret = wl1271_acx_arp_ip_filter(wl, wlvif, 0, addr); - } - - if (ret < 0) - goto out; - } - out: return; } @@ -4151,7 +4012,6 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw, { struct wl1271 *wl = hw->priv; - struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); u64 mactime = ULLONG_MAX; int ret; @@ -4166,7 +4026,7 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw, if (ret < 0) goto out; - ret = wl12xx_acx_tsf_info(wl, wlvif, &mactime); + ret = wl1271_acx_tsf_info(wl, &mactime); if (ret < 0) goto out_sleep; @@ -4513,7 +4373,7 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, /* TODO: change mac80211 to pass vif as param */ wl12xx_for_each_wlvif_sta(wl, wlvif) { - ret = wl12xx_cmd_channel_switch(wl, wlvif, ch_switch); + ret = wl12xx_cmd_channel_switch(wl, ch_switch); if (!ret) set_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags); @@ -4607,7 +4467,6 @@ static struct ieee80211_channel wl1271_channels[] = { /* mapping to indexes for wl1271_rates */ static const u8 wl1271_rate_to_idx_2ghz[] = { /* MCS rates are used only with 11n */ - 7, /* CONF_HW_RXTX_RATE_MCS7_SGI */ 7, /* CONF_HW_RXTX_RATE_MCS7 */ 6, /* CONF_HW_RXTX_RATE_MCS6 */ 5, /* CONF_HW_RXTX_RATE_MCS5 */ @@ -4729,7 +4588,6 @@ static struct ieee80211_channel wl1271_channels_5ghz[] = { /* mapping to indexes for wl1271_rates_5ghz */ static const u8 wl1271_rate_to_idx_5ghz[] = { /* MCS rates are used only with 11n */ - 7, /* CONF_HW_RXTX_RATE_MCS7_SGI */ 7, /* CONF_HW_RXTX_RATE_MCS7 */ 6, /* CONF_HW_RXTX_RATE_MCS6 */ 5, /* CONF_HW_RXTX_RATE_MCS5 */ @@ -4970,120 +4828,13 @@ static struct bin_attribute fwlog_attr = { .read = wl1271_sysfs_read_fwlog, }; -static bool wl12xx_mac_in_fuse(struct wl1271 *wl) -{ - bool supported = false; - u8 major, minor; - - if (wl->chip.id == CHIP_ID_1283_PG20) { - major = WL128X_PG_GET_MAJOR(wl->hw_pg_ver); - minor = WL128X_PG_GET_MINOR(wl->hw_pg_ver); - - /* in wl128x we have the MAC address if the PG is >= (2, 1) */ - if (major > 2 || (major == 2 && minor >= 1)) - supported = true; - } else { - major = WL127X_PG_GET_MAJOR(wl->hw_pg_ver); - minor = WL127X_PG_GET_MINOR(wl->hw_pg_ver); - - /* in wl127x we have the MAC address if the PG is >= (3, 1) */ - if (major == 3 && minor >= 1) - supported = true; - } - - wl1271_debug(DEBUG_PROBE, - "PG Ver major = %d minor = %d, MAC %s present", - major, minor, supported ? "is" : "is not"); - - return supported; -} - -static void wl12xx_derive_mac_addresses(struct wl1271 *wl, - u32 oui, u32 nic, int n) -{ - int i; - - wl1271_debug(DEBUG_PROBE, "base address: oui %06x nic %06x, n %d", - oui, nic, n); - - if (nic + n - 1 > 0xffffff) - wl1271_warning("NIC part of the MAC address wraps around!"); - - for (i = 0; i < n; i++) { - wl->addresses[i].addr[0] = (u8)(oui >> 16); - wl->addresses[i].addr[1] = (u8)(oui >> 8); - wl->addresses[i].addr[2] = (u8) oui; - wl->addresses[i].addr[3] = (u8)(nic >> 16); - wl->addresses[i].addr[4] = (u8)(nic >> 8); - wl->addresses[i].addr[5] = (u8) nic; - nic++; - } - - wl->hw->wiphy->n_addresses = n; - wl->hw->wiphy->addresses = wl->addresses; -} - -static void wl12xx_get_fuse_mac(struct wl1271 *wl) -{ - u32 mac1, mac2; - - wl1271_set_partition(wl, &wl12xx_part_table[PART_DRPW]); - - mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1); - mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2); - - /* these are the two parts of the BD_ADDR */ - wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + - ((mac1 & 0xff000000) >> 24); - wl->fuse_nic_addr = mac1 & 0xffffff; - - wl1271_set_partition(wl, &wl12xx_part_table[PART_DOWN]); -} - -static int wl12xx_get_hw_info(struct wl1271 *wl) -{ - int ret; - u32 die_info; - - ret = wl12xx_set_power_on(wl); - if (ret < 0) - goto out; - - wl->chip.id = wl1271_read32(wl, CHIP_ID_B); - - if (wl->chip.id == CHIP_ID_1283_PG20) - die_info = wl1271_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1); - else - die_info = wl1271_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1); - - wl->hw_pg_ver = (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET; - - if (!wl12xx_mac_in_fuse(wl)) { - wl->fuse_oui_addr = 0; - wl->fuse_nic_addr = 0; - } else { - wl12xx_get_fuse_mac(wl); - } - - wl1271_power_off(wl); -out: - return ret; -} - static int wl1271_register_hw(struct wl1271 *wl) { int ret; - u32 oui_addr = 0, nic_addr = 0; if (wl->mac80211_registered) return 0; - ret = wl12xx_get_hw_info(wl); - if (ret < 0) { - wl1271_error("couldn't get hw info"); - goto out; - } - ret = wl1271_fetch_nvs(wl); if (ret == 0) { /* NOTE: The wl->nvs->nvs element must be first, in @@ -5092,25 +4843,20 @@ static int wl1271_register_hw(struct wl1271 *wl) */ u8 *nvs_ptr = (u8 *)wl->nvs; - oui_addr = - (nvs_ptr[11] << 16) + (nvs_ptr[10] << 8) + nvs_ptr[6]; - nic_addr = - (nvs_ptr[5] << 16) + (nvs_ptr[4] << 8) + nvs_ptr[3]; + wl->mac_addr[0] = nvs_ptr[11]; + wl->mac_addr[1] = nvs_ptr[10]; + wl->mac_addr[2] = nvs_ptr[6]; + wl->mac_addr[3] = nvs_ptr[5]; + wl->mac_addr[4] = nvs_ptr[4]; + wl->mac_addr[5] = nvs_ptr[3]; } - /* if the MAC address is zeroed in the NVS derive from fuse */ - if (oui_addr == 0 && nic_addr == 0) { - oui_addr = wl->fuse_oui_addr; - /* fuse has the BD_ADDR, the WLAN addresses are the next two */ - nic_addr = wl->fuse_nic_addr + 1; - } - - wl12xx_derive_mac_addresses(wl, oui_addr, nic_addr, 2); + SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); ret = ieee80211_register_hw(wl->hw); if (ret < 0) { wl1271_error("unable to register mac80211 hw: %d", ret); - goto out; + return ret; } wl->mac80211_registered = true; @@ -5121,14 +4867,13 @@ static int wl1271_register_hw(struct wl1271 *wl) wl1271_notice("loaded"); -out: - return ret; + return 0; } static void wl1271_unregister_hw(struct wl1271 *wl) { - if (wl->plt) - wl1271_plt_stop(wl); + if (wl->state == WL1271_STATE_PLT) + __wl1271_plt_stop(wl); unregister_netdevice_notifier(&wl1271_dev_notifier); ieee80211_unregister_hw(wl->hw); @@ -5147,7 +4892,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) }; /* The tx descriptor buffer and the TKIP space. */ - wl->hw->extra_tx_headroom = WL1271_EXTRA_SPACE_TKIP + + wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE + sizeof(struct wl1271_tx_hw_descr); /* unit us */ @@ -5157,7 +4902,6 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_SUPPORTS_DYNAMIC_PS | IEEE80211_HW_SUPPORTS_UAPSD | IEEE80211_HW_HAS_RATE_CONTROL | IEEE80211_HW_CONNECTION_MONITOR | @@ -5165,8 +4909,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_AP_LINK_PS | IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_TX_AMPDU_SETUP_IN_HW | - IEEE80211_HW_SCAN_WHILE_IDLE; + IEEE80211_HW_TX_AMPDU_SETUP_IN_HW; wl->hw->wiphy->cipher_suites = cipher_suites; wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); @@ -5182,10 +4925,10 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) * should be the maximum length possible for a template, without * the IEEE80211 header of the template */ - wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - + wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE - sizeof(struct ieee80211_header); - wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE - + wl->hw->wiphy->max_sched_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE - sizeof(struct ieee80211_header); wl->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; @@ -5279,6 +5022,7 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) wl->rx_counter = 0; wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->band = IEEE80211_BAND_2GHZ; + wl->vif = NULL; wl->flags = 0; wl->sg_enabled = true; wl->hw_pg_ver = -1; @@ -5303,7 +5047,6 @@ static struct ieee80211_hw *wl1271_alloc_hw(void) spin_lock_init(&wl->wl_lock); wl->state = WL1271_STATE_OFF; - wl->fw_type = WL12XX_FW_TYPE_NONE; mutex_init(&wl->mutex); /* Apply default driver configuration. */ @@ -5371,7 +5114,6 @@ static int wl1271_free_hw(struct wl1271 *wl) vfree(wl->fw); wl->fw = NULL; - wl->fw_type = WL12XX_FW_TYPE_NONE; kfree(wl->nvs); wl->nvs = NULL; @@ -5558,7 +5300,7 @@ module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR); MODULE_PARM_DESC(debug_level, "wl12xx debugging level"); module_param_named(fwlog, fwlog_param, charp, 0); -MODULE_PARM_DESC(fwlog, +MODULE_PARM_DESC(keymap, "FW logger options: continuous, ondemand, dbgpins or disable"); module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR); diff --git a/trunk/drivers/net/wireless/wl12xx/ps.c b/trunk/drivers/net/wireless/wl12xx/ps.c index 23d67501c50a..a2bdacdd7e1d 100644 --- a/trunk/drivers/net/wireless/wl12xx/ps.c +++ b/trunk/drivers/net/wireless/wl12xx/ps.c @@ -56,7 +56,7 @@ void wl1271_elp_work(struct work_struct *work) if (wlvif->bss_type == BSS_TYPE_AP_BSS) goto out; - if (!test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags) && + if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) && test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) goto out; } @@ -84,7 +84,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) if (wlvif->bss_type == BSS_TYPE_AP_BSS) return; - if (!test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags) && + if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags) && test_bit(WLVIF_FLAG_IN_USE, &wlvif->flags)) return; } @@ -160,39 +160,28 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) } int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, - enum wl1271_cmd_ps_mode mode) + enum wl1271_cmd_ps_mode mode, u32 rates, bool send) { int ret; - u16 timeout = wl->conf.conn.dynamic_ps_timeout; switch (mode) { - case STATION_AUTO_PS_MODE: case STATION_POWER_SAVE_MODE: - wl1271_debug(DEBUG_PSM, "entering psm (mode=%d,timeout=%u)", - mode, timeout); + wl1271_debug(DEBUG_PSM, "entering psm"); - ret = wl1271_acx_wake_up_conditions(wl, wlvif, - wl->conf.conn.wake_up_event, - wl->conf.conn.listen_interval); + ret = wl1271_acx_wake_up_conditions(wl, wlvif); if (ret < 0) { wl1271_error("couldn't set wake up conditions"); return ret; } - ret = wl1271_cmd_ps_mode(wl, wlvif, mode, timeout); + ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_POWER_SAVE_MODE); if (ret < 0) return ret; - set_bit(WLVIF_FLAG_IN_PS, &wlvif->flags); - - /* enable beacon early termination. Not relevant for 5GHz */ - if (wlvif->band == IEEE80211_BAND_2GHZ) { - ret = wl1271_acx_bet_enable(wl, wlvif, true); - if (ret < 0) - return ret; - } + set_bit(WLVIF_FLAG_PSM, &wlvif->flags); break; case STATION_ACTIVE_MODE: + default: wl1271_debug(DEBUG_PSM, "leaving psm"); /* disable beacon early termination */ @@ -202,15 +191,12 @@ int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, return ret; } - ret = wl1271_cmd_ps_mode(wl, wlvif, mode, 0); + ret = wl1271_cmd_ps_mode(wl, wlvif, STATION_ACTIVE_MODE); if (ret < 0) return ret; - clear_bit(WLVIF_FLAG_IN_PS, &wlvif->flags); + clear_bit(WLVIF_FLAG_PSM, &wlvif->flags); break; - default: - wl1271_warning("trying to set ps to unsupported mode %d", mode); - ret = -EINVAL; } return ret; diff --git a/trunk/drivers/net/wireless/wl12xx/ps.h b/trunk/drivers/net/wireless/wl12xx/ps.h index 5f19d4fbbf27..a12052f02026 100644 --- a/trunk/drivers/net/wireless/wl12xx/ps.h +++ b/trunk/drivers/net/wireless/wl12xx/ps.h @@ -28,7 +28,7 @@ #include "acx.h" int wl1271_ps_set_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif, - enum wl1271_cmd_ps_mode mode); + enum wl1271_cmd_ps_mode mode, u32 rates, bool send); void wl1271_ps_elp_sleep(struct wl1271 *wl); int wl1271_ps_elp_wakeup(struct wl1271 *wl); void wl1271_elp_work(struct work_struct *work); diff --git a/trunk/drivers/net/wireless/wl12xx/reg.h b/trunk/drivers/net/wireless/wl12xx/reg.h index 340db324bc26..df34d5977b98 100644 --- a/trunk/drivers/net/wireless/wl12xx/reg.h +++ b/trunk/drivers/net/wireless/wl12xx/reg.h @@ -525,31 +525,4 @@ b12-b0 - Supported Rate indicator bits as defined below. */ #define INTR_TRIG_TX_PROC1 BIT(18) -#define WL127X_REG_FUSE_DATA_2_1 0x050a -#define WL128X_REG_FUSE_DATA_2_1 0x2152 -#define PG_VER_MASK 0x3c -#define PG_VER_OFFSET 2 - -#define WL127X_PG_MAJOR_VER_MASK 0x3 -#define WL127X_PG_MAJOR_VER_OFFSET 0x0 -#define WL127X_PG_MINOR_VER_MASK 0xc -#define WL127X_PG_MINOR_VER_OFFSET 0x2 - -#define WL128X_PG_MAJOR_VER_MASK 0xc -#define WL128X_PG_MAJOR_VER_OFFSET 0x2 -#define WL128X_PG_MINOR_VER_MASK 0x3 -#define WL128X_PG_MINOR_VER_OFFSET 0x0 - -#define WL127X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL127X_PG_MAJOR_VER_MASK) >> \ - WL127X_PG_MAJOR_VER_OFFSET) -#define WL127X_PG_GET_MINOR(pg_ver) ((pg_ver & WL127X_PG_MINOR_VER_MASK) >> \ - WL127X_PG_MINOR_VER_OFFSET) -#define WL128X_PG_GET_MAJOR(pg_ver) ((pg_ver & WL128X_PG_MAJOR_VER_MASK) >> \ - WL128X_PG_MAJOR_VER_OFFSET) -#define WL128X_PG_GET_MINOR(pg_ver) ((pg_ver & WL128X_PG_MINOR_VER_MASK) >> \ - WL128X_PG_MINOR_VER_OFFSET) - -#define WL12XX_REG_FUSE_BD_ADDR_1 0x00310eb4 -#define WL12XX_REG_FUSE_BD_ADDR_2 0x00310eb8 - #endif diff --git a/trunk/drivers/net/wireless/wl12xx/rx.c b/trunk/drivers/net/wireless/wl12xx/rx.c index cfa6071704c5..4fbd2a722ffa 100644 --- a/trunk/drivers/net/wireless/wl12xx/rx.c +++ b/trunk/drivers/net/wireless/wl12xx/rx.c @@ -113,7 +113,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, * In PLT mode we seem to get frames and mac80211 warns about them, * workaround this by not retrieving them at all. */ - if (unlikely(wl->plt)) + if (unlikely(wl->state == WL1271_STATE_PLT)) return -EINVAL; /* the data read starts with the descriptor */ diff --git a/trunk/drivers/net/wireless/wl12xx/scan.c b/trunk/drivers/net/wireless/wl12xx/scan.c index e43a6b2c1d91..e24111ececc5 100644 --- a/trunk/drivers/net/wireless/wl12xx/scan.c +++ b/trunk/drivers/net/wireless/wl12xx/scan.c @@ -38,6 +38,7 @@ void wl1271_scan_complete_work(struct work_struct *work) struct ieee80211_vif *vif; struct wl12xx_vif *wlvif; int ret; + bool is_sta, is_ibss; dwork = container_of(work, struct delayed_work, work); wl = container_of(dwork, struct wl1271, scan_complete_work); @@ -69,6 +70,15 @@ void wl1271_scan_complete_work(struct work_struct *work) wl1271_cmd_build_ap_probe_req(wl, wlvif, wlvif->probereq); } + /* return to ROC if needed */ + is_sta = (wlvif->bss_type == BSS_TYPE_STA_BSS); + is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); + if (((is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) || + (is_ibss && !test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags))) && + !test_bit(wlvif->dev_role_id, wl->roc_map)) { + /* restore remain on channel */ + wl12xx_start_dev(wl, wlvif); + } wl1271_ps_elp_sleep(wl); if (wl->scan.failed) { @@ -172,23 +182,14 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, goto out; } - if (wl->conf.scan.split_scan_timeout) - scan_options |= WL1271_SCAN_OPT_SPLIT_SCAN; - if (passive) scan_options |= WL1271_SCAN_OPT_PASSIVE; - if (wlvif->bss_type == BSS_TYPE_AP_BSS || - test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) - cmd->params.role_id = wlvif->role_id; - else - cmd->params.role_id = wlvif->dev_role_id; - - if (WARN_ON(cmd->params.role_id == WL12XX_INVALID_ROLE_ID)) { + if (WARN_ON(wlvif->role_id == WL12XX_INVALID_ROLE_ID)) { ret = -EINVAL; goto out; } - + cmd->params.role_id = wlvif->role_id; cmd->params.scan_options = cpu_to_le16(scan_options); cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req, @@ -201,7 +202,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, cmd->params.tx_rate = cpu_to_le32(basic_rate); cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs; - cmd->params.tid_trigger = CONF_TX_AC_ANY_TID; + cmd->params.tid_trigger = 0; cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; if (band == IEEE80211_BAND_2GHZ) @@ -216,17 +217,16 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, memcpy(cmd->addr, vif->addr, ETH_ALEN); - ret = wl12xx_cmd_build_probe_req(wl, wlvif, - cmd->params.role_id, band, - wl->scan.ssid, wl->scan.ssid_len, - wl->scan.req->ie, - wl->scan.req->ie_len); + ret = wl1271_cmd_build_probe_req(wl, wlvif, wl->scan.ssid, + wl->scan.ssid_len, wl->scan.req->ie, + wl->scan.req->ie_len, band); if (ret < 0) { wl1271_error("PROBE request template failed"); goto out; } - trigger->timeout = cpu_to_le32(wl->conf.scan.split_scan_timeout); + /* disable the timeout */ + trigger->timeout = 0; ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, sizeof(*trigger), 0); if (ret < 0) { @@ -658,13 +658,11 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, } if (!force_passive && cfg->active[0]) { - u8 band = IEEE80211_BAND_2GHZ; - ret = wl12xx_cmd_build_probe_req(wl, wlvif, - wlvif->dev_role_id, band, - req->ssids[0].ssid, + ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid, req->ssids[0].ssid_len, - ies->ie[band], - ies->len[band]); + ies->ie[IEEE80211_BAND_2GHZ], + ies->len[IEEE80211_BAND_2GHZ], + IEEE80211_BAND_2GHZ); if (ret < 0) { wl1271_error("2.4GHz PROBE request template failed"); goto out; @@ -672,13 +670,11 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, } if (!force_passive && cfg->active[1]) { - u8 band = IEEE80211_BAND_5GHZ; - ret = wl12xx_cmd_build_probe_req(wl, wlvif, - wlvif->dev_role_id, band, - req->ssids[0].ssid, + ret = wl1271_cmd_build_probe_req(wl, wlvif, req->ssids[0].ssid, req->ssids[0].ssid_len, - ies->ie[band], - ies->len[band]); + ies->ie[IEEE80211_BAND_5GHZ], + ies->len[IEEE80211_BAND_5GHZ], + IEEE80211_BAND_5GHZ); if (ret < 0) { wl1271_error("5GHz PROBE request template failed"); goto out; diff --git a/trunk/drivers/net/wireless/wl12xx/scan.h b/trunk/drivers/net/wireless/wl12xx/scan.h index 96ff457a3a0b..a7ed43dc08c9 100644 --- a/trunk/drivers/net/wireless/wl12xx/scan.h +++ b/trunk/drivers/net/wireless/wl12xx/scan.h @@ -48,7 +48,7 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl); #define WL1271_SCAN_CURRENT_TX_PWR 0 #define WL1271_SCAN_OPT_ACTIVE 0 #define WL1271_SCAN_OPT_PASSIVE 1 -#define WL1271_SCAN_OPT_SPLIT_SCAN 2 +#define WL1271_SCAN_OPT_TRIGGERED_SCAN 2 #define WL1271_SCAN_OPT_PRIORITY_HIGH 4 /* scan even if we fail to enter psm */ #define WL1271_SCAN_OPT_FORCE 8 diff --git a/trunk/drivers/net/wireless/wl12xx/sdio.c b/trunk/drivers/net/wireless/wl12xx/sdio.c index 4b3c32774bae..468a50553fac 100644 --- a/trunk/drivers/net/wireless/wl12xx/sdio.c +++ b/trunk/drivers/net/wireless/wl12xx/sdio.c @@ -74,8 +74,6 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); struct sdio_func *func = dev_to_sdio_func(glue->dev); - sdio_claim_host(func); - if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { ((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret); dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n", @@ -90,8 +88,6 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, addr, len); } - sdio_release_host(func); - if (ret) dev_err(child->parent, "sdio read failed (%d)\n", ret); } @@ -103,8 +99,6 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); struct sdio_func *func = dev_to_sdio_func(glue->dev); - sdio_claim_host(func); - if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) { sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret); dev_dbg(child->parent, "sdio write 52 addr 0x%x, byte 0x%02x\n", @@ -119,8 +113,6 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, ret = sdio_memcpy_toio(func, addr, buf, len); } - sdio_release_host(func); - if (ret) dev_err(child->parent, "sdio write failed (%d)\n", ret); } @@ -144,7 +136,6 @@ static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) sdio_claim_host(func); sdio_enable_func(func); - sdio_release_host(func); out: return ret; @@ -155,7 +146,6 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue) int ret; struct sdio_func *func = dev_to_sdio_func(glue->dev); - sdio_claim_host(func); sdio_disable_func(func); sdio_release_host(func); @@ -324,6 +314,9 @@ static int wl1271_suspend(struct device *dev) dev_err(dev, "error while trying to keep power\n"); goto out; } + + /* release host */ + sdio_release_host(func); } out: return ret; @@ -331,7 +324,15 @@ static int wl1271_suspend(struct device *dev) static int wl1271_resume(struct device *dev) { + struct sdio_func *func = dev_to_sdio_func(dev); + struct wl12xx_sdio_glue *glue = sdio_get_drvdata(func); + struct wl1271 *wl = platform_get_drvdata(glue->core); + dev_dbg(dev, "wl1271 resume\n"); + if (wl->wow_enabled) { + /* claim back host */ + sdio_claim_host(func); + } return 0; } @@ -370,9 +371,5 @@ module_exit(wl1271_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); -MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE); -MODULE_FIRMWARE(WL127X_FW_NAME_MULTI); -MODULE_FIRMWARE(WL127X_PLT_FW_NAME); -MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE); -MODULE_FIRMWARE(WL128X_FW_NAME_MULTI); -MODULE_FIRMWARE(WL128X_PLT_FW_NAME); +MODULE_FIRMWARE(WL127X_FW_NAME); +MODULE_FIRMWARE(WL128X_FW_NAME); diff --git a/trunk/drivers/net/wireless/wl12xx/spi.c b/trunk/drivers/net/wireless/wl12xx/spi.c index 2fc18a8dcce8..92caa7ce6053 100644 --- a/trunk/drivers/net/wireless/wl12xx/spi.c +++ b/trunk/drivers/net/wireless/wl12xx/spi.c @@ -433,10 +433,6 @@ module_exit(wl1271_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); -MODULE_FIRMWARE(WL127X_FW_NAME_SINGLE); -MODULE_FIRMWARE(WL127X_FW_NAME_MULTI); -MODULE_FIRMWARE(WL127X_PLT_FW_NAME); -MODULE_FIRMWARE(WL128X_FW_NAME_SINGLE); -MODULE_FIRMWARE(WL128X_FW_NAME_MULTI); -MODULE_FIRMWARE(WL128X_PLT_FW_NAME); +MODULE_FIRMWARE(WL127X_FW_NAME); +MODULE_FIRMWARE(WL128X_FW_NAME); MODULE_ALIAS("spi:wl1271"); diff --git a/trunk/drivers/net/wireless/wl12xx/testmode.c b/trunk/drivers/net/wireless/wl12xx/testmode.c index 1e93bb9c0246..25093c0cb0ed 100644 --- a/trunk/drivers/net/wireless/wl12xx/testmode.c +++ b/trunk/drivers/net/wireless/wl12xx/testmode.c @@ -30,7 +30,6 @@ #include "acx.h" #include "reg.h" #include "ps.h" -#include "io.h" #define WL1271_TM_MAX_DATA_LENGTH 1024 @@ -42,7 +41,6 @@ enum wl1271_tm_commands { WL1271_TM_CMD_NVS_PUSH, /* Not in use. Keep to not break ABI */ WL1271_TM_CMD_SET_PLT_MODE, WL1271_TM_CMD_RECOVER, - WL1271_TM_CMD_GET_MAC, __WL1271_TM_CMD_AFTER_LAST }; @@ -266,52 +264,6 @@ static int wl1271_tm_cmd_recover(struct wl1271 *wl, struct nlattr *tb[]) return 0; } -static int wl12xx_tm_cmd_get_mac(struct wl1271 *wl, struct nlattr *tb[]) -{ - struct sk_buff *skb; - u8 mac_addr[ETH_ALEN]; - int ret = 0; - - mutex_lock(&wl->mutex); - - if (!wl->plt) { - ret = -EINVAL; - goto out; - } - - if (wl->fuse_oui_addr == 0 && wl->fuse_nic_addr == 0) { - ret = -EOPNOTSUPP; - goto out; - } - - mac_addr[0] = (u8)(wl->fuse_oui_addr >> 16); - mac_addr[1] = (u8)(wl->fuse_oui_addr >> 8); - mac_addr[2] = (u8) wl->fuse_oui_addr; - mac_addr[3] = (u8)(wl->fuse_nic_addr >> 16); - mac_addr[4] = (u8)(wl->fuse_nic_addr >> 8); - mac_addr[5] = (u8) wl->fuse_nic_addr; - - skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, ETH_ALEN); - if (!skb) { - ret = -ENOMEM; - goto out; - } - - NLA_PUT(skb, WL1271_TM_ATTR_DATA, ETH_ALEN, mac_addr); - ret = cfg80211_testmode_reply(skb); - if (ret < 0) - goto out; - -out: - mutex_unlock(&wl->mutex); - return ret; - -nla_put_failure: - kfree_skb(skb); - ret = -EMSGSIZE; - goto out; -} - int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) { struct wl1271 *wl = hw->priv; @@ -336,8 +288,6 @@ int wl1271_tm_cmd(struct ieee80211_hw *hw, void *data, int len) return wl1271_tm_cmd_set_plt_mode(wl, tb); case WL1271_TM_CMD_RECOVER: return wl1271_tm_cmd_recover(wl, tb); - case WL1271_TM_CMD_GET_MAC: - return wl12xx_tm_cmd_get_mac(wl, tb); default: return -EOPNOTSUPP; } diff --git a/trunk/drivers/net/wireless/wl12xx/tx.c b/trunk/drivers/net/wireless/wl12xx/tx.c index 6446e4d3e8f9..4508ccd78328 100644 --- a/trunk/drivers/net/wireless/wl12xx/tx.c +++ b/trunk/drivers/net/wireless/wl12xx/tx.c @@ -77,6 +77,35 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id) } } +static int wl1271_tx_update_filters(struct wl1271 *wl, + struct wl12xx_vif *wlvif, + struct sk_buff *skb) +{ + struct ieee80211_hdr *hdr; + int ret; + + hdr = (struct ieee80211_hdr *)skb->data; + + /* + * stop bssid-based filtering before transmitting authentication + * requests. this way the hw will never drop authentication + * responses coming from BSSIDs it isn't familiar with (e.g. on + * roaming) + */ + if (!ieee80211_is_auth(hdr->frame_control)) + return 0; + + if (wlvif->dev_hlid != WL12XX_INVALID_LINK_ID) + goto out; + + wl1271_debug(DEBUG_CMD, "starting device role for roaming"); + ret = wl12xx_start_dev(wl, wlvif); + if (ret < 0) + goto out; +out: + return 0; +} + static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl, struct sk_buff *skb) { @@ -158,6 +187,8 @@ u8 wl12xx_tx_get_hlid(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (wlvif->bss_type == BSS_TYPE_AP_BSS) return wl12xx_tx_get_hlid_ap(wl, wlvif, skb); + wl1271_tx_update_filters(wl, wlvif, skb); + if ((test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || test_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags)) && !ieee80211_is_auth(hdr->frame_control) && @@ -255,20 +286,16 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, int aligned_len, ac, rate_idx; s64 hosttime; u16 tx_attr = 0; - __le16 frame_control; - struct ieee80211_hdr *hdr; - u8 *frame_start; bool is_dummy; desc = (struct wl1271_tx_hw_descr *) skb->data; - frame_start = (u8 *)(desc + 1); - hdr = (struct ieee80211_hdr *)(frame_start + extra); - frame_control = hdr->frame_control; /* relocate space for security header */ if (extra) { - int hdrlen = ieee80211_hdrlen(frame_control); - memmove(frame_start, hdr, hdrlen); + void *framestart = skb->data + sizeof(*desc); + u16 fc = *(u16 *)(framestart + extra); + int hdrlen = ieee80211_hdrlen(cpu_to_le16(fc)); + memmove(framestart, framestart + extra, hdrlen); } /* configure packet life time */ @@ -357,11 +384,6 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, desc->wl127x_mem.total_mem_blocks); } - /* for WEP shared auth - no fw encryption is needed */ - if (ieee80211_is_auth(frame_control) && - ieee80211_has_protected(frame_control)) - tx_attr |= TX_HW_ATTR_HOST_ENCRYPT; - desc->tx_attr = cpu_to_le16(tx_attr); } @@ -386,7 +408,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (info->control.hw_key && info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) - extra = WL1271_EXTRA_SPACE_TKIP; + extra = WL1271_TKIP_IV_SPACE; if (info->control.hw_key) { bool is_wep; @@ -773,18 +795,6 @@ void wl1271_tx_work(struct work_struct *work) mutex_unlock(&wl->mutex); } -static u8 wl1271_tx_get_rate_flags(u8 rate_class_index) -{ - u8 flags = 0; - - if (rate_class_index >= CONF_HW_RXTX_RATE_MCS_MIN && - rate_class_index <= CONF_HW_RXTX_RATE_MCS_MAX) - flags |= IEEE80211_TX_RC_MCS; - if (rate_class_index == CONF_HW_RXTX_RATE_MCS7_SGI) - flags |= IEEE80211_TX_RC_SHORT_GI; - return flags; -} - static void wl1271_tx_complete_packet(struct wl1271 *wl, struct wl1271_tx_hw_res_descr *result) { @@ -794,7 +804,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, struct sk_buff *skb; int id = result->id; int rate = -1; - u8 rate_flags = 0; u8 retries = 0; /* check for id legality */ @@ -821,7 +830,6 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, info->flags |= IEEE80211_TX_STAT_ACK; rate = wl1271_rate_to_idx(result->rate_class_index, wlvif->band); - rate_flags = wl1271_tx_get_rate_flags(result->rate_class_index); retries = result->ack_failures; } else if (result->status == TX_RETRY_EXCEEDED) { wl->stats.excessive_retries++; @@ -830,7 +838,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, info->status.rates[0].idx = rate; info->status.rates[0].count = retries; - info->status.rates[0].flags = rate_flags; + info->status.rates[0].flags = 0; info->status.ack_signal = -1; wl->stats.retry_count += result->ack_failures; @@ -861,9 +869,8 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, if (info->control.hw_key && info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { int hdrlen = ieee80211_get_hdrlen_from_skb(skb); - memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, skb->data, - hdrlen); - skb_pull(skb, WL1271_EXTRA_SPACE_TKIP); + memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen); + skb_pull(skb, WL1271_TKIP_IV_SPACE); } wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x" @@ -1005,9 +1012,9 @@ void wl12xx_tx_reset(struct wl1271 *wl, bool reset_tx_queues) info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { int hdrlen = ieee80211_get_hdrlen_from_skb(skb); - memmove(skb->data + WL1271_EXTRA_SPACE_TKIP, + memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen); - skb_pull(skb, WL1271_EXTRA_SPACE_TKIP); + skb_pull(skb, WL1271_TKIP_IV_SPACE); } info->status.rates[0].idx = -1; diff --git a/trunk/drivers/net/wireless/wl12xx/tx.h b/trunk/drivers/net/wireless/wl12xx/tx.h index e3977b55a710..2dbb24e6d541 100644 --- a/trunk/drivers/net/wireless/wl12xx/tx.h +++ b/trunk/drivers/net/wireless/wl12xx/tx.h @@ -39,7 +39,6 @@ #define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11)) #define TX_HW_ATTR_TX_CMPLT_REQ BIT(12) #define TX_HW_ATTR_TX_DUMMY_REQ BIT(13) -#define TX_HW_ATTR_HOST_ENCRYPT BIT(14) #define TX_HW_ATTR_OFST_SAVE_RETRIES 0 #define TX_HW_ATTR_OFST_HEADER_PAD 1 @@ -52,9 +51,7 @@ #define TX_HW_RESULT_QUEUE_LEN_MASK 0xf #define WL1271_TX_ALIGN_TO 4 -#define WL1271_EXTRA_SPACE_TKIP 4 -#define WL1271_EXTRA_SPACE_AES 8 -#define WL1271_EXTRA_SPACE_MAX 8 +#define WL1271_TKIP_IV_SPACE 4 /* Used for management frames and dummy packets */ #define WL1271_TID_MGMT 7 diff --git a/trunk/drivers/net/wireless/wl12xx/wl12xx.h b/trunk/drivers/net/wireless/wl12xx/wl12xx.h index 90352415e2aa..b2b09cd02022 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl12xx.h +++ b/trunk/drivers/net/wireless/wl12xx/wl12xx.h @@ -35,14 +35,8 @@ #include "conf.h" #include "ini.h" -#define WL127X_FW_NAME_MULTI "ti-connectivity/wl127x-fw-4-mr.bin" -#define WL127X_FW_NAME_SINGLE "ti-connectivity/wl127x-fw-4-sr.bin" - -#define WL128X_FW_NAME_MULTI "ti-connectivity/wl128x-fw-4-mr.bin" -#define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin" - -#define WL127X_PLT_FW_NAME "ti-connectivity/wl127x-fw-4-plt.bin" -#define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin" +#define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin" +#define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin" /* * wl127x and wl128x are using the same NVS file name. However, the @@ -96,13 +90,7 @@ enum wl1271_state { WL1271_STATE_OFF, WL1271_STATE_ON, -}; - -enum wl12xx_fw_type { - WL12XX_FW_TYPE_NONE, - WL12XX_FW_TYPE_NORMAL, - WL12XX_FW_TYPE_MULTI, - WL12XX_FW_TYPE_PLT, + WL1271_STATE_PLT, }; enum wl1271_partition_type { @@ -259,7 +247,6 @@ enum wl12xx_flags { WL1271_FLAG_PENDING_WORK, WL1271_FLAG_SOFT_GEMINI, WL1271_FLAG_RECOVERY_IN_PROGRESS, - WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, }; enum wl12xx_vif_flags { @@ -267,7 +254,8 @@ enum wl12xx_vif_flags { WLVIF_FLAG_STA_ASSOCIATED, WLVIF_FLAG_IBSS_JOINED, WLVIF_FLAG_AP_STARTED, - WLVIF_FLAG_IN_PS, + WLVIF_FLAG_PSM, + WLVIF_FLAG_PSM_REQUESTED, WLVIF_FLAG_STA_STATE_SENT, WLVIF_FLAG_RX_STREAMING_STARTED, WLVIF_FLAG_PSPOLL_FAILURE, @@ -307,9 +295,6 @@ struct wl1271 { spinlock_t wl_lock; enum wl1271_state state; - enum wl12xx_fw_type fw_type; - bool plt; - u8 last_vif_count; struct mutex mutex; unsigned long flags; @@ -328,12 +313,7 @@ struct wl1271 { s8 hw_pg_ver; - /* address read from the fuse ROM */ - u32 fuse_oui_addr; - u32 fuse_nic_addr; - - /* we have up to 2 MAC addresses */ - struct mac_address addresses[2]; + u8 mac_addr[ETH_ALEN]; int channel; u8 system_hlid; @@ -445,6 +425,8 @@ struct wl1271 { struct wl12xx_fw_status *fw_status; struct wl1271_tx_hw_res_if *tx_res_if; + struct ieee80211_vif *vif; + /* Current chipset configuration */ struct conf_drv_settings conf; @@ -521,8 +503,6 @@ struct wl12xx_vif { u8 basic_rate_idx; u8 ap_rate_idx; u8 p2p_rate_idx; - - bool qos; } sta; struct { u8 global_hlid; @@ -580,6 +560,12 @@ struct wl12xx_vif { /* Session counter for the chipset */ int session_counter; + struct completion *ps_compl; + struct delayed_work pspoll_work; + + /* counter for ps-poll delivery failures */ + int ps_poll_failures; + /* retry counter for PSM entries */ u8 psm_entry_retry; @@ -589,10 +575,6 @@ struct wl12xx_vif { int rssi_thold; int last_rssi_event; - /* save the current encryption type for auto-arp config */ - u8 encryption_type; - __be32 ip_addr; - /* RX BA constraint value */ bool ba_support; bool ba_allowed; diff --git a/trunk/drivers/net/wireless/wl12xx/wl12xx_80211.h b/trunk/drivers/net/wireless/wl12xx/wl12xx_80211.h index 22b0bc98d7b5..8f0ffaf62309 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl12xx_80211.h +++ b/trunk/drivers/net/wireless/wl12xx/wl12xx_80211.h @@ -117,7 +117,7 @@ struct wl12xx_ps_poll_template { } __packed; struct wl12xx_arp_rsp_template { - /* not including ieee80211 header */ + struct ieee80211_hdr_3addr hdr; u8 llc_hdr[sizeof(rfc1042_header)]; __be16 llc_type; diff --git a/trunk/include/linux/nl80211.h b/trunk/include/linux/nl80211.h index be35a68746a7..ad56e21a9f10 100644 --- a/trunk/include/linux/nl80211.h +++ b/trunk/include/linux/nl80211.h @@ -156,23 +156,21 @@ * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX * or %NL80211_ATTR_MAC. * - * @NL80211_CMD_GET_BEACON: (not used) - * @NL80211_CMD_SET_BEACON: change the beacon on an access point interface - * using the %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL - * attributes. For drivers that generate the beacon and probe responses - * internally, the following attributes must be provided: %NL80211_ATTR_IE, - * %NL80211_ATTR_IE_PROBE_RESP and %NL80211_ATTR_IE_ASSOC_RESP. - * @NL80211_CMD_START_AP: Start AP operation on an AP interface, parameters - * are like for %NL80211_CMD_SET_BEACON, and additionally parameters that - * do not change are used, these include %NL80211_ATTR_BEACON_INTERVAL, - * %NL80211_ATTR_DTIM_PERIOD, %NL80211_ATTR_SSID, + * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a + * %NL80222_CMD_NEW_BEACON message) + * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface + * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD, + * %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes. + * Following attributes are provided for drivers that generate full Beacon + * and Probe Response frames internally: %NL80211_ATTR_SSID, * %NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE, * %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS, - * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY and - * %NL80211_ATTR_AUTH_TYPE. - * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP - * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface - * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP + * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, + * %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_IE, %NL80211_ATTR_IE_PROBE_RESP, + * %NL80211_ATTR_IE_ASSOC_RESP. + * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface, + * parameters are like for %NL80211_CMD_SET_BEACON. + * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it * * @NL80211_CMD_GET_STATION: Get station attributes for station identified by * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. @@ -567,10 +565,8 @@ enum nl80211_commands { NL80211_CMD_GET_BEACON, NL80211_CMD_SET_BEACON, - NL80211_CMD_START_AP, - NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP, - NL80211_CMD_STOP_AP, - NL80211_CMD_DEL_BEACON = NL80211_CMD_STOP_AP, + NL80211_CMD_NEW_BEACON, + NL80211_CMD_DEL_BEACON, NL80211_CMD_GET_STATION, NL80211_CMD_SET_STATION, diff --git a/trunk/include/net/cfg80211.h b/trunk/include/net/cfg80211.h index 755a7707a7c5..e0c9ff3a1977 100644 --- a/trunk/include/net/cfg80211.h +++ b/trunk/include/net/cfg80211.h @@ -366,13 +366,25 @@ struct cfg80211_crypto_settings { }; /** - * struct cfg80211_beacon_data - beacon data + * struct beacon_parameters - beacon parameters + * + * Used to configure the beacon for an interface. + * * @head: head portion of beacon (before TIM IE) * or %NULL if not changed * @tail: tail portion of beacon (after TIM IE) * or %NULL if not changed + * @interval: beacon interval or zero if not changed + * @dtim_period: DTIM period or zero if not changed * @head_len: length of @head * @tail_len: length of @tail + * @ssid: SSID to be used in the BSS (note: may be %NULL if not provided from + * user space) + * @ssid_len: length of @ssid + * @hidden_ssid: whether to hide the SSID in Beacon/Probe Response frames + * @crypto: crypto settings + * @privacy: the BSS uses privacy + * @auth_type: Authentication type (algorithm) * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL * @beacon_ies_len: length of beacon_ies in octets * @proberesp_ies: extra information element(s) to add into Probe Response @@ -384,46 +396,24 @@ struct cfg80211_crypto_settings { * @probe_resp_len: length of probe response template (@probe_resp) * @probe_resp: probe response template (AP mode only) */ -struct cfg80211_beacon_data { - const u8 *head, *tail; - const u8 *beacon_ies; - const u8 *proberesp_ies; - const u8 *assocresp_ies; - const u8 *probe_resp; - - size_t head_len, tail_len; - size_t beacon_ies_len; - size_t proberesp_ies_len; - size_t assocresp_ies_len; - size_t probe_resp_len; -}; - -/** - * struct cfg80211_ap_settings - AP configuration - * - * Used to configure an AP interface. - * - * @beacon: beacon data - * @beacon_interval: beacon interval - * @dtim_period: DTIM period - * @ssid: SSID to be used in the BSS (note: may be %NULL if not provided from - * user space) - * @ssid_len: length of @ssid - * @hidden_ssid: whether to hide the SSID in Beacon/Probe Response frames - * @crypto: crypto settings - * @privacy: the BSS uses privacy - * @auth_type: Authentication type (algorithm) - */ -struct cfg80211_ap_settings { - struct cfg80211_beacon_data beacon; - - int beacon_interval, dtim_period; +struct beacon_parameters { + u8 *head, *tail; + int interval, dtim_period; + int head_len, tail_len; const u8 *ssid; size_t ssid_len; enum nl80211_hidden_ssid hidden_ssid; struct cfg80211_crypto_settings crypto; bool privacy; enum nl80211_auth_type auth_type; + const u8 *beacon_ies; + size_t beacon_ies_len; + const u8 *proberesp_ies; + size_t proberesp_ies_len; + const u8 *assocresp_ies; + size_t assocresp_ies_len; + int probe_resp_len; + u8 *probe_resp; }; /** @@ -1528,11 +1518,11 @@ struct cfg80211_ops { struct net_device *netdev, u8 key_index); - int (*start_ap)(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ap_settings *settings); - int (*change_beacon)(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_beacon_data *info); - int (*stop_ap)(struct wiphy *wiphy, struct net_device *dev); + int (*add_beacon)(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *info); + int (*set_beacon)(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *info); + int (*del_beacon)(struct wiphy *wiphy, struct net_device *dev); int (*add_station)(struct wiphy *wiphy, struct net_device *dev, diff --git a/trunk/net/mac80211/cfg.c b/trunk/net/mac80211/cfg.c index f7eb25aabf8f..c3de921c8cfd 100644 --- a/trunk/net/mac80211/cfg.c +++ b/trunk/net/mac80211/cfg.c @@ -489,13 +489,27 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, return ret; } +static void ieee80211_config_ap_ssid(struct ieee80211_sub_if_data *sdata, + struct beacon_parameters *params) +{ + struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; + + bss_conf->ssid_len = params->ssid_len; + + if (params->ssid_len) + memcpy(bss_conf->ssid, params->ssid, params->ssid_len); + + bss_conf->hidden_ssid = + (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); +} + static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, - const u8 *resp, size_t resp_len) + u8 *resp, size_t resp_len) { struct sk_buff *new, *old; if (!resp || !resp_len) - return 1; + return -EINVAL; old = rtnl_dereference(sdata->u.ap.probe_resp); @@ -506,28 +520,50 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, memcpy(skb_put(new, resp_len), resp, resp_len); rcu_assign_pointer(sdata->u.ap.probe_resp, new); - if (old) { - /* TODO: use call_rcu() */ - synchronize_rcu(); + synchronize_rcu(); + + if (old) dev_kfree_skb(old); - } return 0; } -static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, - struct cfg80211_beacon_data *params) +/* + * This handles both adding a beacon and setting new beacon info + */ +static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, + struct beacon_parameters *params) { struct beacon_data *new, *old; int new_head_len, new_tail_len; - int size, err; - u32 changed = BSS_CHANGED_BEACON; + int size; + int err = -EINVAL; + u32 changed = 0; old = rtnl_dereference(sdata->u.ap.beacon); + /* head must not be zero-length */ + if (params->head && !params->head_len) + return -EINVAL; + + /* + * This is a kludge. beacon interval should really be part + * of the beacon information. + */ + if (params->interval && + (sdata->vif.bss_conf.beacon_int != params->interval)) { + sdata->vif.bss_conf.beacon_int = params->interval; + ieee80211_bss_info_change_notify(sdata, + BSS_CHANGED_BEACON_INT); + } + /* Need to have a beacon head if we don't have one yet */ if (!params->head && !old) - return -EINVAL; + return err; + + /* sorry, no way to start beaconing without dtim period */ + if (!params->dtim_period && !old) + return err; /* new or old head? */ if (params->head) @@ -550,6 +586,12 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, /* start filling the new info now */ + /* new or old dtim period? */ + if (params->dtim_period) + new->dtim_period = params->dtim_period; + else + new->dtim_period = old->dtim_period; + /* * pointers go into the block we allocated, * memory is | beacon_data | head | tail | @@ -572,37 +614,46 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, if (old) memcpy(new->tail, old->tail, new_tail_len); + sdata->vif.bss_conf.dtim_period = new->dtim_period; + + rcu_assign_pointer(sdata->u.ap.beacon, new); + + synchronize_rcu(); + + kfree(old); + err = ieee80211_set_probe_resp(sdata, params->probe_resp, params->probe_resp_len); - if (err < 0) - return err; - if (err == 0) + if (!err) changed |= BSS_CHANGED_AP_PROBE_RESP; - rcu_assign_pointer(sdata->u.ap.beacon, new); - - if (old) - kfree_rcu(old, rcu_head); + ieee80211_config_ap_ssid(sdata, params); + changed |= BSS_CHANGED_BEACON_ENABLED | + BSS_CHANGED_BEACON | + BSS_CHANGED_SSID; - return changed; + ieee80211_bss_info_change_notify(sdata, changed); + return 0; } -static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ap_settings *params) +static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *params) { - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); + struct ieee80211_sub_if_data *sdata; struct beacon_data *old; struct ieee80211_sub_if_data *vlan; - u32 changed = BSS_CHANGED_BEACON_INT | - BSS_CHANGED_BEACON_ENABLED | - BSS_CHANGED_BEACON | - BSS_CHANGED_SSID; - int err; + int ret; + + sdata = IEEE80211_DEV_TO_SUB_IF(dev); old = rtnl_dereference(sdata->u.ap.beacon); if (old) return -EALREADY; + ret = ieee80211_config_beacon(sdata, params); + if (ret) + return ret; + /* * Apply control port protocol, this allows us to * not encrypt dynamic WEP control frames. @@ -616,32 +667,14 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, params->crypto.control_port_no_encrypt; } - sdata->vif.bss_conf.beacon_int = params->beacon_interval; - sdata->vif.bss_conf.dtim_period = params->dtim_period; - - sdata->vif.bss_conf.ssid_len = params->ssid_len; - if (params->ssid_len) - memcpy(sdata->vif.bss_conf.ssid, params->ssid, - params->ssid_len); - sdata->vif.bss_conf.hidden_ssid = - (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE); - - err = ieee80211_assign_beacon(sdata, ¶ms->beacon); - if (err < 0) - return err; - changed |= err; - - ieee80211_bss_info_change_notify(sdata, changed); - return 0; } -static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_beacon_data *params) +static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *params) { struct ieee80211_sub_if_data *sdata; struct beacon_data *old; - int err; sdata = IEEE80211_DEV_TO_SUB_IF(dev); @@ -649,14 +682,10 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, if (!old) return -ENOENT; - err = ieee80211_assign_beacon(sdata, params); - if (err < 0) - return err; - ieee80211_bss_info_change_notify(sdata, err); - return 0; + return ieee80211_config_beacon(sdata, params); } -static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) +static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) { struct ieee80211_sub_if_data *sdata; struct beacon_data *old; @@ -668,11 +697,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) return -ENOENT; RCU_INIT_POINTER(sdata->u.ap.beacon, NULL); - - kfree_rcu(old, rcu_head); + synchronize_rcu(); + kfree(old); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); - return 0; } @@ -2671,9 +2699,9 @@ struct cfg80211_ops mac80211_config_ops = { .get_key = ieee80211_get_key, .set_default_key = ieee80211_config_default_key, .set_default_mgmt_key = ieee80211_config_default_mgmt_key, - .start_ap = ieee80211_start_ap, - .change_beacon = ieee80211_change_beacon, - .stop_ap = ieee80211_stop_ap, + .add_beacon = ieee80211_add_beacon, + .set_beacon = ieee80211_set_beacon, + .del_beacon = ieee80211_del_beacon, .add_station = ieee80211_add_station, .del_station = ieee80211_del_station, .change_station = ieee80211_change_station, diff --git a/trunk/net/mac80211/ieee80211_i.h b/trunk/net/mac80211/ieee80211_i.h index 67aed1eff135..74594f012cd3 100644 --- a/trunk/net/mac80211/ieee80211_i.h +++ b/trunk/net/mac80211/ieee80211_i.h @@ -228,7 +228,7 @@ struct ieee80211_rx_data { struct beacon_data { u8 *head, *tail; int head_len, tail_len; - struct rcu_head rcu_head; + int dtim_period; }; struct ieee80211_if_ap { diff --git a/trunk/net/mac80211/tx.c b/trunk/net/mac80211/tx.c index c6eadac9ca4e..1be0ca2b5936 100644 --- a/trunk/net/mac80211/tx.c +++ b/trunk/net/mac80211/tx.c @@ -2206,8 +2206,7 @@ void ieee80211_tx_pending(unsigned long data) /* functions for drivers to get certain frames */ -static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, - struct ieee80211_if_ap *bss, +static void ieee80211_beacon_add_tim(struct ieee80211_if_ap *bss, struct sk_buff *skb, struct beacon_data *beacon) { @@ -2224,7 +2223,7 @@ static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, IEEE80211_MAX_AID+1); if (bss->dtim_count == 0) - bss->dtim_count = sdata->vif.bss_conf.dtim_period - 1; + bss->dtim_count = beacon->dtim_period - 1; else bss->dtim_count--; @@ -2232,7 +2231,7 @@ static void ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, *pos++ = WLAN_EID_TIM; *pos++ = 4; *pos++ = bss->dtim_count; - *pos++ = sdata->vif.bss_conf.dtim_period; + *pos++ = beacon->dtim_period; if (bss->dtim_count == 0 && !skb_queue_empty(&bss->ps_bc_buf)) aid0 = 1; @@ -2325,14 +2324,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, * of the tim bitmap in mac80211 and the driver. */ if (local->tim_in_locked_section) { - ieee80211_beacon_add_tim(sdata, ap, skb, - beacon); + ieee80211_beacon_add_tim(ap, skb, beacon); } else { unsigned long flags; spin_lock_irqsave(&local->tim_lock, flags); - ieee80211_beacon_add_tim(sdata, ap, skb, - beacon); + ieee80211_beacon_add_tim(ap, skb, beacon); spin_unlock_irqrestore(&local->tim_lock, flags); } diff --git a/trunk/net/wireless/nl80211.c b/trunk/net/wireless/nl80211.c index 1998c3682774..fe2747653564 100644 --- a/trunk/net/wireless/nl80211.c +++ b/trunk/net/wireless/nl80211.c @@ -871,7 +871,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, CMD(add_virtual_intf, NEW_INTERFACE); CMD(change_virtual_intf, SET_INTERFACE); CMD(add_key, NEW_KEY); - CMD(start_ap, START_AP); + CMD(add_beacon, NEW_BEACON); CMD(add_station, NEW_STATION); CMD(add_mpath, NEW_MPATH); CMD(update_mesh_config, SET_MESH_CONFIG); @@ -2075,10 +2075,15 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) return err; } -static int nl80211_parse_beacon(struct genl_info *info, - struct cfg80211_beacon_data *bcn) +static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) { - bool haveinfo = false; + int (*call)(struct wiphy *wiphy, struct net_device *dev, + struct beacon_parameters *info); + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct net_device *dev = info->user_ptr[1]; + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct beacon_parameters params; + int haveinfo = 0, err; if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]) || !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]) || @@ -2086,183 +2091,149 @@ static int nl80211_parse_beacon(struct genl_info *info, !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_ASSOC_RESP])) return -EINVAL; - memset(bcn, 0, sizeof(*bcn)); + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) + return -EOPNOTSUPP; - if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { - bcn->head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); - bcn->head_len = nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]); - if (!bcn->head_len) + memset(¶ms, 0, sizeof(params)); + + switch (info->genlhdr->cmd) { + case NL80211_CMD_NEW_BEACON: + /* these are required for NEW_BEACON */ + if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] || + !info->attrs[NL80211_ATTR_DTIM_PERIOD] || + !info->attrs[NL80211_ATTR_BEACON_HEAD]) return -EINVAL; - haveinfo = true; + + params.interval = + nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); + params.dtim_period = + nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); + + err = cfg80211_validate_beacon_int(rdev, params.interval); + if (err) + return err; + + /* + * In theory, some of these attributes could be required for + * NEW_BEACON, but since they were not used when the command was + * originally added, keep them optional for old user space + * programs to work with drivers that do not need the additional + * information. + */ + if (info->attrs[NL80211_ATTR_SSID]) { + params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); + params.ssid_len = + nla_len(info->attrs[NL80211_ATTR_SSID]); + if (params.ssid_len == 0 || + params.ssid_len > IEEE80211_MAX_SSID_LEN) + return -EINVAL; + } + + if (info->attrs[NL80211_ATTR_HIDDEN_SSID]) { + params.hidden_ssid = nla_get_u32( + info->attrs[NL80211_ATTR_HIDDEN_SSID]); + if (params.hidden_ssid != + NL80211_HIDDEN_SSID_NOT_IN_USE && + params.hidden_ssid != + NL80211_HIDDEN_SSID_ZERO_LEN && + params.hidden_ssid != + NL80211_HIDDEN_SSID_ZERO_CONTENTS) + return -EINVAL; + } + + params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; + + if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { + params.auth_type = nla_get_u32( + info->attrs[NL80211_ATTR_AUTH_TYPE]); + if (!nl80211_valid_auth_type(params.auth_type)) + return -EINVAL; + } else + params.auth_type = NL80211_AUTHTYPE_AUTOMATIC; + + err = nl80211_crypto_settings(rdev, info, ¶ms.crypto, + NL80211_MAX_NR_CIPHER_SUITES); + if (err) + return err; + + call = rdev->ops->add_beacon; + break; + case NL80211_CMD_SET_BEACON: + call = rdev->ops->set_beacon; + break; + default: + WARN_ON(1); + return -EOPNOTSUPP; + } + + if (!call) + return -EOPNOTSUPP; + + if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { + params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); + params.head_len = + nla_len(info->attrs[NL80211_ATTR_BEACON_HEAD]); + haveinfo = 1; } if (info->attrs[NL80211_ATTR_BEACON_TAIL]) { - bcn->tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]); - bcn->tail_len = + params.tail = nla_data(info->attrs[NL80211_ATTR_BEACON_TAIL]); + params.tail_len = nla_len(info->attrs[NL80211_ATTR_BEACON_TAIL]); - haveinfo = true; + haveinfo = 1; } if (!haveinfo) return -EINVAL; if (info->attrs[NL80211_ATTR_IE]) { - bcn->beacon_ies = nla_data(info->attrs[NL80211_ATTR_IE]); - bcn->beacon_ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); + params.beacon_ies = nla_data(info->attrs[NL80211_ATTR_IE]); + params.beacon_ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); } if (info->attrs[NL80211_ATTR_IE_PROBE_RESP]) { - bcn->proberesp_ies = + params.proberesp_ies = nla_data(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); - bcn->proberesp_ies_len = + params.proberesp_ies_len = nla_len(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); } if (info->attrs[NL80211_ATTR_IE_ASSOC_RESP]) { - bcn->assocresp_ies = + params.assocresp_ies = nla_data(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); - bcn->assocresp_ies_len = + params.assocresp_ies_len = nla_len(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); } if (info->attrs[NL80211_ATTR_PROBE_RESP]) { - bcn->probe_resp = + params.probe_resp = nla_data(info->attrs[NL80211_ATTR_PROBE_RESP]); - bcn->probe_resp_len = + params.probe_resp_len = nla_len(info->attrs[NL80211_ATTR_PROBE_RESP]); } - return 0; -} - -static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) -{ - struct cfg80211_registered_device *rdev = info->user_ptr[0]; - struct net_device *dev = info->user_ptr[1]; - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_ap_settings params; - int err; - - if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && - dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) - return -EOPNOTSUPP; - - if (!rdev->ops->start_ap) - return -EOPNOTSUPP; - - if (wdev->beacon_interval) - return -EALREADY; - - memset(¶ms, 0, sizeof(params)); - - /* these are required for START_AP */ - if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] || - !info->attrs[NL80211_ATTR_DTIM_PERIOD] || - !info->attrs[NL80211_ATTR_BEACON_HEAD]) - return -EINVAL; - - err = nl80211_parse_beacon(info, ¶ms.beacon); - if (err) - return err; - - params.beacon_interval = - nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); - params.dtim_period = - nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); - - err = cfg80211_validate_beacon_int(rdev, params.beacon_interval); - if (err) - return err; - - /* - * In theory, some of these attributes should be required here - * but since they were not used when the command was originally - * added, keep them optional for old user space programs to let - * them continue to work with drivers that do not need the - * additional information -- drivers must check! - */ - if (info->attrs[NL80211_ATTR_SSID]) { - params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); - params.ssid_len = - nla_len(info->attrs[NL80211_ATTR_SSID]); - if (params.ssid_len == 0 || - params.ssid_len > IEEE80211_MAX_SSID_LEN) - return -EINVAL; - } - - if (info->attrs[NL80211_ATTR_HIDDEN_SSID]) { - params.hidden_ssid = nla_get_u32( - info->attrs[NL80211_ATTR_HIDDEN_SSID]); - if (params.hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE && - params.hidden_ssid != NL80211_HIDDEN_SSID_ZERO_LEN && - params.hidden_ssid != NL80211_HIDDEN_SSID_ZERO_CONTENTS) - return -EINVAL; - } - - params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; - - if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { - params.auth_type = nla_get_u32( - info->attrs[NL80211_ATTR_AUTH_TYPE]); - if (!nl80211_valid_auth_type(params.auth_type)) - return -EINVAL; - } else - params.auth_type = NL80211_AUTHTYPE_AUTOMATIC; - - err = nl80211_crypto_settings(rdev, info, ¶ms.crypto, - NL80211_MAX_NR_CIPHER_SUITES); - if (err) - return err; - - err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); - if (!err) - wdev->beacon_interval = params.beacon_interval; + err = call(&rdev->wiphy, dev, ¶ms); + if (!err && params.interval) + wdev->beacon_interval = params.interval; return err; } -static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info) -{ - struct cfg80211_registered_device *rdev = info->user_ptr[0]; - struct net_device *dev = info->user_ptr[1]; - struct wireless_dev *wdev = dev->ieee80211_ptr; - struct cfg80211_beacon_data params; - int err; - - if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && - dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) - return -EOPNOTSUPP; - - if (!rdev->ops->change_beacon) - return -EOPNOTSUPP; - - if (!wdev->beacon_interval) - return -EINVAL; - - err = nl80211_parse_beacon(info, ¶ms); - if (err) - return err; - - return rdev->ops->change_beacon(&rdev->wiphy, dev, ¶ms); -} - -static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info) +static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; struct net_device *dev = info->user_ptr[1]; struct wireless_dev *wdev = dev->ieee80211_ptr; int err; - if (!rdev->ops->stop_ap) + if (!rdev->ops->del_beacon) return -EOPNOTSUPP; if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) return -EOPNOTSUPP; - if (!wdev->beacon_interval) - return -ENOENT; - - err = rdev->ops->stop_ap(&rdev->wiphy, dev); + err = rdev->ops->del_beacon(&rdev->wiphy, dev); if (!err) wdev->beacon_interval = 0; return err; @@ -6386,23 +6357,23 @@ static struct genl_ops nl80211_ops[] = { .cmd = NL80211_CMD_SET_BEACON, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, - .doit = nl80211_set_beacon, + .doit = nl80211_addset_beacon, .internal_flags = NL80211_FLAG_NEED_NETDEV | NL80211_FLAG_NEED_RTNL, }, { - .cmd = NL80211_CMD_START_AP, + .cmd = NL80211_CMD_NEW_BEACON, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, - .doit = nl80211_start_ap, + .doit = nl80211_addset_beacon, .internal_flags = NL80211_FLAG_NEED_NETDEV | NL80211_FLAG_NEED_RTNL, }, { - .cmd = NL80211_CMD_STOP_AP, + .cmd = NL80211_CMD_DEL_BEACON, .policy = nl80211_policy, .flags = GENL_ADMIN_PERM, - .doit = nl80211_stop_ap, + .doit = nl80211_del_beacon, .internal_flags = NL80211_FLAG_NEED_NETDEV | NL80211_FLAG_NEED_RTNL, },