diff options
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 130 |
1 files changed, 82 insertions, 48 deletions
@@ -31,9 +31,6 @@ #ifdef CONFIG_DEBUG_FS #include "debugfs.h" #endif -#ifdef SUPPORT_MFG -#include "mfg.h" -#endif #define MWL_DESC "Marvell 802.11ac Wireless Network Driver" #define MWL_DEV_NAME "Marvell 802.11ac Adapter" @@ -135,9 +132,6 @@ static const struct ieee80211_rate mwl_rates_50[] = { static const struct ieee80211_iface_limit ap_if_limits[] = { { .max = SYSADPT_NUM_OF_AP, .types = BIT(NL80211_IFTYPE_AP) }, -#ifdef CONFIG_MAC80211_MESH - { .max = 1, .types = BIT(NL80211_IFTYPE_MESH_POINT) }, -#endif { .max = 1, .types = BIT(NL80211_IFTYPE_STATION) }, }; @@ -152,6 +146,23 @@ static const struct ieee80211_iface_combination ap_if_comb = { BIT(NL80211_CHAN_WIDTH_80), }; +struct region_code_mapping { + const char *alpha2; + u32 region_code; +}; + +static const struct region_code_mapping regmap[] = { + {"US", 0x10}, /* US FCC */ + {"CA", 0x20}, /* Canada */ + {"EU", 0x30}, /* ETSI */ + {"ES", 0x31}, /* Spain */ + {"FR", 0x32}, /* France */ + {"JP", 0x40}, /* Japan */ + {"TW", 0x80}, /* Taiwan */ + {"AU", 0x81}, /* Australia */ + {"CN", 0x90}, /* China (Asia) */ +}; + static int mwl_alloc_pci_resource(struct mwl_priv *priv) { struct pci_dev *pdev = priv->pdev; @@ -211,32 +222,21 @@ static int mwl_init_firmware(struct mwl_priv *priv, const char *fw_name) { int rc = 0; -#ifdef SUPPORT_MFG - if (priv->mfg_mode) - rc = mwl_mfg_request_firmware(priv); - else -#endif - rc = request_firmware((const struct firmware **)&priv->fw_ucode, - fw_name, priv->dev); + rc = request_firmware((const struct firmware **)&priv->fw_ucode, + fw_name, priv->dev); if (rc) { - if (priv->mfg_mode) - wiphy_err(priv->hw->wiphy, "cannot find firmware\n"); - else - wiphy_err(priv->hw->wiphy, - "%s: cannot find firmware image <%s>\n", + wiphy_err(priv->hw->wiphy, + "%s: cannot find firmware image <%s>\n", MWL_DRV_NAME, fw_name); goto err_load_fw; } rc = mwl_fwdl_download_firmware(priv->hw); if (rc) { - if (priv->mfg_mode) - wiphy_err(priv->hw->wiphy, "download firmware fail\n"); - else - wiphy_err(priv->hw->wiphy, - "%s: cannot download firmware image <%s>\n", - MWL_DRV_NAME, fw_name); + wiphy_err(priv->hw->wiphy, + "%s: cannot download firmware image <%s>\n", + MWL_DRV_NAME, fw_name); goto err_download_fw; } @@ -244,12 +244,7 @@ static int mwl_init_firmware(struct mwl_priv *priv, const char *fw_name) err_download_fw: -#ifdef SUPPORT_MFG - if (priv->mfg_mode) - mwl_mfg_release_firmware(priv); - else -#endif - release_firmware(priv->fw_ucode); + release_firmware(priv->fw_ucode); err_load_fw: @@ -275,6 +270,17 @@ static void mwl_reg_notifier(struct wiphy *wiphy, hw = (struct ieee80211_hw *)wiphy_priv(wiphy); priv = hw->priv; + if (priv->forbidden_setting) { + if (!priv->regulatory_set) { + regulatory_hint(wiphy, priv->fw_alpha2); + priv->regulatory_set = true; + } else { + if (memcmp(priv->fw_alpha2, request->alpha2, 2)) + regulatory_hint(wiphy, priv->fw_alpha2); + } + return; + } + priv->dfs_region = request->dfs_region; #ifdef CONFIG_OF @@ -424,6 +430,7 @@ static void mwl_set_ht_caps(struct mwl_priv *priv, band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; ieee80211_hw_set(hw, AMPDU_AGGREGATION); + ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_4; @@ -441,7 +448,7 @@ static void mwl_set_vht_caps(struct mwl_priv *priv, { band->vht_cap.vht_supported = 1; - band->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; + band->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895; band->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC; band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; band->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1; @@ -513,6 +520,37 @@ static void mwl_set_caps(struct mwl_priv *priv) } } +static void mwl_regd_init(struct mwl_priv *priv) +{ + u8 region_code; + int i; + + /* hook regulatory domain change notification */ + priv->hw->wiphy->reg_notifier = mwl_reg_notifier; + + if (mwl_fwcmd_get_device_pwr_tbl(priv->hw, + &priv->device_pwr_tbl[0], + ®ion_code, + &priv->number_of_channels, + 0)) + return; + + priv->forbidden_setting = true; + + for (i = 0; i < priv->number_of_channels; i++) + mwl_fwcmd_get_device_pwr_tbl(priv->hw, + &priv->device_pwr_tbl[i], + ®ion_code, + &priv->number_of_channels, + i); + + for (i = 0; i < ARRAY_SIZE(regmap); i++) + if (regmap[i].region_code == priv->fw_region_code) { + memcpy(priv->fw_alpha2, regmap[i].alpha2, 2); + break; + } +} + static void timer_routine(unsigned long data) { struct mwl_priv *priv = (struct mwl_priv *)data; @@ -573,6 +611,8 @@ static int mwl_wl_init(struct mwl_priv *priv) hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; + hw->vif_data_size = sizeof(struct mwl_vif); hw->sta_data_size = sizeof(struct mwl_sta); @@ -674,6 +714,13 @@ static int mwl_wl_init(struct mwl_priv *priv) wiphy_info(hw->wiphy, "firmware version: 0x%x\n", priv->hw_data.fw_release_num); + if (!mwl_fwcmd_get_fw_region_code(hw, &priv->fw_region_code)) { + priv->fw_device_pwrtbl = true; + mwl_regd_init(priv); + wiphy_info(hw->wiphy, + "firmware region code: %x\n", priv->fw_region_code); + } + mwl_fwcmd_radio_disable(hw); mwl_fwcmd_rf_antenna(hw, WL_ANTENNATYPE_TX, priv->antenna_tx); @@ -682,9 +729,6 @@ static int mwl_wl_init(struct mwl_priv *priv) hw->wiphy->interface_modes = 0; hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); -#ifdef CONFIG_MAC80211_MESH - hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT); -#endif hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION); hw->wiphy->iface_combinations = &ap_if_comb; hw->wiphy->n_iface_combinations = 1; @@ -796,9 +840,6 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_pci_disable_device; } - /* hook regulatory domain change notification */ - hw->wiphy->reg_notifier = mwl_reg_notifier; - pci_set_drvdata(pdev, hw); priv = hw->priv; @@ -806,6 +847,9 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) priv->pdev = pdev; priv->dev = &pdev->dev; priv->chip_type = id->driver_data; + priv->fw_device_pwrtbl = false; + priv->forbidden_setting = false; + priv->regulatory_set = false; priv->disable_2g = false; priv->disable_5g = false; priv->antenna_tx = mwl_chip_tbl[priv->chip_type].antenna_tx; @@ -819,11 +863,6 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) fw_name = mwl_chip_tbl[priv->chip_type].fw_image; -#ifdef SUPPORT_MFG - if (mfg_mode) - mwl_mfg_handler_init(priv); -#endif - rc = mwl_init_firmware(priv, fw_name); if (rc) { @@ -833,12 +872,7 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) } /* firmware is loaded to H/W, it can be released now */ -#ifdef SUPPORT_MFG - if (priv->mfg_mode) - mwl_mfg_release_firmware(priv); - else -#endif - release_firmware(priv->fw_ucode); + release_firmware(priv->fw_ucode); mwl_process_of_dts(priv); |