summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c130
1 files changed, 82 insertions, 48 deletions
diff --git a/main.c b/main.c
index 0ce348b..4ece819 100644
--- a/main.c
+++ b/main.c
@@ -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],
+ &region_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],
+ &region_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);