summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-02-09 03:11:37 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-02-09 03:11:36 -0800
commit6aa70da703dbe9dc5ed0565ce2bed80278da6a50 (patch)
treedf818e044d2a0d3c0feda345cefe6e44dcd1e7e7 /drivers/net/wireless/ath
parenta6135288c38ef935821dc399035721d1586ece80 (diff)
parent6786441d1b3fb0f84c85fe2507e417b6d65ae9c0 (diff)
Merge "ath10k: Add support for BASE MAC ADDRESS CMD"
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h2
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-ops.h24
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c28
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.h5
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c39
6 files changed, 98 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 4d01846e6115..2da6589bf57e 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1536,6 +1536,7 @@ static void ath10k_core_restart(struct work_struct *work)
struct ath10k *ar = container_of(work, struct ath10k, restart_work);
set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
+ ath10k_gen_set_base_mac_addr(ar, ar->base_mac_addr);
/* Place a barrier to make sure the compiler doesn't reorder
* CRASH_FLUSH and calling other functions.
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 9310de85f2a0..f2f0338696e0 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -24,6 +24,7 @@
#include <linux/pci.h>
#include <linux/uuid.h>
#include <linux/time.h>
+#include <soc/qcom/socinfo.h>
#include "htt.h"
#include "htc.h"
@@ -708,6 +709,7 @@ struct ath10k {
struct ieee80211_ops *ops;
struct device *dev;
u8 mac_addr[ETH_ALEN];
+ u8 base_mac_addr[ETH_ALEN];
enum ath10k_hw_rev hw_rev;
u16 dev_id;
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
index 9817c89cd76d..129859255295 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -188,6 +188,9 @@ struct wmi_ops {
u8 enable,
u32 detect_level,
u32 detect_margin);
+ struct sk_buff *(*gen_set_pdev_mac_addr)(struct ath10k *ar, u32 pdev_id,
+ u8 *mac_addr);
+
struct sk_buff *(*ext_resource_config)(struct ath10k *ar,
enum wmi_host_platform_type type,
u32 fw_feature_bitmap);
@@ -1417,4 +1420,25 @@ ath10k_wmi_echo(struct ath10k *ar, u32 value)
return ath10k_wmi_cmd_send(ar, skb, wmi->cmd->echo_cmdid);
}
+static inline int
+ath10k_gen_set_base_mac_addr(struct ath10k *ar, u8 *mac)
+{
+ struct sk_buff *skb;
+ int ret;
+
+ if (!ar->wmi.ops->gen_set_pdev_mac_addr)
+ return -EOPNOTSUPP;
+
+ skb = ar->wmi.ops->gen_set_pdev_mac_addr(ar, 0, mac);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ ret = ath10k_wmi_cmd_send(ar, skb,
+ ar->wmi.cmd->pdev_set_base_macaddr_cmdid);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
#endif
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index b0f3e9b9ef6f..de95e13a6036 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -3174,6 +3174,33 @@ ath10k_wmi_tlv_op_gen_wow_del_pattern(struct ath10k *ar, u32 vdev_id,
}
static struct sk_buff *
+ath10k_wmi_tlv_op_gen_set_base_mac_addr(struct ath10k *ar, u32 pdev_id,
+ u8 *mac_addr)
+{
+ struct wmi_tlv_mac_addr_cmd *cmd;
+ struct wmi_tlv *tlv;
+ struct sk_buff *skb;
+ size_t len;
+
+ len = sizeof(*tlv) + sizeof(*cmd);
+ skb = ath10k_wmi_alloc_skb(ar, len);
+ if (!skb)
+ return ERR_PTR(-ENOMEM);
+
+ tlv = (struct wmi_tlv *)skb->data;
+ tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_BASE_MACADDR_CMD);
+ tlv->len = __cpu_to_le16(sizeof(*cmd));
+ cmd = (void *)tlv->value;
+
+ cmd->pdev_id = __cpu_to_le32(pdev_id);
+ ether_addr_copy(cmd->mac_addr.addr, mac_addr);
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv set_base_mac addr pdev_id %d mac addr %pM\n",
+ cmd->pdev_id, cmd->mac_addr.addr);
+ return skb;
+}
+
+static struct sk_buff *
ath10k_wmi_tlv_op_gen_adaptive_qcs(struct ath10k *ar, bool enable)
{
struct wmi_tlv_adaptive_qcs *cmd;
@@ -3719,6 +3746,7 @@ static const struct wmi_ops wmi_hl_1_0_ops = {
.gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update,
.gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs,
.fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
+ .gen_set_pdev_mac_addr = ath10k_wmi_tlv_op_gen_set_base_mac_addr,
};
void ath10k_wmi_hl_1_0_attach(struct ath10k *ar)
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index 2b8318010a35..31f34b43e381 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -1849,4 +1849,9 @@ struct wmi_tlv_mgmt_tx_cmd {
__le16 data_tag;
u8 buf[0];
} __packed;
+
+struct wmi_tlv_mac_addr_cmd {
+ __le32 pdev_id;
+ struct wmi_mac_addr mac_addr;
+} __packed;
#endif
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index f7ada7147136..2ce61e64c82e 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -4844,6 +4844,39 @@ static int ath10k_wmi_op_pull_echo_ev(struct ath10k *ar,
return 0;
}
+void
+ath10k_generate_mac_addr_auto(struct ath10k *ar, struct wmi_rdy_ev_arg *arg)
+{
+ unsigned int soc_serial_num;
+ u8 bdata_mac_addr[ETH_ALEN];
+ u8 udef_mac_addr[] = {0x00, 0x0A, 0xF5, 0x00, 0x00, 0x00};
+
+ soc_serial_num = socinfo_get_serial_number();
+ if (!soc_serial_num)
+ return;
+
+ if (arg->mac_addr) {
+ ether_addr_copy(ar->base_mac_addr, arg->mac_addr);
+ ether_addr_copy(bdata_mac_addr, arg->mac_addr);
+ soc_serial_num &= 0x00ffffff;
+ bdata_mac_addr[3] = (soc_serial_num >> 16) & 0xff;
+ bdata_mac_addr[4] = (soc_serial_num >> 8) & 0xff;
+ bdata_mac_addr[5] = soc_serial_num & 0xff;
+ ether_addr_copy(ar->mac_addr, bdata_mac_addr);
+ } else {
+ /* If mac address not encoded in wlan board data,
+ * Auto-generate mac address using device serial
+ * number and user defined mac address 'udef_mac_addr'.
+ */
+ udef_mac_addr[3] = (soc_serial_num >> 16) & 0xff;
+ udef_mac_addr[4] = (soc_serial_num >> 8) & 0xff;
+ udef_mac_addr[5] = soc_serial_num & 0xff;
+ ether_addr_copy(ar->base_mac_addr, udef_mac_addr);
+ udef_mac_addr[2] = (soc_serial_num >> 24) & 0xff;
+ ether_addr_copy(ar->mac_addr, udef_mac_addr);
+ }
+}
+
int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_rdy_ev_arg arg = {};
@@ -4862,7 +4895,11 @@ int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
arg.mac_addr,
__le32_to_cpu(arg.status));
- ether_addr_copy(ar->mac_addr, arg.mac_addr);
+ if (QCA_REV_WCN3990(ar))
+ ath10k_generate_mac_addr_auto(ar, &arg);
+ else
+ ether_addr_copy(ar->mac_addr, arg.mac_addr);
+
complete(&ar->wmi.unified_ready);
return 0;
}