ath10k: Add support for BASE MAC ADDRESS CMD

Base address needs to be set for SAP interface
in HL 1.0 firmware. If base mac address has not
encoded in WLAN firmware board data file then auto
generate base mac address using device serial number
and user defined mac address.

Change-Id: I66f72c3c14b620107b48664d753c9dcf7a9b418e
Signed-off-by: Govind Singh <govinds@codeaurora.org>
Signed-off-by: Sarada Prasanna Garnayak <sgarna@codeaurora.org>
This commit is contained in:
Govind Singh 2017-01-15 21:41:01 +05:30 committed by Gerrit - the friendly Code Review server
parent 01e31721d2
commit 6786441d1b
6 changed files with 98 additions and 1 deletions

View file

@ -1528,6 +1528,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.

View file

@ -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;

View file

@ -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

View file

@ -3173,6 +3173,33 @@ ath10k_wmi_tlv_op_gen_wow_del_pattern(struct ath10k *ar, u32 vdev_id,
return skb;
}
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)
{
@ -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)

View file

@ -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

View file

@ -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;
}