diff options
Diffstat (limited to 'drivers/net/wireless')
71 files changed, 1756 insertions, 840 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c index 2d3a5dd07a3f..1068a2a4494c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c @@ -445,6 +445,11 @@ brcmf_proto_bcdc_init_done(struct brcmf_pub *drvr) return 0; } +static void brcmf_proto_bcdc_debugfs_create(struct brcmf_pub *drvr) +{ + brcmf_fws_debugfs_create(drvr); +} + int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { struct brcmf_bcdc *bcdc; @@ -472,6 +477,7 @@ int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) drvr->proto->del_if = brcmf_proto_bcdc_del_if; drvr->proto->reset_if = brcmf_proto_bcdc_reset_if; drvr->proto->init_done = brcmf_proto_bcdc_init_done; + drvr->proto->debugfs_create = brcmf_proto_bcdc_debugfs_create; drvr->proto->pd = bcdc; drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c index 03aae6bc1838..372363a6e752 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/btcoex.c @@ -462,7 +462,7 @@ static void brcmf_btcoex_dhcp_end(struct brcmf_btcoex_info *btci) int brcmf_btcoex_set_mode(struct brcmf_cfg80211_vif *vif, enum brcmf_btcoex_mode mode, u16 duration) { - struct brcmf_cfg80211_info *cfg = wiphy_priv(vif->wdev.wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(vif->wdev.wiphy); struct brcmf_btcoex_info *btci = cfg->btcoex; struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h index 0b90a63bdeb1..27e693e93f21 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h @@ -88,7 +88,7 @@ struct brcmf_bus_ops { void (*wowl_config)(struct device *dev, bool enabled); size_t (*get_ramsize)(struct device *dev); int (*get_memdump)(struct device *dev, void *data, size_t len); - int (*get_fwname)(struct device *dev, uint chip, uint chiprev, + int (*get_fwname)(struct device *dev, const char *ext, unsigned char *fw_name); }; @@ -140,6 +140,7 @@ struct brcmf_bus_stats { * @always_use_fws_queue: bus wants use queue also when fwsignal is inactive. * @wowl_supported: is wowl supported by bus driver. * @chiprev: revision of the dongle chip. + * @msgbuf: msgbuf protocol parameters provided by bus layer. */ struct brcmf_bus { union { @@ -228,10 +229,10 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len) } static inline -int brcmf_bus_get_fwname(struct brcmf_bus *bus, uint chip, uint chiprev, +int brcmf_bus_get_fwname(struct brcmf_bus *bus, const char *ext, unsigned char *fw_name) { - return bus->ops->get_fwname(bus->dev, chip, chiprev, fw_name); + return bus->ops->get_fwname(bus->dev, ext, fw_name); } /* diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 74a83020c073..89b86251910e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -753,7 +753,7 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy, struct wireless_dev *wdev) { - struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct net_device *ndev = wdev->netdev; struct brcmf_if *ifp = netdev_priv(ndev); int ret; @@ -786,7 +786,7 @@ err_unarm: static int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) { - struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct net_device *ndev = wdev->netdev; if (ndev && ndev == cfg_to_ndev(cfg)) @@ -831,7 +831,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, enum nl80211_iftype type, struct vif_params *params) { - struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_cfg80211_vif *vif = ifp->vif; s32 infra = 0; @@ -2127,17 +2127,15 @@ static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, s32 *dbm) { - struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); - struct net_device *ndev = cfg_to_ndev(cfg); - struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_cfg80211_vif *vif = wdev_to_vif(wdev); s32 qdbm = 0; s32 err; brcmf_dbg(TRACE, "Enter\n"); - if (!check_vif_up(ifp->vif)) + if (!check_vif_up(vif)) return -EIO; - err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &qdbm); + err = brcmf_fil_iovar_int_get(vif->ifp, "qtxpower", &qdbm); if (err) { brcmf_err("error (%d)\n", err); goto done; @@ -3358,7 +3356,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, struct cfg80211_sched_scan_request *req) { struct brcmf_if *ifp = netdev_priv(ndev); - struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); brcmf_dbg(SCAN, "Enter: n_match_sets=%d n_ssids=%d\n", req->n_match_sets, req->n_ssids); @@ -5190,6 +5188,12 @@ static struct cfg80211_ops brcmf_cfg80211_ops = { .del_pmk = brcmf_cfg80211_del_pmk, }; +struct cfg80211_ops *brcmf_cfg80211_get_ops(void) +{ + return kmemdup(&brcmf_cfg80211_ops, sizeof(brcmf_cfg80211_ops), + GFP_KERNEL); +} + struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, enum nl80211_iftype type) { @@ -5897,7 +5901,7 @@ static void brcmf_update_bw40_channel_flag(struct ieee80211_channel *channel, static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg, u32 bw_cap[]) { - struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); + struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); struct ieee80211_supported_band *band; struct ieee80211_channel *channel; struct wiphy *wiphy; @@ -6012,7 +6016,7 @@ fail_pbuf: static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) { - struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); + struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); struct ieee80211_supported_band *band; struct brcmf_fil_bwcap_le band_bwcap; struct brcmf_chanspec_list *list; @@ -6197,10 +6201,10 @@ static void brcmf_update_vht_cap(struct ieee80211_supported_band *band, } } -static int brcmf_setup_wiphybands(struct wiphy *wiphy) +static int brcmf_setup_wiphybands(struct brcmf_cfg80211_info *cfg) { - struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); - struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); + struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); + struct wiphy *wiphy; u32 nmode = 0; u32 vhtmode = 0; u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT }; @@ -6794,8 +6798,8 @@ static s32 brcmf_translate_country_code(struct brcmf_pub *drvr, char alpha2[2], static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *req) { - struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); - struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_if *ifp = brcmf_get_ifp(cfg->pub, 0); struct brcmf_fil_country_le ccreq; s32 err; int i; @@ -6805,7 +6809,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, return; /* ignore non-ISO3166 country codes */ - for (i = 0; i < sizeof(req->alpha2); i++) + for (i = 0; i < 2; i++) if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') { brcmf_err("not an ISO3166 code (0x%02x 0x%02x)\n", req->alpha2[0], req->alpha2[1]); @@ -6830,7 +6834,7 @@ static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy, brcmf_err("Firmware rejected country setting\n"); return; } - brcmf_setup_wiphybands(wiphy); + brcmf_setup_wiphybands(cfg); } static void brcmf_free_wiphy(struct wiphy *wiphy) @@ -6857,17 +6861,15 @@ static void brcmf_free_wiphy(struct wiphy *wiphy) if (wiphy->wowlan != &brcmf_wowlan_support) kfree(wiphy->wowlan); #endif - wiphy_free(wiphy); } struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, - struct device *busdev, + struct cfg80211_ops *ops, bool p2pdev_forced) { + struct wiphy *wiphy = drvr->wiphy; struct net_device *ndev = brcmf_get_ifp(drvr, 0)->ndev; struct brcmf_cfg80211_info *cfg; - struct wiphy *wiphy; - struct cfg80211_ops *ops; struct brcmf_cfg80211_vif *vif; struct brcmf_if *ifp; s32 err = 0; @@ -6879,26 +6881,13 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, return NULL; } - ops = kmemdup(&brcmf_cfg80211_ops, sizeof(*ops), GFP_KERNEL); - if (!ops) - return NULL; - - ifp = netdev_priv(ndev); -#ifdef CONFIG_PM - if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) - ops->set_rekey_data = brcmf_cfg80211_set_rekey_data; -#endif - wiphy = wiphy_new(ops, sizeof(struct brcmf_cfg80211_info)); - if (!wiphy) { + cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); + if (!cfg) { brcmf_err("Could not allocate wiphy device\n"); - goto ops_out; + return NULL; } - memcpy(wiphy->perm_addr, drvr->mac, ETH_ALEN); - set_wiphy_dev(wiphy, busdev); - cfg = wiphy_priv(wiphy); cfg->wiphy = wiphy; - cfg->ops = ops; cfg->pub = drvr; init_vif_event(&cfg->vif_event); INIT_LIST_HEAD(&cfg->vif_list); @@ -6907,6 +6896,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, if (IS_ERR(vif)) goto wiphy_out; + ifp = netdev_priv(ndev); vif->ifp = ifp; vif->wdev.netdev = ndev; ndev->ieee80211_ptr = &vif->wdev; @@ -6933,6 +6923,11 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, if (err < 0) goto priv_out; + /* regulatory notifer below needs access to cfg so + * assign it now. + */ + drvr->config = cfg; + brcmf_dbg(INFO, "Registering custom regulatory\n"); wiphy->reg_notifier = brcmf_cfg80211_reg_notifier; wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; @@ -6946,13 +6941,17 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, cap = &wiphy->bands[NL80211_BAND_2GHZ]->ht_cap.cap; *cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; } +#ifdef CONFIG_PM + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) + ops->set_rekey_data = brcmf_cfg80211_set_rekey_data; +#endif err = wiphy_register(wiphy); if (err < 0) { brcmf_err("Could not register wiphy device (%d)\n", err); goto priv_out; } - err = brcmf_setup_wiphybands(wiphy); + err = brcmf_setup_wiphybands(cfg); if (err) { brcmf_err("Setting wiphy bands failed (%d)\n", err); goto wiphy_unreg_out; @@ -6969,12 +6968,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, else *cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; } - /* p2p might require that "if-events" get processed by fweh. So - * activate the already registered event handlers now and activate - * the rest when initialization has completed. drvr->config needs to - * be assigned before activating events. - */ - drvr->config = cfg; + err = brcmf_fweh_activate_events(ifp); if (err) { brcmf_err("FWEH activation failed (%d)\n", err); @@ -7042,8 +7036,7 @@ priv_out: ifp->vif = NULL; wiphy_out: brcmf_free_wiphy(wiphy); -ops_out: - kfree(ops); + kfree(cfg); return NULL; } @@ -7058,4 +7051,5 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) kfree(cfg->ops); wl_deinit_priv(cfg); brcmf_free_wiphy(cfg->wiphy); + kfree(cfg); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h index b5b5f0f10b63..a4aec0004e4f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h @@ -355,20 +355,24 @@ static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg) static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w) { - return (struct brcmf_cfg80211_info *)(wiphy_priv(w)); + struct brcmf_pub *drvr = wiphy_priv(w); + return drvr->config; } static inline struct brcmf_cfg80211_info *wdev_to_cfg(struct wireless_dev *wd) { - return (struct brcmf_cfg80211_info *)(wdev_priv(wd)); + return wiphy_to_cfg(wd->wiphy); +} + +static inline struct brcmf_cfg80211_vif *wdev_to_vif(struct wireless_dev *wdev) +{ + return container_of(wdev, struct brcmf_cfg80211_vif, wdev); } static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg) { - struct brcmf_cfg80211_vif *vif; - vif = list_first_entry(&cfg->vif_list, struct brcmf_cfg80211_vif, list); - return vif->wdev.netdev; + return brcmf_get_ifp(cfg->pub, 0)->ndev; } static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev) @@ -395,11 +399,12 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg) } struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, - struct device *busdev, + struct cfg80211_ops *ops, bool p2pdev_forced); void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); s32 brcmf_cfg80211_up(struct net_device *ndev); s32 brcmf_cfg80211_down(struct net_device *ndev); +struct cfg80211_ops *brcmf_cfg80211_get_ops(void); enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp); struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index f7b30ce2300d..3b829fed8631 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -464,12 +464,12 @@ static void brcmf_chip_ai_resetcore(struct brcmf_core_priv *core, u32 prereset, ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL); } -static char *brcmf_chip_name(uint chipid, char *buf, uint len) +char *brcmf_chip_name(u32 id, u32 rev, char *buf, uint len) { const char *fmt; - fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x"; - snprintf(buf, len, fmt, chipid); + fmt = ((id > 0xa000) || (id < 0x4000)) ? "BCM%d/%u" : "BCM%x/%u"; + snprintf(buf, len, fmt, id, rev); return buf; } @@ -924,10 +924,10 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; - brcmf_chip_name(ci->pub.chip, ci->pub.name, sizeof(ci->pub.name)); - brcmf_dbg(INFO, "found %s chip: BCM%s, rev=%d\n", - socitype == SOCI_SB ? "SB" : "AXI", ci->pub.name, - ci->pub.chiprev); + brcmf_chip_name(ci->pub.chip, ci->pub.chiprev, + ci->pub.name, sizeof(ci->pub.name)); + brcmf_dbg(INFO, "found %s chip: %s\n", + socitype == SOCI_SB ? "SB" : "AXI", ci->pub.name); if (socitype == SOCI_SB) { if (ci->pub.chip != BRCM_CC_4329_CHIP_ID) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h index dd0ec3eba6a9..0ae3b33bab62 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h @@ -45,7 +45,7 @@ struct brcmf_chip { u32 rambase; u32 ramsize; u32 srsize; - char name[8]; + char name[12]; }; /** @@ -93,5 +93,6 @@ void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset, void brcmf_chip_set_passive(struct brcmf_chip *ci); bool brcmf_chip_set_active(struct brcmf_chip *ci, u32 rstvec); bool brcmf_chip_sr_capable(struct brcmf_chip *pub); +char *brcmf_chip_name(u32 chipid, u32 chiprev, char *buf, uint len); #endif /* BRCMF_AXIDMP_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c index 74f7b56bc7d4..105b8774fca9 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -30,6 +30,7 @@ #include "common.h" #include "of.h" #include "firmware.h" +#include "chip.h" MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom 802.11 wireless LAN fullmac driver."); @@ -75,6 +76,10 @@ static int brcmf_roamoff; module_param_named(roamoff, brcmf_roamoff, int, 0400); MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine"); +static int brcmf_iapp_enable; +module_param_named(iapp, brcmf_iapp_enable, int, 0); +MODULE_PARM_DESC(iapp, "Enable partial support for the obsoleted Inter-Access Point Protocol"); + #ifdef DEBUG /* always succeed brcmf_bus_started() */ static int brcmf_ignore_probe_fail; @@ -124,43 +129,9 @@ static int brcmf_c_download(struct brcmf_if *ifp, u16 flag, return err; } -static int brcmf_c_get_clm_name(struct brcmf_if *ifp, u8 *clm_name) -{ - struct brcmf_bus *bus = ifp->drvr->bus_if; - struct brcmf_rev_info *ri = &ifp->drvr->revinfo; - u8 fw_name[BRCMF_FW_NAME_LEN]; - u8 *ptr; - size_t len; - s32 err; - - memset(fw_name, 0, BRCMF_FW_NAME_LEN); - err = brcmf_bus_get_fwname(bus, ri->chipnum, ri->chiprev, fw_name); - if (err) { - brcmf_err("get firmware name failed (%d)\n", err); - goto done; - } - - /* generate CLM blob file name */ - ptr = strrchr(fw_name, '.'); - if (!ptr) { - err = -ENOENT; - goto done; - } - - len = ptr - fw_name + 1; - if (len + strlen(".clm_blob") > BRCMF_FW_NAME_LEN) { - err = -E2BIG; - } else { - strlcpy(clm_name, fw_name, len); - strlcat(clm_name, ".clm_blob", BRCMF_FW_NAME_LEN); - } -done: - return err; -} - static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) { - struct device *dev = ifp->drvr->bus_if->dev; + struct brcmf_bus *bus = ifp->drvr->bus_if; struct brcmf_dload_data_le *chunk_buf; const struct firmware *clm = NULL; u8 clm_name[BRCMF_FW_NAME_LEN]; @@ -173,16 +144,16 @@ static int brcmf_c_process_clm_blob(struct brcmf_if *ifp) brcmf_dbg(TRACE, "Enter\n"); - memset(clm_name, 0, BRCMF_FW_NAME_LEN); - err = brcmf_c_get_clm_name(ifp, clm_name); + memset(clm_name, 0, sizeof(clm_name)); + err = brcmf_bus_get_fwname(bus, ".clm_blob", clm_name); if (err) { brcmf_err("get CLM blob file name failed (%d)\n", err); return err; } - err = request_firmware(&clm, clm_name, dev); + err = request_firmware(&clm, clm_name, bus->dev); if (err) { - brcmf_info("no clm_blob available(err=%d), device may have limited channels available\n", + brcmf_info("no clm_blob available (err=%d), device may have limited channels available\n", err); return 0; } @@ -234,6 +205,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) { s8 eventmask[BRCMF_EVENTING_MASK_LEN]; u8 buf[BRCMF_DCMD_SMLEN]; + struct brcmf_bus *bus; struct brcmf_rev_info_le revinfo; struct brcmf_rev_info *ri; char *clmver; @@ -247,18 +219,21 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) brcmf_err("Retreiving cur_etheraddr failed, %d\n", err); goto done; } + memcpy(ifp->drvr->wiphy->perm_addr, ifp->drvr->mac, ETH_ALEN); memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); + bus = ifp->drvr->bus_if; + ri = &ifp->drvr->revinfo; + err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_REVINFO, &revinfo, sizeof(revinfo)); - ri = &ifp->drvr->revinfo; if (err < 0) { brcmf_err("retrieving revision info failed, %d\n", err); + strlcpy(ri->chipname, "UNKNOWN", sizeof(ri->chipname)); } else { ri->vendorid = le32_to_cpu(revinfo.vendorid); ri->deviceid = le32_to_cpu(revinfo.deviceid); ri->radiorev = le32_to_cpu(revinfo.radiorev); - ri->chiprev = le32_to_cpu(revinfo.chiprev); ri->corerev = le32_to_cpu(revinfo.corerev); ri->boardid = le32_to_cpu(revinfo.boardid); ri->boardvendor = le32_to_cpu(revinfo.boardvendor); @@ -266,15 +241,24 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) ri->driverrev = le32_to_cpu(revinfo.driverrev); ri->ucoderev = le32_to_cpu(revinfo.ucoderev); ri->bus = le32_to_cpu(revinfo.bus); - ri->chipnum = le32_to_cpu(revinfo.chipnum); ri->phytype = le32_to_cpu(revinfo.phytype); ri->phyrev = le32_to_cpu(revinfo.phyrev); ri->anarev = le32_to_cpu(revinfo.anarev); ri->chippkg = le32_to_cpu(revinfo.chippkg); ri->nvramrev = le32_to_cpu(revinfo.nvramrev); + + /* use revinfo if not known yet */ + if (!bus->chip) { + bus->chip = le32_to_cpu(revinfo.chipnum); + bus->chiprev = le32_to_cpu(revinfo.chiprev); + } } ri->result = err; + if (bus->chip) + brcmf_chip_name(bus->chip, bus->chiprev, + ri->chipname, sizeof(ri->chipname)); + /* Do any CLM downloading */ err = brcmf_c_process_clm_blob(ifp); if (err < 0) { @@ -295,7 +279,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) strsep(&ptr, "\n"); /* Print fw version info */ - brcmf_info("Firmware version = %s\n", buf); + brcmf_info("Firmware: %s %s\n", ri->chipname, buf); /* locate firmware version number for ethtool */ ptr = strrchr(buf, ' ') + 1; @@ -438,6 +422,7 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, settings->feature_disable = brcmf_feature_disable; settings->fcmode = brcmf_fcmode; settings->roamoff = !!brcmf_roamoff; + settings->iapp = !!brcmf_iapp_enable; #ifdef DEBUG settings->ignore_probe_fail = !!brcmf_ignore_probe_fail; #endif @@ -511,9 +496,6 @@ static int __init brcmfmac_module_init(void) { int err; - /* Initialize debug system first */ - brcmf_debugfs_init(); - /* Get the platform data (if available) for our devices */ err = platform_driver_probe(&brcmf_pd, brcmf_common_pd_probe); if (err == -ENODEV) @@ -525,7 +507,6 @@ static int __init brcmfmac_module_init(void) /* Continue the initialization by registering the different busses */ err = brcmf_core_init(); if (err) { - brcmf_debugfs_exit(); if (brcmfmac_pdata) platform_driver_unregister(&brcmf_pd); } @@ -538,7 +519,6 @@ static void __exit brcmfmac_module_exit(void) brcmf_core_exit(); if (brcmfmac_pdata) platform_driver_unregister(&brcmf_pd); - brcmf_debugfs_exit(); } module_init(brcmfmac_module_init); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h index a62f8e70b320..ef914619e8e1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h @@ -58,6 +58,7 @@ struct brcmf_mp_device { unsigned int feature_disable; int fcmode; bool roamoff; + bool iapp; bool ignore_probe_fail; struct brcmfmac_pd_cc *country_codes; union { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 19048526b4af..8d4511eaa9b9 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -230,6 +230,37 @@ static void brcmf_netdev_set_multicast_list(struct net_device *ndev) schedule_work(&ifp->multicast_work); } +/** + * brcmf_skb_is_iapp - checks if skb is an IAPP packet + * + * @skb: skb to check + */ +static bool brcmf_skb_is_iapp(struct sk_buff *skb) +{ + static const u8 iapp_l2_update_packet[6] __aligned(2) = { + 0x00, 0x01, 0xaf, 0x81, 0x01, 0x00, + }; + unsigned char *eth_data; +#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) + const u16 *a, *b; +#endif + + if (skb->len - skb->mac_len != 6 || + !is_multicast_ether_addr(eth_hdr(skb)->h_dest)) + return false; + + eth_data = skb_mac_header(skb) + ETH_HLEN; +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) + return !(((*(const u32 *)eth_data) ^ (*(const u32 *)iapp_l2_update_packet)) | + ((*(const u16 *)(eth_data + 4)) ^ (*(const u16 *)(iapp_l2_update_packet + 4)))); +#else + a = (const u16 *)eth_data; + b = (const u16 *)iapp_l2_update_packet; + + return !((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])); +#endif +} + static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) { @@ -250,6 +281,23 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb, goto done; } + /* Some recent Broadcom's firmwares disassociate STA when they receive + * an 802.11f ADD frame. This behavior can lead to a local DoS security + * issue. Attacker may trigger disassociation of any STA by sending a + * proper Ethernet frame to the wireless interface. + * + * Moreover this feature may break AP interfaces in some specific + * setups. This applies e.g. to the bridge with hairpin mode enabled and + * IFLA_BRPORT_MCAST_TO_UCAST set. IAPP packet generated by a firmware + * will get passed back to the wireless interface and cause immediate + * disassociation of a just-connected STA. + */ + if (!drvr->settings->iapp && brcmf_skb_is_iapp(skb)) { + dev_kfree_skb(skb); + ret = -EINVAL; + goto done; + } + /* Make sure there's enough writeable headroom */ if (skb_headroom(skb) < drvr->hdrlen || skb_header_cloned(skb)) { head_delta = max_t(int, drvr->hdrlen - skb_headroom(skb), 0); @@ -325,6 +373,15 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp, void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb) { + /* Most of Broadcom's firmwares send 802.11f ADD frame every time a new + * STA connects to the AP interface. This is an obsoleted standard most + * users don't use, so don't pass these frames up unless requested. + */ + if (!ifp->drvr->settings->iapp && brcmf_skb_is_iapp(skb)) { + brcmu_pkt_buf_free_skb(skb); + return; + } + if (skb->pkt_type == PACKET_MULTICAST) ifp->ndev->stats.multicast++; @@ -924,8 +981,7 @@ static int brcmf_revinfo_read(struct seq_file *s, void *data) seq_printf(s, "vendorid: 0x%04x\n", ri->vendorid); seq_printf(s, "deviceid: 0x%04x\n", ri->deviceid); seq_printf(s, "radiorev: %s\n", brcmu_dotrev_str(ri->radiorev, drev)); - seq_printf(s, "chipnum: %u (%x)\n", ri->chipnum, ri->chipnum); - seq_printf(s, "chiprev: %u\n", ri->chiprev); + seq_printf(s, "chip: %s\n", ri->chipname); seq_printf(s, "chippkg: %u\n", ri->chippkg); seq_printf(s, "corerev: %u\n", ri->corerev); seq_printf(s, "boardid: 0x%04x\n", ri->boardid); @@ -944,7 +1000,7 @@ static int brcmf_revinfo_read(struct seq_file *s, void *data) return 0; } -static int brcmf_bus_started(struct brcmf_pub *drvr) +static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops) { int ret = -1; struct brcmf_bus *bus_if = drvr->bus_if; @@ -973,15 +1029,6 @@ static int brcmf_bus_started(struct brcmf_pub *drvr) if (ret < 0) goto fail; - brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read); - - /* assure we have chipid before feature attach */ - if (!bus_if->chip) { - bus_if->chip = drvr->revinfo.chipnum; - bus_if->chiprev = drvr->revinfo.chiprev; - brcmf_dbg(INFO, "firmware revinfo: chip %x (%d) rev %d\n", - bus_if->chip, bus_if->chip, bus_if->chiprev); - } brcmf_feat_attach(drvr); ret = brcmf_proto_init_done(drvr); @@ -990,7 +1037,7 @@ static int brcmf_bus_started(struct brcmf_pub *drvr) brcmf_proto_add_if(drvr, ifp); - drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev, + drvr->config = brcmf_cfg80211_attach(drvr, ops, drvr->settings->p2p_enable); if (drvr->config == NULL) { ret = -ENOMEM; @@ -1024,6 +1071,11 @@ static int brcmf_bus_started(struct brcmf_pub *drvr) #endif #endif /* CONFIG_INET */ + /* populate debugfs */ + brcmf_debugfs_add_entry(drvr, "revinfo", brcmf_revinfo_read); + brcmf_feat_debugfs_create(drvr); + brcmf_proto_debugfs_create(drvr); + return 0; fail: @@ -1045,17 +1097,26 @@ fail: int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings) { + struct wiphy *wiphy; + struct cfg80211_ops *ops; struct brcmf_pub *drvr = NULL; int ret = 0; int i; brcmf_dbg(TRACE, "Enter\n"); - /* Allocate primary brcmf_info */ - drvr = kzalloc(sizeof(*drvr), GFP_ATOMIC); - if (!drvr) + ops = brcmf_cfg80211_get_ops(); + if (!ops) + return -ENOMEM; + + wiphy = wiphy_new(ops, sizeof(*drvr)); + if (!wiphy) return -ENOMEM; + set_wiphy_dev(wiphy, dev); + drvr = wiphy_priv(wiphy); + drvr->wiphy = wiphy; + for (i = 0; i < ARRAY_SIZE(drvr->if2bss); i++) drvr->if2bss[i] = BRCMF_BSSIDX_INVALID; @@ -1067,9 +1128,6 @@ int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings) drvr->bus_if->drvr = drvr; drvr->settings = settings; - /* attach debug facilities */ - brcmf_debug_attach(drvr); - /* Attach and link in the protocol */ ret = brcmf_proto_attach(drvr); if (ret != 0) { @@ -1084,15 +1142,18 @@ int brcmf_attach(struct device *dev, struct brcmf_mp_device *settings) /* attach firmware event handler */ brcmf_fweh_attach(drvr); - ret = brcmf_bus_started(drvr); + ret = brcmf_bus_started(drvr, ops); if (ret != 0) { brcmf_err("dongle is not responding: err=%d\n", ret); goto fail; } + + drvr->config->ops = ops; return 0; fail: brcmf_detach(dev); + kfree(ops); return ret; } @@ -1150,14 +1211,14 @@ void brcmf_detach(struct device *dev) brcmf_remove_interface(drvr->iflist[i], false); brcmf_cfg80211_detach(drvr->config); + drvr->config = NULL; brcmf_bus_stop(drvr->bus_if); brcmf_proto_detach(drvr); - brcmf_debug_detach(drvr); bus_if->drvr = NULL; - kfree(drvr); + wiphy_free(drvr->wiphy); } s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index 232dcbb83311..401f50458686 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -87,7 +87,6 @@ struct brcmf_rev_info { u32 vendorid; u32 deviceid; u32 radiorev; - u32 chiprev; u32 corerev; u32 boardid; u32 boardvendor; @@ -95,7 +94,7 @@ struct brcmf_rev_info { u32 driverrev; u32 ucoderev; u32 bus; - u32 chipnum; + char chipname[12]; u32 phytype; u32 phyrev; u32 anarev; @@ -108,6 +107,7 @@ struct brcmf_pub { /* Linkage ponters */ struct brcmf_bus *bus_if; struct brcmf_proto *proto; + struct wiphy *wiphy; struct brcmf_cfg80211_info *config; /* Internal brcmf items */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c index 2d3e5e263a32..504832084eca 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c @@ -25,8 +25,6 @@ #include "fweh.h" #include "debug.h" -static struct dentry *root_folder; - int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data, size_t len) { @@ -54,44 +52,9 @@ int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data, return 0; } -void brcmf_debugfs_init(void) -{ - root_folder = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (IS_ERR(root_folder)) - root_folder = NULL; -} - -void brcmf_debugfs_exit(void) -{ - if (!root_folder) - return; - - debugfs_remove_recursive(root_folder); - root_folder = NULL; -} - -int brcmf_debug_attach(struct brcmf_pub *drvr) -{ - struct device *dev = drvr->bus_if->dev; - - if (!root_folder) - return -ENODEV; - - drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); - return PTR_ERR_OR_ZERO(drvr->dbgfs_dir); -} - -void brcmf_debug_detach(struct brcmf_pub *drvr) -{ - brcmf_fweh_unregister(drvr, BRCMF_E_PSM_WATCHDOG); - - if (!IS_ERR_OR_NULL(drvr->dbgfs_dir)) - debugfs_remove_recursive(drvr->dbgfs_dir); -} - struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr) { - return drvr->dbgfs_dir; + return drvr->wiphy->debugfsdir; } int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, @@ -99,7 +62,8 @@ int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, { struct dentry *e; + WARN(!drvr->wiphy->debugfsdir, "wiphy not (yet) registered\n"); e = debugfs_create_devm_seqfile(drvr->bus_if->dev, fn, - drvr->dbgfs_dir, read_fn); + drvr->wiphy->debugfsdir, read_fn); return PTR_ERR_OR_ZERO(e); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h index 35919d9e8e13..cfed0626bf5a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h @@ -113,29 +113,12 @@ extern int brcmf_msg_level; struct brcmf_bus; struct brcmf_pub; #ifdef DEBUG -void brcmf_debugfs_init(void); -void brcmf_debugfs_exit(void); -int brcmf_debug_attach(struct brcmf_pub *drvr); -void brcmf_debug_detach(struct brcmf_pub *drvr); struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, int (*read_fn)(struct seq_file *seq, void *data)); int brcmf_debug_create_memdump(struct brcmf_bus *bus, const void *data, size_t len); #else -static inline void brcmf_debugfs_init(void) -{ -} -static inline void brcmf_debugfs_exit(void) -{ -} -static inline int brcmf_debug_attach(struct brcmf_pub *drvr) -{ - return 0; -} -static inline void brcmf_debug_detach(struct brcmf_pub *drvr) -{ -} static inline int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, int (*read_fn)(struct seq_file *seq, void *data)) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c index bede7b7fd996..876731c57bf5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c @@ -228,7 +228,10 @@ void brcmf_feat_attach(struct brcmf_pub *drvr) /* no quirks */ break; } +} +void brcmf_feat_debugfs_create(struct brcmf_pub *drvr) +{ brcmf_debugfs_add_entry(drvr, "features", brcmf_feat_debugfs_read); } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h index 1ab4f1617112..d1193825e559 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h @@ -90,6 +90,13 @@ enum brcmf_feat_quirk { void brcmf_feat_attach(struct brcmf_pub *drvr); /** + * brcmf_feat_debugfs_create() - create debugfs entries. + * + * @drvr: driver instance. + */ +void brcmf_feat_debugfs_create(struct brcmf_pub *drvr); + +/** * brcmf_feat_is_enabled() - query feature. * * @ifp: interface instance. diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c index 091b52979e03..9277f4c2bfeb 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c @@ -25,6 +25,7 @@ #include "firmware.h" #include "core.h" #include "common.h" +#include "chip.h" #define BRCMF_FW_MAX_NVRAM_SIZE 64000 #define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */ @@ -437,18 +438,31 @@ void brcmf_fw_nvram_free(void *nvram) struct brcmf_fw { struct device *dev; - u16 flags; - const struct firmware *code; - const char *nvram_name; - u16 domain_nr; - u16 bus_nr; - void (*done)(struct device *dev, int err, const struct firmware *fw, - void *nvram_image, u32 nvram_len); + struct brcmf_fw_request *req; + u32 curpos; + void (*done)(struct device *dev, int err, struct brcmf_fw_request *req); }; +static void brcmf_fw_request_done(const struct firmware *fw, void *ctx); + +static void brcmf_fw_free_request(struct brcmf_fw_request *req) +{ + struct brcmf_fw_item *item; + int i; + + for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) { + if (item->type == BRCMF_FW_TYPE_BINARY) + release_firmware(item->binary); + else if (item->type == BRCMF_FW_TYPE_NVRAM) + brcmf_fw_nvram_free(item->nv_data.data); + } + kfree(req); +} + static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) { struct brcmf_fw *fwctx = ctx; + struct brcmf_fw_item *cur; u32 nvram_length = 0; void *nvram = NULL; u8 *data = NULL; @@ -456,83 +470,150 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) bool raw_nvram; brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev)); + + cur = &fwctx->req->items[fwctx->curpos]; + if (fw && fw->data) { data = (u8 *)fw->data; data_len = fw->size; raw_nvram = false; } else { data = bcm47xx_nvram_get_contents(&data_len); - if (!data && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) + if (!data && !(cur->flags & BRCMF_FW_REQF_OPTIONAL)) goto fail; raw_nvram = true; } if (data) nvram = brcmf_fw_nvram_strip(data, data_len, &nvram_length, - fwctx->domain_nr, fwctx->bus_nr); + fwctx->req->domain_nr, + fwctx->req->bus_nr); if (raw_nvram) bcm47xx_nvram_release_contents(data); release_firmware(fw); - if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) + if (!nvram && !(cur->flags & BRCMF_FW_REQF_OPTIONAL)) goto fail; - fwctx->done(fwctx->dev, 0, fwctx->code, nvram, nvram_length); - kfree(fwctx); + brcmf_dbg(TRACE, "nvram %p len %d\n", nvram, nvram_length); + cur->nv_data.data = nvram; + cur->nv_data.len = nvram_length; return; fail: brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); - release_firmware(fwctx->code); - fwctx->done(fwctx->dev, -ENOENT, NULL, NULL, 0); + fwctx->done(fwctx->dev, -ENOENT, NULL); + brcmf_fw_free_request(fwctx->req); kfree(fwctx); } -static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx) +static int brcmf_fw_request_next_item(struct brcmf_fw *fwctx, bool async) +{ + struct brcmf_fw_item *cur; + const struct firmware *fw = NULL; + int ret; + + cur = &fwctx->req->items[fwctx->curpos]; + + brcmf_dbg(TRACE, "%srequest for %s\n", async ? "async " : "", + cur->path); + + if (async) + ret = request_firmware_nowait(THIS_MODULE, true, cur->path, + fwctx->dev, GFP_KERNEL, fwctx, + brcmf_fw_request_done); + else + ret = request_firmware(&fw, cur->path, fwctx->dev); + + if (ret < 0) { + brcmf_fw_request_done(NULL, fwctx); + } else if (!async && fw) { + brcmf_dbg(TRACE, "firmware %s %sfound\n", cur->path, + fw ? "" : "not "); + if (cur->type == BRCMF_FW_TYPE_BINARY) + cur->binary = fw; + else if (cur->type == BRCMF_FW_TYPE_NVRAM) + brcmf_fw_request_nvram_done(fw, fwctx); + else + release_firmware(fw); + + return -EAGAIN; + } + return 0; +} + +static void brcmf_fw_request_done(const struct firmware *fw, void *ctx) { struct brcmf_fw *fwctx = ctx; + struct brcmf_fw_item *cur; int ret = 0; - brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev)); - if (!fw) { + cur = &fwctx->req->items[fwctx->curpos]; + + brcmf_dbg(TRACE, "enter: firmware %s %sfound\n", cur->path, + fw ? "" : "not "); + + if (fw) { + if (cur->type == BRCMF_FW_TYPE_BINARY) + cur->binary = fw; + else if (cur->type == BRCMF_FW_TYPE_NVRAM) + brcmf_fw_request_nvram_done(fw, fwctx); + else + release_firmware(fw); + } else if (cur->type == BRCMF_FW_TYPE_NVRAM) { + brcmf_fw_request_nvram_done(NULL, fwctx); + } else if (!(cur->flags & BRCMF_FW_REQF_OPTIONAL)) { ret = -ENOENT; goto fail; } - /* only requested code so done here */ - if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) - goto done; - fwctx->code = fw; - ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name, - fwctx->dev, GFP_KERNEL, fwctx, - brcmf_fw_request_nvram_done); + do { + if (++fwctx->curpos == fwctx->req->n_items) { + ret = 0; + goto done; + } + + ret = brcmf_fw_request_next_item(fwctx, false); + } while (ret == -EAGAIN); - /* pass NULL to nvram callback for bcm47xx fallback */ - if (ret) - brcmf_fw_request_nvram_done(NULL, fwctx); return; fail: - brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); + brcmf_dbg(TRACE, "failed err=%d: dev=%s, fw=%s\n", ret, + dev_name(fwctx->dev), cur->path); + brcmf_fw_free_request(fwctx->req); + fwctx->req = NULL; done: - fwctx->done(fwctx->dev, ret, fw, NULL, 0); + fwctx->done(fwctx->dev, ret, fwctx->req); kfree(fwctx); } -int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, - const char *code, const char *nvram, - void (*fw_cb)(struct device *dev, int err, - const struct firmware *fw, - void *nvram_image, u32 nvram_len), - u16 domain_nr, u16 bus_nr) +static bool brcmf_fw_request_is_valid(struct brcmf_fw_request *req) +{ + struct brcmf_fw_item *item; + int i; + + if (!req->n_items) + return false; + + for (i = 0, item = &req->items[0]; i < req->n_items; i++, item++) { + if (!item->path) + return false; + } + return true; +} + +int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req, + void (*fw_cb)(struct device *dev, int err, + struct brcmf_fw_request *req)) { struct brcmf_fw *fwctx; brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev)); - if (!fw_cb || !code) + if (!fw_cb) return -EINVAL; - if ((flags & BRCMF_FW_REQUEST_NVRAM) && !nvram) + if (!brcmf_fw_request_is_valid(req)) return -EINVAL; fwctx = kzalloc(sizeof(*fwctx), GFP_KERNEL); @@ -540,35 +621,25 @@ int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, return -ENOMEM; fwctx->dev = dev; - fwctx->flags = flags; + fwctx->req = req; fwctx->done = fw_cb; - if (flags & BRCMF_FW_REQUEST_NVRAM) - fwctx->nvram_name = nvram; - fwctx->domain_nr = domain_nr; - fwctx->bus_nr = bus_nr; - - return request_firmware_nowait(THIS_MODULE, true, code, dev, - GFP_KERNEL, fwctx, - brcmf_fw_request_code_done); -} -int brcmf_fw_get_firmwares(struct device *dev, u16 flags, - const char *code, const char *nvram, - void (*fw_cb)(struct device *dev, int err, - const struct firmware *fw, - void *nvram_image, u32 nvram_len)) -{ - return brcmf_fw_get_firmwares_pcie(dev, flags, code, nvram, fw_cb, 0, - 0); + brcmf_fw_request_next_item(fwctx, true); + return 0; } -int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev, - struct brcmf_firmware_mapping mapping_table[], - u32 table_size, char fw_name[BRCMF_FW_NAME_LEN], - char nvram_name[BRCMF_FW_NAME_LEN]) +struct brcmf_fw_request * +brcmf_fw_alloc_request(u32 chip, u32 chiprev, + struct brcmf_firmware_mapping mapping_table[], + u32 table_size, struct brcmf_fw_name *fwnames, + u32 n_fwnames) { - u32 i; + struct brcmf_fw_request *fwreq; + char chipname[12]; + const char *mp_path; + u32 i, j; char end; + size_t reqsz; for (i = 0; i < table_size; i++) { if (mapping_table[i].chipid == chip && @@ -578,32 +649,41 @@ int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev, if (i == table_size) { brcmf_err("Unknown chipid %d [%d]\n", chip, chiprev); - return -ENODEV; + return NULL; } - /* check if firmware path is provided by module parameter */ - if (brcmf_mp_global.firmware_path[0] != '\0') { - strlcpy(fw_name, brcmf_mp_global.firmware_path, - BRCMF_FW_NAME_LEN); - if ((nvram_name) && (mapping_table[i].nvram)) - strlcpy(nvram_name, brcmf_mp_global.firmware_path, + reqsz = sizeof(*fwreq) + n_fwnames * sizeof(struct brcmf_fw_item); + fwreq = kzalloc(reqsz, GFP_KERNEL); + if (!fwreq) + return NULL; + + brcmf_chip_name(chip, chiprev, chipname, sizeof(chipname)); + + brcmf_info("using %s for chip %s\n", + mapping_table[i].fw_base, chipname); + + mp_path = brcmf_mp_global.firmware_path; + end = mp_path[strlen(mp_path) - 1]; + fwreq->n_items = n_fwnames; + + for (j = 0; j < n_fwnames; j++) { + fwreq->items[j].path = fwnames[j].path; + /* check if firmware path is provided by module parameter */ + if (brcmf_mp_global.firmware_path[0] != '\0') { + strlcpy(fwnames[j].path, mp_path, BRCMF_FW_NAME_LEN); - end = brcmf_mp_global.firmware_path[ - strlen(brcmf_mp_global.firmware_path) - 1]; - if (end != '/') { - strlcat(fw_name, "/", BRCMF_FW_NAME_LEN); - if ((nvram_name) && (mapping_table[i].nvram)) - strlcat(nvram_name, "/", BRCMF_FW_NAME_LEN); + if (end != '/') { + strlcat(fwnames[j].path, "/", + BRCMF_FW_NAME_LEN); + } } + strlcat(fwnames[j].path, mapping_table[i].fw_base, + BRCMF_FW_NAME_LEN); + strlcat(fwnames[j].path, fwnames[j].extension, + BRCMF_FW_NAME_LEN); + fwreq->items[j].path = fwnames[j].path; } - strlcat(fw_name, mapping_table[i].fw, BRCMF_FW_NAME_LEN); - if ((nvram_name) && (mapping_table[i].nvram)) - strlcat(nvram_name, mapping_table[i].nvram, BRCMF_FW_NAME_LEN); - brcmf_info("using %s for chip %#08x(%d) rev %#08x\n", - fw_name, chip, chip, chiprev); - - return 0; + return fwreq; } - diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h index 8fa4b7e1ab3d..79a21095c349 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h @@ -16,10 +16,7 @@ #ifndef BRCMFMAC_FIRMWARE_H #define BRCMFMAC_FIRMWARE_H -#define BRCMF_FW_REQUEST 0x000F -#define BRCMF_FW_REQUEST_NVRAM 0x0001 -#define BRCMF_FW_REQ_FLAGS 0x00F0 -#define BRCMF_FW_REQ_NV_OPTIONAL 0x0010 +#define BRCMF_FW_REQF_OPTIONAL 0x0001 #define BRCMF_FW_NAME_LEN 320 @@ -38,49 +35,62 @@ struct brcmf_firmware_mapping { u32 chipid; u32 revmask; - const char *fw; - const char *nvram; + const char *fw_base; }; -#define BRCMF_FW_NVRAM_DEF(fw_nvram_name, fw, nvram) \ -static const char BRCM_ ## fw_nvram_name ## _FIRMWARE_NAME[] = \ - BRCMF_FW_DEFAULT_PATH fw; \ -static const char BRCM_ ## fw_nvram_name ## _NVRAM_NAME[] = \ - BRCMF_FW_DEFAULT_PATH nvram; \ -MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw); - -#define BRCMF_FW_DEF(fw_name, fw) \ -static const char BRCM_ ## fw_name ## _FIRMWARE_NAME[] = \ - BRCMF_FW_DEFAULT_PATH fw; \ -MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw) \ - -#define BRCMF_FW_NVRAM_ENTRY(chipid, mask, name) \ - { chipid, mask, \ - BRCM_ ## name ## _FIRMWARE_NAME, BRCM_ ## name ## _NVRAM_NAME } +#define BRCMF_FW_DEF(fw_name, fw_base) \ +static const char BRCM_ ## fw_name ## _FIRMWARE_BASENAME[] = \ + BRCMF_FW_DEFAULT_PATH fw_base; \ +MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw_base ".bin") #define BRCMF_FW_ENTRY(chipid, mask, name) \ - { chipid, mask, BRCM_ ## name ## _FIRMWARE_NAME, NULL } + { chipid, mask, BRCM_ ## name ## _FIRMWARE_BASENAME } -int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev, - struct brcmf_firmware_mapping mapping_table[], - u32 table_size, char fw_name[BRCMF_FW_NAME_LEN], - char nvram_name[BRCMF_FW_NAME_LEN]); void brcmf_fw_nvram_free(void *nvram); + +enum brcmf_fw_type { + BRCMF_FW_TYPE_BINARY, + BRCMF_FW_TYPE_NVRAM +}; + +struct brcmf_fw_item { + const char *path; + enum brcmf_fw_type type; + u16 flags; + union { + const struct firmware *binary; + struct { + void *data; + u32 len; + } nv_data; + }; +}; + +struct brcmf_fw_request { + u16 domain_nr; + u16 bus_nr; + u32 n_items; + struct brcmf_fw_item items[0]; +}; + +struct brcmf_fw_name { + const char *extension; + char *path; +}; + +struct brcmf_fw_request * +brcmf_fw_alloc_request(u32 chip, u32 chiprev, + struct brcmf_firmware_mapping mapping_table[], + u32 table_size, struct brcmf_fw_name *fwnames, + u32 n_fwnames); + /* * Request firmware(s) asynchronously. When the asynchronous request * fails it will not use the callback, but call device_release_driver() * instead which will call the driver .remove() callback. */ -int brcmf_fw_get_firmwares_pcie(struct device *dev, u16 flags, - const char *code, const char *nvram, - void (*fw_cb)(struct device *dev, int err, - const struct firmware *fw, - void *nvram_image, u32 nvram_len), - u16 domain_nr, u16 bus_nr); -int brcmf_fw_get_firmwares(struct device *dev, u16 flags, - const char *code, const char *nvram, +int brcmf_fw_get_firmwares(struct device *dev, struct brcmf_fw_request *req, void (*fw_cb)(struct device *dev, int err, - const struct firmware *fw, - void *nvram_image, u32 nvram_len)); + struct brcmf_fw_request *req)); #endif /* BRCMFMAC_FIRMWARE_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c index fc5751116d99..802d7cb73b80 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c @@ -124,8 +124,7 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) data, len, &fwerr); if (err) { - brcmf_dbg(FIL, "Failed: %s (%d)\n", - brcmf_fil_get_errstr((u32)(-err)), err); + brcmf_dbg(FIL, "Failed: error=%d\n", err); } else if (fwerr < 0) { brcmf_dbg(FIL, "Firmware error: %s (%d)\n", brcmf_fil_get_errstr((u32)(-fwerr)), fwerr); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index f59642b2c935..f3cbf78c8899 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -2399,10 +2399,6 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr) brcmu_pktq_init(&fws->desc.other.psq, BRCMF_FWS_PSQ_PREC_COUNT, BRCMF_FWS_PSQ_LEN); - /* create debugfs file for statistics */ - brcmf_debugfs_add_entry(drvr, "fws_stats", - brcmf_debugfs_fws_stats_read); - brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n", fws->fw_signals ? "enabled" : "disabled", tlv); return fws; @@ -2429,6 +2425,13 @@ void brcmf_fws_detach(struct brcmf_fws_info *fws) kfree(fws); } +void brcmf_fws_debugfs_create(struct brcmf_pub *drvr) +{ + /* create debugfs file for statistics */ + brcmf_debugfs_add_entry(drvr, "fws_stats", + brcmf_debugfs_fws_stats_read); +} + bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws) { return !fws->avoid_queueing; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h index ba07bd972002..4e6835766d5d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h @@ -20,6 +20,7 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr); void brcmf_fws_detach(struct brcmf_fws_info *fws); +void brcmf_fws_debugfs_create(struct brcmf_pub *drvr); bool brcmf_fws_queue_skbs(struct brcmf_fws_info *fws); bool brcmf_fws_fc_active(struct brcmf_fws_info *fws); void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index e212a791a072..49d37ad96958 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -1418,6 +1418,11 @@ static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data) } #endif +static void brcmf_msgbuf_debugfs_create(struct brcmf_pub *drvr) +{ + brcmf_debugfs_add_entry(drvr, "msgbuf_stats", brcmf_msgbuf_stats_read); +} + int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) { struct brcmf_bus_msgbuf *if_msgbuf; @@ -1472,6 +1477,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) drvr->proto->delete_peer = brcmf_msgbuf_delete_peer; drvr->proto->add_tdls_peer = brcmf_msgbuf_add_tdls_peer; drvr->proto->rxreorder = brcmf_msgbuf_rxreorder; + drvr->proto->debugfs_create = brcmf_msgbuf_debugfs_create; drvr->proto->pd = msgbuf; init_waitqueue_head(&msgbuf->ioctl_resp_wait); @@ -1525,8 +1531,6 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) spin_lock_init(&msgbuf->flowring_work_lock); INIT_LIST_HEAD(&msgbuf->work_queue); - brcmf_debugfs_add_entry(drvr, "msgbuf_stats", brcmf_msgbuf_stats_read); - return 0; fail: diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index 82064e909784..bcef208a81a5 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -2227,7 +2227,7 @@ fail: */ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) { - struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_p2p_info *p2p = &cfg->p2p; struct brcmf_cfg80211_vif *vif; enum nl80211_iftype iftype; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index a7d827ce1684..091c191ce259 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -46,36 +46,36 @@ enum brcmf_pcie_state { BRCMFMAC_PCIE_STATE_UP }; -BRCMF_FW_NVRAM_DEF(43602, "brcmfmac43602-pcie.bin", "brcmfmac43602-pcie.txt"); -BRCMF_FW_NVRAM_DEF(4350, "brcmfmac4350-pcie.bin", "brcmfmac4350-pcie.txt"); -BRCMF_FW_NVRAM_DEF(4350C, "brcmfmac4350c2-pcie.bin", "brcmfmac4350c2-pcie.txt"); -BRCMF_FW_NVRAM_DEF(4356, "brcmfmac4356-pcie.bin", "brcmfmac4356-pcie.txt"); -BRCMF_FW_NVRAM_DEF(43570, "brcmfmac43570-pcie.bin", "brcmfmac43570-pcie.txt"); -BRCMF_FW_NVRAM_DEF(4358, "brcmfmac4358-pcie.bin", "brcmfmac4358-pcie.txt"); -BRCMF_FW_NVRAM_DEF(4359, "brcmfmac4359-pcie.bin", "brcmfmac4359-pcie.txt"); -BRCMF_FW_NVRAM_DEF(4365B, "brcmfmac4365b-pcie.bin", "brcmfmac4365b-pcie.txt"); -BRCMF_FW_NVRAM_DEF(4365C, "brcmfmac4365c-pcie.bin", "brcmfmac4365c-pcie.txt"); -BRCMF_FW_NVRAM_DEF(4366B, "brcmfmac4366b-pcie.bin", "brcmfmac4366b-pcie.txt"); -BRCMF_FW_NVRAM_DEF(4366C, "brcmfmac4366c-pcie.bin", "brcmfmac4366c-pcie.txt"); -BRCMF_FW_NVRAM_DEF(4371, "brcmfmac4371-pcie.bin", "brcmfmac4371-pcie.txt"); +BRCMF_FW_DEF(43602, "brcmfmac43602-pcie"); +BRCMF_FW_DEF(4350, "brcmfmac4350-pcie"); +BRCMF_FW_DEF(4350C, "brcmfmac4350c2-pcie"); +BRCMF_FW_DEF(4356, "brcmfmac4356-pcie"); +BRCMF_FW_DEF(43570, "brcmfmac43570-pcie"); +BRCMF_FW_DEF(4358, "brcmfmac4358-pcie"); +BRCMF_FW_DEF(4359, "brcmfmac4359-pcie"); +BRCMF_FW_DEF(4365B, "brcmfmac4365b-pcie"); +BRCMF_FW_DEF(4365C, "brcmfmac4365c-pcie"); +BRCMF_FW_DEF(4366B, "brcmfmac4366b-pcie"); +BRCMF_FW_DEF(4366C, "brcmfmac4366c-pcie"); +BRCMF_FW_DEF(4371, "brcmfmac4371-pcie"); static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43465_CHIP_ID, 0xFFFFFFF0, 4366C), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4350_CHIP_ID, 0x000000FF, 4350C), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFF00, 4350), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43525_CHIP_ID, 0xFFFFFFF0, 4365C), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43567_CHIP_ID, 0xFFFFFFFF, 43570), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43570), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4365_CHIP_ID, 0x0000000F, 4365B), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFF0, 4365C), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFF0, 4366C), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371), + BRCMF_FW_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602), + BRCMF_FW_ENTRY(BRCM_CC_43465_CHIP_ID, 0xFFFFFFF0, 4366C), + BRCMF_FW_ENTRY(BRCM_CC_4350_CHIP_ID, 0x000000FF, 4350C), + BRCMF_FW_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFF00, 4350), + BRCMF_FW_ENTRY(BRCM_CC_43525_CHIP_ID, 0xFFFFFFF0, 4365C), + BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356), + BRCMF_FW_ENTRY(BRCM_CC_43567_CHIP_ID, 0xFFFFFFFF, 43570), + BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43570), + BRCMF_FW_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570), + BRCMF_FW_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358), + BRCMF_FW_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359), + BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0x0000000F, 4365B), + BRCMF_FW_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFF0, 4365C), + BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0x0000000F, 4366B), + BRCMF_FW_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFF0, 4366C), + BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371), }; #define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */ @@ -1350,23 +1350,24 @@ static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len) return 0; } -static int brcmf_pcie_get_fwname(struct device *dev, u32 chip, u32 chiprev, - u8 *fw_name) +static +int brcmf_pcie_get_fwname(struct device *dev, const char *ext, u8 *fw_name) { struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_pciedev *buspub = bus_if->bus_priv.pcie; - struct brcmf_pciedev_info *devinfo = buspub->devinfo; - int ret = 0; - - if (devinfo->fw_name[0] != '\0') - strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN); - else - ret = brcmf_fw_map_chip_to_name(chip, chiprev, - brcmf_pcie_fwnames, - ARRAY_SIZE(brcmf_pcie_fwnames), - fw_name, NULL); - - return ret; + struct brcmf_fw_request *fwreq; + struct brcmf_fw_name fwnames[] = { + { ext, fw_name }, + }; + + fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev, + brcmf_pcie_fwnames, + ARRAY_SIZE(brcmf_pcie_fwnames), + fwnames, ARRAY_SIZE(fwnames)); + if (!fwreq) + return -ENOMEM; + + kfree(fwreq); + return 0; } static const struct brcmf_bus_ops brcmf_pcie_bus_ops = { @@ -1651,15 +1652,19 @@ static const struct brcmf_buscore_ops brcmf_pcie_buscore_ops = { .write32 = brcmf_pcie_buscore_write32, }; +#define BRCMF_PCIE_FW_CODE 0 +#define BRCMF_PCIE_FW_NVRAM 1 + static void brcmf_pcie_setup(struct device *dev, int ret, - const struct firmware *fw, - void *nvram, u32 nvram_len) + struct brcmf_fw_request *fwreq) { + const struct firmware *fw; + void *nvram; struct brcmf_bus *bus; struct brcmf_pciedev *pcie_bus_dev; struct brcmf_pciedev_info *devinfo; struct brcmf_commonring **flowrings; - u32 i; + u32 i, nvram_len; /* check firmware loading result */ if (ret) @@ -1670,6 +1675,11 @@ static void brcmf_pcie_setup(struct device *dev, int ret, devinfo = pcie_bus_dev->devinfo; brcmf_pcie_attach(devinfo); + fw = fwreq->items[BRCMF_PCIE_FW_CODE].binary; + nvram = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.data; + nvram_len = fwreq->items[BRCMF_PCIE_FW_NVRAM].nv_data.len; + kfree(fwreq); + /* Some of the firmwares have the size of the memory of the device * defined inside the firmware. This is because part of the memory in * the device is shared and the devision is determined by FW. Parse @@ -1726,20 +1736,41 @@ fail: device_release_driver(dev); } +static struct brcmf_fw_request * +brcmf_pcie_prepare_fw_request(struct brcmf_pciedev_info *devinfo) +{ + struct brcmf_fw_request *fwreq; + struct brcmf_fw_name fwnames[] = { + { ".bin", devinfo->fw_name }, + { ".txt", devinfo->nvram_name }, + }; + + fwreq = brcmf_fw_alloc_request(devinfo->ci->chip, devinfo->ci->chiprev, + brcmf_pcie_fwnames, + ARRAY_SIZE(brcmf_pcie_fwnames), + fwnames, ARRAY_SIZE(fwnames)); + if (!fwreq) + return NULL; + + fwreq->items[BRCMF_PCIE_FW_CODE].type = BRCMF_FW_TYPE_BINARY; + fwreq->items[BRCMF_PCIE_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM; + fwreq->items[BRCMF_PCIE_FW_NVRAM].flags = BRCMF_FW_REQF_OPTIONAL; + fwreq->domain_nr = pci_domain_nr(devinfo->pdev->bus); + fwreq->bus_nr = devinfo->pdev->bus->number; + + return fwreq; +} + static int brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) { int ret; + struct brcmf_fw_request *fwreq; struct brcmf_pciedev_info *devinfo; struct brcmf_pciedev *pcie_bus_dev; struct brcmf_bus *bus; - u16 domain_nr; - u16 bus_nr; - domain_nr = pci_domain_nr(pdev->bus) + 1; - bus_nr = pdev->bus->number; - brcmf_dbg(PCIE, "Enter %x:%x (%d/%d)\n", pdev->vendor, pdev->device, - domain_nr, bus_nr); + brcmf_dbg(PCIE, "Enter %x:%x\n", pdev->vendor, pdev->device); ret = -ENOMEM; devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL); @@ -1793,19 +1824,19 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot); dev_set_drvdata(&pdev->dev, bus); - ret = brcmf_fw_map_chip_to_name(devinfo->ci->chip, devinfo->ci->chiprev, - brcmf_pcie_fwnames, - ARRAY_SIZE(brcmf_pcie_fwnames), - devinfo->fw_name, devinfo->nvram_name); - if (ret) + fwreq = brcmf_pcie_prepare_fw_request(devinfo); + if (!fwreq) { + ret = -ENOMEM; goto fail_bus; + } + + ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup); + if (ret < 0) { + kfree(fwreq); + goto fail_bus; + } + return 0; - ret = brcmf_fw_get_firmwares_pcie(bus->dev, BRCMF_FW_REQUEST_NVRAM | - BRCMF_FW_REQ_NV_OPTIONAL, - devinfo->fw_name, devinfo->nvram_name, - brcmf_pcie_setup, domain_nr, bus_nr); - if (ret == 0) - return 0; fail_bus: kfree(bus->msgbuf); kfree(bus); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c index d26ff219ef66..c5ff551ec659 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.c @@ -54,7 +54,8 @@ int brcmf_proto_attach(struct brcmf_pub *drvr) if (!proto->tx_queue_data || (proto->hdrpull == NULL) || (proto->query_dcmd == NULL) || (proto->set_dcmd == NULL) || (proto->configure_addr_mode == NULL) || - (proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL)) { + (proto->delete_peer == NULL) || (proto->add_tdls_peer == NULL) || + (proto->debugfs_create == NULL)) { brcmf_err("Not all proto handlers have been installed\n"); goto fail; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h index 8a8e08f09ea0..d3c3b9a815ad 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/proto.h @@ -48,6 +48,7 @@ struct brcmf_proto { void (*del_if)(struct brcmf_if *ifp); void (*reset_if)(struct brcmf_if *ifp); int (*init_done)(struct brcmf_pub *drvr); + void (*debugfs_create)(struct brcmf_pub *drvr); void *pd; }; @@ -156,4 +157,10 @@ brcmf_proto_init_done(struct brcmf_pub *drvr) return drvr->proto->init_done(drvr); } +static inline void +brcmf_proto_debugfs_create(struct brcmf_pub *drvr) +{ + drvr->proto->debugfs_create(drvr); +} + #endif /* BRCMFMAC_PROTO_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 4a6459a429ec..1037df7297bb 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -600,47 +600,44 @@ static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = { {4, 0x1} }; -BRCMF_FW_NVRAM_DEF(43143, "brcmfmac43143-sdio.bin", "brcmfmac43143-sdio.txt"); -BRCMF_FW_NVRAM_DEF(43241B0, "brcmfmac43241b0-sdio.bin", - "brcmfmac43241b0-sdio.txt"); -BRCMF_FW_NVRAM_DEF(43241B4, "brcmfmac43241b4-sdio.bin", - "brcmfmac43241b4-sdio.txt"); -BRCMF_FW_NVRAM_DEF(43241B5, "brcmfmac43241b5-sdio.bin", - "brcmfmac43241b5-sdio.txt"); -BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt"); -BRCMF_FW_NVRAM_DEF(4330, "brcmfmac4330-sdio.bin", "brcmfmac4330-sdio.txt"); -BRCMF_FW_NVRAM_DEF(4334, "brcmfmac4334-sdio.bin", "brcmfmac4334-sdio.txt"); -BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt"); -BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt"); -BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt"); -BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt"); -BRCMF_FW_NVRAM_DEF(43430A0, "brcmfmac43430a0-sdio.bin", "brcmfmac43430a0-sdio.txt"); +BRCMF_FW_DEF(43143, "brcmfmac43143-sdio"); +BRCMF_FW_DEF(43241B0, "brcmfmac43241b0-sdio"); +BRCMF_FW_DEF(43241B4, "brcmfmac43241b4-sdio"); +BRCMF_FW_DEF(43241B5, "brcmfmac43241b5-sdio"); +BRCMF_FW_DEF(4329, "brcmfmac4329-sdio"); +BRCMF_FW_DEF(4330, "brcmfmac4330-sdio"); +BRCMF_FW_DEF(4334, "brcmfmac4334-sdio"); +BRCMF_FW_DEF(43340, "brcmfmac43340-sdio"); +BRCMF_FW_DEF(4335, "brcmfmac4335-sdio"); +BRCMF_FW_DEF(43362, "brcmfmac43362-sdio"); +BRCMF_FW_DEF(4339, "brcmfmac4339-sdio"); +BRCMF_FW_DEF(43430A0, "brcmfmac43430a0-sdio"); /* Note the names are not postfixed with a1 for backward compatibility */ -BRCMF_FW_NVRAM_DEF(43430A1, "brcmfmac43430-sdio.bin", "brcmfmac43430-sdio.txt"); -BRCMF_FW_NVRAM_DEF(43455, "brcmfmac43455-sdio.bin", "brcmfmac43455-sdio.txt"); -BRCMF_FW_NVRAM_DEF(4354, "brcmfmac4354-sdio.bin", "brcmfmac4354-sdio.txt"); -BRCMF_FW_NVRAM_DEF(4356, "brcmfmac4356-sdio.bin", "brcmfmac4356-sdio.txt"); -BRCMF_FW_NVRAM_DEF(4373, "brcmfmac4373-sdio.bin", "brcmfmac4373-sdio.txt"); +BRCMF_FW_DEF(43430A1, "brcmfmac43430-sdio"); +BRCMF_FW_DEF(43455, "brcmfmac43455-sdio"); +BRCMF_FW_DEF(4354, "brcmfmac4354-sdio"); +BRCMF_FW_DEF(4356, "brcmfmac4356-sdio"); +BRCMF_FW_DEF(4373, "brcmfmac4373-sdio"); static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = { - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0xFFFFFFC0, 43241B5), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, 4329), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43340), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000001, 43430A0), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFE, 43430A1), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354), - BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356), - BRCMF_FW_NVRAM_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373) + BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143), + BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0), + BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4), + BRCMF_FW_ENTRY(BRCM_CC_43241_CHIP_ID, 0xFFFFFFC0, 43241B5), + BRCMF_FW_ENTRY(BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, 4329), + BRCMF_FW_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330), + BRCMF_FW_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334), + BRCMF_FW_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340), + BRCMF_FW_ENTRY(BRCM_CC_43341_CHIP_ID, 0xFFFFFFFF, 43340), + BRCMF_FW_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335), + BRCMF_FW_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362), + BRCMF_FW_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339), + BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0x00000001, 43430A0), + BRCMF_FW_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFE, 43430A1), + BRCMF_FW_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455), + BRCMF_FW_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354), + BRCMF_FW_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356), + BRCMF_FW_ENTRY(CY_CC_4373_CHIP_ID, 0xFFFFFFFF, 4373) }; static void pkt_align(struct sk_buff *p, int len, int align) @@ -4003,22 +4000,24 @@ brcmf_sdio_watchdog(struct timer_list *t) } } -static int brcmf_sdio_get_fwname(struct device *dev, u32 chip, u32 chiprev, - u8 *fw_name) +static +int brcmf_sdio_get_fwname(struct device *dev, const char *ext, u8 *fw_name) { struct brcmf_bus *bus_if = dev_get_drvdata(dev); - struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; - int ret = 0; - - if (sdiodev->fw_name[0] != '\0') - strlcpy(fw_name, sdiodev->fw_name, BRCMF_FW_NAME_LEN); - else - ret = brcmf_fw_map_chip_to_name(chip, chiprev, - brcmf_sdio_fwnames, - ARRAY_SIZE(brcmf_sdio_fwnames), - fw_name, NULL); + struct brcmf_fw_request *fwreq; + struct brcmf_fw_name fwnames[] = { + { ext, fw_name }, + }; + + fwreq = brcmf_fw_alloc_request(bus_if->chip, bus_if->chiprev, + brcmf_sdio_fwnames, + ARRAY_SIZE(brcmf_sdio_fwnames), + fwnames, ARRAY_SIZE(fwnames)); + if (!fwreq) + return -ENOMEM; - return ret; + kfree(fwreq); + return 0; } static const struct brcmf_bus_ops brcmf_sdio_bus_ops = { @@ -4034,14 +4033,19 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = { .get_fwname = brcmf_sdio_get_fwname, }; +#define BRCMF_SDIO_FW_CODE 0 +#define BRCMF_SDIO_FW_NVRAM 1 + static void brcmf_sdio_firmware_callback(struct device *dev, int err, - const struct firmware *code, - void *nvram, u32 nvram_len) + struct brcmf_fw_request *fwreq) { struct brcmf_bus *bus_if = dev_get_drvdata(dev); struct brcmf_sdio_dev *sdiod = bus_if->bus_priv.sdio; struct brcmf_sdio *bus = sdiod->bus; struct brcmf_core *core = bus->sdio_core; + const struct firmware *code; + void *nvram; + u32 nvram_len; u8 saveclk; brcmf_dbg(TRACE, "Enter: dev=%s, err=%d\n", dev_name(dev), err); @@ -4049,6 +4053,11 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, if (err) goto fail; + code = fwreq->items[BRCMF_SDIO_FW_CODE].binary; + nvram = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.data; + nvram_len = fwreq->items[BRCMF_SDIO_FW_NVRAM].nv_data.len; + kfree(fwreq); + /* try to download image and nvram to the dongle */ bus->alp_only = true; err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len); @@ -4148,11 +4157,34 @@ fail: device_release_driver(dev); } +static struct brcmf_fw_request * +brcmf_sdio_prepare_fw_request(struct brcmf_sdio *bus) +{ + struct brcmf_fw_request *fwreq; + struct brcmf_fw_name fwnames[] = { + { ".bin", bus->sdiodev->fw_name }, + { ".txt", bus->sdiodev->nvram_name }, + }; + + fwreq = brcmf_fw_alloc_request(bus->ci->chip, bus->ci->chiprev, + brcmf_sdio_fwnames, + ARRAY_SIZE(brcmf_sdio_fwnames), + fwnames, ARRAY_SIZE(fwnames)); + if (!fwreq) + return NULL; + + fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY; + fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM; + + return fwreq; +} + struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) { int ret; struct brcmf_sdio *bus; struct workqueue_struct *wq; + struct brcmf_fw_request *fwreq; brcmf_dbg(TRACE, "Enter\n"); @@ -4235,18 +4267,17 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) brcmf_dbg(INFO, "completed!!\n"); - ret = brcmf_fw_map_chip_to_name(bus->ci->chip, bus->ci->chiprev, - brcmf_sdio_fwnames, - ARRAY_SIZE(brcmf_sdio_fwnames), - sdiodev->fw_name, sdiodev->nvram_name); - if (ret) + fwreq = brcmf_sdio_prepare_fw_request(bus); + if (!fwreq) { + ret = -ENOMEM; goto fail; + } - ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM, - sdiodev->fw_name, sdiodev->nvram_name, + ret = brcmf_fw_get_firmwares(sdiodev->dev, fwreq, brcmf_sdio_firmware_callback); if (ret != 0) { brcmf_err("async firmware request failed: %d\n", ret); + kfree(fwreq); goto fail; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 41642dda40fd..a0873adcc01c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -46,11 +46,11 @@ #define BRCMF_USB_CBCTL_READ 1 #define BRCMF_USB_MAX_PKT_SIZE 1600 -BRCMF_FW_DEF(43143, "brcmfmac43143.bin"); -BRCMF_FW_DEF(43236B, "brcmfmac43236b.bin"); -BRCMF_FW_DEF(43242A, "brcmfmac43242a.bin"); -BRCMF_FW_DEF(43569, "brcmfmac43569.bin"); -BRCMF_FW_DEF(4373, "brcmfmac4373.bin"); +BRCMF_FW_DEF(43143, "brcmfmac43143"); +BRCMF_FW_DEF(43236B, "brcmfmac43236b"); +BRCMF_FW_DEF(43242A, "brcmfmac43242a"); +BRCMF_FW_DEF(43569, "brcmfmac43569"); +BRCMF_FW_DEF(4373, "brcmfmac4373"); static struct brcmf_firmware_mapping brcmf_usb_fwnames[] = { BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143), @@ -1128,21 +1128,24 @@ static void brcmf_usb_wowl_config(struct device *dev, bool enabled) device_set_wakeup_enable(devinfo->dev, false); } -static int brcmf_usb_get_fwname(struct device *dev, u32 chip, u32 chiprev, - u8 *fw_name) +static +int brcmf_usb_get_fwname(struct device *dev, const char *ext, u8 *fw_name) { - struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); - int ret = 0; - - if (devinfo->fw_name[0] != '\0') - strlcpy(fw_name, devinfo->fw_name, BRCMF_FW_NAME_LEN); - else - ret = brcmf_fw_map_chip_to_name(chip, chiprev, - brcmf_usb_fwnames, - ARRAY_SIZE(brcmf_usb_fwnames), - fw_name, NULL); + struct brcmf_bus *bus = dev_get_drvdata(dev); + struct brcmf_fw_request *fwreq; + struct brcmf_fw_name fwnames[] = { + { ext, fw_name }, + }; + + fwreq = brcmf_fw_alloc_request(bus->chip, bus->chiprev, + brcmf_usb_fwnames, + ARRAY_SIZE(brcmf_usb_fwnames), + fwnames, ARRAY_SIZE(fwnames)); + if (!fwreq) + return -ENOMEM; - return ret; + kfree(fwreq); + return 0; } static const struct brcmf_bus_ops brcmf_usb_bus_ops = { @@ -1155,18 +1158,23 @@ static const struct brcmf_bus_ops brcmf_usb_bus_ops = { .get_fwname = brcmf_usb_get_fwname, }; +#define BRCMF_USB_FW_CODE 0 + static void brcmf_usb_probe_phase2(struct device *dev, int ret, - const struct firmware *fw, - void *nvram, u32 nvlen) + struct brcmf_fw_request *fwreq) { struct brcmf_bus *bus = dev_get_drvdata(dev); struct brcmf_usbdev_info *devinfo = bus->bus_priv.usb->devinfo; + const struct firmware *fw; if (ret) goto error; brcmf_dbg(USB, "Start fw downloading\n"); + fw = fwreq->items[BRCMF_USB_FW_CODE].binary; + kfree(fwreq); + ret = check_file(fw->data); if (ret < 0) { brcmf_err("invalid firmware\n"); @@ -1195,11 +1203,33 @@ error: device_release_driver(dev); } +static struct brcmf_fw_request * +brcmf_usb_prepare_fw_request(struct brcmf_usbdev_info *devinfo) +{ + struct brcmf_fw_request *fwreq; + struct brcmf_fw_name fwnames[] = { + { ".bin", devinfo->fw_name }, + }; + + fwreq = brcmf_fw_alloc_request(devinfo->bus_pub.devid, + devinfo->bus_pub.chiprev, + brcmf_usb_fwnames, + ARRAY_SIZE(brcmf_usb_fwnames), + fwnames, ARRAY_SIZE(fwnames)); + if (!fwreq) + return NULL; + + fwreq->items[BRCMF_USB_FW_CODE].type = BRCMF_FW_TYPE_BINARY; + + return fwreq; +} + static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) { struct brcmf_bus *bus = NULL; struct brcmf_usbdev *bus_pub = NULL; struct device *dev = devinfo->dev; + struct brcmf_fw_request *fwreq; int ret; brcmf_dbg(USB, "Enter\n"); @@ -1243,18 +1273,17 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) bus->chip = bus_pub->devid; bus->chiprev = bus_pub->chiprev; - ret = brcmf_fw_map_chip_to_name(bus_pub->devid, bus_pub->chiprev, - brcmf_usb_fwnames, - ARRAY_SIZE(brcmf_usb_fwnames), - devinfo->fw_name, NULL); - if (ret) + fwreq = brcmf_usb_prepare_fw_request(devinfo); + if (!fwreq) { + ret = -ENOMEM; goto fail; + } /* request firmware here */ - ret = brcmf_fw_get_firmwares(dev, 0, devinfo->fw_name, NULL, - brcmf_usb_probe_phase2); + ret = brcmf_fw_get_firmwares(dev, fwreq, brcmf_usb_probe_phase2); if (ret) { brcmf_err("firmware request failed: %d\n", ret); + kfree(fwreq); goto fail; } @@ -1447,11 +1476,20 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf) { struct usb_device *usb = interface_to_usbdev(intf); struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); + struct brcmf_fw_request *fwreq; + int ret; brcmf_dbg(USB, "Enter\n"); - return brcmf_fw_get_firmwares(&usb->dev, 0, devinfo->fw_name, NULL, - brcmf_usb_probe_phase2); + fwreq = brcmf_usb_prepare_fw_request(devinfo); + if (!fwreq) + return -ENOMEM; + + ret = brcmf_fw_get_firmwares(&usb->dev, fwreq, brcmf_usb_probe_phase2); + if (ret < 0) + kfree(fwreq); + + return ret; } #define BRCMF_USB_DEVICE(dev_id) \ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c index 8e58f6800483..ecc89e718b9c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c @@ -1563,7 +1563,7 @@ void brcms_free_timer(struct brcms_timer *t) } /* - * precondition: perimeter lock has been acquired + * precondition: no locking required */ int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx) { @@ -1578,7 +1578,7 @@ int brcms_ucode_init_buf(struct brcms_info *wl, void **pbuf, u32 idx) if (le32_to_cpu(hdr->idx) == idx) { pdata = wl->fw.fw_bin[i]->data + le32_to_cpu(hdr->offset); - *pbuf = kmemdup(pdata, len, GFP_ATOMIC); + *pbuf = kmemdup(pdata, len, GFP_KERNEL); if (*pbuf == NULL) goto fail; diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 48f6f80eb24b..dffd9df782b0 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -6,6 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2015-2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -19,6 +20,7 @@ * BSD LICENSE * * Copyright(c) 2015-2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -55,7 +57,7 @@ #include "iwl-agn-hw.h" /* Highest firmware API version supported */ -#define IWL_22000_UCODE_API_MAX 36 +#define IWL_22000_UCODE_API_MAX 38 /* Lowest firmware API version supported */ #define IWL_22000_UCODE_API_MIN 24 diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 90a1d14cf7d2..e1c869a1f8cc 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -6,6 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2015-2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -19,6 +20,7 @@ * BSD LICENSE * * Copyright(c) 2015-2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,9 +55,10 @@ #include <linux/stringify.h> #include "iwl-config.h" #include "iwl-agn-hw.h" +#include "fw/file.h" /* Highest firmware API version supported */ -#define IWL9000_UCODE_API_MAX 36 +#define IWL9000_UCODE_API_MAX 38 /* Lowest firmware API version supported */ #define IWL9000_UCODE_API_MIN 30 @@ -265,6 +268,67 @@ const struct iwl_cfg iwl9560_2ac_cfg_soc = { .integrated = true, .soc_latency = 5000, }; + +const struct iwl_cfg iwl9460_2ac_cfg_shared_clk = { + .name = "Intel(R) Dual Band Wireless AC 9460", + .fw_name_pre = IWL9000A_FW_PRE, + .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, + .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + IWL_DEVICE_9000, + .ht_params = &iwl9000_ht_params, + .nvm_ver = IWL9000_NVM_VERSION, + .nvm_calib_ver = IWL9000_TX_POWER_VERSION, + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, + .integrated = true, + .soc_latency = 5000, + .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK +}; + +const struct iwl_cfg iwl9461_2ac_cfg_shared_clk = { + .name = "Intel(R) Dual Band Wireless AC 9461", + .fw_name_pre = IWL9000A_FW_PRE, + .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, + .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + IWL_DEVICE_9000, + .ht_params = &iwl9000_ht_params, + .nvm_ver = IWL9000_NVM_VERSION, + .nvm_calib_ver = IWL9000_TX_POWER_VERSION, + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, + .integrated = true, + .soc_latency = 5000, + .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK +}; + +const struct iwl_cfg iwl9462_2ac_cfg_shared_clk = { + .name = "Intel(R) Dual Band Wireless AC 9462", + .fw_name_pre = IWL9000A_FW_PRE, + .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, + .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + IWL_DEVICE_9000, + .ht_params = &iwl9000_ht_params, + .nvm_ver = IWL9000_NVM_VERSION, + .nvm_calib_ver = IWL9000_TX_POWER_VERSION, + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, + .integrated = true, + .soc_latency = 5000, + .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK +}; + +const struct iwl_cfg iwl9560_2ac_cfg_shared_clk = { + .name = "Intel(R) Dual Band Wireless AC 9560", + .fw_name_pre = IWL9000A_FW_PRE, + .fw_name_pre_b_or_c_step = IWL9000B_FW_PRE, + .fw_name_pre_rf_next_step = IWL9000RFB_FW_PRE, + IWL_DEVICE_9000, + .ht_params = &iwl9000_ht_params, + .nvm_ver = IWL9000_NVM_VERSION, + .nvm_calib_ver = IWL9000_TX_POWER_VERSION, + .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, + .integrated = true, + .soc_latency = 5000, + .extra_phy_cfg_flags = FW_PHY_CFG_SHARED_CLK +}; + MODULE_FIRMWARE(IWL9000A_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL9000B_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL9000RFB_MODULE_FIRMWARE(IWL9000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index 3fd07bc80f54..37c57bcbfb4a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -8,6 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,6 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -311,6 +313,17 @@ struct iwl_mcc_update_resp_v1 { } __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_1 */ /** + * enum iwl_geo_information - geographic information. + * @GEO_NO_INFO: no special info for this geo profile. + * @GEO_WMM_ETSI_5GHZ_INFO: this geo profile limits the WMM params + * for the 5 GHz band. + */ +enum iwl_geo_information { + GEO_NO_INFO = 0, + GEO_WMM_ETSI_5GHZ_INFO = BIT(0), +}; + +/** * struct iwl_mcc_update_resp - response to MCC_UPDATE_CMD. * Contains the new channel control profile map, if changed, and the new MCC * (mobile country code). @@ -320,7 +333,8 @@ struct iwl_mcc_update_resp_v1 { * @cap: capabilities for all channels which matches the MCC * @source_id: the MCC source, see iwl_mcc_source * @time: time elapsed from the MCC test start (in 30 seconds TU) - * @reserved: reserved. + * @geo_info: geographic specific profile information + * see &enum iwl_geo_information. * @n_channels: number of channels in @channels_data (may be 14, 39, 50 or 51 * channels, depending on platform) * @channels: channel control data map, DWORD for each channel. Only the first @@ -332,10 +346,10 @@ struct iwl_mcc_update_resp { u8 cap; u8 source_id; __le16 time; - __le16 reserved; + __le16 geo_info; __le32 n_channels; __le32 channels[0]; -} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_2 */ +} __packed; /* LAR_UPDATE_MCC_CMD_RESP_S_VER_3 */ /** * struct iwl_mcc_chub_notif - chub notifies of mcc change diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h index 3bfc657f6b42..7af3a0f51b77 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/scan.h @@ -30,6 +30,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -579,8 +580,23 @@ enum iwl_umac_scan_general_flags { IWL_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED = BIT(8), IWL_UMAC_SCAN_GEN_FLAGS_MATCH = BIT(9), IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL = BIT(10), + /* Extended dwell is obselete when adaptive dwell is used, making this + * bit reusable. Hence, probe request defer is used only when adaptive + * dwell is supported. */ + IWL_UMAC_SCAN_GEN_FLAGS_PROB_REQ_DEFER_SUPP = BIT(10), IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED = BIT(11), IWL_UMAC_SCAN_GEN_FLAGS_ADAPTIVE_DWELL = BIT(13), + IWL_UMAC_SCAN_GEN_FLAGS_MAX_CHNL_TIME = BIT(14), + IWL_UMAC_SCAN_GEN_FLAGS_PROB_REQ_HIGH_TX_RATE = BIT(15), +}; + +/** + * enum iwl_umac_scan_general_flags2 - UMAC scan general flags #2 + * @IWL_UMAC_SCAN_GEN_FLAGS2_NOTIF_PER_CHNL: Whether to send a complete + * notification per channel or not. + */ +enum iwl_umac_scan_general_flags2 { + IWL_UMAC_SCAN_GEN_FLAGS2_NOTIF_PER_CHNL = BIT(0), }; /** @@ -629,6 +645,18 @@ struct iwl_scan_req_umac_tail { } __packed; /** + * struct iwl_scan_umac_chan_param + * @flags: channel flags &enum iwl_scan_channel_flags + * @count: num of channels in scan request + * @reserved: for future use and alignment + */ +struct iwl_scan_umac_chan_param { + u8 flags; + u8 count; + __le16 reserved; +} __packed; /*SCAN_CHANNEL_PARAMS_API_S_VER_1 */ + +/** * struct iwl_scan_req_umac * @flags: &enum iwl_umac_scan_flags * @uid: scan id, &enum iwl_umac_scan_uid_offsets @@ -636,23 +664,24 @@ struct iwl_scan_req_umac_tail { * @general_flags: &enum iwl_umac_scan_general_flags * @scan_start_mac_id: report the scan start TSF time according to this mac TSF * @extended_dwell: dwell time for channels 1, 6 and 11 - * @active_dwell: dwell time for active scan - * @passive_dwell: dwell time for passive scan + * @active_dwell: dwell time for active scan per LMAC + * @passive_dwell: dwell time for passive scan per LMAC * @fragmented_dwell: dwell time for fragmented passive scan * @adwell_default_n_aps: for adaptive dwell the default number of APs * per channel * @adwell_default_n_aps_social: for adaptive dwell the default * number of APs per social (1,6,11) channel + * @general_flags2: &enum iwl_umac_scan_general_flags2 * @adwell_max_budget: for adaptive dwell the maximal budget of TU to be added * to total scan time * @max_out_time: max out of serving channel time, per LMAC - for CDB there * are 2 LMACs * @suspend_time: max suspend time, per LMAC - for CDB there are 2 LMACs * @scan_priority: scan internal prioritization &enum iwl_scan_priority - * @channel_flags: &enum iwl_scan_channel_flags - * @n_channels: num of channels in scan request + * @num_of_fragments: Number of fragments needed for full coverage per band. + * Relevant only for fragmented scan. + * @channel: &struct iwl_scan_umac_chan_param * @reserved: for future use and alignment - * @reserved2: for future use and alignment * @reserved3: for future use and alignment * @data: &struct iwl_scan_channel_cfg_umac and * &struct iwl_scan_req_umac_tail @@ -673,10 +702,7 @@ struct iwl_scan_req_umac { __le32 max_out_time; __le32 suspend_time; __le32 scan_priority; - /* SCAN_CHANNEL_PARAMS_API_S_VER_1 */ - u8 channel_flags; - u8 n_channels; - __le16 reserved2; + struct iwl_scan_umac_chan_param channel; u8 data[]; } v1; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */ struct { @@ -687,10 +713,7 @@ struct iwl_scan_req_umac { __le32 max_out_time[SCAN_TWO_LMACS]; __le32 suspend_time[SCAN_TWO_LMACS]; __le32 scan_priority; - /* SCAN_CHANNEL_PARAMS_API_S_VER_1 */ - u8 channel_flags; - u8 n_channels; - __le16 reserved2; + struct iwl_scan_umac_chan_param channel; u8 data[]; } v6; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_6 */ struct { @@ -704,16 +727,30 @@ struct iwl_scan_req_umac { __le32 max_out_time[SCAN_TWO_LMACS]; __le32 suspend_time[SCAN_TWO_LMACS]; __le32 scan_priority; - /* SCAN_CHANNEL_PARAMS_API_S_VER_1 */ - u8 channel_flags; - u8 n_channels; - __le16 reserved2; + struct iwl_scan_umac_chan_param channel; u8 data[]; } v7; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_7 */ + struct { + u8 active_dwell[SCAN_TWO_LMACS]; + u8 reserved2; + u8 adwell_default_n_aps; + u8 adwell_default_n_aps_social; + u8 general_flags2; + __le16 adwell_max_budget; + __le32 max_out_time[SCAN_TWO_LMACS]; + __le32 suspend_time[SCAN_TWO_LMACS]; + __le32 scan_priority; + u8 passive_dwell[SCAN_TWO_LMACS]; + u8 num_of_fragments[SCAN_TWO_LMACS]; + struct iwl_scan_umac_chan_param channel; + u8 data[]; + } v8; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_8 */ }; } __packed; -#define IWL_SCAN_REQ_UMAC_SIZE_V7 sizeof(struct iwl_scan_req_umac) +#define IWL_SCAN_REQ_UMAC_SIZE_V8 sizeof(struct iwl_scan_req_umac) +#define IWL_SCAN_REQ_UMAC_SIZE_V7 (sizeof(struct iwl_scan_req_umac) - \ + 4 * sizeof(u8)) #define IWL_SCAN_REQ_UMAC_SIZE_V6 (sizeof(struct iwl_scan_req_umac) - \ 2 * sizeof(u8) - sizeof(__le16)) #define IWL_SCAN_REQ_UMAC_SIZE_V1 (sizeof(struct iwl_scan_req_umac) - \ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 7bd704a3e640..fa283285fcbe 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -68,6 +68,7 @@ #include "iwl-drv.h" #include "runtime.h" #include "dbg.h" +#include "debugfs.h" #include "iwl-io.h" #include "iwl-prph.h" #include "iwl-csr.h" @@ -1007,6 +1008,12 @@ int iwl_fw_dbg_collect(struct iwl_fw_runtime *fwrt, { struct iwl_fw_dump_desc *desc; + if (trigger && trigger->flags & IWL_FW_DBG_FORCE_RESTART) { + IWL_WARN(fwrt, "Force restart: trigger %d fired.\n", trig); + iwl_force_nmi(fwrt->trans); + return 0; + } + desc = kzalloc(sizeof(*desc) + len, GFP_ATOMIC); if (!desc) return -ENOMEM; @@ -1080,6 +1087,9 @@ int iwl_fw_start_dbg_conf(struct iwl_fw_runtime *fwrt, u8 conf_id) IWL_WARN(fwrt, "FW already configured (%d) - re-configuring\n", fwrt->dump.conf); + /* start default config marker cmd for syncing logs */ + iwl_fw_trigger_timestamp(fwrt, 1); + /* Send all HCMDs for configuring the FW debug */ ptr = (void *)&fwrt->fw->dbg_conf_tlv[conf_id]->hcmd; for (i = 0; i < fwrt->fw->dbg_conf_tlv[conf_id]->num_of_hcmds; i++) { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c index baec2fbaaf68..8f005cd69559 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c @@ -157,6 +157,20 @@ static void iwl_fw_timestamp_marker_wk(struct work_struct *work) ret, jiffies_to_msecs(delay) / 1000); } +void iwl_fw_trigger_timestamp(struct iwl_fw_runtime *fwrt, u32 delay) +{ + IWL_INFO(fwrt, + "starting timestamp_marker trigger with delay: %us\n", + delay); + + iwl_fw_cancel_timestamp(fwrt); + + fwrt->timestamp.delay = msecs_to_jiffies(delay * 1000); + + schedule_delayed_work(&fwrt->timestamp.wk, + round_jiffies_relative(fwrt->timestamp.delay)); +} + static ssize_t iwl_dbgfs_timestamp_marker_write(struct iwl_fw_runtime *fwrt, char *buf, size_t count, loff_t *ppos) @@ -168,16 +182,8 @@ static ssize_t iwl_dbgfs_timestamp_marker_write(struct iwl_fw_runtime *fwrt, if (ret < 0) return ret; - IWL_INFO(fwrt, - "starting timestamp_marker trigger with delay: %us\n", - delay); + iwl_fw_trigger_timestamp(fwrt, delay); - iwl_fw_cancel_timestamp(fwrt); - - fwrt->timestamp.delay = msecs_to_jiffies(delay * 1000); - - schedule_delayed_work(&fwrt->timestamp.wk, - round_jiffies_relative(fwrt->timestamp.delay)); return count; } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h index 3da468d2cc92..d93f6a4bb22d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.h @@ -89,6 +89,8 @@ static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) round_jiffies_relative(fwrt->timestamp.delay)); } +void iwl_fw_trigger_timestamp(struct iwl_fw_runtime *fwrt, u32 delay); + #else static inline int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, struct dentry *dbgfs_dir) @@ -102,4 +104,7 @@ static inline void iwl_fw_suspend_timestamp(struct iwl_fw_runtime *fwrt) {} static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {} +static inline void iwl_fw_trigger_timestamp(struct iwl_fw_runtime *fwrt, + u32 delay) {} + #endif /* CONFIG_IWLWIFI_DEBUGFS */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index 1a05d506ac9a..9b2805e1e3b1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -250,6 +250,8 @@ typedef unsigned int __bitwise iwl_ucode_tlv_api_t; * indicating low latency direction. * @IWL_UCODE_TLV_API_DEPRECATE_TTAK: RX status flag TTAK ok (bit 7) is * deprecated. + * @IWL_UCODE_TLV_API_ADAPTIVE_DWELL_V2: This ucode supports version 8 + * of scan request: SCAN_REQUEST_CMD_UMAC_API_S_VER_8 * * @NUM_IWL_UCODE_TLV_API: number of bits used */ @@ -265,10 +267,12 @@ enum iwl_ucode_tlv_api { IWL_UCODE_TLV_API_NAN2_VER2 = (__force iwl_ucode_tlv_api_t)31, /* API Set 1 */ IWL_UCODE_TLV_API_ADAPTIVE_DWELL = (__force iwl_ucode_tlv_api_t)32, + IWL_UCODE_TLV_API_OCE = (__force iwl_ucode_tlv_api_t)33, IWL_UCODE_TLV_API_NEW_BEACON_TEMPLATE = (__force iwl_ucode_tlv_api_t)34, IWL_UCODE_TLV_API_NEW_RX_STATS = (__force iwl_ucode_tlv_api_t)35, IWL_UCODE_TLV_API_QUOTA_LOW_LATENCY = (__force iwl_ucode_tlv_api_t)38, IWL_UCODE_TLV_API_DEPRECATE_TTAK = (__force iwl_ucode_tlv_api_t)41, + IWL_UCODE_TLV_API_ADAPTIVE_DWELL_V2 = (__force iwl_ucode_tlv_api_t)42, NUM_IWL_UCODE_TLV_API #ifdef __CHECKER__ @@ -441,6 +445,7 @@ enum iwl_fw_phy_cfg { FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS, FW_PHY_CFG_RX_CHAIN_POS = 20, FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS, + FW_PHY_CFG_SHARED_CLK = BIT(31), }; #define IWL_UCODE_MAX_CS 1 @@ -616,6 +621,14 @@ enum iwl_fw_dbg_trigger_mode { }; /** + * enum iwl_fw_dbg_trigger_flags - the flags supported by wrt triggers + * @IWL_FW_DBG_FORCE_RESTART: force a firmware restart + */ +enum iwl_fw_dbg_trigger_flags { + IWL_FW_DBG_FORCE_RESTART = BIT(0), +}; + +/** * enum iwl_fw_dbg_trigger_vif_type - define the VIF type for a trigger * @IWL_FW_DBG_CONF_VIF_ANY: any vif type * @IWL_FW_DBG_CONF_VIF_IBSS: IBSS mode @@ -651,6 +664,7 @@ enum iwl_fw_dbg_trigger_vif_type { * @occurrences: number of occurrences. 0 means the trigger will never fire. * @trig_dis_ms: the time, in milliseconds, after an occurrence of this * trigger in which another occurrence should be ignored. + * @flags: &enum iwl_fw_dbg_trigger_flags */ struct iwl_fw_dbg_trigger_tlv { __le32 id; @@ -661,7 +675,8 @@ struct iwl_fw_dbg_trigger_tlv { u8 start_conf_id; __le16 occurrences; __le16 trig_dis_ms; - __le16 reserved[3]; + u8 flags; + u8 reserved[5]; u8 data[0]; } __packed; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 258d439bb0a9..f0f5636dd3ea 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -398,6 +398,7 @@ struct iwl_cfg { u8 ucode_api_max; u8 ucode_api_min; u32 min_umac_error_event_table; + u32 extra_phy_cfg_flags; }; /* @@ -477,6 +478,10 @@ extern const struct iwl_cfg iwl9460_2ac_cfg_soc; extern const struct iwl_cfg iwl9461_2ac_cfg_soc; extern const struct iwl_cfg iwl9462_2ac_cfg_soc; extern const struct iwl_cfg iwl9560_2ac_cfg_soc; +extern const struct iwl_cfg iwl9460_2ac_cfg_shared_clk; +extern const struct iwl_cfg iwl9461_2ac_cfg_shared_clk; +extern const struct iwl_cfg iwl9462_2ac_cfg_shared_clk; +extern const struct iwl_cfg iwl9560_2ac_cfg_shared_clk; extern const struct iwl_cfg iwl22000_2ac_cfg_hr; extern const struct iwl_cfg iwl22000_2ac_cfg_hr_cdb; extern const struct iwl_cfg iwl22000_2ac_cfg_jf; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h index 976640fed334..96b52a275ee3 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/constants.h @@ -110,6 +110,8 @@ #define IWL_MVM_SW_TX_CSUM_OFFLOAD 0 #define IWL_MVM_HW_CSUM_DISABLE 0 #define IWL_MVM_PARSE_NVM 0 +#define IWL_MVM_ADWELL_ENABLE 1 +#define IWL_MVM_ADWELL_MAX_BUDGET 0 #define IWL_MVM_RS_NUM_TRY_BEFORE_ANT_TOGGLE 1 #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE 2 #define IWL_MVM_RS_HT_VHT_RETRIES_PER_RATE_TW 1 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c index 4e9d1792baf3..f7fcf700196b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs-vif.c @@ -1276,7 +1276,6 @@ static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm *mvm = mvmvif->mvm; - bool prev; u8 value; int ret; @@ -1287,9 +1286,7 @@ static ssize_t iwl_dbgfs_low_latency_write(struct ieee80211_vif *vif, char *buf, return -EINVAL; mutex_lock(&mvm->mutex); - prev = iwl_mvm_vif_low_latency(mvmvif); - mvmvif->low_latency_dbgfs = value; - iwl_mvm_update_low_latency(mvm, vif, prev); + iwl_mvm_update_low_latency(mvm, vif, value, LOW_LATENCY_DEBUGFS); mutex_unlock(&mvm->mutex); return count; @@ -1306,9 +1303,9 @@ static ssize_t iwl_dbgfs_low_latency_read(struct file *file, len = scnprintf(buf, sizeof(buf) - 1, "traffic=%d\ndbgfs=%d\nvcmd=%d\n", - mvmvif->low_latency_traffic, - mvmvif->low_latency_dbgfs, - mvmvif->low_latency_vcmd); + !!(mvmvif->low_latency & LOW_LATENCY_TRAFFIC), + !!(mvmvif->low_latency & LOW_LATENCY_DEBUGFS), + !!(mvmvif->low_latency & LOW_LATENCY_VCMD)); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 0920be637b57..3c59109bea20 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -433,6 +433,10 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) /* Set parameters */ phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_get_phy_config(mvm)); + + /* set flags extra PHY configuration flags from the device's cfg */ + phy_cfg_cmd.phy_cfg |= cpu_to_le32(mvm->cfg->extra_phy_cfg_flags); + phy_cfg_cmd.calib_control.event_trigger = mvm->fw->default_calib[ucode_type].event_trigger; phy_cfg_cmd.calib_control.flow_trigger = diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index ebf511150f4d..51b30424575b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -421,6 +421,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS); ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); ieee80211_hw_set(hw, NEEDS_UNIQUE_STA_ADDR); + ieee80211_hw_set(hw, DEAUTH_NEED_MGD_TX_PREP); if (iwl_mvm_has_tlc_offload(mvm)) { ieee80211_hw_set(hw, TX_AMPDU_SETUP_IN_HW); @@ -661,6 +662,17 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) NL80211_EXT_FEATURE_SET_SCAN_DWELL); } + if (iwl_mvm_is_oce_supported(mvm)) { + wiphy_ext_feature_set(hw->wiphy, + NL80211_EXT_FEATURE_ACCEPT_BCAST_PROBE_RESP); + wiphy_ext_feature_set(hw->wiphy, + NL80211_EXT_FEATURE_FILS_MAX_CHANNEL_TIME); + wiphy_ext_feature_set(hw->wiphy, + NL80211_EXT_FEATURE_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION); + wiphy_ext_feature_set(hw->wiphy, + NL80211_EXT_FEATURE_OCE_PROBE_REQ_HIGH_TX_RATE); + } + mvm->rts_threshold = IEEE80211_MAX_RTS_THRESHOLD; #ifdef CONFIG_PM_SLEEP @@ -2132,10 +2144,10 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, * Send the bcast station. At this stage the TBTT and DTIM time * events are added and applied to the scheduler */ - iwl_mvm_send_add_bcast_sta(mvm, vif); + ret = iwl_mvm_send_add_bcast_sta(mvm, vif); if (ret) goto out_unbind; - iwl_mvm_add_mcast_sta(mvm, vif); + ret = iwl_mvm_add_mcast_sta(mvm, vif); if (ret) { iwl_mvm_send_rm_bcast_sta(mvm, vif); goto out_unbind; @@ -2804,9 +2816,6 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw, u32 duration = IWL_MVM_TE_SESSION_PROTECTION_MAX_TIME_MS; u32 min_duration = IWL_MVM_TE_SESSION_PROTECTION_MIN_TIME_MS; - if (WARN_ON_ONCE(vif->bss_conf.assoc)) - return; - /* * iwl_mvm_protect_session() reads directly from the device * (the system time), so make sure it is available. @@ -3494,6 +3503,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, ret = 0; goto out; case NL80211_IFTYPE_STATION: + mvmvif->csa_bcn_pending = false; break; case NL80211_IFTYPE_MONITOR: /* always disable PS when a monitor interface is active */ @@ -3537,7 +3547,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, } if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) { - u32 duration = 2 * vif->bss_conf.beacon_int; + u32 duration = 3 * vif->bss_conf.beacon_int; /* iwl_mvm_protect_session() reads directly from the * device (the system time), so make sure it is @@ -3550,6 +3560,7 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm, /* Protect the session to make sure we hear the first * beacon on the new channel. */ + mvmvif->csa_bcn_pending = true; iwl_mvm_protect_session(mvm, vif, duration, duration, vif->bss_conf.beacon_int / 2, true); @@ -3988,6 +3999,7 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw, if (vif->type == NL80211_IFTYPE_STATION) { struct iwl_mvm_sta *mvmsta; + mvmvif->csa_bcn_pending = false; mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 89ff02d7c876..d2cf751db68d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -300,6 +300,18 @@ enum iwl_bt_force_ant_mode { }; /** +* struct iwl_mvm_low_latency_cause - low latency set causes +* @LOW_LATENCY_TRAFFIC: indicates low latency traffic was detected +* @LOW_LATENCY_DEBUGFS: low latency mode set from debugfs +* @LOW_LATENCY_VCMD: low latency mode set from vendor command +*/ +enum iwl_mvm_low_latency_cause { + LOW_LATENCY_TRAFFIC = BIT(0), + LOW_LATENCY_DEBUGFS = BIT(1), + LOW_LATENCY_VCMD = BIT(2), +}; + +/** * struct iwl_mvm_vif_bf_data - beacon filtering related data * @bf_enabled: indicates if beacon filtering is enabled * @ba_enabled: indicated if beacon abort is enabled @@ -335,9 +347,8 @@ struct iwl_mvm_vif_bf_data { * @pm_enabled - Indicate if MAC power management is allowed * @monitor_active: indicates that monitor context is configured, and that the * interface should get quota etc. - * @low_latency_traffic: indicates low latency traffic was detected - * @low_latency_dbgfs: low latency mode set from debugfs - * @low_latency_vcmd: low latency mode set from vendor command + * @low_latency: indicates low latency is set, see + * enum &iwl_mvm_low_latency_cause for causes. * @ps_disabled: indicates that this interface requires PS to be disabled * @queue_params: QoS params for this MAC * @bcast_sta: station used for broadcast packets. Used by the following @@ -367,7 +378,7 @@ struct iwl_mvm_vif { bool ap_ibss_active; bool pm_enabled; bool monitor_active; - bool low_latency_traffic, low_latency_dbgfs, low_latency_vcmd; + u8 low_latency; bool ps_disabled; struct iwl_mvm_vif_bf_data bf_data; @@ -438,6 +449,9 @@ struct iwl_mvm_vif { bool csa_failed; u16 csa_target_freq; + /* Indicates that we are waiting for a beacon on a new channel */ + bool csa_bcn_pending; + /* TCP Checksum Offload */ netdev_features_t features; }; @@ -1152,6 +1166,18 @@ static inline bool iwl_mvm_is_adaptive_dwell_supported(struct iwl_mvm *mvm) IWL_UCODE_TLV_API_ADAPTIVE_DWELL); } +static inline bool iwl_mvm_is_adaptive_dwell_v2_supported(struct iwl_mvm *mvm) +{ + return fw_has_api(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_API_ADAPTIVE_DWELL_V2); +} + +static inline bool iwl_mvm_is_oce_supported(struct iwl_mvm *mvm) +{ + /* OCE should never be enabled for LMAC scan FWs */ + return fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_OCE); +} + static inline bool iwl_mvm_enter_d0i3_on_suspend(struct iwl_mvm *mvm) { /* For now we only use this mode to differentiate between @@ -1741,7 +1767,8 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm); /* Low latency */ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - bool value); + bool low_latency, + enum iwl_mvm_low_latency_cause cause); /* get SystemLowLatencyMode - only needed for beacon threshold? */ bool iwl_mvm_low_latency(struct iwl_mvm *mvm); /* get VMACLowLatencyMode */ @@ -1757,9 +1784,17 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif) * binding, so this has no real impact. For now, just return * the current desired low-latency state. */ - return mvmvif->low_latency_dbgfs || - mvmvif->low_latency_traffic || - mvmvif->low_latency_vcmd; + return mvmvif->low_latency; +} + +static inline +void iwl_mvm_vif_set_low_latency(struct iwl_mvm_vif *mvmvif, bool set, + enum iwl_mvm_low_latency_cause cause) +{ + if (set) + mvmvif->low_latency |= cause; + else + mvmvif->low_latency &= ~cause; } /* hw scheduler queue config */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c index 305cd56bf746..7f5434b34d0d 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/phy-ctxt.c @@ -8,6 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -18,11 +19,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * * The full GNU General Public License is included in this distribution * in the file called COPYING. * @@ -34,6 +30,7 @@ * * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -286,6 +283,20 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt) return; ctxt->ref--; + + /* + * Move unused phy's to a default channel. When the phy is moved the, + * fw will cleanup immediate quiet bit if it was previously set, + * otherwise we might not be able to reuse this phy. + */ + if (ctxt->ref == 0) { + struct ieee80211_channel *chan; + struct cfg80211_chan_def chandef; + + chan = &mvm->hw->wiphy->bands[NL80211_BAND_2GHZ]->channels[0]; + cfg80211_chandef_create(&chandef, chan, NL80211_CHAN_NO_HT); + iwl_mvm_phy_ctxt_changed(mvm, ctxt, &chandef, 1, 1); + } } static void iwl_mvm_binding_iterator(void *_data, u8 *mac, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c index 55d1274c6092..fb5745660509 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c @@ -234,13 +234,15 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt) struct iwl_mvm_sta *mvmsta; struct iwl_lq_sta_rs_fw *lq_sta; + rcu_read_lock(); + notif = (void *)pkt->data; mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, notif->sta_id); if (!mvmsta) { IWL_ERR(mvm, "Invalid sta id (%d) in FW TLC notification\n", notif->sta_id); - return; + goto out; } lq_sta = &mvmsta->lq_sta.rs_fw; @@ -251,6 +253,8 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt) IWL_DEBUG_RATE(mvm, "new rate_n_flags: 0x%X\n", lq_sta->last_rate_n_flags); } +out: + rcu_read_unlock(); } void rs_fw_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 580de5851fc7..4a4ccfd11e5b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -831,6 +831,16 @@ out: rcu_read_unlock(); } +static void iwl_mvm_flip_address(u8 *addr) +{ + int i; + u8 mac_addr[ETH_ALEN]; + + for (i = 0; i < ETH_ALEN; i++) + mac_addr[i] = addr[ETH_ALEN - i - 1]; + ether_addr_copy(addr, mac_addr); +} + void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, struct iwl_rx_cmd_buffer *rxb, int queue) { @@ -985,21 +995,16 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, */ if ((desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU) && !WARN_ON(!ieee80211_is_data_qos(hdr->frame_control))) { - int i; u8 *qc = ieee80211_get_qos_ctl(hdr); - u8 mac_addr[ETH_ALEN]; *qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; - for (i = 0; i < ETH_ALEN; i++) - mac_addr[i] = hdr->addr3[ETH_ALEN - i - 1]; - ether_addr_copy(hdr->addr3, mac_addr); + if (mvm->trans->cfg->device_family == + IWL_DEVICE_FAMILY_9000) { + iwl_mvm_flip_address(hdr->addr3); - if (ieee80211_has_a4(hdr->frame_control)) { - for (i = 0; i < ETH_ALEN; i++) - mac_addr[i] = - hdr->addr4[ETH_ALEN - i - 1]; - ether_addr_copy(hdr->addr4, mac_addr); + if (ieee80211_has_a4(hdr->frame_control)) + iwl_mvm_flip_address(hdr->addr4); } } if (baid != IWL_RX_REORDER_DATA_INVALID_BAID) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 356b16f40e78..b31f0ffbbbf0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -35,6 +35,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -85,6 +86,17 @@ enum iwl_mvm_traffic_load { #define IWL_SCAN_DWELL_PASSIVE 110 #define IWL_SCAN_DWELL_FRAGMENTED 44 #define IWL_SCAN_DWELL_EXTENDED 90 +#define IWL_SCAN_NUM_OF_FRAGS 3 + + +/* adaptive dwell max budget time [TU] for full scan */ +#define IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN 300 +/* adaptive dwell max budget time [TU] for directed scan */ +#define IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN 100 +/* adaptive dwell default APs number */ +#define IWL_SCAN_ADWELL_DEFAULT_N_APS 2 +/* adaptive dwell default APs number in social channels (1, 6, 11) */ +#define IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL 10 struct iwl_mvm_scan_timing_params { u32 suspend_time; @@ -134,6 +146,9 @@ static inline void *iwl_mvm_get_scan_req_umac_data(struct iwl_mvm *mvm) { struct iwl_scan_req_umac *cmd = mvm->scan_cmd; + if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm)) + return (void *)&cmd->v8.data; + if (iwl_mvm_is_adaptive_dwell_supported(mvm)) return (void *)&cmd->v7.data; @@ -143,6 +158,23 @@ static inline void *iwl_mvm_get_scan_req_umac_data(struct iwl_mvm *mvm) return (void *)&cmd->v1.data; } +static inline struct iwl_scan_umac_chan_param * +iwl_mvm_get_scan_req_umac_channel(struct iwl_mvm *mvm) +{ + struct iwl_scan_req_umac *cmd = mvm->scan_cmd; + + if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm)) + return &cmd->v8.channel; + + if (iwl_mvm_is_adaptive_dwell_supported(mvm)) + return &cmd->v7.channel; + + if (iwl_mvm_has_new_tx_api(mvm)) + return &cmd->v6.channel; + + return &cmd->v1.channel; +} + static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm) { if (mvm->scan_rx_ant != ANT_NONE) @@ -1113,66 +1145,92 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm, struct iwl_scan_req_umac *cmd, struct iwl_mvm_scan_params *params) { - struct iwl_mvm_scan_timing_params *timing = &scan_timing[params->type]; + struct iwl_mvm_scan_timing_params *timing, *hb_timing; + u8 active_dwell, passive_dwell; - if (iwl_mvm_is_regular_scan(params)) - cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6); - else - cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_2); + timing = &scan_timing[params->type]; + active_dwell = params->measurement_dwell ? + params->measurement_dwell : IWL_SCAN_DWELL_ACTIVE; + passive_dwell = params->measurement_dwell ? + params->measurement_dwell : IWL_SCAN_DWELL_PASSIVE; if (iwl_mvm_is_adaptive_dwell_supported(mvm)) { - if (params->measurement_dwell) { - cmd->v7.active_dwell = params->measurement_dwell; - cmd->v7.passive_dwell = params->measurement_dwell; - } else { - cmd->v7.active_dwell = IWL_SCAN_DWELL_ACTIVE; - cmd->v7.passive_dwell = IWL_SCAN_DWELL_PASSIVE; - } - cmd->v7.fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED; + cmd->v7.adwell_default_n_aps_social = + IWL_SCAN_ADWELL_DEFAULT_N_APS_SOCIAL; + cmd->v7.adwell_default_n_aps = + IWL_SCAN_ADWELL_DEFAULT_N_APS; + + /* if custom max budget was configured with debugfs */ + if (IWL_MVM_ADWELL_MAX_BUDGET) + cmd->v7.adwell_max_budget = + cpu_to_le16(IWL_MVM_ADWELL_MAX_BUDGET); + else if (params->ssids && params->ssids[0].ssid_len) + cmd->v7.adwell_max_budget = + cpu_to_le16(IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN); + else + cmd->v7.adwell_max_budget = + cpu_to_le16(IWL_SCAN_ADWELL_MAX_BUDGET_FULL_SCAN); cmd->v7.scan_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6); cmd->v7.max_out_time[SCAN_LB_LMAC_IDX] = cpu_to_le32(timing->max_out_time); cmd->v7.suspend_time[SCAN_LB_LMAC_IDX] = cpu_to_le32(timing->suspend_time); + if (iwl_mvm_is_cdb_supported(mvm)) { + hb_timing = &scan_timing[params->type]; + cmd->v7.max_out_time[SCAN_HB_LMAC_IDX] = - cpu_to_le32(timing->max_out_time); + cpu_to_le32(hb_timing->max_out_time); cmd->v7.suspend_time[SCAN_HB_LMAC_IDX] = - cpu_to_le32(timing->suspend_time); + cpu_to_le32(hb_timing->suspend_time); } - return; - } - - if (params->measurement_dwell) { - cmd->v1.active_dwell = params->measurement_dwell; - cmd->v1.passive_dwell = params->measurement_dwell; - cmd->v1.extended_dwell = params->measurement_dwell; + if (!iwl_mvm_is_adaptive_dwell_v2_supported(mvm)) { + cmd->v7.active_dwell = active_dwell; + cmd->v7.passive_dwell = passive_dwell; + cmd->v7.fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED; + } else { + cmd->v8.active_dwell[SCAN_LB_LMAC_IDX] = active_dwell; + cmd->v8.passive_dwell[SCAN_LB_LMAC_IDX] = passive_dwell; + if (iwl_mvm_is_cdb_supported(mvm)) { + cmd->v8.active_dwell[SCAN_HB_LMAC_IDX] = + active_dwell; + cmd->v8.passive_dwell[SCAN_HB_LMAC_IDX] = + passive_dwell; + } + } } else { - cmd->v1.active_dwell = IWL_SCAN_DWELL_ACTIVE; - cmd->v1.passive_dwell = IWL_SCAN_DWELL_PASSIVE; - cmd->v1.extended_dwell = IWL_SCAN_DWELL_EXTENDED; - } - cmd->v1.fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED; + cmd->v1.extended_dwell = params->measurement_dwell ? + params->measurement_dwell : IWL_SCAN_DWELL_EXTENDED; + cmd->v1.active_dwell = active_dwell; + cmd->v1.passive_dwell = passive_dwell; + cmd->v1.fragmented_dwell = IWL_SCAN_DWELL_FRAGMENTED; - if (iwl_mvm_has_new_tx_api(mvm)) { - cmd->v6.scan_priority = cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6); - cmd->v6.max_out_time[SCAN_LB_LMAC_IDX] = - cpu_to_le32(timing->max_out_time); - cmd->v6.suspend_time[SCAN_LB_LMAC_IDX] = - cpu_to_le32(timing->suspend_time); if (iwl_mvm_is_cdb_supported(mvm)) { + hb_timing = &scan_timing[params->type]; + cmd->v6.max_out_time[SCAN_HB_LMAC_IDX] = - cpu_to_le32(timing->max_out_time); + cpu_to_le32(hb_timing->max_out_time); cmd->v6.suspend_time[SCAN_HB_LMAC_IDX] = + cpu_to_le32(hb_timing->suspend_time); + } + + if (iwl_mvm_has_new_tx_api(mvm)) { + cmd->v6.scan_priority = + cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6); + cmd->v6.max_out_time[SCAN_LB_LMAC_IDX] = + cpu_to_le32(timing->max_out_time); + cmd->v6.suspend_time[SCAN_LB_LMAC_IDX] = + cpu_to_le32(timing->suspend_time); + } else { + cmd->v1.scan_priority = + cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6); + cmd->v1.max_out_time = + cpu_to_le32(timing->max_out_time); + cmd->v1.suspend_time = cpu_to_le32(timing->suspend_time); } - } else { - cmd->v1.max_out_time = cpu_to_le32(timing->max_out_time); - cmd->v1.suspend_time = cpu_to_le32(timing->suspend_time); - cmd->v1.scan_priority = - cpu_to_le32(IWL_SCAN_PRIORITY_EXT_6); } } @@ -1234,11 +1292,39 @@ static u16 iwl_mvm_scan_umac_flags(struct iwl_mvm *mvm, if (mvm->sched_scan_pass_all == SCHED_SCAN_PASS_ALL_ENABLED) flags |= IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE; + if (iwl_mvm_is_adaptive_dwell_supported(mvm) && IWL_MVM_ADWELL_ENABLE && + vif->type != NL80211_IFTYPE_P2P_DEVICE) + flags |= IWL_UMAC_SCAN_GEN_FLAGS_ADAPTIVE_DWELL; + + /* + * Extended dwell is relevant only for low band to start with, as it is + * being used for social channles only (1, 6, 11), so we can check + * only scan type on low band also for CDB. + */ if (iwl_mvm_is_regular_scan(params) && vif->type != NL80211_IFTYPE_P2P_DEVICE && - params->type != IWL_SCAN_TYPE_FRAGMENTED) + params->type != IWL_SCAN_TYPE_FRAGMENTED && + !iwl_mvm_is_adaptive_dwell_supported(mvm) && + !iwl_mvm_is_oce_supported(mvm)) flags |= IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL; + if (iwl_mvm_is_oce_supported(mvm)) { + if ((params->flags & + NL80211_SCAN_FLAG_OCE_PROBE_REQ_HIGH_TX_RATE)) + flags |= IWL_UMAC_SCAN_GEN_FLAGS_PROB_REQ_HIGH_TX_RATE; + /* Since IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL and + * NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION shares + * the same bit, we need to make sure that we use this bit here + * only when IWL_UMAC_SCAN_GEN_FLAGS_EXTENDED_DWELL cannot be + * used. */ + if ((params->flags & + NL80211_SCAN_FLAG_OCE_PROBE_REQ_DEFERRAL_SUPPRESSION) && + !WARN_ON_ONCE(!iwl_mvm_is_adaptive_dwell_supported(mvm))) + flags |= IWL_UMAC_SCAN_GEN_FLAGS_PROB_REQ_DEFER_SUPP; + if ((params->flags & NL80211_SCAN_FLAG_FILS_MAX_CHANNEL_TIME)) + flags |= IWL_UMAC_SCAN_GEN_FLAGS_MAX_CHNL_TIME; + } + return flags; } @@ -1247,6 +1333,7 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int type) { struct iwl_scan_req_umac *cmd = mvm->scan_cmd; + struct iwl_scan_umac_chan_param *chan_param; void *cmd_data = iwl_mvm_get_scan_req_umac_data(mvm); struct iwl_scan_req_umac_tail *sec_part = cmd_data + sizeof(struct iwl_scan_channel_cfg_umac) * @@ -1254,8 +1341,11 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int uid, i; u32 ssid_bitmap = 0; u8 channel_flags = 0; + u16 gen_flags; struct iwl_mvm_vif *scan_vif = iwl_mvm_vif_from_mac80211(vif); + chan_param = iwl_mvm_get_scan_req_umac_channel(mvm); + lockdep_assert_held(&mvm->mutex); if (WARN_ON(params->n_scan_plans > IWL_MAX_SCHED_SCAN_PLANS)) @@ -1272,8 +1362,17 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, mvm->scan_uid_status[uid] = type; cmd->uid = cpu_to_le32(uid); - cmd->general_flags = cpu_to_le16(iwl_mvm_scan_umac_flags(mvm, params, - vif)); + gen_flags = iwl_mvm_scan_umac_flags(mvm, params, vif); + cmd->general_flags = cpu_to_le16(gen_flags); + if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm)) { + if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED) + cmd->v8.num_of_fragments[SCAN_LB_LMAC_IDX] = + IWL_SCAN_NUM_OF_FRAGS; + if (gen_flags & IWL_UMAC_SCAN_GEN_FLAGS_LMAC2_FRAGMENTED) + cmd->v8.num_of_fragments[SCAN_HB_LMAC_IDX] = + IWL_SCAN_NUM_OF_FRAGS; + } + cmd->scan_start_mac_id = scan_vif->id; if (type == IWL_MVM_SCAN_SCHED || type == IWL_MVM_SCAN_NETDETECT) @@ -1284,16 +1383,8 @@ static int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif, IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE | IWL_SCAN_CHANNEL_FLAG_CACHE_ADD; - if (iwl_mvm_is_adaptive_dwell_supported(mvm)) { - cmd->v7.channel_flags = channel_flags; - cmd->v7.n_channels = params->n_channels; - } else if (iwl_mvm_has_new_tx_api(mvm)) { - cmd->v6.channel_flags = channel_flags; - cmd->v6.n_channels = params->n_channels; - } else { - cmd->v1.channel_flags = channel_flags; - cmd->v1.n_channels = params->n_channels; - } + chan_param->flags = channel_flags; + chan_param->count = params->n_channels; iwl_scan_build_ssids(params, sec_part->direct_scan, &ssid_bitmap); @@ -1732,7 +1823,9 @@ int iwl_mvm_scan_size(struct iwl_mvm *mvm) { int base_size = IWL_SCAN_REQ_UMAC_SIZE_V1; - if (iwl_mvm_is_adaptive_dwell_supported(mvm)) + if (iwl_mvm_is_adaptive_dwell_v2_supported(mvm)) + base_size = IWL_SCAN_REQ_UMAC_SIZE_V8; + else if (iwl_mvm_is_adaptive_dwell_supported(mvm)) base_size = IWL_SCAN_REQ_UMAC_SIZE_V7; else if (iwl_mvm_has_new_tx_api(mvm)) base_size = IWL_SCAN_REQ_UMAC_SIZE_V6; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 630e23cb0ffb..80067eb9ea05 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1695,7 +1695,8 @@ int iwl_mvm_allocate_int_sta(struct iwl_mvm *mvm, u32 qmask, enum nl80211_iftype iftype, enum iwl_sta_type type) { - if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { + if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) || + sta->sta_id == IWL_MVM_INVALID_STA) { sta->sta_id = iwl_mvm_find_free_sta_id(mvm, iftype); if (WARN_ON_ONCE(sta->sta_id == IWL_MVM_INVALID_STA)) return -ENOSPC; @@ -2478,28 +2479,12 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, /* * Note the possible cases: - * 1. In DQA mode with an enabled TXQ - TXQ needs to become agg'ed - * 2. Non-DQA mode: the TXQ hasn't yet been enabled, so find a free - * one and mark it as reserved - * 3. In DQA mode, but no traffic yet on this TID: same treatment as in - * non-DQA mode, since the TXQ hasn't yet been allocated - * Don't support case 3 for new TX path as it is not expected to happen - * and aggregation will be offloaded soon anyway + * 1. An enabled TXQ - TXQ needs to become agg'ed + * 2. The TXQ hasn't yet been enabled, so find a free one and mark + * it as reserved */ txq_id = mvmsta->tid_data[tid].txq_id; - if (iwl_mvm_has_new_tx_api(mvm)) { - if (txq_id == IWL_MVM_INVALID_QUEUE) { - ret = -ENXIO; - goto release_locks; - } - } else if (unlikely(mvm->queue_info[txq_id].status == - IWL_MVM_QUEUE_SHARED)) { - ret = -ENXIO; - IWL_DEBUG_TX_QUEUES(mvm, - "Can't start tid %d agg on shared queue!\n", - tid); - goto release_locks; - } else if (mvm->queue_info[txq_id].status != IWL_MVM_QUEUE_READY) { + if (txq_id == IWL_MVM_INVALID_QUEUE) { txq_id = iwl_mvm_find_free_queue(mvm, mvmsta->sta_id, IWL_MVM_DQA_MIN_DATA_QUEUE, IWL_MVM_DQA_MAX_DATA_QUEUE); @@ -2508,16 +2493,16 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, IWL_ERR(mvm, "Failed to allocate agg queue\n"); goto release_locks; } - /* - * TXQ shouldn't be in inactive mode for non-DQA, so getting - * an inactive queue from iwl_mvm_find_free_queue() is - * certainly a bug - */ - WARN_ON(mvm->queue_info[txq_id].status == - IWL_MVM_QUEUE_INACTIVE); /* TXQ hasn't yet been enabled, so mark it only as reserved */ mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_RESERVED; + } else if (unlikely(mvm->queue_info[txq_id].status == + IWL_MVM_QUEUE_SHARED)) { + ret = -ENXIO; + IWL_DEBUG_TX_QUEUES(mvm, + "Can't start tid %d agg on shared queue!\n", + tid); + goto release_locks; } spin_unlock(&mvm->queue_info_lock); @@ -2696,8 +2681,10 @@ out: static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, - u16 txq_id) + struct iwl_mvm_tid_data *tid_data) { + u16 txq_id = tid_data->txq_id; + if (iwl_mvm_has_new_tx_api(mvm)) return; @@ -2709,8 +2696,10 @@ static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm, * allocated through iwl_mvm_enable_txq, so we can just mark it back as * free. */ - if (mvm->queue_info[txq_id].status == IWL_MVM_QUEUE_RESERVED) + if (mvm->queue_info[txq_id].status == IWL_MVM_QUEUE_RESERVED) { mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_FREE; + tid_data->txq_id = IWL_MVM_INVALID_QUEUE; + } spin_unlock_bh(&mvm->queue_info_lock); } @@ -2741,7 +2730,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, mvmsta->agg_tids &= ~BIT(tid); - iwl_mvm_unreserve_agg_queue(mvm, mvmsta, txq_id); + iwl_mvm_unreserve_agg_queue(mvm, mvmsta, tid_data); switch (tid_data->state) { case IWL_AGG_ON: @@ -2808,7 +2797,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif, mvmsta->agg_tids &= ~BIT(tid); spin_unlock_bh(&mvmsta->lock); - iwl_mvm_unreserve_agg_queue(mvm, mvmsta, txq_id); + iwl_mvm_unreserve_agg_queue(mvm, mvmsta, tid_data); if (old_state >= IWL_AGG_ON) { iwl_mvm_drain_sta(mvm, mvmsta, true); @@ -3233,17 +3222,9 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, } sta_id = mvm_sta->sta_id; - if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC || - keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || - keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) { - ret = iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, - false); - goto end; - } - /* * It is possible that the 'sta' parameter is NULL, and thus - * there is a need to retrieve the sta from the local station + * there is a need to retrieve the sta from the local station * table. */ if (!sta) { @@ -3258,6 +3239,17 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm, if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif)) return -EINVAL; + } else { + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + + sta_id = mvmvif->mcast_sta.sta_id; + } + + if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC || + keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || + keyconf->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256) { + ret = iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, false); + goto end; } /* If the key_offset is not pre-assigned, we need to find a diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index acb217e666db..cd91bc44259c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -8,6 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -18,11 +19,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * * The full GNU General Public License is included in this distribution * in the file called COPYING. * @@ -35,6 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -198,9 +195,13 @@ static bool iwl_mvm_te_check_disconnect(struct iwl_mvm *mvm, struct ieee80211_vif *vif, const char *errmsg) { + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + if (vif->type != NL80211_IFTYPE_STATION) return false; - if (vif->bss_conf.assoc && vif->bss_conf.dtim_period) + + if (!mvmvif->csa_bcn_pending && vif->bss_conf.assoc && + vif->bss_conf.dtim_period) return false; if (errmsg) IWL_ERR(mvm, "%s\n", errmsg); @@ -344,7 +345,7 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, * and know the dtim period. */ iwl_mvm_te_check_disconnect(mvm, te_data->vif, - "No association and the time event is over already..."); + "No beacon heard and the time event is over already..."); break; default: break; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index af6dfceab6b8..795065974d78 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -687,6 +687,74 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) } #ifdef CONFIG_INET + +static int +iwl_mvm_tx_tso_segment(struct sk_buff *skb, unsigned int num_subframes, + netdev_features_t netdev_flags, + struct sk_buff_head *mpdus_skb) +{ + struct sk_buff *tmp, *next; + struct ieee80211_hdr *hdr = (void *)skb->data; + char cb[sizeof(skb->cb)]; + u16 i = 0; + unsigned int tcp_payload_len; + unsigned int mss = skb_shinfo(skb)->gso_size; + bool ipv4 = (skb->protocol == htons(ETH_P_IP)); + u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0; + + skb_shinfo(skb)->gso_size = num_subframes * mss; + memcpy(cb, skb->cb, sizeof(cb)); + + next = skb_gso_segment(skb, netdev_flags); + skb_shinfo(skb)->gso_size = mss; + if (WARN_ON_ONCE(IS_ERR(next))) + return -EINVAL; + else if (next) + consume_skb(skb); + + while (next) { + tmp = next; + next = tmp->next; + + memcpy(tmp->cb, cb, sizeof(tmp->cb)); + /* + * Compute the length of all the data added for the A-MSDU. + * This will be used to compute the length to write in the TX + * command. We have: SNAP + IP + TCP for n -1 subframes and + * ETH header for n subframes. + */ + tcp_payload_len = skb_tail_pointer(tmp) - + skb_transport_header(tmp) - + tcp_hdrlen(tmp) + tmp->data_len; + + if (ipv4) + ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes); + + if (tcp_payload_len > mss) { + skb_shinfo(tmp)->gso_size = mss; + } else { + if (ieee80211_is_data_qos(hdr->frame_control)) { + u8 *qc; + + if (ipv4) + ip_send_check(ip_hdr(tmp)); + + qc = ieee80211_get_qos_ctl((void *)tmp->data); + *qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; + } + skb_shinfo(tmp)->gso_size = 0; + } + + tmp->prev = NULL; + tmp->next = NULL; + + __skb_queue_tail(mpdus_skb, tmp); + i++; + } + + return 0; +} + static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, @@ -695,14 +763,10 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); struct ieee80211_hdr *hdr = (void *)skb->data; unsigned int mss = skb_shinfo(skb)->gso_size; - struct sk_buff *tmp, *next; - char cb[sizeof(skb->cb)]; unsigned int num_subframes, tcp_payload_len, subf_len, max_amsdu_len; - bool ipv4 = (skb->protocol == htons(ETH_P_IP)); - u16 ip_base_id = ipv4 ? ntohs(ip_hdr(skb)->id) : 0; - u16 snap_ip_tcp, pad, i = 0; + u16 snap_ip_tcp, pad; unsigned int dbg_max_amsdu_len; - netdev_features_t netdev_features = NETIF_F_CSUM_MASK | NETIF_F_SG; + netdev_features_t netdev_flags = NETIF_F_CSUM_MASK | NETIF_F_SG; u8 *qc, tid, txf; snap_ip_tcp = 8 + skb_transport_header(skb) - skb_network_header(skb) + @@ -712,16 +776,8 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, if (!sta->max_amsdu_len || !ieee80211_is_data_qos(hdr->frame_control) || - (!mvmsta->tlc_amsdu && !dbg_max_amsdu_len)) { - num_subframes = 1; - pad = 0; - goto segment; - } - - qc = ieee80211_get_qos_ctl(hdr); - tid = *qc & IEEE80211_QOS_CTL_TID_MASK; - if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) - return -EINVAL; + (!mvmsta->tlc_amsdu && !dbg_max_amsdu_len)) + return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); /* * Do not build AMSDU for IPv6 with extension headers. @@ -730,22 +786,22 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, if (skb->protocol == htons(ETH_P_IPV6) && ((struct ipv6hdr *)skb_network_header(skb))->nexthdr != IPPROTO_TCP) { - num_subframes = 1; - pad = 0; - netdev_features &= ~NETIF_F_CSUM_MASK; - goto segment; + netdev_flags &= ~NETIF_F_CSUM_MASK; + return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); } + qc = ieee80211_get_qos_ctl(hdr); + tid = *qc & IEEE80211_QOS_CTL_TID_MASK; + if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) + return -EINVAL; + /* * No need to lock amsdu_in_ampdu_allowed since it can't be modified * during an BA session. */ if (info->flags & IEEE80211_TX_CTL_AMPDU && - !mvmsta->tid_data[tid].amsdu_in_ampdu_allowed) { - num_subframes = 1; - pad = 0; - goto segment; - } + !mvmsta->tid_data[tid].amsdu_in_ampdu_allowed) + return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); max_amsdu_len = sta->max_amsdu_len; @@ -811,56 +867,8 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, * Trick the segmentation function to make it * create SKBs that can fit into one A-MSDU. */ -segment: - skb_shinfo(skb)->gso_size = num_subframes * mss; - memcpy(cb, skb->cb, sizeof(cb)); - - next = skb_gso_segment(skb, netdev_features); - skb_shinfo(skb)->gso_size = mss; - if (WARN_ON_ONCE(IS_ERR(next))) - return -EINVAL; - else if (next) - consume_skb(skb); - - while (next) { - tmp = next; - next = tmp->next; - - memcpy(tmp->cb, cb, sizeof(tmp->cb)); - /* - * Compute the length of all the data added for the A-MSDU. - * This will be used to compute the length to write in the TX - * command. We have: SNAP + IP + TCP for n -1 subframes and - * ETH header for n subframes. - */ - tcp_payload_len = skb_tail_pointer(tmp) - - skb_transport_header(tmp) - - tcp_hdrlen(tmp) + tmp->data_len; - - if (ipv4) - ip_hdr(tmp)->id = htons(ip_base_id + i * num_subframes); - - if (tcp_payload_len > mss) { - skb_shinfo(tmp)->gso_size = mss; - } else { - if (ieee80211_is_data_qos(hdr->frame_control)) { - qc = ieee80211_get_qos_ctl((void *)tmp->data); - - if (ipv4) - ip_send_check(ip_hdr(tmp)); - *qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; - } - skb_shinfo(tmp)->gso_size = 0; - } - - tmp->prev = NULL; - tmp->next = NULL; - - __skb_queue_tail(mpdus_skb, tmp); - i++; - } - - return 0; + return iwl_mvm_tx_tso_segment(skb, num_subframes, netdev_flags, + mpdus_skb); } #else /* CONFIG_INET */ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, @@ -1894,14 +1902,12 @@ int iwl_mvm_flush_sta(struct iwl_mvm *mvm, void *sta, bool internal, u32 flags) struct iwl_mvm_int_sta *int_sta = sta; struct iwl_mvm_sta *mvm_sta = sta; - if (iwl_mvm_has_new_tx_api(mvm)) { - if (internal) - return iwl_mvm_flush_sta_tids(mvm, int_sta->sta_id, - BIT(IWL_MGMT_TID), flags); + BUILD_BUG_ON(offsetof(struct iwl_mvm_int_sta, sta_id) != + offsetof(struct iwl_mvm_sta, sta_id)); + if (iwl_mvm_has_new_tx_api(mvm)) return iwl_mvm_flush_sta_tids(mvm, mvm_sta->sta_id, - 0xFF, flags); - } + 0xff | BIT(IWL_MGMT_TID), flags); if (internal) return iwl_mvm_flush_tx_path(mvm, int_sta->tfd_queue_msk, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index d65e1db7c097..bebcfb44c8c2 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -800,12 +800,19 @@ int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue, .scd_queue = queue, .action = SCD_CFG_DISABLE_QUEUE, }; - bool remove_mac_queue = true; + bool remove_mac_queue = mac80211_queue != IEEE80211_INVAL_HW_QUEUE; int ret; + if (WARN_ON(remove_mac_queue && mac80211_queue >= IEEE80211_MAX_QUEUES)) + return -EINVAL; + if (iwl_mvm_has_new_tx_api(mvm)) { spin_lock_bh(&mvm->queue_info_lock); - mvm->hw_queue_to_mac80211[queue] &= ~BIT(mac80211_queue); + + if (remove_mac_queue) + mvm->hw_queue_to_mac80211[queue] &= + ~BIT(mac80211_queue); + spin_unlock_bh(&mvm->queue_info_lock); iwl_trans_txq_free(mvm->trans, queue); @@ -1027,14 +1034,18 @@ bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm) } int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - bool prev) + bool low_latency, + enum iwl_mvm_low_latency_cause cause) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); int res; - bool low_latency; + bool prev; lockdep_assert_held(&mvm->mutex); + prev = iwl_mvm_vif_low_latency(mvmvif); + iwl_mvm_vif_set_low_latency(mvmvif, low_latency, cause); + low_latency = iwl_mvm_vif_low_latency(mvmvif); if (low_latency == prev) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 56fc28750a41..959de2f8bb28 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -8,6 +8,7 @@ * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016-2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -36,6 +37,7 @@ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * All rights reserved. * Copyright(c) 2017 Intel Deutschland GmbH + * Copyright(c) 2018 Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -517,9 +519,9 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x24FD, 0x9074, iwl8265_2ac_cfg)}, /* 9000 Series */ - {IWL_PCI_DEVICE(0x2526, 0x0000, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0010, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0014, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x0018, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0030, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0034, iwl9560_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x0038, iwl9560_2ac_cfg)}, @@ -544,11 +546,15 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2526, 0x1410, iwl9270_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x1420, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x1610, iwl9270_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x2030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2526, 0x2034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x4010, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x2526, 0x4030, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x4034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x40A4, iwl9460_2ac_cfg)}, - {IWL_PCI_DEVICE(0x2526, 0xA014, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2526, 0x4234, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2526, 0x42A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2526, 0xA014, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x271B, 0x0010, iwl9160_2ac_cfg)}, {IWL_PCI_DEVICE(0x271B, 0x0014, iwl9160_2ac_cfg)}, {IWL_PCI_DEVICE(0x271B, 0x0210, iwl9160_2ac_cfg)}, @@ -569,38 +575,146 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x2720, 0x0264, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x02A0, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x02A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2720, 0x1010, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2720, 0x1030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2720, 0x1210, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2720, 0x2030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2720, 0x2034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x4030, iwl9560_2ac_cfg)}, + {IWL_PCI_DEVICE(0x2720, 0x4034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x2720, 0x40A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2720, 0x4234, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x2720, 0x42A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x0030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x0034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x0038, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x003C, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x0060, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x0064, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x00A0, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x00A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x0230, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x0234, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x0238, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x023C, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x0260, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x0264, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x02A0, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x30DC, 0x02A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x0030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x0034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x0038, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x003C, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x0060, iwl9460_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x0064, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x00A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x00A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x0230, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x0234, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x0238, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x023C, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x0260, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x0264, iwl9461_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x02A0, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x02A4, iwl9462_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x4030, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x4034, iwl9560_2ac_cfg_soc)}, - {IWL_PCI_DEVICE(0x31DC, 0x40A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x1010, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x30DC, 0x1030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x1210, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x30DC, 0x2030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x2034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x4030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x40A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x4234, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x30DC, 0x42A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x31DC, 0x0030, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x0034, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x0038, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x003C, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x0060, iwl9460_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x0064, iwl9461_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x00A0, iwl9462_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x00A4, iwl9462_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x0230, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x0234, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x0238, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x023C, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x0260, iwl9461_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x0264, iwl9461_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x02A0, iwl9462_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x02A4, iwl9462_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x1010, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x31DC, 0x1030, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x1210, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x31DC, 0x2030, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x2034, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x4030, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x4034, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x40A4, iwl9462_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x4234, iwl9560_2ac_cfg_shared_clk)}, + {IWL_PCI_DEVICE(0x31DC, 0x42A4, iwl9462_2ac_cfg_shared_clk)}, {IWL_PCI_DEVICE(0x34F0, 0x0030, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x34F0, 0x0034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x0038, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x003C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x0060, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x0064, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x00A0, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x00A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x0230, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x0234, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x0238, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x023C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x0260, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x0264, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x02A0, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x34F0, 0x02A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x1010, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x34F0, 0x1030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x1210, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x34F0, 0x2030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x2034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x4030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x40A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x4234, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x34F0, 0x42A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0038, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x003C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0060, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0064, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x00A0, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x00A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0230, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0234, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0238, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x023C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0260, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x0264, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x02A0, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x02A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x1010, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x3DF0, 0x1030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x1210, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x3DF0, 0x2030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x2034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x4030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x40A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x4234, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x3DF0, 0x42A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0038, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x003C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0060, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0064, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x00A0, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x00A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0230, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0234, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0238, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x023C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0260, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x0264, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x02A0, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x02A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x1010, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x43F0, 0x1030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x1210, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x43F0, 0x2030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x2034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x4030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x40A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x4234, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x43F0, 0x42A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x0000, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x0010, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x0030, iwl9560_2ac_cfg_soc)}, @@ -626,11 +740,44 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x9DF0, 0x0610, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x0710, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x0A10, iwl9460_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x9DF0, 0x1010, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0x9DF0, 0x1030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x9DF0, 0x1210, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0x9DF0, 0x2010, iwl9460_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x9DF0, 0x2030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x9DF0, 0x2034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x2A10, iwl9460_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x4030, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x4034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0x9DF0, 0x40A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x9DF0, 0x4234, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0x9DF0, 0x42A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0038, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x003C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0060, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0064, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x00A0, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x00A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0230, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0234, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0238, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x023C, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0260, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x0264, iwl9461_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x02A0, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x02A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x1010, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0xA0F0, 0x1030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x1210, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0xA0F0, 0x2030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x2034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x4030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x4034, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x40A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x4234, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA0F0, 0x42A4, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x0030, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x0034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x0038, iwl9560_2ac_cfg_soc)}, @@ -647,10 +794,16 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0xA370, 0x0264, iwl9461_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x02A0, iwl9462_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x02A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA370, 0x1010, iwl9260_2ac_cfg)}, {IWL_PCI_DEVICE(0xA370, 0x1030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA370, 0x1210, iwl9260_2ac_cfg)}, + {IWL_PCI_DEVICE(0xA370, 0x2030, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA370, 0x2034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x4030, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x4034, iwl9560_2ac_cfg_soc)}, {IWL_PCI_DEVICE(0xA370, 0x40A4, iwl9462_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA370, 0x4234, iwl9560_2ac_cfg_soc)}, + {IWL_PCI_DEVICE(0xA370, 0x42A4, iwl9462_2ac_cfg_soc)}, /* 22000 Series */ {IWL_PCI_DEVICE(0x2720, 0x0A10, iwl22000_2ac_cfg_hr_cdb)}, diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2_main.c index 25f4cebef26d..73c127f92613 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2_main.c @@ -336,6 +336,17 @@ mt76x2_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, int idx = key->keyidx; int ret; + /* fall back to sw encryption for unsupported ciphers */ + switch (key->cipher) { + case WLAN_CIPHER_SUITE_WEP40: + case WLAN_CIPHER_SUITE_WEP104: + case WLAN_CIPHER_SUITE_TKIP: + case WLAN_CIPHER_SUITE_CCMP: + break; + default: + return -EOPNOTSUPP; + } + /* * The hardware does not support per-STA RX GTK, fall back * to software mode for these. diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c index 15820b11f9db..dfd36d736b06 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2_mcu.c @@ -187,7 +187,7 @@ mt76pci_load_firmware(struct mt76x2_dev *dev) { const struct firmware *fw; const struct mt76x2_fw_header *hdr; - int i, len, ret; + int len, ret; __le32 *cur; u32 offset, val; @@ -240,16 +240,7 @@ mt76pci_load_firmware(struct mt76x2_dev *dev) /* trigger firmware */ mt76_wr(dev, MT_MCU_INT_LEVEL, 2); - for (i = 200; i > 0; i--) { - val = mt76_rr(dev, MT_MCU_COM_REG0); - - if (val & 1) - break; - - msleep(10); - } - - if (!i) { + if (!mt76_poll_msec(dev, MT_MCU_COM_REG0, 1, 1, 200)) { dev_err(dev->mt76.dev, "Firmware failed to start\n"); release_firmware(fw); return -ETIMEDOUT; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c b/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c index 534e4bf9a34c..e46eafc4c436 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2_tx.c @@ -36,9 +36,12 @@ void mt76x2_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, msta = (struct mt76x2_sta *) control->sta->drv_priv; wcid = &msta->wcid; + /* sw encrypted frames */ + if (!info->control.hw_key && wcid->hw_key_idx != -1) + control->sta = NULL; } - if (vif || (!info->control.hw_key && wcid->hw_key_idx != -1)) { + if (vif && !control->sta) { struct mt76x2_vif *mvif; mvif = (struct mt76x2_vif *) vif->drv_priv; diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 6db3389e2ced..762a29cdf7ad 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -1549,7 +1549,6 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx, /* EAPOL is seens as in-4way */ rtlpriv->btcoexist.btc_info.in_4way = true; rtlpriv->btcoexist.btc_info.in_4way_ts = jiffies; - rtlpriv->btcoexist.btc_info.in_4way_ts = jiffies; RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG, "802.1X %s EAPOL pkt!!\n", (is_tx) ? "Tx" : "Rx"); diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c index 05beb16f0a0a..59553db020ef 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c @@ -1436,6 +1436,7 @@ static void halbtc8723b1ant_ps_tdma(struct btc_coexist *btcoexist, coex_dm->pre_ps_tdma = coex_dm->cur_ps_tdma; } +static void btc8723b1ant_tdma_dur_adj_for_acl(struct btc_coexist *btcoexist, u8 wifi_status) { diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c index 4907c2ffadfe..73ec31972944 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c @@ -833,9 +833,9 @@ static void btc8723b2ant_set_sw_fulltime_dac_swing(struct btc_coexist *btcoex, btc8723b2ant_set_dac_swing_reg(btcoex, 0x18); } -void btc8723b2ant_dac_swing(struct btc_coexist *btcoexist, - bool force_exec, bool dac_swing_on, - u32 dac_swing_lvl) +static void btc8723b2ant_dac_swing(struct btc_coexist *btcoexist, + bool force_exec, bool dac_swing_on, + u32 dac_swing_lvl) { struct rtl_priv *rtlpriv = btcoexist->adapter; diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c index 0b26419881c0..202597cf8915 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c @@ -426,39 +426,6 @@ static void btc8821a1ant_query_bt_info(struct btc_coexist *btcoexist) btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); } -bool btc8821a1ant_is_wifi_status_changed(struct btc_coexist *btcoexist) -{ - static bool pre_wifi_busy = true; - static bool pre_under_4way = true; - static bool pre_bt_hs_on = true; - bool wifi_busy = false, under_4way = false, bt_hs_on = false; - bool wifi_connected = false; - - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_CONNECTED, - &wifi_connected); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_BUSY, &wifi_busy); - btcoexist->btc_get(btcoexist, BTC_GET_BL_HS_OPERATION, &bt_hs_on); - btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_4_WAY_PROGRESS, - &under_4way); - - if (wifi_connected) { - if (wifi_busy != pre_wifi_busy) { - pre_wifi_busy = wifi_busy; - return true; - } - if (under_4way != pre_under_4way) { - pre_under_4way = under_4way; - return true; - } - if (bt_hs_on != pre_bt_hs_on) { - pre_bt_hs_on = bt_hs_on; - return true; - } - } - - return false; -} - static void btc8821a1ant_update_bt_link_info(struct btc_coexist *btcoexist) { struct btc_bt_link_info *bt_link_info = &btcoexist->bt_link_info; diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c index d5f282cb9d24..2202d5e18977 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c @@ -359,7 +359,7 @@ static void btc8821a2ant_query_bt_info(struct btc_coexist *btcoexist) btcoexist->btc_fill_h2c(btcoexist, 0x61, 1, h2c_parameter); } -bool btc8821a2ant_is_wifi_status_changed(struct btc_coexist *btcoexist) +static bool btc8821a2ant_is_wifi_status_changed(struct btc_coexist *btcoexist) { static bool pre_wifi_busy = true; static bool pre_under_4way = true; @@ -1517,7 +1517,7 @@ static void btc8821a2ant_action_bt_inquiry(struct btc_coexist *btcoexist) btc8821a2ant_sw_mechanism2(btcoexist, false, false, false, 0x18); } -void btc8821a2ant_action_wifi_link_process(struct btc_coexist *btcoexist) +static void btc8821a2ant_action_wifi_link_process(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; u8 u8tmpa, u8tmpb; diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c index 823694cb4fdb..8b6b07a936f5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.c @@ -363,6 +363,22 @@ static void halbtc_normal_lps(struct btc_coexist *btcoexist) } } +static void halbtc_pre_normal_lps(struct btc_coexist *btcoexist) +{ + struct rtl_priv *rtlpriv = btcoexist->adapter; + + if (btcoexist->bt_info.bt_ctrl_lps) { + btcoexist->bt_info.bt_lps_on = false; + rtl_lps_leave(rtlpriv->mac80211.hw); + } +} + +static void halbtc_post_normal_lps(struct btc_coexist *btcoexist) +{ + if (btcoexist->bt_info.bt_ctrl_lps) + btcoexist->bt_info.bt_ctrl_lps = false; +} + static void halbtc_leave_low_power(struct btc_coexist *btcoexist) { } @@ -577,6 +593,9 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf) tmp = true; *bool_tmp = tmp; break; + case BTC_GET_BL_WIFI_DUAL_BAND_CONNECTED: + *u8_tmp = BTC_MULTIPORT_SCC; + break; case BTC_GET_BL_WIFI_BUSY: if (halbtc_is_wifi_busy(rtlpriv)) *bool_tmp = true; @@ -637,6 +656,9 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf) case BTC_GET_BL_IS_ASUS_8723B: *bool_tmp = false; break; + case BTC_GET_BL_RF4CE_CONNECTED: + *bool_tmp = false; + break; case BTC_GET_S4_WIFI_RSSI: *s32_tmp = halbtc_get_wifi_rssi(rtlpriv); break; @@ -677,6 +699,21 @@ static bool halbtc_get(void *void_btcoexist, u8 get_type, void *out_buf) case BTC_GET_U4_BT_FORBIDDEN_SLOT_VAL: *u32_tmp = halbtc_get_bt_forbidden_slot_val(btcoexist); break; + case BTC_GET_U4_WIFI_IQK_TOTAL: + *u32_tmp = + btcoexist->btc_phydm_query_phy_counter(btcoexist, + DM_INFO_IQK_ALL); + break; + case BTC_GET_U4_WIFI_IQK_OK: + *u32_tmp = + btcoexist->btc_phydm_query_phy_counter(btcoexist, + DM_INFO_IQK_OK); + break; + case BTC_GET_U4_WIFI_IQK_FAIL: + *u32_tmp = + btcoexist->btc_phydm_query_phy_counter(btcoexist, + DM_INFO_IQK_NG); + break; case BTC_GET_U1_WIFI_DOT11_CHNL: *u8_tmp = rtlphy->current_channel; break; @@ -788,6 +825,12 @@ static bool halbtc_set(void *void_btcoexist, u8 set_type, void *in_buf) case BTC_SET_ACT_NORMAL_LPS: halbtc_normal_lps(btcoexist); break; + case BTC_SET_ACT_PRE_NORMAL_LPS: + halbtc_pre_normal_lps(btcoexist); + break; + case BTC_SET_ACT_POST_NORMAL_LPS: + halbtc_post_normal_lps(btcoexist); + break; case BTC_SET_ACT_DISABLE_LOW_POWER: halbtc_disable_low_power(btcoexist, *bool_tmp); break; @@ -1101,6 +1144,11 @@ static void halbtc_display_dbg_msg(void *bt_context, u8 disp_type, } } +static u32 halbtc_get_bt_reg(void *btc_context, u8 reg_type, u32 offset) +{ + return 0; +} + static bool halbtc_under_ips(struct btc_coexist *btcoexist) { struct rtl_priv *rtlpriv = btcoexist->adapter; @@ -1119,6 +1167,25 @@ static bool halbtc_under_ips(struct btc_coexist *btcoexist) return false; } +static +u32 halbtc_get_phydm_version(void *btc_context) +{ + return 0; +} + +static +void halbtc_phydm_modify_ra_pcr_threshold(void *btc_context, + u8 ra_offset_direction, + u8 ra_threshold_offset) +{ +} + +static +u32 halbtc_phydm_query_phy_counter(void *btc_context, enum dm_info_query dm_id) +{ + return 0; +} + static u8 halbtc_get_ant_det_val_from_bt(void *btc_context) { struct btc_coexist *btcoexist = (struct btc_coexist *)btc_context; @@ -1232,6 +1299,7 @@ bool exhalbtc_initlize_variables(struct rtl_priv *rtlpriv) btcoexist->btc_get = halbtc_get; btcoexist->btc_set = halbtc_set; btcoexist->btc_set_bt_reg = halbtc_set_bt_reg; + btcoexist->btc_get_bt_reg = halbtc_get_bt_reg; btcoexist->bt_info.bt_ctrl_buf_size = false; btcoexist->bt_info.agg_buf_size = 5; @@ -1242,6 +1310,10 @@ bool exhalbtc_initlize_variables(struct rtl_priv *rtlpriv) halbtc_get_bt_coex_supported_feature; btcoexist->btc_get_bt_coex_supported_version = halbtc_get_bt_coex_supported_version; + btcoexist->btc_get_bt_phydm_version = halbtc_get_phydm_version; + btcoexist->btc_phydm_modify_ra_pcr_threshold = + halbtc_phydm_modify_ra_pcr_threshold; + btcoexist->btc_phydm_query_phy_counter = halbtc_phydm_query_phy_counter; btcoexist->btc_get_ant_det_val_from_bt = halbtc_get_ant_det_val_from_bt; btcoexist->btc_get_ble_scan_type_from_bt = halbtc_get_ble_scan_type_from_bt; @@ -1547,7 +1619,8 @@ void exhalbtc_scan_notify_wifi_only(struct wifi_only_cfg *wifionly_cfg, void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action) { - u8 asso_type; + u8 asso_type, asso_type_v2; + bool wifi_under_5g; if (!halbtc_is_bt_coexist_available(btcoexist)) return; @@ -1555,10 +1628,17 @@ void exhalbtc_connect_notify(struct btc_coexist *btcoexist, u8 action) if (btcoexist->manual_control) return; - if (action) + btcoexist->btc_get(btcoexist, BTC_GET_BL_WIFI_UNDER_5G, &wifi_under_5g); + + if (action) { asso_type = BTC_ASSOCIATE_START; - else + asso_type_v2 = wifi_under_5g ? BTC_ASSOCIATE_5G_START : + BTC_ASSOCIATE_START; + } else { asso_type = BTC_ASSOCIATE_FINISH; + asso_type_v2 = wifi_under_5g ? BTC_ASSOCIATE_5G_FINISH : + BTC_ASSOCIATE_FINISH; + } halbtc_leave_low_power(btcoexist); diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h index f5d8159a88eb..9eae87d19120 100644 --- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h +++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtcoutsrc.h @@ -62,6 +62,8 @@ #define BTC_ANT_PATH_WIFI 0 #define BTC_ANT_PATH_BT 1 #define BTC_ANT_PATH_PTA 2 +#define BTC_ANT_PATH_WIFI5G 3 +#define BTC_ANT_PATH_AUTO 4 /* dual Antenna definition */ #define BTC_ANT_WIFI_AT_MAIN 0 #define BTC_ANT_WIFI_AT_AUX 1 @@ -154,6 +156,7 @@ struct btc_board_info { u8 rfe_type; u8 ant_div_cfg; + u8 customer_id; }; enum btc_dbg_opcode { @@ -204,6 +207,7 @@ enum btc_wifi_traffic_dir { enum btc_wifi_pnp { BTC_WIFI_PNP_WAKE_UP = 0x0, BTC_WIFI_PNP_SLEEP = 0x1, + BTC_WIFI_PNP_SLEEP_KEEP_ANT = 0x2, BTC_WIFI_PNP_MAX }; @@ -250,6 +254,7 @@ enum btc_get_type { BTC_GET_BL_HS_OPERATION, BTC_GET_BL_HS_CONNECTING, BTC_GET_BL_WIFI_CONNECTED, + BTC_GET_BL_WIFI_DUAL_BAND_CONNECTED, BTC_GET_BL_WIFI_BUSY, BTC_GET_BL_WIFI_SCAN, BTC_GET_BL_WIFI_LINK, @@ -333,6 +338,7 @@ enum btc_set_type { BTC_SET_ACT_GET_BT_RSSI, BTC_SET_ACT_AGGREGATE_CTRL, BTC_SET_ACT_ANTPOSREGRISTRY_CTRL, + BTC_SET_MIMO_PS_MODE, /********* for 1Ant **********/ /* type bool */ @@ -347,8 +353,11 @@ enum btc_set_type { BTC_SET_ACT_LEAVE_LPS, BTC_SET_ACT_ENTER_LPS, BTC_SET_ACT_NORMAL_LPS, + BTC_SET_ACT_PRE_NORMAL_LPS, + BTC_SET_ACT_POST_NORMAL_LPS, BTC_SET_ACT_INC_FORCE_EXEC_PWR_CMD_CNT, BTC_SET_ACT_DISABLE_LOW_POWER, + BTC_SET_BL_BT_LNA_CONSTRAIN_LEVEL, BTC_SET_ACT_UPDATE_RAMASK, BTC_SET_ACT_SEND_MIMO_PS, /* BT Coex related */ @@ -383,6 +392,7 @@ enum btc_notify_type_lps { enum btc_notify_type_scan { BTC_SCAN_FINISH = 0x0, BTC_SCAN_START = 0x1, + BTC_SCAN_START_2G = 0x2, BTC_SCAN_MAX }; @@ -397,6 +407,8 @@ enum btc_notify_type_switchband { enum btc_notify_type_associate { BTC_ASSOCIATE_FINISH = 0x0, BTC_ASSOCIATE_START = 0x1, + BTC_ASSOCIATE_5G_FINISH = 0x2, + BTC_ASSOCIATE_5G_START = 0x3, BTC_ASSOCIATE_MAX }; @@ -435,6 +447,107 @@ enum btc_notify_type_stack_operation { BTC_STACK_OP_MAX }; +enum { + BTC_CCK_1, + BTC_CCK_2, + BTC_CCK_5_5, + BTC_CCK_11, + BTC_OFDM_6, + BTC_OFDM_9, + BTC_OFDM_12, + BTC_OFDM_18, + BTC_OFDM_24, + BTC_OFDM_36, + BTC_OFDM_48, + BTC_OFDM_54, + BTC_MCS_0, + BTC_MCS_1, + BTC_MCS_2, + BTC_MCS_3, + BTC_MCS_4, + BTC_MCS_5, + BTC_MCS_6, + BTC_MCS_7, + BTC_MCS_8, + BTC_MCS_9, + BTC_MCS_10, + BTC_MCS_11, + BTC_MCS_12, + BTC_MCS_13, + BTC_MCS_14, + BTC_MCS_15, + BTC_MCS_16, + BTC_MCS_17, + BTC_MCS_18, + BTC_MCS_19, + BTC_MCS_20, + BTC_MCS_21, + BTC_MCS_22, + BTC_MCS_23, + BTC_MCS_24, + BTC_MCS_25, + BTC_MCS_26, + BTC_MCS_27, + BTC_MCS_28, + BTC_MCS_29, + BTC_MCS_30, + BTC_MCS_31, + BTC_VHT_1SS_MCS_0, + BTC_VHT_1SS_MCS_1, + BTC_VHT_1SS_MCS_2, + BTC_VHT_1SS_MCS_3, + BTC_VHT_1SS_MCS_4, + BTC_VHT_1SS_MCS_5, + BTC_VHT_1SS_MCS_6, + BTC_VHT_1SS_MCS_7, + BTC_VHT_1SS_MCS_8, + BTC_VHT_1SS_MCS_9, + BTC_VHT_2SS_MCS_0, + BTC_VHT_2SS_MCS_1, + BTC_VHT_2SS_MCS_2, + BTC_VHT_2SS_MCS_3, + BTC_VHT_2SS_MCS_4, + BTC_VHT_2SS_MCS_5, + BTC_VHT_2SS_MCS_6, + BTC_VHT_2SS_MCS_7, + BTC_VHT_2SS_MCS_8, + BTC_VHT_2SS_MCS_9, + BTC_VHT_3SS_MCS_0, + BTC_VHT_3SS_MCS_1, + BTC_VHT_3SS_MCS_2, + BTC_VHT_3SS_MCS_3, + BTC_VHT_3SS_MCS_4, + BTC_VHT_3SS_MCS_5, + BTC_VHT_3SS_MCS_6, + BTC_VHT_3SS_MCS_7, + BTC_VHT_3SS_MCS_8, + BTC_VHT_3SS_MCS_9, + BTC_VHT_4SS_MCS_0, + BTC_VHT_4SS_MCS_1, + BTC_VHT_4SS_MCS_2, + BTC_VHT_4SS_MCS_3, + BTC_VHT_4SS_MCS_4, + BTC_VHT_4SS_MCS_5, + BTC_VHT_4SS_MCS_6, + BTC_VHT_4SS_MCS_7, + BTC_VHT_4SS_MCS_8, + BTC_VHT_4SS_MCS_9, + BTC_MCS_32, + BTC_UNKNOWN, + BTC_PKT_MGNT, + BTC_PKT_CTRL, + BTC_PKT_UNKNOWN, + BTC_PKT_NOT_FOR_ME, + BTC_RATE_MAX +}; + +enum { + BTC_MULTIPORT_SCC, + BTC_MULTIPORT_MCC_2CHANNEL, + BTC_MULTIPORT_MCC_2BAND, + BTC_MULTIPORT_MAX +}; + struct btc_bt_info { bool bt_disabled; u8 rssi_adjust_for_agc_table_on; @@ -454,6 +567,7 @@ struct btc_bt_info { u16 bt_hci_ver; u16 bt_real_fw_ver; u8 bt_fw_ver; + u32 bt_get_fw_ver; bool bt_disable_low_pwr; @@ -525,6 +639,7 @@ struct btc_bt_link_info { bool pan_exist; bool pan_only; bool slave_role; + bool acl_busy; }; enum btc_antenna_pos { @@ -625,8 +740,15 @@ struct btc_coexist { void (*btc_set_bt_reg)(void *btc_context, u8 reg_type, u32 offset, u32 value); + u32 (*btc_get_bt_reg)(void *btc_context, u8 reg_type, u32 offset); u32 (*btc_get_bt_coex_supported_feature)(void *btcoexist); u32 (*btc_get_bt_coex_supported_version)(void *btcoexist); + u32 (*btc_get_bt_phydm_version)(void *btcoexist); + void (*btc_phydm_modify_ra_pcr_threshold)(void *btcoexist, + u8 ra_offset_direction, + u8 ra_threshold_offset); + u32 (*btc_phydm_query_phy_counter)(void *btcoexist, + enum dm_info_query dm_id); u8 (*btc_get_ant_det_val_from_bt)(void *btcoexist); u8 (*btc_get_ble_scan_type_from_bt)(void *btcoexist); u32 (*btc_get_ble_scan_para_from_bt)(void *btcoexist, u8 scan_type); diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h index f2d9c6116e5c..8379a3e5198c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/pwrseq.h @@ -142,7 +142,7 @@ /*wait power state to suspend*/}, \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3) | BIT(4), 0 \ - /*0x04[12:11] = 2b'01enable WL suspend*/}, + /*0x04[12:11] = 2b'00 disable WL suspend*/}, #define RTL8188EE_TRANS_CARDEMU_TO_CARDDIS \ {0x0026, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ @@ -179,7 +179,7 @@ /*wait power state to suspend*/}, \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0 \ - /*0x04[12:11] = 2b'01enable WL suspend*/}, + /*0x04[12:11] = 2b'00 disable WL suspend*/}, #define RTL8188EE_TRANS_CARDEMU_TO_PDN \ {0x0006, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h index 781eeaa6af49..c570801508cc 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/pwrseq.h @@ -134,7 +134,7 @@ /*wait power state to suspend*/ \ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ PWR_BASEADDR_SDIO , PWR_CMD_POLLING, BIT(1), BIT(1)}, \ - /*0x04[12:11] = 2b'01enable WL suspend*/ \ + /*0x04[12:11] = 2b'00 disable WL suspend*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, @@ -181,7 +181,7 @@ /*Lock small LDO Register*/ \ {0x00CC, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(2), 0}, \ - /*0x04[12:11] = 2b'01enable WL suspend*/ \ + /*0x04[12:11] = 2b'00 disable WL suspend*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ PWR_BASEADDR_MAC , PWR_CMD_WRITE, BIT(3) | BIT(4), 0}, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h index 4ac7db526f15..e6c3aac3e9fd 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/pwrseq.h @@ -135,7 +135,7 @@ /*wait power state to suspend*/ \ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ PWR_BASEADDR_SDIO, PWR_CMD_POLLING, BIT(1), BIT(1)},\ - /*0x04[12:11] = 2b'01enable WL suspend*/ \ + /*0x04[12:11] = 2b'00 disable WL suspend*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, @@ -172,7 +172,7 @@ {0x0086, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ PWR_INTF_SDIO_MSK, PWR_BASEADDR_SDIO,\ PWR_CMD_POLLING, BIT(1), BIT(1)},\ - /*0x04[12:11] = 2b'00enable WL suspend*/ \ + /*0x04[12:11] = 2b'00 disable WL suspend*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, \ PWR_INTF_ALL_MSK, PWR_BASEADDR_MAC,\ PWR_CMD_WRITE, BIT(3)|BIT(4), 0},\ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h index 0fee5e0e55c2..3367cfbc9502 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/pwrseq.h @@ -204,7 +204,7 @@ /*0x23[4] = 1b'0 12H LDO enter normal mode*/ \ {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, \ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(4), 0}, \ - /*0x04[12:11] = 2b'01enable WL suspend*/ \ + /*0x04[12:11] = 2b'00 disable WL suspend*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, @@ -251,7 +251,7 @@ /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/ \ {0x004A, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_USB_MSK, \ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(0), 0}, \ - /*0x04[12:11] = 2b'01enable WL suspend*/ \ + /*0x04[12:11] = 2b'00 disable WL suspend*/ \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK, \ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT(3)|BIT(4), 0}, \ /*0x23[4] = 1b'0 12H LDO enter normal mode*/ \ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c index b11365a5ee1f..9111ba7ff0a1 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/dm.c @@ -1475,7 +1475,7 @@ void rtl8812ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw, } } else if (method == MIX_MODE) { RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pDM_Odm->DefaultOfdmIndex=%d, pDM_Odm->Aboslute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n", + "pDM_Odm->DefaultOfdmIndex=%d, pDM_Odm->Absolute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n", rtldm->default_ofdm_index, rtldm->absolute_ofdm_swing_idx[rf_path], rf_path); @@ -1750,7 +1750,7 @@ void rtl8812ae_dm_txpower_tracking_callback_thermalmeter( /*Record delta swing for mix mode power tracking*/ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", + "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, @@ -1766,7 +1766,7 @@ void rtl8812ae_dm_txpower_tracking_callback_thermalmeter( /*Record delta swing for mix mode power tracking*/ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", + "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]); } else { RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, @@ -1782,7 +1782,7 @@ void rtl8812ae_dm_txpower_tracking_callback_thermalmeter( -1 * delta_swing_table_idx_tdown_a[delta]; /* Record delta swing for mix mode power tracking*/ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", + "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, @@ -1799,7 +1799,7 @@ void rtl8812ae_dm_txpower_tracking_callback_thermalmeter( /*Record delta swing for mix mode power tracking*/ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", + "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_B] = %d\n", rtldm->absolute_ofdm_swing_idx[RF90_PATH_B]); } @@ -2115,7 +2115,7 @@ void rtl8821ae_dm_txpwr_track_set_pwr(struct ieee80211_hw *hw, } } else if (method == MIX_MODE) { RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "pDM_Odm->DefaultOfdmIndex=%d,pDM_Odm->Aboslute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n", + "pDM_Odm->DefaultOfdmIndex=%d,pDM_Odm->Absolute_OFDMSwingIdx[RFPath]=%d, RF_Path = %d\n", rtldm->default_ofdm_index, rtldm->absolute_ofdm_swing_idx[rf_path], rf_path); @@ -2329,7 +2329,7 @@ void rtl8821ae_dm_txpower_tracking_callback_thermalmeter( /*Record delta swing for mix mode power tracking*/ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Temp is higher and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", + "******Temp is higher and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); } else { RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, @@ -2345,7 +2345,7 @@ void rtl8821ae_dm_txpower_tracking_callback_thermalmeter( -1 * delta_swing_table_idx_tdown_a[delta]; /* Record delta swing for mix mode power tracking*/ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, - "******Temp is lower and pDM_Odm->Aboslute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", + "******Temp is lower and pDM_Odm->Absolute_OFDMSwingIdx[ODM_RF_PATH_A] = %d\n", rtldm->absolute_ofdm_swing_idx[RF90_PATH_A]); } diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h index 36b3e91d996e..6dd575435c63 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/pwrseq.h @@ -531,7 +531,7 @@ extern struct wlan_pwr_cfg rtl8812_leave_lps_flow /*0x23[4] = 1b'0 12H LDO enter normal mode*/}, \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, 0 \ - /*0x04[12:11] = 2b'01enable WL suspend*/}, + /*0x04[12:11] = 2b'00 disable WL suspend*/}, #define RTL8821A_TRANS_CARDEMU_TO_CARDDIS \ {0x0007, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ @@ -572,7 +572,7 @@ extern struct wlan_pwr_cfg rtl8812_leave_lps_flow /*0x48[16] = 0 to disable GPIO9 as EXT WAKEUP*/}, \ {0x0005, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_ALL_MSK,\ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT3|BIT4, 0 \ - /*0x04[12:11] = 2b'01enable WL suspend*/},\ + /*0x04[12:11] = 2b'00 disable WL suspend*/},\ {0x0023, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK,\ PWR_BASEADDR_MAC, PWR_CMD_WRITE, BIT4, 0 \ /*0x23[4] = 1b'0 12H LDO enter normal mode*/}, \ diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 4f48b934ec01..d27e33960e77 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -556,6 +556,7 @@ enum rt_oem_id { RT_CID_NETGEAR = 36, RT_CID_PLANEX = 37, RT_CID_CC_C = 38, + RT_CID_LENOVO_CHINA = 40, }; enum hw_descs { @@ -977,6 +978,38 @@ enum rtl_spec_ver { RTL_SPEC_EXT_C2H = BIT(2), /* extend FW C2H (e.g. TX REPORT) */ }; +enum dm_info_query { + DM_INFO_FA_OFDM, + DM_INFO_FA_CCK, + DM_INFO_FA_TOTAL, + DM_INFO_CCA_OFDM, + DM_INFO_CCA_CCK, + DM_INFO_CCA_ALL, + DM_INFO_CRC32_OK_VHT, + DM_INFO_CRC32_OK_HT, + DM_INFO_CRC32_OK_LEGACY, + DM_INFO_CRC32_OK_CCK, + DM_INFO_CRC32_ERROR_VHT, + DM_INFO_CRC32_ERROR_HT, + DM_INFO_CRC32_ERROR_LEGACY, + DM_INFO_CRC32_ERROR_CCK, + DM_INFO_EDCCA_FLAG, + DM_INFO_OFDM_ENABLE, + DM_INFO_CCK_ENABLE, + DM_INFO_CRC32_OK_HT_AGG, + DM_INFO_CRC32_ERROR_HT_AGG, + DM_INFO_DBG_PORT_0, + DM_INFO_CURR_IGI, + DM_INFO_RSSI_MIN, + DM_INFO_RSSI_MAX, + DM_INFO_CLM_RATIO, + DM_INFO_NHM_RATIO, + DM_INFO_IQK_ALL, + DM_INFO_IQK_OK, + DM_INFO_IQK_NG, + DM_INFO_SIZE, +}; + struct octet_string { u8 *octet; u16 length; diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 13705fca59dd..d76e69c0beaa 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -653,11 +653,14 @@ static int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr, u32 *read_buf, u16 size) { u32 addr_on_bus, *data; - u32 align[2] = {}; u16 ms_addr; int status; - data = PTR_ALIGN(&align[0], 8); + data = kzalloc(RSI_MASTER_REG_BUF_SIZE, GFP_KERNEL); + if (!data) + return -ENOMEM; + + data = PTR_ALIGN(data, 8); ms_addr = (addr >> 16); status = rsi_sdio_master_access_msword(adapter, ms_addr); @@ -665,7 +668,7 @@ static int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr, rsi_dbg(ERR_ZONE, "%s: Unable to set ms word to common reg\n", __func__); - return status; + goto err; } addr &= 0xFFFF; @@ -683,7 +686,7 @@ static int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr, (u8 *)data, 4); if (status < 0) { rsi_dbg(ERR_ZONE, "%s: AHB register read failed\n", __func__); - return status; + goto err; } if (size == 2) { if ((addr & 0x3) == 0) @@ -705,17 +708,23 @@ static int rsi_sdio_master_reg_read(struct rsi_hw *adapter, u32 addr, *read_buf = *data; } - return 0; +err: + kfree(data); + return status; } static int rsi_sdio_master_reg_write(struct rsi_hw *adapter, unsigned long addr, unsigned long data, u16 size) { - unsigned long data1[2], *data_aligned; + unsigned long *data_aligned; int status; - data_aligned = PTR_ALIGN(&data1[0], 8); + data_aligned = kzalloc(RSI_MASTER_REG_BUF_SIZE, GFP_KERNEL); + if (!data_aligned) + return -ENOMEM; + + data_aligned = PTR_ALIGN(data_aligned, 8); if (size == 2) { *data_aligned = ((data << 16) | (data & 0xFFFF)); @@ -734,6 +743,7 @@ static int rsi_sdio_master_reg_write(struct rsi_hw *adapter, rsi_dbg(ERR_ZONE, "%s: Unable to set ms word to common reg\n", __func__); + kfree(data_aligned); return -EIO; } addr = addr & 0xFFFF; @@ -743,12 +753,12 @@ static int rsi_sdio_master_reg_write(struct rsi_hw *adapter, (adapter, (addr | RSI_SD_REQUEST_MASTER), (u8 *)data_aligned, size); - if (status < 0) { + if (status < 0) rsi_dbg(ERR_ZONE, "%s: Unable to do AHB reg write\n", __func__); - return status; - } - return 0; + + kfree(data_aligned); + return status; } /** @@ -967,7 +977,7 @@ static int rsi_probe(struct sdio_func *pfunction, rsi_sdio_rx_thread, "SDIO-RX-Thread"); if (status) { rsi_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__); - goto fail_free_adapter; + goto fail_kill_thread; } skb_queue_head_init(&sdev->rx_q.head); sdev->rx_q.num_rx_pkts = 0; @@ -977,7 +987,7 @@ static int rsi_probe(struct sdio_func *pfunction, rsi_dbg(ERR_ZONE, "%s: Failed to request IRQ\n", __func__); sdio_release_host(pfunction); status = -EIO; - goto fail_kill_thread; + goto fail_claim_irq; } sdio_release_host(pfunction); rsi_dbg(INIT_ZONE, "%s: Registered Interrupt handler\n", __func__); @@ -985,7 +995,7 @@ static int rsi_probe(struct sdio_func *pfunction, if (rsi_hal_device_init(adapter)) { rsi_dbg(ERR_ZONE, "%s: Failed in device init\n", __func__); status = -EINVAL; - goto fail_kill_thread; + goto fail_dev_init; } rsi_dbg(INFO_ZONE, "===> RSI Device Init Done <===\n"); @@ -1002,10 +1012,13 @@ static int rsi_probe(struct sdio_func *pfunction, fail_dev_init: sdio_claim_host(pfunction); sdio_release_irq(pfunction); - sdio_disable_func(pfunction); sdio_release_host(pfunction); -fail_kill_thread: +fail_claim_irq: rsi_kill_thread(&sdev->rx_thread); +fail_kill_thread: + sdio_claim_host(pfunction); + sdio_disable_func(pfunction); + sdio_release_host(pfunction); fail_free_adapter: rsi_91x_deinit(adapter); rsi_dbg(ERR_ZONE, "%s: Failed in probe...Exiting\n", __func__); diff --git a/drivers/net/wireless/rsi/rsi_91x_usb.c b/drivers/net/wireless/rsi/rsi_91x_usb.c index be8236f404b5..7b8bae313aa9 100644 --- a/drivers/net/wireless/rsi/rsi_91x_usb.c +++ b/drivers/net/wireless/rsi/rsi_91x_usb.c @@ -140,7 +140,6 @@ static int rsi_find_bulk_in_and_out_endpoints(struct usb_interface *interface, buffer_size = endpoint->wMaxPacketSize; dev->bulkout_endpoint_addr[bout_found] = endpoint->bEndpointAddress; - buffer_size = endpoint->wMaxPacketSize; dev->bulkout_size[bout_found] = buffer_size; bout_found++; } diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h index ba649be284af..ead8e7c4df3a 100644 --- a/drivers/net/wireless/rsi/rsi_sdio.h +++ b/drivers/net/wireless/rsi/rsi_sdio.h @@ -46,6 +46,8 @@ enum sdio_interrupt_type { #define PKT_BUFF_AVAILABLE 1 #define FW_ASSERT_IND 2 +#define RSI_MASTER_REG_BUF_SIZE 12 + #define RSI_DEVICE_BUFFER_STATUS_REGISTER 0xf3 #define RSI_FN1_INT_REGISTER 0xf9 #define RSI_INT_ENABLE_REGISTER 0x04 |