diff options
author | Dong Aisheng <aisheng.dong@nxp.com> | 2019-12-02 18:05:33 +0800 |
---|---|---|
committer | Dong Aisheng <aisheng.dong@nxp.com> | 2019-12-02 18:05:33 +0800 |
commit | 9c3a4bfcf6a428317245a5f83cf56d62f7d5f573 (patch) | |
tree | a3d27cf1feb8d20c412f44be5c88030b64bf6057 | |
parent | 88db34eef0718fc1fbbdf73a2b785adcc8f9fc97 (diff) | |
parent | 322bc87dd3ce29af1de6e5e043ab41eca5390403 (diff) |
Merge branch 'wifi/next' into next
* wifi/next: (51 commits)
MLK-22949 brcmfmac: add chip id check for clm_blob firmware load
MLK-22948 brcmfmac: avoid to send mailbox interrupt twice for core version 0xb
MLK-22946 brcmfmac: freeing wiphy after brcmf attach failed
dt-bindings: add new property to enable board_type
brcmfmac: let board_type is optional
...
28 files changed, 2430 insertions, 62 deletions
diff --git a/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt b/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt index cffb2d6876e3..66a7ba1f1c74 100644 --- a/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt +++ b/Documentation/devicetree/bindings/net/wireless/brcm,bcm43xx-fmac.txt @@ -11,6 +11,7 @@ Required properties: Optional properties: - brcm,drive-strength : drive strength used for SDIO pins on device in mA (default = 6). + - brcm,use_board_type : suffix string for NVRAM - interrupts : specifies attributes for the out-of-band interrupt (host-wake). When not specified the device will use in-band SDIO interrupts. - interrupt-names : name of the out-of-band interrupt, which must be set diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c index fc12598b2dd3..987731b29303 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c @@ -22,6 +22,7 @@ #include <linux/errno.h> #include <linux/module.h> #include <linux/acpi.h> +#include <linux/of.h> #include <net/cfg80211.h> #include <defs.h> @@ -36,6 +37,7 @@ #include "sdio.h" #include "core.h" #include "common.h" +#include "cfg80211.h" #define SDIOH_API_ACCESS_RETRY_LIMIT 2 @@ -43,6 +45,7 @@ #define SDIO_FUNC1_BLOCKSIZE 64 #define SDIO_FUNC2_BLOCKSIZE 512 +#define SDIO_4373_FUNC2_BLOCKSIZE 256 /* Maximum milliseconds to wait for F2 to come up */ #define SDIO_WAIT_F2RDY 3000 @@ -903,6 +906,7 @@ static void brcmf_sdiod_host_fixup(struct mmc_host *host) static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) { int ret = 0; + unsigned int f2_blksz = SDIO_FUNC2_BLOCKSIZE; sdio_claim_host(sdiodev->func1); @@ -912,11 +916,18 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) sdio_release_host(sdiodev->func1); goto out; } - ret = sdio_set_block_size(sdiodev->func2, SDIO_FUNC2_BLOCKSIZE); + + if (sdiodev->func1->device == SDIO_DEVICE_ID_CYPRESS_4373) { + f2_blksz = SDIO_4373_FUNC2_BLOCKSIZE; + } + + ret = sdio_set_block_size(sdiodev->func2, f2_blksz); if (ret) { brcmf_err("Failed to set F2 blocksize\n"); sdio_release_host(sdiodev->func1); goto out; + } else { + brcmf_dbg(SDIO, "set F2 blocksize to %d\n", f2_blksz); } /* increase F2 timeout */ @@ -964,6 +975,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = { BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43364), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4339), + BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43428), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345), BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43455), @@ -995,6 +1007,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, struct brcmf_sdio_dev *sdiodev; struct brcmf_bus *bus_if; struct device *dev; + struct device *func_dev; brcmf_dbg(SDIO, "Enter\n"); brcmf_dbg(SDIO, "Class=%x\n", func->class); @@ -1010,6 +1023,11 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, /* prohibit ACPI power management for this device */ brcmf_sdiod_acpi_set_power_manageable(dev, 0); + func_dev = &func->card->sdio_func[0]->dev; + if (!func_dev->of_node || + !of_device_is_compatible(func_dev->of_node, "brcm,bcm4329-fmac")) + return -ENODEV; + /* Consume func num 1 but dont do anything with it. */ if (func->num == 1) return 0; @@ -1039,6 +1057,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, dev_set_drvdata(&func->dev, bus_if); dev_set_drvdata(&sdiodev->func1->dev, bus_if); sdiodev->dev = &sdiodev->func1->dev; + dev_set_drvdata(&sdiodev->func2->dev, bus_if); brcmf_sdiod_change_state(sdiodev, BRCMF_SDIOD_DOWN); @@ -1055,6 +1074,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, fail: dev_set_drvdata(&func->dev, NULL); dev_set_drvdata(&sdiodev->func1->dev, NULL); + dev_set_drvdata(&sdiodev->func2->dev, NULL); kfree(sdiodev); kfree(bus_if); return err; @@ -1093,6 +1113,14 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func) brcmf_dbg(SDIO, "Exit\n"); } +static void brcmf_ops_sdio_shutdown(struct device *dev) +{ + struct sdio_func *func = container_of(dev, struct sdio_func, dev); + + brcmf_ops_sdio_remove(func); + return; +} + void brcmf_sdio_wowl_config(struct device *dev, bool enabled) { struct brcmf_bus *bus_if = dev_get_drvdata(dev); @@ -1109,14 +1137,26 @@ static int brcmf_ops_sdio_suspend(struct device *dev) struct brcmf_bus *bus_if; struct brcmf_sdio_dev *sdiodev; mmc_pm_flag_t sdio_flags; + struct brcmf_cfg80211_info *config; + int retry = BRCMF_PM_WAIT_MAXRETRY; func = container_of(dev, struct sdio_func, dev); + bus_if = dev_get_drvdata(dev); + config = bus_if->drvr->config; + brcmf_dbg(SDIO, "Enter: F%d\n", func->num); + if (func->num != 1) return 0; + while (retry && + config->pm_state == BRCMF_CFG80211_PM_STATE_SUSPENDING) { + usleep_range(10000, 20000); + retry--; + } + if (!retry && config->pm_state == BRCMF_CFG80211_PM_STATE_SUSPENDING) + brcmf_err("timed out wait for cfg80211 suspended\n"); - bus_if = dev_get_drvdata(dev); sdiodev = bus_if->bus_priv.sdio; brcmf_sdiod_freezer_on(sdiodev); @@ -1164,6 +1204,7 @@ static struct sdio_driver brcmf_sdmmc_driver = { #ifdef CONFIG_PM_SLEEP .pm = &brcmf_sdio_pm_ops, #endif /* CONFIG_PM_SLEEP */ + .shutdown = brcmf_ops_sdio_shutdown, .coredump = brcmf_dev_coredump, }, }; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index e3ebb7abbdae..04a58aa2a571 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -3575,7 +3575,7 @@ static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp) err = brcmf_fil_iovar_data_get(ifp, "wowl_wakeind", &wake_ind_le, sizeof(wake_ind_le)); if (err) { - bphy_err(drvr, "Get wowl_wakeind failed, err = %d\n", err); + brcmf_dbg(INFO, "cannet get wowl_wakeind, err = %d\n", err); return; } @@ -3643,10 +3643,24 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) 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_pub *drvr = ifp->drvr; + struct brcmf_bus *bus_if = drvr->bus_if; + struct brcmf_cfg80211_info *config = drvr->config; + int retry = BRCMF_PM_WAIT_MAXRETRY; brcmf_dbg(TRACE, "Enter\n"); + config->pm_state = BRCMF_CFG80211_PM_STATE_RESUMING; + if (cfg->wowl.active) { + /* wait for bus resumed */ + while (retry && bus_if->state != BRCMF_BUS_UP) { + usleep_range(10000, 20000); + retry--; + } + if (!retry && bus_if->state != BRCMF_BUS_UP) + brcmf_err("timed out wait for bus resume\n"); + brcmf_report_wowl_wakeind(wiphy, ifp); brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0); brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0); @@ -3662,7 +3676,12 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) brcmf_notify_sched_scan_results); cfg->wowl.nd_enabled = false; } + + /* disable packet filters */ + brcmf_pktfilter_enable(ifp->ndev, false); + } + config->pm_state = BRCMF_CFG80211_PM_STATE_RESUMED; return 0; } @@ -3720,6 +3739,9 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg, brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1); brcmf_bus_wowl_config(cfg->pub->bus_if, true); cfg->wowl.active = true; + + /* enable packet filters */ + brcmf_pktfilter_enable(ifp->ndev, true); } static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, @@ -3729,9 +3751,12 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, struct net_device *ndev = cfg_to_ndev(cfg); struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_cfg80211_vif *vif; + struct brcmf_cfg80211_info *config = ifp->drvr->config; brcmf_dbg(TRACE, "Enter\n"); + config->pm_state = BRCMF_CFG80211_PM_STATE_SUSPENDING; + /* if the primary net_device is not READY there is nothing * we can do but pray resume goes smoothly. */ @@ -3746,7 +3771,8 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) brcmf_abort_scanning(cfg); - if (wowl == NULL) { + if (!wowl || !test_bit(BRCMF_VIF_STATUS_CONNECTED, + &ifp->vif->sme_state)) { brcmf_bus_wowl_config(cfg->pub->bus_if, false); list_for_each_entry(vif, &cfg->vif_list, list) { if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) @@ -3766,14 +3792,19 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, brcmf_set_mpc(ifp, 1); } else { - /* Configure WOWL paramaters */ - brcmf_configure_wowl(cfg, ifp, wowl); + /* Configure WOWL parameters */ + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL)) + brcmf_configure_wowl(cfg, ifp, wowl); } exit: - brcmf_dbg(TRACE, "Exit\n"); + /* set cfg80211 pm state to cfg80211 suspended state */ + config->pm_state = BRCMF_CFG80211_PM_STATE_SUSPENDED; + /* clear any scanning activity */ cfg->scan_status = 0; + + brcmf_dbg(TRACE, "Exit\n"); return 0; } @@ -4584,9 +4615,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, } } - if ((dev_role == NL80211_IFTYPE_AP) && - ((ifp->ifidx == 0) || - !brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB))) { + if ((dev_role == NL80211_IFTYPE_AP) && (ifp->ifidx == 0)) { err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); if (err < 0) { bphy_err(drvr, "BRCMF_C_DOWN error %d\n", @@ -5006,7 +5035,7 @@ static int brcmf_cfg80211_get_channel(struct wiphy *wiphy, err = brcmf_fil_iovar_int_get(netdev_priv(ndev), "chanspec", &chanspec); if (err) { - bphy_err(drvr, "chanspec failed (%d)\n", err); + brcmf_dbg(TRACE, "chanspec failed (%d)\n", err); return err; } @@ -5235,6 +5264,26 @@ static int brcmf_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev, return brcmf_set_pmk(ifp, NULL, 0); } +static int +brcmf_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev, + struct bss_parameters *params) +{ + struct brcmf_if *ifp; + int ret = 0; + u32 ap_isolate; + + brcmf_dbg(TRACE, "Enter\n"); + ifp = netdev_priv(dev); + if (params->ap_isolate >= 0) { + ap_isolate = (u32)params->ap_isolate; + ret = brcmf_fil_iovar_int_set(ifp, "ap_isolate", ap_isolate); + if (ret < 0) + brcmf_err("ap_isolate iovar failed: ret=%d\n", ret); + } + + return ret; +} + static struct cfg80211_ops brcmf_cfg80211_ops = { .add_virtual_intf = brcmf_cfg80211_add_iface, .del_virtual_intf = brcmf_cfg80211_del_iface, @@ -5280,6 +5329,7 @@ static struct cfg80211_ops brcmf_cfg80211_ops = { .update_connect_params = brcmf_cfg80211_update_conn_params, .set_pmk = brcmf_cfg80211_set_pmk, .del_pmk = brcmf_cfg80211_del_pmk, + .change_bss = brcmf_cfg80211_change_bss, }; struct cfg80211_ops *brcmf_cfg80211_get_ops(struct brcmf_mp_device *settings) @@ -5427,12 +5477,125 @@ static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg) conn_info->resp_ie_len = 0; } +u8 brcmf_map_prio_to_prec(void *config, u8 prio) +{ + struct brcmf_cfg80211_info *cfg = (struct brcmf_cfg80211_info *)config; + + if (!cfg) + return (prio == PRIO_8021D_NONE || prio == PRIO_8021D_BE) ? + (prio ^ 2) : prio; + + /* For those AC(s) with ACM flag set to 1, convert its 4-level priority + * to an 8-level precedence which is the same as BE's */ + if (prio > PRIO_8021D_EE && + cfg->ac_priority[prio] == cfg->ac_priority[PRIO_8021D_BE]) + return cfg->ac_priority[prio] * 2; + + /* Conversion of 4-level priority to 8-level precedence */ + if (prio == PRIO_8021D_BE || prio == PRIO_8021D_BK || + prio == PRIO_8021D_CL || prio == PRIO_8021D_VO) + return cfg->ac_priority[prio] * 2; + else + return cfg->ac_priority[prio] * 2 + 1; +} + +u8 brcmf_map_prio_to_aci(void *config, u8 prio) +{ + /* Prio here refers to the 802.1d priority in range of 0 to 7. + * ACI here refers to the WLAN AC Index in range of 0 to 3. + * This function will return ACI corresponding to input prio. + */ + struct brcmf_cfg80211_info *cfg = (struct brcmf_cfg80211_info *)config; + + if (cfg) + return cfg->ac_priority[prio]; + + return prio; +} + +static void brcmf_wifi_prioritize_acparams(const + struct brcmf_cfg80211_edcf_acparam *acp, u8 *priority) +{ + u8 aci; + u8 aifsn; + u8 ecwmin; + u8 ecwmax; + u8 acm; + u8 ranking_basis[EDCF_AC_COUNT]; + u8 aci_prio[EDCF_AC_COUNT]; /* AC_BE, AC_BK, AC_VI, AC_VO */ + u8 index; + + for (aci = 0; aci < EDCF_AC_COUNT; aci++, acp++) { + aifsn = acp->ACI & EDCF_AIFSN_MASK; + acm = (acp->ACI & EDCF_ACM_MASK) ? 1 : 0; + ecwmin = acp->ECW & EDCF_ECWMIN_MASK; + ecwmax = (acp->ECW & EDCF_ECWMAX_MASK) >> EDCF_ECWMAX_SHIFT; + brcmf_dbg(CONN, "ACI %d aifsn %d acm %d ecwmin %d ecwmax %d\n", + aci, aifsn, acm, ecwmin, ecwmax); + /* Default AC_VO will be the lowest ranking value */ + ranking_basis[aci] = aifsn + ecwmin + ecwmax; + /* Initialise priority starting at 0 (AC_BE) */ + aci_prio[aci] = 0; + + /* If ACM is set, STA can't use this AC as per 802.11. + * Change the ranking to BE + */ + if (aci != AC_BE && aci != AC_BK && acm == 1) + ranking_basis[aci] = ranking_basis[AC_BE]; + } + + /* Ranking method which works for AC priority + * swapping when values for cwmin, cwmax and aifsn are varied + * Compare each aci_prio against each other aci_prio + */ + for (aci = 0; aci < EDCF_AC_COUNT; aci++) { + for (index = 0; index < EDCF_AC_COUNT; index++) { + if (index != aci) { + /* Smaller ranking value has higher priority, + * so increment priority for each ACI which has + * a higher ranking value + */ + if (ranking_basis[aci] < ranking_basis[index]) + aci_prio[aci]++; + } + } + } + + /* By now, aci_prio[] will be in range of 0 to 3. + * Use ACI prio to get the new priority value for + * each 802.1d traffic type, in this range. + */ + + /* 802.1d 0,3 maps to BE */ + priority[0] = aci_prio[AC_BE]; + priority[3] = aci_prio[AC_BE]; + + /* 802.1d 1,2 maps to BK */ + priority[1] = aci_prio[AC_BK]; + priority[2] = aci_prio[AC_BK]; + + /* 802.1d 4,5 maps to VO */ + priority[4] = aci_prio[AC_VI]; + priority[5] = aci_prio[AC_VI]; + + /* 802.1d 6,7 maps to VO */ + priority[6] = aci_prio[AC_VO]; + priority[7] = aci_prio[AC_VO]; + + brcmf_dbg(CONN, "Adj prio BE 0->%d, BK 1->%d, BK 2->%d, BE 3->%d\n", + priority[0], priority[1], priority[2], priority[3]); + + brcmf_dbg(CONN, "Adj prio VI 4->%d, VI 5->%d, VO 6->%d, VO 7->%d\n", + priority[4], priority[5], priority[6], priority[7]); +} + static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp) { struct brcmf_pub *drvr = cfg->pub; struct brcmf_cfg80211_assoc_ielen_le *assoc_info; struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); + struct brcmf_cfg80211_edcf_acparam edcf_acparam_info[EDCF_AC_COUNT]; u32 req_len; u32 resp_len; s32 err = 0; @@ -5481,6 +5644,17 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, GFP_KERNEL); if (!conn_info->resp_ie) conn_info->resp_ie_len = 0; + + err = brcmf_fil_iovar_data_get(ifp, "wme_ac_sta", + edcf_acparam_info, + sizeof(edcf_acparam_info)); + if (err) { + brcmf_err("could not get wme_ac_sta (%d)\n", err); + return err; + } + + brcmf_wifi_prioritize_acparams(edcf_acparam_info, + cfg->ac_priority); } else { conn_info->resp_ie_len = 0; conn_info->resp_ie = NULL; @@ -5798,6 +5972,25 @@ static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf) conf->retry_long = (u32)-1; } +static void brcmf_init_wmm_prio(u8 *priority) +{ + /* Initialize AC priority array to default + * 802.1d priority as per following table: + * 802.1d prio 0,3 maps to BE + * 802.1d prio 1,2 maps to BK + * 802.1d prio 4,5 maps to VI + * 802.1d prio 6,7 maps to VO + */ + priority[0] = AC_BE; + priority[3] = AC_BE; + priority[1] = AC_BK; + priority[2] = AC_BK; + priority[4] = AC_VI; + priority[5] = AC_VI; + priority[6] = AC_VO; + priority[7] = AC_VO; +} + static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg) { brcmf_fweh_register(cfg->pub, BRCMF_E_LINK, @@ -5892,6 +6085,7 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg) mutex_init(&cfg->usr_sync); brcmf_init_escan(cfg); brcmf_init_conf(cfg->conf); + brcmf_init_wmm_prio(cfg->ac_priority); init_completion(&cfg->vif_disabled); return err; } @@ -6579,6 +6773,7 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy, struct brcmf_if *ifp) struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_pub *drvr = cfg->pub; struct wiphy_wowlan_support *wowl; + struct cfg80211_wowlan *brcmf_wowlan_config = NULL; wowl = kmemdup(&brcmf_wowlan_support, sizeof(brcmf_wowlan_support), GFP_KERNEL); @@ -6601,6 +6796,27 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy, struct brcmf_if *ifp) } wiphy->wowlan = wowl; + + /* wowlan_config structure report for kernels */ + brcmf_wowlan_config = kzalloc(sizeof(*brcmf_wowlan_config), + GFP_KERNEL); + if (brcmf_wowlan_config) { + brcmf_wowlan_config->any = false; + brcmf_wowlan_config->disconnect = true; + brcmf_wowlan_config->eap_identity_req = true; + brcmf_wowlan_config->four_way_handshake = true; + brcmf_wowlan_config->rfkill_release = false; + brcmf_wowlan_config->patterns = NULL; + brcmf_wowlan_config->n_patterns = 0; + brcmf_wowlan_config->tcp = NULL; + if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) + brcmf_wowlan_config->gtk_rekey_failure = true; + else + brcmf_wowlan_config->gtk_rekey_failure = false; + } else { + brcmf_err("Can not allocate memory for brcm_wowlan_config\n"); + } + wiphy->wowlan_config = brcmf_wowlan_config; #endif } @@ -6739,6 +6955,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) struct wireless_dev *wdev; struct brcmf_if *ifp; s32 power_mode; + s32 eap_restrict; s32 err = 0; if (cfg->dongle_up) @@ -6763,6 +6980,14 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) err = brcmf_dongle_roam(ifp); if (err) goto default_conf_out; + + eap_restrict = ifp->drvr->settings->eap_restrict; + if (eap_restrict) { + err = brcmf_fil_iovar_int_set(ifp, "eap_restrict", + eap_restrict); + if (err) + brcmf_info("eap_restrict error (%d)\n", err); + } err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, NULL); if (err) @@ -7043,6 +7268,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr, cfg->wiphy = wiphy; cfg->pub = drvr; + cfg->pm_state = BRCMF_CFG80211_PM_STATE_RESUMED; init_vif_event(&cfg->vif_event); INIT_LIST_HEAD(&cfg->vif_list); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h index 14d5bbad1db1..fc3e49bcff70 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h @@ -23,6 +23,23 @@ #define WL_ROAM_TRIGGER_LEVEL -75 #define WL_ROAM_DELTA 20 +/* WME Access Category Indices (ACIs) */ +#define AC_BE 0 /* Best Effort */ +#define AC_BK 1 /* Background */ +#define AC_VI 2 /* Video */ +#define AC_VO 3 /* Voice */ +#define EDCF_AC_COUNT 4 +#define MAX_8021D_PRIO 8 + +#define EDCF_ACI_MASK 0x60 +#define EDCF_ACI_SHIFT 5 +#define EDCF_ACM_MASK 0x10 +#define EDCF_ECWMIN_MASK 0x0f +#define EDCF_ECWMAX_SHIFT 4 +#define EDCF_AIFSN_MASK 0x0f +#define EDCF_AIFSN_MAX 15 +#define EDCF_ECWMAX_MASK 0xf0 + /* Keep BRCMF_ESCAN_BUF_SIZE below 64K (65536). Allocing over 64K can be * problematic on some systems and should be avoided. */ @@ -75,6 +92,15 @@ #define BRCMF_VIF_EVENT_TIMEOUT msecs_to_jiffies(1500) +#define BRCMF_PM_WAIT_MAXRETRY 100 + +/* cfg80211 wowlan definitions */ +#define WL_WOWLAN_MAX_PATTERNS 8 +#define WL_WOWLAN_MIN_PATTERN_LEN 1 +#define WL_WOWLAN_MAX_PATTERN_LEN 255 +#define WL_WOWLAN_PKT_FILTER_ID_FIRST 201 +#define WL_WOWLAN_PKT_FILTER_ID_LAST (WL_WOWLAN_PKT_FILTER_ID_FIRST + \ + WL_WOWLAN_MAX_PATTERNS - 1) /** * enum brcmf_scan_status - scan engine status * @@ -145,6 +171,13 @@ enum brcmf_vif_status { BRCMF_VIF_STATUS_ASSOC_SUCCESS, }; +enum brcmf_cfg80211_pm_state { + BRCMF_CFG80211_PM_STATE_RESUMED, + BRCMF_CFG80211_PM_STATE_RESUMING, + BRCMF_CFG80211_PM_STATE_SUSPENDED, + BRCMF_CFG80211_PM_STATE_SUSPENDING, +}; + /** * struct vif_saved_ie - holds saved IEs for a virtual interface. * @@ -203,6 +236,12 @@ struct brcmf_cfg80211_assoc_ielen_le { __le32 resp_len; }; +struct brcmf_cfg80211_edcf_acparam { + u8 ACI; + u8 ECW; + u16 TXOP; /* stored in network order (ls octet first) */ +}; + /* dongle escan state */ enum wl_escan_state { WL_ESCAN_STATE_IDLE, @@ -321,6 +360,8 @@ struct brcmf_cfg80211_info { struct brcmf_assoclist_le assoclist; struct brcmf_cfg80211_wowl wowl; struct brcmf_pno_info *pno; + u8 ac_priority[MAX_8021D_PRIO]; + u8 pm_state; }; /** diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index dd586a96b57a..0ad43feb748b 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -433,11 +433,25 @@ static void brcmf_chip_ai_resetcore(struct brcmf_core_priv *core, u32 prereset, { struct brcmf_chip_priv *ci; int count; + struct brcmf_core *d11core2 = NULL; + struct brcmf_core_priv *d11priv2 = NULL; ci = core->chip; + /* special handle two D11 cores reset */ + if (core->pub.id == BCMA_CORE_80211) { + d11core2 = brcmf_chip_get_d11core(&ci->pub, 1); + if (d11core2) { + brcmf_dbg(INFO, "found two d11 cores, reset both\n"); + d11priv2 = container_of(d11core2, struct brcmf_core_priv, + pub); + } + } + /* must disable first to work for arbitrary current core state */ brcmf_chip_ai_coredisable(core, prereset, reset); + if (d11priv2) + brcmf_chip_ai_coredisable(d11priv2, prereset, reset); count = 0; while (ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) & @@ -449,9 +463,30 @@ static void brcmf_chip_ai_resetcore(struct brcmf_core_priv *core, u32 prereset, usleep_range(40, 60); } + if (d11priv2) { + count = 0; + while (ci->ops->read32(ci->ctx, + d11priv2->wrapbase + BCMA_RESET_CTL) & + BCMA_RESET_CTL_RESET) { + ci->ops->write32(ci->ctx, + d11priv2->wrapbase + BCMA_RESET_CTL, + 0); + count++; + if (count > 50) + break; + usleep_range(40, 60); + } + } + ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL, postreset | BCMA_IOCTL_CLK); ci->ops->read32(ci->ctx, core->wrapbase + BCMA_IOCTL); + + if (d11priv2) { + ci->ops->write32(ci->ctx, d11priv2->wrapbase + BCMA_IOCTL, + postreset | BCMA_IOCTL_CLK); + ci->ops->read32(ci->ctx, d11priv2->wrapbase + BCMA_IOCTL); + } } char *brcmf_chip_name(u32 id, u32 rev, char *buf, uint len) @@ -463,6 +498,16 @@ char *brcmf_chip_name(u32 id, u32 rev, char *buf, uint len) return buf; } +bool brcmf_chip_has_clm_blob(u32 id) +{ + bool ret = true; + + if (id == BRCM_CC_4339_CHIP_ID) + return false; + + return ret; +} + static struct brcmf_core *brcmf_chip_add_core(struct brcmf_chip_priv *ci, u16 coreid, u32 base, u32 wrapbase) @@ -1113,6 +1158,21 @@ void brcmf_chip_detach(struct brcmf_chip *pub) kfree(chip); } +struct brcmf_core *brcmf_chip_get_d11core(struct brcmf_chip *pub, u8 unit) +{ + struct brcmf_chip_priv *chip; + struct brcmf_core_priv *core; + + chip = container_of(pub, struct brcmf_chip_priv, pub); + list_for_each_entry(core, &chip->cores, list) { + if (core->pub.id == BCMA_CORE_80211) { + if (unit-- == 0) + return &core->pub; + } + } + return NULL; +} + struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *pub, u16 coreid) { struct brcmf_chip_priv *chip; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h index 7b00f6a59e89..6693614e207e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.h @@ -76,6 +76,7 @@ void brcmf_chip_detach(struct brcmf_chip *chip); struct brcmf_core *brcmf_chip_get_core(struct brcmf_chip *chip, u16 coreid); struct brcmf_core *brcmf_chip_get_chipcommon(struct brcmf_chip *chip); struct brcmf_core *brcmf_chip_get_pmu(struct brcmf_chip *pub); +struct brcmf_core *brcmf_chip_get_d11core(struct brcmf_chip *pub, u8 unit); bool brcmf_chip_iscoreup(struct brcmf_core *core); void brcmf_chip_coredisable(struct brcmf_core *core, u32 prereset, u32 reset); void brcmf_chip_resetcore(struct brcmf_core *core, u32 prereset, u32 reset, @@ -84,5 +85,6 @@ 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); +bool brcmf_chip_has_clm_blob(u32 id); #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 dec25e415619..f1b9faafdda1 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c @@ -8,6 +8,7 @@ #include <linux/netdevice.h> #include <linux/module.h> #include <linux/firmware.h> +#include <linux/pinctrl/consumer.h> #include <brcmu_wifi.h> #include <brcmu_utils.h> #include "core.h" @@ -67,6 +68,14 @@ 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"); +static int brcmf_eap_restrict; +module_param_named(eap_restrict, brcmf_eap_restrict, int, 0400); +MODULE_PARM_DESC(eap_restrict, "Block non-802.1X frames until auth finished"); + +static int brcmf_sdio_wq_highpri; +module_param_named(sdio_wq_highpri, brcmf_sdio_wq_highpri, int, 0); +MODULE_PARM_DESC(sdio_wq_highpri, "SDIO workqueue is set to high priority"); + #ifdef DEBUG /* always succeed brcmf_bus_started() */ static int brcmf_ignore_probe_fail; @@ -202,7 +211,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) char *ptr; s32 err; - /* retreive mac address */ + /* retrieve mac addresses */ err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, sizeof(ifp->mac_addr)); if (err < 0) { @@ -250,10 +259,12 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) ri->chipname, sizeof(ri->chipname)); /* Do any CLM downloading */ - err = brcmf_c_process_clm_blob(ifp); - if (err < 0) { - bphy_err(drvr, "download CLM blob file failed, %d\n", err); - goto done; + if (brcmf_chip_has_clm_blob(bus->chip)) { + err = brcmf_c_process_clm_blob(ifp); + if (err < 0) { + bphy_err(drvr, "download CLM blob file failed, %d\n", err); + goto done; + } } /* query for 'ver' to get version info from firmware */ @@ -336,6 +347,13 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) /* Enable tx beamforming, errors can be ignored (not supported) */ (void)brcmf_fil_iovar_int_set(ifp, "txbf", 1); + + /* add unicast packet filter */ + err = brcmf_pktfilter_add_remove(ifp->ndev, + BRCMF_UNICAST_FILTER_NUM, true); + if (err) + brcmf_info("Add unicast filter error (%d)\n", err); + done: return err; } @@ -407,12 +425,14 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, if (!settings) return NULL; - /* start by using the module paramaters */ + /* start by using the module parameters */ settings->p2p_enable = !!brcmf_p2p_enable; settings->feature_disable = brcmf_feature_disable; settings->fcmode = brcmf_fcmode; settings->roamoff = !!brcmf_roamoff; settings->iapp = !!brcmf_iapp_enable; + settings->eap_restrict = !!brcmf_eap_restrict; + settings->sdio_wq_highpri = !!brcmf_sdio_wq_highpri; #ifdef DEBUG settings->ignore_probe_fail = !!brcmf_ignore_probe_fail; #endif @@ -423,6 +443,7 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev, /* See if there is any device specific platform data configured */ found = false; if (brcmfmac_pdata) { + pinctrl_pm_select_default_state(brcmfmac_pdata->dev); for (i = 0; i < brcmfmac_pdata->device_count; i++) { device_pd = &brcmfmac_pdata->devices[i]; if ((device_pd->bus_type == bus_type) && @@ -456,10 +477,30 @@ void brcmf_release_module_param(struct brcmf_mp_device *module_param) static int __init brcmf_common_pd_probe(struct platform_device *pdev) { + int err; + struct brcmfmac_platform_data pdata = { + .power_on = NULL, + .power_off = NULL, + .fw_alternative_path = NULL, + .device_count = 0, + }; + brcmf_dbg(INFO, "Enter\n"); brcmfmac_pdata = dev_get_platdata(&pdev->dev); + if (!brcmfmac_pdata) { + err = platform_device_add_data(pdev, &pdata, + sizeof(pdata)); + if (err) + brcmf_err("platform data allocation failed\n"); + brcmfmac_pdata = dev_get_platdata(&pdev->dev); + pinctrl_pm_select_idle_state(&pdev->dev); + } + + if (!brcmfmac_pdata) + return 0; + brcmfmac_pdata->dev = &pdev->dev; if (brcmfmac_pdata->power_on) brcmfmac_pdata->power_on(); @@ -470,7 +511,7 @@ static int brcmf_common_pd_remove(struct platform_device *pdev) { brcmf_dbg(INFO, "Enter\n"); - if (brcmfmac_pdata->power_off) + if (brcmfmac_pdata && brcmfmac_pdata->power_off) brcmfmac_pdata->power_off(); return 0; @@ -492,7 +533,7 @@ static int __init brcmfmac_module_init(void) if (err == -ENODEV) brcmf_dbg(INFO, "No platform data available.\n"); - /* Initialize global module paramaters */ + /* Initialize global module parameters */ brcmf_mp_attach(); /* Continue the initialization by registering the different busses */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h index 144cf4570bc3..6184ca09e29e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h @@ -37,6 +37,8 @@ extern struct brcmf_mp_global_t brcmf_mp_global; * @feature_disable: Feature_disable bitmask. * @fcmode: FWS flow control. * @roamoff: Firmware roaming off? + * @eap_restrict: Not allow data tx/rx until 802.1X auth succeeds + * @sdio_wq_highpri: Tasks submitted to SDIO workqueue will run immediately. * @ignore_probe_fail: Ignore probe failure. * @country_codes: If available, pointer to struct for translating country codes * @bus: Bus specific platform data. Only SDIO at the mmoment. @@ -47,6 +49,9 @@ struct brcmf_mp_device { int fcmode; bool roamoff; bool iapp; + bool eap_restrict; + int sdio_dpc_prio; + bool sdio_wq_highpri; bool ignore_probe_fail; struct brcmfmac_pd_cc *country_codes; const char *board_type; @@ -71,5 +76,8 @@ void brcmf_dmi_probe(struct brcmf_mp_device *settings, u32 chip, u32 chiprev); static inline void brcmf_dmi_probe(struct brcmf_mp_device *settings, u32 chip, u32 chiprev) {} #endif +u8 brcmf_map_prio_to_prec(void *cfg, u8 prio); + +u8 brcmf_map_prio_to_aci(void *cfg, u8 prio); #endif /* BRCMFMAC_COMMON_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index 406b367c284c..9cd555f1526a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -536,6 +536,11 @@ void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success) struct ethhdr *eh; u16 type; + if (!ifp) { + brcmu_pkt_buf_free_skb(txp); + return; + } + eh = (struct ethhdr *)(txp->data); type = ntohs(eh->h_proto); @@ -1470,3 +1475,177 @@ void __exit brcmf_core_exit(void) #endif } +int +brcmf_pktfilter_add_remove(struct net_device *ndev, int filter_num, bool add) +{ + struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = ifp->drvr; + struct brcmf_pkt_filter_le *pkt_filter; + int filter_fixed_len = offsetof(struct brcmf_pkt_filter_le, u); + int pattern_fixed_len = offsetof(struct brcmf_pkt_filter_pattern_le, + mask_and_pattern); + u16 mask_and_pattern[MAX_PKTFILTER_PATTERN_SIZE]; + int buflen = 0; + int ret = 0; + + brcmf_dbg(INFO, "%s packet filter number %d\n", + (add ? "add" : "remove"), filter_num); + + pkt_filter = kzalloc(sizeof(*pkt_filter) + + (MAX_PKTFILTER_PATTERN_SIZE * 2), GFP_ATOMIC); + if (!pkt_filter) + return -ENOMEM; + + switch (filter_num) { + case BRCMF_UNICAST_FILTER_NUM: + pkt_filter->id = 100; + pkt_filter->type = 0; + pkt_filter->negate_match = 0; + pkt_filter->u.pattern.offset = 0; + pkt_filter->u.pattern.size_bytes = 1; + mask_and_pattern[0] = 0x0001; + break; + case BRCMF_BROADCAST_FILTER_NUM: + //filter_pattern = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF"; + pkt_filter->id = 101; + pkt_filter->type = 0; + pkt_filter->negate_match = 0; + pkt_filter->u.pattern.offset = 0; + pkt_filter->u.pattern.size_bytes = 6; + mask_and_pattern[0] = 0xFFFF; + mask_and_pattern[1] = 0xFFFF; + mask_and_pattern[2] = 0xFFFF; + mask_and_pattern[3] = 0xFFFF; + mask_and_pattern[4] = 0xFFFF; + mask_and_pattern[5] = 0xFFFF; + break; + case BRCMF_MULTICAST4_FILTER_NUM: + //filter_pattern = "102 0 0 0 0xFFFFFF 0x01005E"; + pkt_filter->id = 102; + pkt_filter->type = 0; + pkt_filter->negate_match = 0; + pkt_filter->u.pattern.offset = 0; + pkt_filter->u.pattern.size_bytes = 3; + mask_and_pattern[0] = 0xFFFF; + mask_and_pattern[1] = 0x01FF; + mask_and_pattern[2] = 0x5E00; + break; + case BRCMF_MULTICAST6_FILTER_NUM: + //filter_pattern = "103 0 0 0 0xFFFF 0x3333"; + pkt_filter->id = 103; + pkt_filter->type = 0; + pkt_filter->negate_match = 0; + pkt_filter->u.pattern.offset = 0; + pkt_filter->u.pattern.size_bytes = 2; + mask_and_pattern[0] = 0xFFFF; + mask_and_pattern[1] = 0x3333; + break; + case BRCMF_MDNS_FILTER_NUM: + //filter_pattern = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB"; + pkt_filter->id = 104; + pkt_filter->type = 0; + pkt_filter->negate_match = 0; + pkt_filter->u.pattern.offset = 0; + pkt_filter->u.pattern.size_bytes = 6; + mask_and_pattern[0] = 0xFFFF; + mask_and_pattern[1] = 0xFFFF; + mask_and_pattern[2] = 0xFFFF; + mask_and_pattern[3] = 0x0001; + mask_and_pattern[4] = 0x005E; + mask_and_pattern[5] = 0xFB00; + break; + case BRCMF_ARP_FILTER_NUM: + //filter_pattern = "105 0 0 12 0xFFFF 0x0806"; + pkt_filter->id = 105; + pkt_filter->type = 0; + pkt_filter->negate_match = 0; + pkt_filter->u.pattern.offset = 12; + pkt_filter->u.pattern.size_bytes = 2; + mask_and_pattern[0] = 0xFFFF; + mask_and_pattern[1] = 0x0608; + break; + case BRCMF_BROADCAST_ARP_FILTER_NUM: + //filter_pattern = "106 0 0 0 + //0xFFFFFFFFFFFF0000000000000806 + //0xFFFFFFFFFFFF0000000000000806"; + pkt_filter->id = 106; + pkt_filter->type = 0; + pkt_filter->negate_match = 0; + pkt_filter->u.pattern.offset = 0; + pkt_filter->u.pattern.size_bytes = 14; + mask_and_pattern[0] = 0xFFFF; + mask_and_pattern[1] = 0xFFFF; + mask_and_pattern[2] = 0xFFFF; + mask_and_pattern[3] = 0x0000; + mask_and_pattern[4] = 0x0000; + mask_and_pattern[5] = 0x0000; + mask_and_pattern[6] = 0x0608; + mask_and_pattern[7] = 0xFFFF; + mask_and_pattern[8] = 0xFFFF; + mask_and_pattern[9] = 0xFFFF; + mask_and_pattern[10] = 0x0000; + mask_and_pattern[11] = 0x0000; + mask_and_pattern[12] = 0x0000; + mask_and_pattern[13] = 0x0608; + break; + default: + ret = -EINVAL; + goto failed; + } + memcpy(pkt_filter->u.pattern.mask_and_pattern, mask_and_pattern, + pkt_filter->u.pattern.size_bytes * 2); + buflen = filter_fixed_len + pattern_fixed_len + + pkt_filter->u.pattern.size_bytes * 2; + + if (add) { + /* Add filter */ + ret = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", + pkt_filter, buflen); + if (ret) + goto failed; + drvr->pkt_filter[filter_num].id = pkt_filter->id; + drvr->pkt_filter[filter_num].enable = 0; + + } else { + /* Delete filter */ + ret = brcmf_fil_iovar_int_set(ifp, "pkt_filter_delete", + pkt_filter->id); + if (ret == -ENOENT) + ret = 0; + if (ret) + goto failed; + + drvr->pkt_filter[filter_num].id = 0; + drvr->pkt_filter[filter_num].enable = 0; + } +failed: + if (ret) + brcmf_err("%s packet filter failed, ret=%d\n", + (add ? "add" : "remove"), ret); + + kfree(pkt_filter); + return ret; +} + +int brcmf_pktfilter_enable(struct net_device *ndev, bool enable) +{ + struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_pub *drvr = ifp->drvr; + int ret = 0; + int idx = 0; + + for (idx = 0; idx < MAX_PKT_FILTER_COUNT; ++idx) { + if (drvr->pkt_filter[idx].id != 0) { + drvr->pkt_filter[idx].enable = enable; + ret = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", + &drvr->pkt_filter[idx], + sizeof(struct brcmf_pkt_filter_enable_le)); + if (ret) { + brcmf_err("%s packet filter id(%d) failed, ret=%d\n", + (enable ? "enable" : "disable"), + drvr->pkt_filter[idx].id, ret); + } + } + } + return ret; +} diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index 6699637d3bf8..6def862f6008 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -12,6 +12,7 @@ #include <net/cfg80211.h> #include "fweh.h" +#include "fwil_types.h" #define TOE_TX_CSUM_OL 0x00000001 #define TOE_RX_CSUM_OL 0x00000002 @@ -136,6 +137,8 @@ struct brcmf_pub { struct work_struct bus_reset; u8 clmver[BRCMF_DCMD_SMLEN]; + struct brcmf_pkt_filter_enable_le pkt_filter[MAX_PKT_FILTER_COUNT]; + }; /* forward declarations */ @@ -213,5 +216,7 @@ void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb); void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); int __init brcmf_core_init(void); void __exit brcmf_core_exit(void); - +int brcmf_pktfilter_add_remove(struct net_device *ndev, int filter_num, + bool add); +int brcmf_pktfilter_enable(struct net_device *ndev, bool enable); #endif /* BRCMFMAC_CORE_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c index 9ed85420f3ca..164735f613f2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c @@ -99,7 +99,7 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) s32 err, fwerr; if (drvr->bus_if->state != BRCMF_BUS_UP) { - bphy_err(drvr, "bus is down. we have nothing to do.\n"); + brcmf_dbg(FIL, "bus is down. we have nothing to do.\n"); return -EIO; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h index 37c512036e0e..f3f7b1514167 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h @@ -136,6 +136,19 @@ #define BRCMF_WOWL_MAXPATTERNS 8 #define BRCMF_WOWL_MAXPATTERNSIZE 128 +enum { + BRCMF_UNICAST_FILTER_NUM = 0, + BRCMF_BROADCAST_FILTER_NUM, + BRCMF_MULTICAST4_FILTER_NUM, + BRCMF_MULTICAST6_FILTER_NUM, + BRCMF_MDNS_FILTER_NUM, + BRCMF_ARP_FILTER_NUM, + BRCMF_BROADCAST_ARP_FILTER_NUM, + MAX_PKT_FILTER_COUNT +}; + +#define MAX_PKTFILTER_PATTERN_SIZE 16 + #define BRCMF_COUNTRY_BUF_SZ 4 #define BRCMF_ANT_MAX 4 diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index 2bd892df83cc..06aab9001f78 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -404,7 +404,7 @@ struct brcmf_fws_mac_descriptor { u8 traffic_lastreported_bmp; }; -#define BRCMF_FWS_HANGER_MAXITEMS 1024 +#define BRCMF_FWS_HANGER_MAXITEMS 3072 /** * enum brcmf_fws_hanger_item_state - state of hanger item. @@ -1865,6 +1865,9 @@ void brcmf_fws_hdrpull(struct brcmf_if *ifp, s16 siglen, struct sk_buff *skb) WARN_ON(siglen > skb->len); + if (siglen > skb->len) + siglen = skb->len; + if (!siglen) return; /* if flow control disabled, skip to packet data and leave */ @@ -2130,8 +2133,10 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb) skcb->if_flags = 0; skcb->state = BRCMF_FWS_SKBSTATE_NEW; brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx); + + /* mapping from 802.1d priority to firmware fifo index */ if (!multicast) - fifo = brcmf_fws_prio2fifo[skb->priority]; + fifo = brcmf_map_prio_to_aci(drvr->config, skb->priority); brcmf_fws_lock(fws); if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC) @@ -2343,7 +2348,7 @@ struct brcmf_fws_info *brcmf_fws_attach(struct brcmf_pub *drvr) struct brcmf_if *ifp; u32 tlv = BRCMF_FWS_FLAGS_RSSI_SIGNALS; int rc; - u32 mode; + u32 mode = 0; fws = kzalloc(sizeof(*fws), GFP_KERNEL); if (!fws) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c index b886b56a5e5a..625471007b6c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/of.c @@ -18,15 +18,17 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio; struct device_node *root, *np = dev->of_node; struct property *prop; + const char *cp = NULL; int irq; u32 irqf; - u32 val; + u32 val32; + u16 val16; /* Set board-type to the first string of the machine compatible prop */ root = of_find_node_by_path("/"); if (root) { prop = of_find_property(root, "compatible", NULL); - settings->board_type = of_prop_next_string(prop, NULL); + cp = of_prop_next_string(prop, NULL); of_node_put(root); } @@ -34,8 +36,18 @@ void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type, !of_device_is_compatible(np, "brcm,bcm4329-fmac")) return; - if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0) - sdio->drive_strength = val; + if (of_property_read_u32(np, "brcm,drive-strength", &val32) == 0) + sdio->drive_strength = val32; + + if (of_property_read_bool(np, "brcm,use_board_type")) + settings->board_type = cp; + + sdio->broken_sg_support = of_property_read_bool(np, + "brcm,broken_sg_support"); + if (of_property_read_u16(np, "brcm,sd_head_align", &val16) == 0) + sdio->sd_head_align = val16; + if (of_property_read_u16(np, "brcm,sd_sgentry_align", &val16) == 0) + sdio->sd_sgentry_align = val16; /* make sure there are interrupts defined in the node */ if (!of_find_property(np, "interrupts", NULL)) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index 7ba9f6a68645..2345f0c8383d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -457,10 +457,21 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac) */ static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr) { + struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; bool random_addr = false; + bool local_admin = false; - if (!dev_addr || is_zero_ether_addr(dev_addr)) - random_addr = true; + if (!dev_addr || is_zero_ether_addr(dev_addr)) { + /* If the primary interface address is already locally + * administered, create a new random address. + */ + if (pri_ifp->mac_addr[0] & 0x02) { + random_addr = true; + } else { + dev_addr = pri_ifp->mac_addr; + local_admin = true; + } + } /* Generate the P2P Device Address obtaining a random ethernet * address with the locally administered bit set. @@ -470,6 +481,9 @@ static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr) else memcpy(p2p->dev_addr, dev_addr, ETH_ALEN); + if (local_admin) + p2p->dev_addr[0] |= 0x02; + /* Generate the P2P Interface Address. If the discovery and connection * BSSCFGs need to simultaneously co-exist, then this address must be * different from the P2P Device Address, but also locally administered. @@ -1491,6 +1505,7 @@ static s32 brcmf_p2p_tx_action_frame(struct brcmf_p2p_info *p2p, { struct brcmf_pub *drvr = p2p->cfg->pub; struct brcmf_cfg80211_vif *vif; + struct brcmf_p2p_action_frame *p2p_act_frame; s32 err = 0; s32 timeout = 0; @@ -1500,7 +1515,13 @@ static s32 brcmf_p2p_tx_action_frame(struct brcmf_p2p_info *p2p, clear_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status); clear_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status); - vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; + /* check if it is a p2p_presence response */ + p2p_act_frame = (struct brcmf_p2p_action_frame *) af_params->action_frame.data; + if (p2p_act_frame->subtype == P2P_AF_PRESENCE_RSP) + vif = p2p->bss_idx[P2PAPI_BSSCFG_CONNECTION].vif; + else + vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif; + err = brcmf_fil_bsscfg_data_set(vif->ifp, "actframe", af_params, sizeof(*af_params)); if (err) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 6c463475e90b..b19ee61b3543 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -38,6 +38,7 @@ #include "chip.h" #include "core.h" #include "common.h" +#include "cfg80211.h" enum brcmf_pcie_state { @@ -78,7 +79,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { BRCMF_FW_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371), }; -#define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */ +#define BRCMF_PCIE_FW_UP_TIMEOUT 5000 /* msec */ #define BRCMF_PCIE_REG_MAP_SIZE (32 * 1024) @@ -188,7 +189,7 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = { #define BRCMF_H2D_HOST_D0_INFORM_IN_USE 0x00000008 #define BRCMF_H2D_HOST_D0_INFORM 0x00000010 -#define BRCMF_PCIE_MBDATA_TIMEOUT msecs_to_jiffies(2000) +#define BRCMF_PCIE_MBDATA_TIMEOUT msecs_to_jiffies(5000) #define BRCMF_PCIE_CFGREG_STATUS_CMD 0x4 #define BRCMF_PCIE_CFGREG_PM_CSR 0x4C @@ -692,7 +693,7 @@ brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data) /* Send mailbox interrupt twice as a hardware workaround */ core = brcmf_chip_get_core(devinfo->ci, BCMA_CORE_PCIE2); - if (core->rev <= 13) + if (core && (core->rev <= 0xd && core->rev != 0xb)) pci_write_config_dword(devinfo->pdev, BRCMF_PCIE_REG_SBMBX, 1); return 0; @@ -1834,6 +1835,7 @@ static void brcmf_pcie_setup(struct device *dev, int ret, return; fail: + brcmf_free(dev); device_release_driver(dev); } @@ -2001,6 +2003,11 @@ brcmf_pcie_remove(struct pci_dev *pdev) dev_set_drvdata(&pdev->dev, NULL); } +static void brcmf_pcie_shutdown(struct pci_dev *pdev) +{ + brcmf_pcie_remove(pdev); + return; +} #ifdef CONFIG_PM @@ -2009,11 +2016,22 @@ static int brcmf_pcie_pm_enter_D3(struct device *dev) { struct brcmf_pciedev_info *devinfo; struct brcmf_bus *bus; + struct brcmf_cfg80211_info *config; + int retry = BRCMF_PM_WAIT_MAXRETRY; brcmf_dbg(PCIE, "Enter\n"); bus = dev_get_drvdata(dev); devinfo = bus->bus_priv.pcie->devinfo; + config = bus->drvr->config; + + while (retry && + config->pm_state == BRCMF_CFG80211_PM_STATE_SUSPENDING) { + usleep_range(10000, 20000); + retry--; + } + if (!retry && config->pm_state == BRCMF_CFG80211_PM_STATE_SUSPENDING) + brcmf_err(bus, "timed out wait for cfg80211 suspended\n"); brcmf_bus_change_state(bus, BRCMF_BUS_DOWN); @@ -2023,9 +2041,21 @@ static int brcmf_pcie_pm_enter_D3(struct device *dev) wait_event_timeout(devinfo->mbdata_resp_wait, devinfo->mbdata_completed, BRCMF_PCIE_MBDATA_TIMEOUT); if (!devinfo->mbdata_completed) { - brcmf_err(bus, "Timeout on response for entering D3 substate\n"); - brcmf_bus_change_state(bus, BRCMF_BUS_UP); - return -EIO; + struct brcmf_pcie_shared_info *shared; + u32 addr; + u32 dtoh_mb_data; + + shared = &devinfo->shared; + addr = shared->dtoh_mb_data_addr; + dtoh_mb_data = brcmf_pcie_read_tcm32(devinfo, addr); + + if (dtoh_mb_data & BRCMF_D2H_DEV_D3_ACK) { + brcmf_dbg(PCIE, "D2H_MB_DATA: D3 ACK\n"); + devinfo->mbdata_completed = true; + } + + if (!devinfo->mbdata_completed) + brcmf_err(bus, "Timeout on response for entering D3 substate\n"); } devinfo->state = BRCMFMAC_PCIE_STATE_DOWN; @@ -2033,7 +2063,6 @@ static int brcmf_pcie_pm_enter_D3(struct device *dev) return 0; } - static int brcmf_pcie_pm_leave_D3(struct device *dev) { struct brcmf_pciedev_info *devinfo; @@ -2053,6 +2082,7 @@ static int brcmf_pcie_pm_leave_D3(struct device *dev) if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM)) goto cleanup; brcmf_dbg(PCIE, "Hot resume, continue....\n"); + msleep(10); devinfo->state = BRCMFMAC_PCIE_STATE_UP; brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); brcmf_bus_change_state(bus, BRCMF_BUS_UP); @@ -2126,6 +2156,7 @@ static struct pci_driver brcmf_pciedrvr = { .id_table = brcmf_pcie_devid_table, .probe = brcmf_pcie_probe, .remove = brcmf_pcie_remove, + .shutdown = brcmf_pcie_shutdown, #ifdef CONFIG_PM .driver.pm = &brcmf_pciedrvr_pm, #endif diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 264ad63232f8..f51723c77d38 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -34,15 +34,23 @@ #include "core.h" #include "common.h" #include "bcdc.h" +#include "fwil.h" #define DCMD_RESP_TIMEOUT msecs_to_jiffies(2500) #define CTL_DONE_TIMEOUT msecs_to_jiffies(2500) +#define ULP_HUDI_PROC_DONE_TIME msecs_to_jiffies(2500) /* watermark expressed in number of words */ #define DEFAULT_F2_WATERMARK 0x8 #define CY_4373_F2_WATERMARK 0x40 #define CY_43012_F2_WATERMARK 0x60 - +#define CY_43455_F2_WATERMARK 0x60 +#define CY_43455_MES_WATERMARK 0x50 +#define CY_43455_MESBUSYCTRL (CY_43455_MES_WATERMARK | \ + SBSDIO_MESBUSYCTRL_ENAB) +#define CY_4339_F2_WATERMARK 48 +#define CY_4339_MES_WATERMARK 80 +#define CY_4339_MESBUSYCTRL (CY_4339_MES_WATERMARK | SBSDIO_MESBUSYCTRL_ENAB) #ifdef DEBUG #define BRCMF_TRAP_INFO_SIZE 80 @@ -313,14 +321,8 @@ struct rte_console { #define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US) #define BRCMF_SDIO_MAX_ACCESS_ERRORS 5 -/* - * Conversion of 802.1D priority to precedence level - */ -static uint prio2prec(u32 prio) -{ - return (prio == PRIO_8021D_NONE || prio == PRIO_8021D_BE) ? - (prio^2) : prio; -} +static void brcmf_sdio_firmware_callback(struct device *dev, int err, + struct brcmf_fw_request *fwreq); #ifdef DEBUG /* Device console log buffer state */ @@ -2317,6 +2319,7 @@ static uint brcmf_sdio_sendfromq(struct brcmf_sdio *bus, uint maxframes) &prec_out); if (pkt == NULL) break; + skb_orphan(pkt); __skb_queue_tail(&pktq, pkt); } spin_unlock_bh(&bus->txq_lock); @@ -2540,6 +2543,166 @@ static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus) return ret; } +/* This Function is used to retrieve important + * details from dongle related to ULP mode Mostly + * values/SHM details that will be vary depending + * on the firmware branches + */ +static void +brcmf_sdio_ulp_preinit(struct device *dev) +{ + struct brcmf_bus *bus_if = dev_get_drvdata(dev); + struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; + struct brcmf_if *ifp = bus_if->drvr->iflist[0]; + s32 err = 0; + + brcmf_dbg(TRACE, "Enter\n"); + + /* Query ulp_sdioctrl iovar to get the ULP related SHM offsets */ + err = brcmf_fil_iovar_data_get(ifp, "ulp_sdioctrl", &sdiodev->shm_ulp, + sizeof(sdiodev->shm_ulp)); + if (err) + brcmf_dbg(TRACE, "ulp_sdioctrl iovar returned err = %d\n", err); + + sdiodev->ulp = false; + + brcmf_dbg(TRACE, "m_ulp_ctrl_sdio[%x] m_ulp_wakeevt_ind [%x]\n", + M_DS1_CTRL_SDIO(sdiodev->shm_ulp), + M_WAKEEVENT_IND(sdiodev->shm_ulp)); + brcmf_dbg(TRACE, "m_ulp_wakeind [%x]\n", + M_ULP_WAKE_IND(sdiodev->shm_ulp)); +} + +#define BRCMF_SDIO_FW_CODE 0 +#define BRCMF_SDIO_FW_NVRAM 1 + +/* Reinitialize ARM because In DS1 mode ARM got off */ +static int +brcmf_sdio_ulp_reinit_fw(struct brcmf_sdio *bus) +{ + struct brcmf_sdio_dev *sdiodev = bus->sdiodev; + struct brcmf_fw_request *fwreq; + int err = 0; + + /* After firmware redownload tx/rx seq are reset accordingly + * these values are reset on FMAC side tx_max is initially set to 4, + * which later is updated by FW. + */ + bus->tx_seq = 0; + bus->rx_seq = 0; + bus->tx_max = 4; + + fwreq = kzalloc(sizeof(fwreq) + 2 * sizeof(struct brcmf_fw_item), + GFP_KERNEL); + if (!fwreq) + return -ENOMEM; + + fwreq->items[BRCMF_SDIO_FW_CODE].path = sdiodev->fw_name; + fwreq->items[BRCMF_SDIO_FW_CODE].type = BRCMF_FW_TYPE_BINARY; + fwreq->items[BRCMF_SDIO_FW_NVRAM].path = sdiodev->nvram_name; + fwreq->items[BRCMF_SDIO_FW_NVRAM].type = BRCMF_FW_TYPE_NVRAM; + fwreq->n_items = 2; + + err = brcmf_fw_get_firmwares(sdiodev->dev, fwreq, + brcmf_sdio_firmware_callback); + if (err != 0) { + brcmf_err("async firmware request failed: %d\n", err); + kfree(fwreq); + } + + return err; +} + +/* Check if device is in DS1 mode and handshake with ULP UCODE */ +static bool +brcmf_sdio_ulp_pre_redownload_check(struct brcmf_sdio *bus) +{ + int err = 0; + u32 value = 0; + u32 val32, ulp_wake_ind, wowl_wake_ind; + int reg_addr; + unsigned long timeout; + + value = brcmf_sdiod_readb(bus->sdiodev, SDIO_CCCR_IOEx, &err); + + if (value == SDIO_FUNC_ENABLE_1) { + brcmf_dbg(SDIO, "GOT THE INTERRUPT FROM UCODE\n"); + bus->sdiodev->ulp = true; + ulp_wake_ind = D11SHM_RD(bus->sdiodev, M_ULP_WAKE_IND( + bus->sdiodev->shm_ulp), &err) >> 16; + wowl_wake_ind = D11SHM_RD(bus->sdiodev, M_WAKEEVENT_IND( + bus->sdiodev->shm_ulp), &err) >> 16; + + brcmf_dbg(SDIO, "wowl_wake_ind: 0x%08x, ulp_wake_ind: 0x%08x\n", + wowl_wake_ind, ulp_wake_ind); + + if (wowl_wake_ind || ulp_wake_ind) { + /* TX wake Don't do anything. + * Just bail out and re-download firmware. + */ + } else { + /* RX wake negotiate with MAC */ + brcmf_dbg(SDIO, "M_DS1_CTRL_SDIO: 0x%08x\n", + (u32)D11SHM_RD(bus->sdiodev, + M_DS1_CTRL_SDIO(bus->sdiodev->shm_ulp), + &err)); + D11SHM_WR(bus->sdiodev, M_DS1_CTRL_SDIO( + bus->sdiodev->shm_ulp), + C_DS1_CTRL_SDIO_DS1_EXIT | + C_DS1_CTRL_REQ_VALID, + &err); + val32 = D11REG_RD(bus->sdiodev, + D11_MACCONTROL_REG, &err); + val32 = val32 | D11_MACCONTROL_REG_WAKE; + D11REG_WR(bus->sdiodev, + D11_MACCONTROL_REG, val32, &err); + + /* Poll for PROC_DONE to be set by ucode */ + value = D11SHM_RD(bus->sdiodev, + M_DS1_CTRL_SDIO( + bus->sdiodev->shm_ulp), &err); + /* Wait here (polling) for C_DS1_CTRL_PROC_DONE */ + timeout = jiffies + ULP_HUDI_PROC_DONE_TIME; + while (!(value & C_DS1_CTRL_PROC_DONE)) { + value = D11SHM_RD(bus->sdiodev, + M_DS1_CTRL_SDIO( + bus->sdiodev->shm_ulp), &err); + if (time_after(jiffies, timeout)) + break; + usleep_range(1000, 2000); + } + brcmf_dbg(SDIO, "M_DS1_CTRL_SDIO: 0x%08x\n", + (u32)D11SHM_RD(bus->sdiodev, + M_DS1_CTRL_SDIO( + bus->sdiodev->shm_ulp), &err)); + value = D11SHM_RD(bus->sdiodev, + M_DS1_CTRL_SDIO( + bus->sdiodev->shm_ulp), &err); + if (!(value & C_DS1_CTRL_PROC_DONE)) { + brcmf_err("%s: timeout Failed to enter DS1 Exit state!\n", + __func__); + return false; + } + } + ulp_wake_ind = D11SHM_RD(bus->sdiodev, M_ULP_WAKE_IND( + bus->sdiodev->shm_ulp), &err) >> 16; + wowl_wake_ind = D11SHM_RD(bus->sdiodev, M_WAKEEVENT_IND( + bus->sdiodev->shm_ulp), &err) >> 16; + brcmf_dbg(SDIO, "wowl_wake_ind: 0x%08x, ulp_wake_ind: 0x%08x\n", + wowl_wake_ind, ulp_wake_ind); + reg_addr = CORE_CC_REG( + brcmf_chip_get_pmu(bus->ci)->base, min_res_mask); + brcmf_sdiod_writel(bus->sdiodev, reg_addr, + DEFAULT_43012_MIN_RES_MASK, &err); + if (err) + brcmf_err("min_res_mask failed\n"); + + return true; + } + + return false; +} + static void brcmf_sdio_dpc(struct brcmf_sdio *bus) { struct brcmf_sdio_dev *sdiod = bus->sdiodev; @@ -2613,6 +2776,9 @@ static void brcmf_sdio_dpc(struct brcmf_sdio *bus) if (intstatus & I_HMB_HOST_INT) { intstatus &= ~I_HMB_HOST_INT; intstatus |= brcmf_sdio_hostmail(bus); + if ((sdiod->func1->device != SDIO_DEVICE_ID_BROADCOM_4339) && + brcmf_sdio_ulp_pre_redownload_check(bus)) + brcmf_sdio_ulp_reinit_fw(bus); } sdio_release_host(bus->sdiodev->func1); @@ -2767,7 +2933,13 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) skb_push(pkt, bus->tx_hdrlen); /* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */ - prec = prio2prec((pkt->priority & PRIOMASK)); + /* In WLAN, priority is always set by the AP using WMM parameters + * and this need not always follow the standard 802.1d priority. + * Based on AP WMM config, map from 802.1d priority to corresponding + * precedence level. + */ + prec = brcmf_map_prio_to_prec(bus_if->drvr->config, + (pkt->priority & PRIOMASK)); /* Check for existing queue, current flow-control, pending event, or pending clock */ @@ -3515,6 +3687,11 @@ static int brcmf_sdio_bus_preinit(struct device *dev) if (err < 0) goto done; + /* initialize SHM address from firmware for DS1 */ + if ((sdiodev->func1->device != SDIO_DEVICE_ID_BROADCOM_4339) && + !bus->sdiodev->ulp) + brcmf_sdio_ulp_preinit(dev); + bus->tx_hdrlen = SDPCM_HWHDR_LEN + SDPCM_SWHDR_LEN; if (sdiodev->sg_support) { bus->txglom = false; @@ -4106,9 +4283,6 @@ static const struct brcmf_bus_ops brcmf_sdio_bus_ops = { .debugfs_create = brcmf_sdio_debugfs_create }; -#define BRCMF_SDIO_FW_CODE 0 -#define BRCMF_SDIO_FW_NVRAM 1 - static void brcmf_sdio_firmware_callback(struct device *dev, int err, struct brcmf_fw_request *fwreq) { @@ -4205,6 +4379,31 @@ static void brcmf_sdio_firmware_callback(struct device *dev, int err, brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl, &err); break; + case SDIO_DEVICE_ID_BROADCOM_43455: + brcmf_dbg(INFO, "set F2 watermark to 0x%x*4 bytes for 43455\n", + CY_43455_F2_WATERMARK); + brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK, + CY_43455_F2_WATERMARK, &err); + devctl = brcmf_sdiod_readb(sdiod, SBSDIO_DEVICE_CTL, + &err); + devctl |= SBSDIO_DEVCTL_F2WM_ENAB; + brcmf_sdiod_writeb(sdiod, SBSDIO_DEVICE_CTL, devctl, + &err); + brcmf_sdiod_writeb(sdiod, SBSDIO_FUNC1_MESBUSYCTRL, + CY_43455_MESBUSYCTRL, &err); + break; + case SDIO_DEVICE_ID_BROADCOM_4339: + brcmf_sdiod_writeb(sdiod, + SBSDIO_WATERMARK, + CY_4339_F2_WATERMARK, &err); + devctl = brcmf_sdiod_readb(sdiod, + SBSDIO_DEVICE_CTL, &err); + devctl |= SBSDIO_DEVCTL_F2WM_ENAB; + brcmf_sdiod_writeb(sdiod, + SBSDIO_DEVICE_CTL, devctl, &err); + brcmf_sdiod_writeb(sdiod, + SBSDIO_FUNC1_MESBUSYCTRL, CY_4339_MESBUSYCTRL, &err); + break; default: brcmf_sdiod_writeb(sdiod, SBSDIO_WATERMARK, DEFAULT_F2_WATERMARK, &err); @@ -4322,9 +4521,21 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) bus->txminmax = BRCMF_TXMINMAX; bus->tx_seq = SDPCM_SEQ_WRAP - 1; + /* attempt to attach to the dongle */ + if (!(brcmf_sdio_probe_attach(bus))) { + brcmf_err("brcmf_sdio_probe_attach failed\n"); + goto fail; + } + /* single-threaded workqueue */ - wq = alloc_ordered_workqueue("brcmf_wq/%s", WQ_MEM_RECLAIM, - dev_name(&sdiodev->func1->dev)); + if (sdiodev->settings->sdio_wq_highpri) { + wq = alloc_workqueue("brcmf_wq/%s", + WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, + 1, dev_name(&sdiodev->func1->dev)); + } else { + wq = alloc_ordered_workqueue("brcmf_wq/%s", WQ_MEM_RECLAIM, + dev_name(&sdiodev->func1->dev)); + } if (!wq) { brcmf_err("insufficient memory to create txworkqueue\n"); goto fail; @@ -4333,12 +4544,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) INIT_WORK(&bus->datawork, brcmf_sdio_dataworker); bus->brcmf_wq = wq; - /* attempt to attach to the dongle */ - if (!(brcmf_sdio_probe_attach(bus))) { - brcmf_err("brcmf_sdio_probe_attach failed\n"); - goto fail; - } - spin_lock_init(&bus->rxctl_lock); spin_lock_init(&bus->txq_lock); init_waitqueue_head(&bus->ctrl_wait); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h index 0bd47c119dae..88acfd2e034c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h @@ -165,6 +165,17 @@ struct brcmf_sdreg { struct brcmf_sdio; struct brcmf_sdiod_freezer; +/* ULP SHM Offsets info */ +struct ulp_shm_info { + u32 m_ulp_ctrl_sdio; + u32 m_ulp_wakeevt_ind; + u32 m_ulp_wakeind; +}; + +struct fmac_ulp { + struct ulp_shm_info ulp_shm_offset; +}; + struct brcmf_sdio_dev { struct sdio_func *func1; struct sdio_func *func2; @@ -190,6 +201,8 @@ struct brcmf_sdio_dev { bool wowl_enabled; enum brcmf_sdiod_state state; struct brcmf_sdiod_freezer *freezer; + struct fmac_ulp shm_ulp; + bool ulp; }; /* sdio core registers */ @@ -377,4 +390,51 @@ void brcmf_sdio_wowl_config(struct device *dev, bool enabled); int brcmf_sdio_sleep(struct brcmf_sdio *bus, bool sleep); void brcmf_sdio_trigger_dpc(struct brcmf_sdio *bus); +/* SHM offsets */ +#define M_DS1_CTRL_SDIO(ptr) ((ptr).ulp_shm_offset.m_ulp_ctrl_sdio) +#define M_WAKEEVENT_IND(ptr) ((ptr).ulp_shm_offset.m_ulp_wakeevt_ind) +#define M_ULP_WAKE_IND(ptr) ((ptr).ulp_shm_offset.m_ulp_wakeind) + +#define D11_BASE_ADDR 0x18001000 +#define D11_AXI_BASE_ADDR 0xE8000000 +#define D11_SHM_BASE_ADDR (D11_AXI_BASE_ADDR + 0x4000) + +#define D11REG_ADDR(offset) (D11_BASE_ADDR + (offset)) +#define D11IHR_ADDR(offset) (D11_AXI_BASE_ADDR + 0x400 + (2 * (offset))) +#define D11SHM_ADDR(offset) (D11_SHM_BASE_ADDR + (offset)) + +/* MacControl register */ +#define D11_MACCONTROL_REG D11REG_ADDR(0x120) +#define D11_MACCONTROL_REG_WAKE 0x4000000 + +/* Following are the offsets in M_DRVR_UCODE_IF_PTR block. Start address of + * M_DRVR_UCODE_IF_PTR block is present in M_DRVR_UCODE_IF_PTR. + */ + +/* M_ULP_WAKE_IND bits */ +#define ULP_WAKE_IND_WATCHDOG_EXP 0x1 +#define ULP_WAKE_IND_FCBS_ERROR 0x2 +#define ULP_WAKE_IND_RE_TRANSMIT_ERR 0x4 +#define ULP_WAKE_IND_HOST_WKUP 0x8 +#define ULP_WAKE_IND_INVALID_FCBS_BLK 0x10 + +#define C_DS1_CTRL_SDIO_DS1_SLEEP 0x1 +#define C_DS1_CTRL_SDIO_MAC_ON 0x2 +#define C_DS1_CTRL_SDIO_RADIO_PHY_ON 0x4 +#define C_DS1_CTRL_SDIO_DS1_EXIT 0x8 +#define C_DS1_CTRL_PROC_DONE 0x100 +#define C_DS1_CTRL_REQ_VALID 0x200 + +#define D11SHM_WR(sdh, offset, val, ret) \ + brcmf_sdiod_writel(sdh, D11SHM_ADDR(offset), val, ret) + +#define D11SHM_RD(sdh, offset, ret) \ + brcmf_sdiod_readl(sdh, D11SHM_ADDR(offset), ret) + +#define D11REG_WR(sdh, addr, val, ret) \ + brcmf_sdiod_writel(sdh, addr, val, ret) + +#define D11REG_RD(sdh, addr, ret) \ + brcmf_sdiod_readl(sdh, addr, ret) + #endif /* BRCMFMAC_SDIO_H */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 06f3c01f10b3..2bd38425d5c2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -19,6 +19,7 @@ #include "core.h" #include "common.h" #include "bcdc.h" +#include "cfg80211.h" #define IOCTL_RESP_TIMEOUT msecs_to_jiffies(2000) @@ -1441,8 +1442,22 @@ static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state) { struct usb_device *usb = interface_to_usbdev(intf); struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); + struct brcmf_bus *bus; + struct brcmf_cfg80211_info *config; + int retry = BRCMF_PM_WAIT_MAXRETRY; brcmf_dbg(USB, "Enter\n"); + + bus = devinfo->bus_pub.bus; + config = bus->drvr->config; + while (retry && + config->pm_state == BRCMF_CFG80211_PM_STATE_SUSPENDING) { + usleep_range(10000, 20000); + retry--; + } + if (!retry && config->pm_state == BRCMF_CFG80211_PM_STATE_SUSPENDING) + brcmf_err("timed out wait for cfg80211 suspended\n"); + devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP; if (devinfo->wowl_enabled) { brcmf_cancel_all_urbs(devinfo); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c index d07e7c7355d9..8bd84482b846 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c @@ -70,8 +70,12 @@ static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy, else ret = brcmf_fil_cmd_data_get(ifp, cmdhdr->cmd, dcmd_buf, ret_len); - if (ret != 0) + + if (ret != 0) { + brcmf_dbg(INFO, "error(%d), return -EPERM\n", ret); + ret = -EPERM; goto exit; + } wr_pointer = dcmd_buf; while (ret_len > 0) { diff --git a/drivers/net/wireless/broadcom/brcm80211/include/chipcommon.h b/drivers/net/wireless/broadcom/brcm80211/include/chipcommon.h index 0340bba96868..1f6fcd4aff5c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/include/chipcommon.h +++ b/drivers/net/wireless/broadcom/brcm80211/include/chipcommon.h @@ -306,6 +306,8 @@ struct chipcregs { * Maximum delay for the PMU state transition in us. * This is an upper bound intended for spinwaits etc. */ -#define PMU_MAX_TRANSITION_DLY 15000 +#define PMU_MAX_TRANSITION_DLY 15000 + +#define DEFAULT_43012_MIN_RES_MASK 0x0f8bfe77 #endif /* _SBCHIPC_H */ diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h index d1a5d5df02f5..171e7ca05e74 100644 --- a/include/linux/mmc/sdio_ids.h +++ b/include/linux/mmc/sdio_ids.h @@ -36,6 +36,7 @@ #define SDIO_DEVICE_ID_BROADCOM_4339 0x4339 #define SDIO_DEVICE_ID_BROADCOM_43362 0xa962 #define SDIO_DEVICE_ID_BROADCOM_43364 0xa9a4 +#define SDIO_DEVICE_ID_BROADCOM_43428 0xa9a4 #define SDIO_DEVICE_ID_BROADCOM_43430 0xa9a6 #define SDIO_DEVICE_ID_BROADCOM_4345 0x4345 #define SDIO_DEVICE_ID_BROADCOM_43455 0xa9bf diff --git a/include/linux/platform_data/brcmfmac.h b/include/linux/platform_data/brcmfmac.h index 1d30bf278231..b737c0a8e58d 100644 --- a/include/linux/platform_data/brcmfmac.h +++ b/include/linux/platform_data/brcmfmac.h @@ -178,6 +178,7 @@ struct brcmfmac_platform_data { void (*power_off)(void); char *fw_alternative_path; int device_count; + struct device *dev; struct brcmfmac_pd_device devices[0]; }; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 4ab2c49423dc..c615db32c5fb 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -4017,6 +4017,7 @@ enum wiphy_flags { WIPHY_FLAG_SUPPORTS_5_10_MHZ = BIT(22), WIPHY_FLAG_HAS_CHANNEL_SWITCH = BIT(23), WIPHY_FLAG_HAS_STATIC_WEP = BIT(24), + WIPHY_FLAG_DFS_OFFLOAD = BIT(25) }; /** @@ -5474,6 +5475,32 @@ void cfg80211_send_layer2_update(struct net_device *dev, const u8 *addr); int regulatory_hint(struct wiphy *wiphy, const char *alpha2); /** + * regulatory_hint_user - hint to the wireless core a regulatory domain + * which the driver has received from an application + * @alpha2: the ISO/IEC 3166 alpha2 the driver claims its regulatory domain + * should be in. If @rd is set this should be NULL. Note that if you + * set this to NULL you should still set rd->alpha2 to some accepted + * alpha2. + * @user_reg_hint_type: the type of user regulatory hint. + * + * Wireless drivers can use this function to hint to the wireless core + * the current regulatory domain as specified by trusted applications, + * it is the driver's responsibilty to estbalish which applications it + * trusts. + * + * The wiphy should be registered to cfg80211 prior to this call. + * For cfg80211 drivers this means you must first use wiphy_register(), + * for mac80211 drivers you must first use ieee80211_register_hw(). + * + * Drivers should check the return value, its possible you can get + * an -ENOMEM or an -EINVAL. + * + * Return: 0 on success. -ENOMEM, -EINVAL. + */ +int regulatory_hint_user(const char *alpha2, + enum nl80211_user_reg_hint_type user_reg_hint_type); + +/** * regulatory_set_wiphy_regd - set regdom info for self managed drivers * @wiphy: the wireless device we want to process the regulatory domain on * @rd: the regulatory domain informatoin to use for this wiphy @@ -7445,6 +7472,15 @@ void cfg80211_pmsr_complete(struct wireless_dev *wdev, bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype, bool is_4addr, u8 check_swif); +/** + * cfg80211_is_gratuitous_arp_unsolicited_na - packet is grat. ARP/unsol. NA + * @skb: the input packet, must be an ethernet frame already + * + * Return: %true if the packet is a gratuitous ARP or unsolicited NA packet. + * This is used to drop packets that shouldn't occur because the AP implements + * a proxy service. + */ +bool cfg80211_is_gratuitous_arp_unsolicited_na(struct sk_buff *skb); /* Logging, debugging and troubleshooting/diagnostic helpers. */ diff --git a/net/wireless/chan.c b/net/wireless/chan.c index fcac5c6366e1..68713164d79f 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c @@ -815,7 +815,8 @@ static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, for (freq = start_freq; freq <= end_freq; freq += 20) { c = ieee80211_get_channel(wiphy, freq); - if (!c || c->flags & prohibited_flags) + if (!c || ((c->flags & prohibited_flags) && + !(wiphy->flags & WIPHY_FLAG_DFS_OFFLOAD))) return false; } diff --git a/net/wireless/db.txt b/net/wireless/db.txt new file mode 100644 index 000000000000..0b34e7ab4d0e --- /dev/null +++ b/net/wireless/db.txt @@ -0,0 +1,1305 @@ +# This is the world regulatory domain +country 00: + (2402 - 2472 @ 40), (20) + # Channel 12 - 13. + (2457 - 2482 @ 20), (20), NO-IR, AUTO-BW + # Channel 14. Only JP enables this and for 802.11b only + (2474 - 2494 @ 20), (20), NO-IR, NO-OFDM + # Channel 36 - 48 + (5170 - 5250 @ 80), (20), NO-IR, AUTO-BW + # Channel 52 - 64 + (5250 - 5330 @ 80), (20), NO-IR, DFS, AUTO-BW + # Channel 100 - 144 + (5490 - 5730 @ 160), (20), NO-IR, DFS + # Channel 149 - 165 + (5735 - 5835 @ 80), (20), NO-IR + # IEEE 802.11ad (60GHz), channels 1..3 + (57240 - 63720 @ 2160), (0) + + +country AD: + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20) + (5250 - 5330 @ 80), (20), DFS + (5490 - 5710 @ 80), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country AE: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country AF: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +# Source: +# http://pucanguilla.org/Downloads/January2005-Anguilla%20Table%20of%20Allocations.pdf +country AI: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country AL: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20.00), AUTO-BW + (5250 - 5330 @ 80), (20.00), DFS, AUTO-BW + (5490 - 5710 @ 160), (27.00), DFS + +country AM: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 20), (18) + (5250 - 5330 @ 20), (18), DFS + +country AN: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country AR: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country AS: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country AT: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country AU: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5710 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country AW: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country AZ: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (18), AUTO-BW + (5250 - 5330 @ 80), (18), DFS, AUTO-BW + +country BA: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country BB: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (23), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5735 - 5835 @ 80), (30) + +country BD: DFS-JP + (2402 - 2482 @ 40), (20) + (5735 - 5835 @ 80), (30) + +country BE: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country BF: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +# Bulgarian rules as defined by the Communications Regulation Commission in the +# following documents: +# +# Rules for carrying out electronic communications through radio equipment using +# radio spectrum, which does not need to be individually assigned (the Rules): +# http://www.crc.bg/files/_bg/Pravila_09_06_2015.pdf +# +# List of radio equipment that uses harmonized within the European Union bands +# and electronic communications terminal equipment (the List): +# http://www.crc.bg/files/_bg/Spisak_2015.pdf +# +# Note: The transmit power limits in the 5250-5350 MHz and 5470-5725 MHz bands +# can be raised by 3 dBm if TPC is enabled. Refer to BDS EN 301 893 for details. +country BG: DFS-ETSI + # Wideband data transmission systems (WDTS) in the 2.4GHz ISM band, ref: + # I.22 of the List, BDS EN 300 328 + (2402 - 2482 @ 40), (20) + # 5 GHz Radio Local Area Networks (RLANs), ref: + # II.H01 of the List, BDS EN 301 893 + (5170 - 5250 @ 80), (23), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + # II.H01 of the List, I.54 from the List, BDS EN 301 893 + (5490 - 5710 @ 160), (27), DFS + # Short range devices (SRDs) in the 5725-5875 MHz frequency range, ref: + # I.43 of the List, BDS EN 300 440-2, BDS EN 300 440-1 + (5725 - 5875 @ 80), (14) + # 60 GHz Multiple-Gigabit RLAN Systems, ref: + # II.H03 of the List, BDS EN 302 567-2 + (57000 - 66000 @ 2160), (40), NO-OUTDOOR + +country BH: DFS-JP + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 20), (20) + (5250 - 5330 @ 20), (20), DFS + (5735 - 5835 @ 20), (20) + +country BL: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country BM: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country BN: DFS-JP + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5735 - 5835 @ 80), (20) + +country BO: DFS-JP + (2402 - 2482 @ 40), (20) + (5250 - 5330 @ 80), (30), DFS + (5735 - 5835 @ 80), (30) + +country BR: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country BS: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +# Source: +# http://www.bicma.gov.bt/paper/publication/nrrpart4.pdf +country BT: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country BY: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country BZ: DFS-JP + (2402 - 2482 @ 40), (30) + (5735 - 5835 @ 80), (30) + +country CA: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5600 @ 80), (24), DFS + (5650 - 5730 @ 80), (24), DFS + (5735 - 5835 @ 80), (30) + +# Source: +# http://www.art-rca.org +country CF: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 40), (17) + (5250 - 5330 @ 40), (24), DFS + (5490 - 5730 @ 40), (24), DFS + (5735 - 5835 @ 40), (30) + +country CH: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country CI: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country CL: DFS-JP + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5735 - 5835 @ 80), (20) + +country CN: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (23), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5735 - 5835 @ 80), (30) + # 60 GHz band channels 1,4: 28dBm, channels 2,3: 44dBm + # ref: http://www.miit.gov.cn/n11293472/n11505629/n11506593/n11960250/n11960606/n11960700/n12330791.files/n12330790.pdf + (57240 - 59400 @ 2160), (28) + (59400 - 63720 @ 2160), (44) + (63720 - 65880 @ 2160), (28) + +country CO: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country CR: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 20), (17) + (5250 - 5330 @ 20), (24), DFS + (5490 - 5730 @ 20), (24), DFS + (5735 - 5835 @ 20), (30) + +# http://www.mincom.gob.cu/?q=marcoregulatorio +# - Redes Informáticas +# Resolución 127, 2011 - Reglamento Banda 2,4 GHz. +country CU: DFS-FCC + (2400 - 2483.5 @ 40), (200 mW) + +country CX: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country CY: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +# Data from http://www.ctu.eu/164/download/VOR/VOR-12-08-2005-34.pdf +# and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf +# Power at 5250 - 5350 MHz and 5470 - 5725 MHz can be doubled if TPC is +# implemented. +country CZ: DFS-ETSI + (2400 - 2483.5 @ 40), (100 mW) + (5150 - 5250 @ 80), (200 mW), NO-OUTDOOR, AUTO-BW + (5250 - 5350 @ 80), (100 mW), NO-OUTDOOR, DFS, AUTO-BW + (5470 - 5725 @ 160), (500 mW), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +# Allocation for the 2.4 GHz band (Vfg 10 / 2013, Allgemeinzuteilung von +# Frequenzen für die Nutzung in lokalen Netzwerken; Wireless Local Area +# Networks (WLAN-Funkanwendungen). +# https://www.bundesnetzagentur.de/SharedDocs/Downloads/DE/Sachgebiete/Telekommunikation/Unternehmen_Institutionen/Frequenzen/Allgemeinzuteilungen/2013_10_WLAN_2,4GHz_pdf.pdf +# +# Allocation for the 5 GHz band (Vfg. 7 / 2010, Allgemeinzuteilung von +# Frequenzen in den Bereichen 5150 MHz - 5350 MHz und 5470 MHz - 5725 MHz für +# Funkanwendungen zur breitbandigen Datenübertragung, WAS/WLAN („Wireless +# Access Systems including Wireless Local Area Networks“). +# https://www.bundesnetzagentur.de/SharedDocs/Downloads/DE/Sachgebiete/Telekommunikation/Unternehmen_Institutionen/Frequenzen/Allgemeinzuteilungen/2010_07_WLAN_5GHz_pdf.pdf +# The values for the 5 GHz have been reduced by a factor of 2 (3db) for non TPC +# devices (in other words: devices with TPC can use twice the tx power of this +# table). Note that the docs do not require TPC for 5150--5250; the reduction +# to 100mW thus is not strictly required -- however the conservative 100mW +# limit is used here as the non-interference with radar and satellite +# apps relies on the attenuation by the building walls only in the +# absence of DFS; the neighbour countries have 100mW limit here as well. +# +# The ETSI EN 300 440-1 standard for short range devices in the 5 GHz band has +# been implemented in Germany: +# https://www.bundesnetzagentur.de/SharedDocs/Downloads/DE/Sachgebiete/Telekommunikation/Unternehmen_Institutionen/Frequenzen/Allgemeinzuteilungen/2014_69_SRD_pdf.pdf +# +# Allocation for the 60 GHz band (Allgemeinzuteilung von Frequenzen im +# Bereich 57 GHz - 66 GHz für Funkanwendungen für weitbandige +# Datenübertragungssysteme; „Multiple Gigabit WAS/RLAN Systems (MGWS)“). +# https://www.bundesnetzagentur.de/SharedDocs/Downloads/DE/Sachgebiete/Telekommunikation/Unternehmen_Institutionen/Frequenzen/Allgemeinzuteilungen/2011_08_MGWS_pdf.pdf + +country DE: DFS-ETSI + (2400 - 2483.5 @ 40), (100 mW) + (5150 - 5250 @ 80), (100 mW), NO-OUTDOOR, AUTO-BW + (5250 - 5350 @ 80), (100 mW), NO-OUTDOOR, DFS, AUTO-BW + (5470 - 5725 @ 160), (500 mW), DFS + # short range devices (ETSI EN 300 440-1) + (5725 - 5875 @ 80), (25 mW) + # 60 GHz band channels 1-4 (ETSI EN 302 567) + (57000 - 66000 @ 2160), (40) + +country DK: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +# Source: +# http://www.ntrcdom.org/index.php?option=com_content&view=category&layout=blog&id=10&Itemid=55 +country DM: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5735 - 5835 @ 80), (30) + +country DO: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5735 - 5835 @ 80), (30) + +country DZ: DFS-JP + (2402 - 2482 @ 40), (20) + (5170.000 - 5250.000 @ 80.000), (23.00), AUTO-BW + (5250.000 - 5330.000 @ 80.000), (23.00), DFS, AUTO-BW + (5490.000 - 5670.000 @ 160.000), (23.00), DFS + +country EC: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 20), (17) + (5250 - 5330 @ 20), (24), DFS + (5490 - 5730 @ 20), (24), DFS + (5735 - 5835 @ 20), (30) + +country EE: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country EG: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 40), (20) + (5250 - 5330 @ 40), (20), DFS + +# Orden IET/787/2013, de 25 de abril, por la que se aprueba +# el cuadro nacional de atribución de frecuencias. +# http://www.boe.es/diario_boe/txt.php?id=BOE-A-2013-4845 +# +# more info at "Cuadro nacional de atribución de frecuencias (CNAF)": +# http://www.minetur.gob.es/telecomunicaciones/espectro/paginas/cnaf.aspx + +country ES: DFS-ETSI + (2400 - 2483.5 @ 40), (100 mW) + (5150 - 5250 @ 80), (200 mW), NO-OUTDOOR, AUTO-BW + (5250 - 5350 @ 80), (100 mW), NO-OUTDOOR, DFS, AUTO-BW + (5470 - 5725 @ 160), (500 mW), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country ET: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country FI: DFS-ETSI + (2400 - 2483.5 @ 40), (20) + (5150 - 5250 @ 80), (23), NO-OUTDOOR, AUTO-BW + (5250 - 5350 @ 80), (20), NO-OUTDOOR, DFS, AUTO-BW + (5470 - 5725 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country FM: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country FR: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country GB: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country GD: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country GE: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (18), AUTO-BW + (5250 - 5330 @ 80), (18), DFS, AUTO-BW + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country GF: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country GH: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country GL: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country GP: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country GR: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country GT: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5735 - 5835 @ 80), (30) + +country GU: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 20), (17) + (5250 - 5330 @ 20), (24), DFS + (5490 - 5730 @ 20), (24), DFS + (5735 - 5835 @ 20), (30) + +country GY: + (2402 - 2482 @ 40), (30) + (5735 - 5835 @ 80), (30) + +country HK: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5710 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country HN: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country HR: DFS-ETSI + (2400 - 2483.5 @ 40), (20) + (5150 - 5250 @ 80), (23), NO-OUTDOOR, AUTO-BW + (5250 - 5350 @ 80), (20), NO-OUTDOOR, DFS, AUTO-BW + (5470 - 5725 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country HT: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country HU: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country ID: DFS-JP + # ref: http://www.postel.go.id/content/ID/regulasi/standardisasi/kepdir/bwa%205,8%20ghz.pdf + (2402 - 2482 @ 20), (20) + (5735 - 5815 @ 20), (23) + +country IE: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country IL: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5150 - 5250 @ 80), (200 mW), NO-OUTDOOR, AUTO-BW + (5250 - 5350 @ 80), (200 mW), NO-OUTDOOR, DFS, AUTO-BW + +country IN: + (2402 - 2482 @ 40), (20) + (5150 - 5350 @ 160), (23) + (5725 - 5875 @ 80), (23) + +country IR: DFS-JP + (2402 - 2482 @ 40), (20) + (5735 - 5835 @ 80), (30) + +country IS: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country IT: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country JM: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country JO: DFS-JP + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (23) + (5735 - 5835 @ 80), (23) + +country JP: DFS-JP + (2402 - 2482 @ 40), (20) + (2474 - 2494 @ 20), (20), NO-OFDM + (4910 - 4990 @ 40), (23) + (5030 - 5090 @ 40), (23) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (23), DFS + # 60 GHz band channels 2-4 at 10mW, + # ref: http://www.arib.or.jp/english/html/overview/doc/1-STD-T74v1_1.pdf + (59000 - 66000 @ 2160), (10 mW) + +country KE: DFS-JP + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (23) + (5490 - 5570 @ 80), (30), DFS + (5735 - 5775 @ 40), (23) + +country KH: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +# Source +# http://ntrc.kn/?page_id=7 +country KN: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (30), DFS + (5735 - 5815 @ 80), (30) + +country KP: DFS-JP + (2402 - 2482 @ 20), (20) + (5170 - 5250 @ 20), (20) + (5250 - 5330 @ 20), (20), DFS + (5490 - 5630 @ 20), (30), DFS + (5735 - 5815 @ 20), (30) + +country KR: DFS-JP + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (30), DFS + (5735 - 5835 @ 80), (30) + # 60 GHz band channels 1-4, + # ref: http://www.law.go.kr/%ED%96%89%EC%A0%95%EA%B7%9C%EC%B9%99/%EB%AC%B4%EC%84%A0%EC%84%A4%EB%B9%84%EA%B7%9C%EC%B9%99 + (57000 - 66000 @ 2160), (43) + +country KW: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + +country KY: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country KZ: + (2402 - 2482 @ 40), (20) + +country LB: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +# Source: +# http://www.ntrc.org.lc/operational_structures.htm +country LC: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (30), DFS + (5735 - 5815 @ 80), (30) + +country LI: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country LK: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 20), (17) + (5250 - 5330 @ 20), (24), DFS + (5490 - 5730 @ 20), (24), DFS + (5735 - 5835 @ 20), (30) + +# Source: +# http://lca.org.ls/images/documents/lesotho_national_frequency_allocation_plan.pdf +country LS: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country LT: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country LU: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country LV: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country MA: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + +country MC: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +# Source: +# http://www.cnfr.md/index.php?pag=sec&id=117&l=en +country MD: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +# Source: +# http://www.cept.org/files/1050/Tools%20and%20Services/EFIS%20-%20ECO%20Frequency%20Information%20System/National%20frequency%20tables/Montenegro%20NAFT%20-%202010.pdf +country ME: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country MF: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country MH: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country MK: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country MN: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country MO: DFS-FCC + (2402 - 2482 @ 40), (23) + (5170 - 5250 @ 80), (23), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5490 - 5730 @ 160), (30), DFS + (5735 - 5835 @ 80), (30) + +country MP: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country MQ: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +# Source: +# http://www.are.mr/pdfs/telec_freq_TNAbf_2010.pdf +country MR: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country MT: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country MU: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +# Source: +# http://www.cam.gov.mv/docs/tech_standards/TAM-TS-100-2004-WLAN.pdf +country MV: DFS-ETSI + (2400 - 2483.5 @ 40), (100 mW) + (5150 - 5250 @ 80), (200 mW), AUTO-BW + (5250 - 5350 @ 80), (100 mW), DFS, AUTO-BW + (5725 - 5850 @ 80), (100 mW) + +country MW: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country MX: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country MY: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5650 @ 160), (24), DFS + (5735 - 5835 @ 80), (24) + +country NG: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5250 - 5330 @ 80), (30), DFS + (5735 - 5835 @ 80), (30) + +country NI: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +# Regulation on the use of frequency space without a license and +# without notification 2015 +# +# http://wetten.overheid.nl/BWBR0036378/2015-03-05 + +country NL: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), NO-OUTDOOR, AUTO-BW + (5250 - 5330 @ 80), (20), NO-OUTDOOR, DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # short range devices (ETSI EN 300 440-1) + (5725 - 5875 @ 80), (25 mW) + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +# Data from http://www.lovdata.no/dokument/SF/forskrift/2012-01-19-77 +# Power at 5250 - 5350 MHz, 5470 - 5725 MHz and 5815 – 5850 MHz can +# be doubled if TPC is implemented. +# Up to 2W (or 4W with TPC) is allowed in the 5725 – 5795 MHz band +# which has been merged with 5470 - 5725 MHz to allow wide channels +country NO: DFS-ETSI + (2400 - 2483.5 @ 40), (100 mW) + (5150 - 5250 @ 80), (200 mW), AUTO-BW + (5250 - 5350 @ 80), (100 mW), DFS, AUTO-BW + (5470 - 5795 @ 160), (500 mW), DFS + (5815 - 5850 @ 35), (2000 mW), DFS + (17100 - 17300 @ 200), (100 mW) + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country NP: DFS-JP + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5735 - 5835 @ 80), (20) + +country NZ: DFS-ETSI + (2402 - 2482 @ 40), (30) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country OM: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country PA: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5735 - 5835 @ 80), (30) + +country PE: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country PF: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country PG: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country PH: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country PK: DFS-JP + (2402 - 2482 @ 40), (20) + (5735 - 5835 @ 80), (30) + +country PL: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country PM: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country PR: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country PT: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country PW: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country PY: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country QA: DFS-JP + (2402 - 2482 @ 40), (20) + (5735 - 5835 @ 80), (30) + +country RE: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country RO: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + + +# Source: +# http://www.ratel.rs/upload/documents/Plan_namene/Plan_namene-sl_glasnik.pdf +country RS: DFS-ETSI + (2400 - 2483.5 @ 40), (100 mW) + (5150 - 5350 @ 40), (200 mW), NO-OUTDOOR + (5470 - 5725 @ 20), (1000 mW), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country RU: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5650 - 5730 @ 80), (30), DFS + (5735 - 5835 @ 80), (30) + # 60 GHz band channels 1-4, ref: Changes to NLA 124_Order №129_22042015.pdf + (57000 - 66000 @ 2160), (40) + +country RW: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country SA: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country SE: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country SG: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country SI: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country SK: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +# Source: +# Regulation N° 2004-005 ART/DG/DRC/D.Rég +country SN: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country SR: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country SV: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 20), (17) + (5250 - 5330 @ 20), (23), DFS + (5735 - 5835 @ 20), (30) + +country SY: + (2402 - 2482 @ 40), (20) + +# Source: +# http://www.telecommission.tc/Spectrum-plan20110324-101210.html +country TC: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country TD: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country TG: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 40), (20) + (5250 - 5330 @ 40), (20), DFS + (5490 - 5710 @ 40), (27), DFS + +country TH: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country TN: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + +country TR: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country TT: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +# Source: +# Table of Frequency Allocations of Republic of China (Taiwan) / Nov 2014: +# http://www.motc.gov.tw/websitedowndoc?file=post/201411171137330.doc& \ +# filedisplay=Table+of+radio+frequency+allocation.doc +# LP0002 Low-power Radio-frequency Devices Technical Regulations / 28 Jun 2011: +# http://www.ncc.gov.tw/english/show_file.aspx?table_name=news&file_sn=681 +# (section 3.10.1, 4.7) +country TW: DFS-FCC + (2400 - 2483.5 @ 40), (30) + # Follow US 5.15 ~ 5.25 GHz: 30 dBm for master mode, 23 dBm for clients + (5150 - 5250 @ 80), (23), AUTO-BW + (5250 - 5350 @ 80), (23), DFS, AUTO-BW + (5470 - 5725 @ 160), (23), DFS + (5725 - 5850 @ 80), (30) + +country TZ: + (2402 - 2482 @ 40), (20) + (5735 - 5835 @ 80), (30) + +# Source: +# #914 / 06 Sep 2007: http://www.ucrf.gov.ua/uk/doc/nkrz/1196068874 +# #1174 / 23 Oct 2008: http://www.nkrz.gov.ua/uk/activities/ruling/1225269361 +# (appendix 8) +# Listed 5GHz range is a lowest common denominator for all related +# rules in the referenced laws. Such a range is used because of +# disputable definitions there. +country UA: DFS-ETSI + (2400 - 2483.5 @ 40), (20), NO-OUTDOOR + (5150 - 5250 @ 80), (20), NO-OUTDOOR, AUTO-BW + (5250 - 5350 @ 80), (20), DFS, NO-OUTDOOR, AUTO-BW + (5490 - 5670 @ 160), (20), DFS + (5735 - 5835 @ 80), (20) + # 60 GHz band channels 1-4, ref: Etsi En 302 567 + (57000 - 66000 @ 2160), (40) + +country UG: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country US: DFS-FCC + (2402 - 2472 @ 40), (30) + # 5.15 ~ 5.25 GHz: 30 dBm for master mode, 23 dBm for clients + (5170 - 5250 @ 80), (23), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5490 - 5730 @ 160), (23), DFS + (5735 - 5835 @ 80), (30) + # 60g band + # reference: http://cfr.regstoday.com/47cfr15.aspx#47_CFR_15p255 + # channels 1,2,3, EIRP=40dBm(43dBm peak) + (57240 - 63720 @ 2160), (40) + +country UY: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (23), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5735 - 5835 @ 80), (30) + +# Source: +# http://cemc.uz/article/1976/ +country UZ: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + +# Source: +# http://www.ntrc.vc/regulations/Jun_2006_Spectrum_Managment_Regulations.pdf +country VC: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +# Source: +# Official Gazette (Gaceta Oficial) concerning Unlicensed transmitter use +# (10 June 2013) +# http://www.conatel.gob.ve/ +country VE: DFS-FCC + (2402 - 2482 @ 40), (30) + (5170 - 5250 @ 80), (23), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5735 - 5835 @ 80), (30) + +country VI: DFS-FCC + (2402 - 2472 @ 40), (30) + (5170 - 5250 @ 80), (24), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country VN: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17) + (5250 - 5330 @ 80), (24), DFS + (5490 - 5730 @ 80), (24), DFS + (5735 - 5835 @ 80), (30) + +# Source: +# http://www.trr.vu/attachments/category/130/GURL_for_Short-range_Radiocommunication_Devices2.pdf +country VU: DFS-FCC + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (17), AUTO-BW + (5250 - 5330 @ 80), (24), DFS, AUTO-BW + (5490 - 5730 @ 160), (24), DFS + (5735 - 5835 @ 80), (30) + +country WF: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country WS: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 40), (20) + (5250 - 5330 @ 40), (20), DFS + (5490 - 5710 @ 40), (27), DFS + +country YE: + (2402 - 2482 @ 40), (20) + +country YT: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS + +country ZA: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (30) + +country ZW: DFS-ETSI + (2402 - 2482 @ 40), (20) + (5170 - 5250 @ 80), (20), AUTO-BW + (5250 - 5330 @ 80), (20), DFS, AUTO-BW + (5490 - 5710 @ 160), (27), DFS diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 446c76d44e65..a46e94846ddd 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2951,6 +2951,7 @@ int regulatory_hint_user(const char *alpha2, return 0; } +EXPORT_SYMBOL(regulatory_hint_user); int regulatory_hint_indoor(bool is_indoor, u32 portid) { diff --git a/net/wireless/util.c b/net/wireless/util.c index 5b4ed5bbc542..eb0427c0730b 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -2150,3 +2150,54 @@ bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype, return false; } EXPORT_SYMBOL(cfg80211_iftype_allowed); + +bool cfg80211_is_gratuitous_arp_unsolicited_na(struct sk_buff *skb) +{ + const struct ethhdr *eth = (void *)skb->data; + const struct { + struct arphdr hdr; + u8 ar_sha[ETH_ALEN]; + u8 ar_sip[4]; + u8 ar_tha[ETH_ALEN]; + u8 ar_tip[4]; + } __packed *arp; + const struct ipv6hdr *ipv6; + const struct icmp6hdr *icmpv6; + + switch (eth->h_proto) { + case cpu_to_be16(ETH_P_ARP): + /* can't say - but will probably be dropped later anyway */ + if (!pskb_may_pull(skb, sizeof(*eth) + sizeof(*arp))) + return false; + + arp = (void *)(eth + 1); + + if ((arp->hdr.ar_op == cpu_to_be16(ARPOP_REPLY) || + arp->hdr.ar_op == cpu_to_be16(ARPOP_REQUEST)) && + !memcmp(arp->ar_sip, arp->ar_tip, sizeof(arp->ar_sip))) + return true; + break; + case cpu_to_be16(ETH_P_IPV6): + /* can't say - but will probably be dropped later anyway */ + if (!pskb_may_pull(skb, sizeof(*eth) + sizeof(*ipv6) + + sizeof(*icmpv6))) + return false; + + ipv6 = (void *)(eth + 1); + icmpv6 = (void *)(ipv6 + 1); + + if (icmpv6->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT && + !memcmp(&ipv6->saddr, &ipv6->daddr, sizeof(ipv6->saddr))) + return true; + break; + default: + /* + * no need to support other protocols, proxy service isn't + * specified for any others + */ + break; + } + + return false; +} +EXPORT_SYMBOL(cfg80211_is_gratuitous_arp_unsolicited_na); |