diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-01-01 15:39:56 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-01-01 15:39:56 -0500 |
commit | ad86c55bac643a745f480d26689d153ec0f38b04 (patch) | |
tree | 8ae3e20d2f3619021393166fe1f50a8ca00c1c33 /drivers/net/wireless/mwifiex | |
parent | 21eb218989523b7bee28900aaec9f9296b70fa27 (diff) | |
parent | 39731b78b4afebb7501c05b68e2443a1b250b41c (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'drivers/net/wireless/mwifiex')
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 35 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/fw.h | 9 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_cmd.c | 77 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/sta_ioctl.c | 15 |
5 files changed, 105 insertions, 35 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 4d23647faef..b994679abce 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -538,23 +538,40 @@ static void mwifiex_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) { struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); + struct mwifiex_private *priv = mwifiex_get_priv(adapter, + MWIFIEX_BSS_ROLE_ANY); wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for %c%c\n", request->alpha2[0], request->alpha2[1]); - memcpy(adapter->country_code, request->alpha2, sizeof(request->alpha2)); - switch (request->initiator) { case NL80211_REGDOM_SET_BY_DRIVER: case NL80211_REGDOM_SET_BY_CORE: case NL80211_REGDOM_SET_BY_USER: - break; - /* Todo: apply driver specific changes in channel flags based - on the request initiator if necessary. */ case NL80211_REGDOM_SET_BY_COUNTRY_IE: break; + default: + wiphy_err(wiphy, "unknown regdom initiator: %d\n", + request->initiator); + return; + } + + /* Don't send world or same regdom info to firmware */ + if (strncmp(request->alpha2, "00", 2) && + strncmp(request->alpha2, adapter->country_code, + sizeof(request->alpha2))) { + memcpy(adapter->country_code, request->alpha2, + sizeof(request->alpha2)); + mwifiex_send_domain_info_cmd_fw(wiphy); + + if (adapter->dt_node) { + char txpwr[] = {"marvell,00_txpwrlimit"}; + + memcpy(&txpwr[8], adapter->country_code, 2); + mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node, + txpwr); + } } - mwifiex_send_domain_info_cmd_fw(wiphy); } /* @@ -1171,10 +1188,10 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, else bitmap_rates[1] = mask->control[band].legacy; - /* Fill MCS rates */ - bitmap_rates[2] = mask->control[band].mcs[0]; + /* Fill HT MCS rates */ + bitmap_rates[2] = mask->control[band].ht_mcs[0]; if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) - bitmap_rates[2] |= mask->control[band].mcs[1] << 8; + bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8; return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, HostCmd_ACT_GEN_SET, 0, bitmap_rates); diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 8fcb500fa09..4cee6ceb7e9 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -468,8 +468,6 @@ enum P2P_MODES { #define MWIFIEX_CRITERIA_UNICAST BIT(1) #define MWIFIEX_CRITERIA_MULTICAST BIT(3) -#define CFG_DATA_TYPE_CAL 2 - struct mwifiex_ie_types_header { __le16 type; __le16 len; @@ -1592,12 +1590,6 @@ struct mwifiex_ie_list { struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX]; } __packed; -struct host_cmd_ds_802_11_cfg_data { - __le16 action; - __le16 type; - __le16 data_len; -} __packed; - struct coalesce_filt_field_param { u8 operation; u8 operand_len; @@ -1678,7 +1670,6 @@ struct host_cmd_ds_command { struct host_cmd_ds_sys_config uap_sys_config; struct host_cmd_ds_sta_deauth sta_deauth; struct host_cmd_11ac_vht_cfg vht_cfg; - struct host_cmd_ds_802_11_cfg_data cfg_data; struct host_cmd_ds_coalesce_cfg coalesce_cfg; } params; } __packed; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index dc34457557f..ab3416449bf 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -32,6 +32,7 @@ #include <net/lib80211.h> #include <linux/firmware.h> #include <linux/ctype.h> +#include <linux/of.h> #include "decl.h" #include "ioctl.h" @@ -739,6 +740,7 @@ struct mwifiex_adapter { u8 scan_delay_cnt; u8 empty_tx_q_cnt; const struct firmware *cal_data; + struct device_node *dt_node; /* 11AC */ u32 is_hw_11ac_capable; @@ -1151,6 +1153,8 @@ void mwifiex_uap_del_sta_data(struct mwifiex_private *priv, void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, struct mwifiex_bssdescriptor *bss_desc); int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv); +int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv, + struct device_node *node, const char *prefix); extern const struct ethtool_ops mwifiex_ethtool_ops; diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 1efa43ec1c6..9c2404cd755 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -1156,30 +1156,61 @@ static u32 mwifiex_parse_cal_cfg(u8 *src, size_t len, u8 *dst) return d - dst; } +int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv, + struct device_node *node, const char *prefix) +{ +#ifdef CONFIG_OF + struct property *prop; + size_t len = strlen(prefix); + int ret; + + /* look for all matching property names */ + for_each_property_of_node(node, prop) { + if (len > strlen(prop->name) || + strncmp(prop->name, prefix, len)) + continue; + + /* property header is 6 bytes */ + if (prop && prop->value && prop->length > 6) { + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA, + HostCmd_ACT_GEN_SET, 0, + prop); + if (ret) + return ret; + } + } +#endif + return 0; +} + /* This function prepares command of set_cfg_data. */ static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action) + struct host_cmd_ds_command *cmd, void *data_buf) { - struct host_cmd_ds_802_11_cfg_data *cfg_data = &cmd->params.cfg_data; struct mwifiex_adapter *adapter = priv->adapter; - u32 len, cal_data_offset; - u8 *tmp_cmd = (u8 *)cmd; + struct property *prop = data_buf; + u32 len; + u8 *data = (u8 *)cmd + S_DS_GEN; + int ret; - cal_data_offset = S_DS_GEN + sizeof(*cfg_data); - if ((adapter->cal_data->data) && (adapter->cal_data->size > 0)) + if (prop) { + len = prop->length; + ret = of_property_read_u8_array(adapter->dt_node, prop->name, + data, len); + if (ret) + return ret; + dev_dbg(adapter->dev, + "download cfg_data from device tree: %s\n", prop->name); + } else if (adapter->cal_data->data && adapter->cal_data->size > 0) { len = mwifiex_parse_cal_cfg((u8 *)adapter->cal_data->data, - adapter->cal_data->size, - (u8 *)(tmp_cmd + cal_data_offset)); - else + adapter->cal_data->size, data); + dev_dbg(adapter->dev, "download cfg_data from config file\n"); + } else { return -1; - - cfg_data->action = cpu_to_le16(cmd_action); - cfg_data->type = cpu_to_le16(CFG_DATA_TYPE_CAL); - cfg_data->data_len = cpu_to_le16(len); + } cmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA); - cmd->size = cpu_to_le16(S_DS_GEN + sizeof(*cfg_data) + len); + cmd->size = cpu_to_le16(S_DS_GEN + len); return 0; } @@ -1267,7 +1298,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr); break; case HostCmd_CMD_CFG_DATA: - ret = mwifiex_cmd_cfg_data(priv, cmd_ptr, cmd_action); + ret = mwifiex_cmd_cfg_data(priv, cmd_ptr, data_buf); break; case HostCmd_CMD_MAC_CONTROL: ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action, @@ -1527,7 +1558,19 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) if (ret) return -1; - /* Download calibration data to firmware */ + /* Download calibration data to firmware. + * The cal-data can be read from device tree and/or + * a configuration file and downloaded to firmware. + */ + adapter->dt_node = + of_find_node_by_name(NULL, "marvell_cfgdata"); + if (adapter->dt_node) { + ret = mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node, + "marvell,caldata"); + if (ret) + return -1; + } + if (adapter->cal_data) { ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_CFG_DATA, HostCmd_ACT_GEN_SET, 0, NULL); diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index a09398fe9e2..3edc92fad31 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -205,6 +205,14 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv, return 0; } + if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) { + rcu_read_unlock(); + wiphy_dbg(priv->wdev->wiphy, + "11D: skip setting domain info in FW\n"); + return 0; + } + memcpy(priv->adapter->country_code, &country_ie[2], 2); + domain_info->country_code[0] = country_ie[2]; domain_info->country_code[1] = country_ie[3]; domain_info->country_code[2] = ' '; @@ -226,6 +234,13 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv, return -1; } + if (priv->adapter->dt_node) { + char txpwr[] = {"marvell,00_txpwrlimit"}; + + memcpy(&txpwr[8], priv->adapter->country_code, 2); + mwifiex_dnld_dt_cfgdata(priv, priv->adapter->dt_node, txpwr); + } + return 0; } |