diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2017-02-09 03:11:37 -0800 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-02-09 03:11:36 -0800 |
| commit | 6aa70da703dbe9dc5ed0565ce2bed80278da6a50 (patch) | |
| tree | df818e044d2a0d3c0feda345cefe6e44dcd1e7e7 /drivers/net/wireless/ath | |
| parent | a6135288c38ef935821dc399035721d1586ece80 (diff) | |
| parent | 6786441d1b3fb0f84c85fe2507e417b6d65ae9c0 (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.c | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/core.h | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi-ops.h | 24 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi-tlv.c | 28 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi-tlv.h | 5 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi.c | 39 |
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; } |
