icnss: Add support of setting MAC address from platform driver

Add support of setting WLAN MAC address from platform driver.
The MAC address will be passed to WLAN driver when WLAN is
turned on.

CRs-Fixed: 1096286
Change-Id: I249222b419dd130241cbc84f4d41709b408941e0
Signed-off-by: Yuanyuan Liu <yuanliu@codeaurora.org>
This commit is contained in:
Yuanyuan Liu 2016-12-01 10:55:25 -08:00
parent a27b2f1789
commit d9a8fa86c0
2 changed files with 86 additions and 0 deletions

View file

@ -36,6 +36,7 @@
#include <linux/thread_info.h> #include <linux/thread_info.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/qpnp/qpnp-adc.h> #include <linux/qpnp/qpnp-adc.h>
#include <linux/etherdevice.h>
#include <soc/qcom/memory_dump.h> #include <soc/qcom/memory_dump.h>
#include <soc/qcom/icnss.h> #include <soc/qcom/icnss.h>
#include <soc/qcom/msm_qmi_interface.h> #include <soc/qcom/msm_qmi_interface.h>
@ -409,6 +410,12 @@ struct icnss_stats {
uint32_t vbatt_req_err; uint32_t vbatt_req_err;
}; };
#define MAX_NO_OF_MAC_ADDR 4
struct icnss_wlan_mac_addr {
u8 mac_addr[MAX_NO_OF_MAC_ADDR][ETH_ALEN];
uint32_t no_of_mac_addr_set;
};
static struct icnss_priv { static struct icnss_priv {
uint32_t magic; uint32_t magic;
struct platform_device *pdev; struct platform_device *pdev;
@ -466,6 +473,8 @@ static struct icnss_priv {
uint64_t vph_pwr; uint64_t vph_pwr;
atomic_t pm_count; atomic_t pm_count;
struct ramdump_device *msa0_dump_dev; struct ramdump_device *msa0_dump_dev;
bool is_wlan_mac_set;
struct icnss_wlan_mac_addr wlan_mac_addr;
} *penv; } *penv;
static void icnss_hw_write_reg(void *base, u32 offset, u32 val) static void icnss_hw_write_reg(void *base, u32 offset, u32 val)
@ -3548,6 +3557,80 @@ unsigned int icnss_socinfo_get_serial_number(struct device *dev)
} }
EXPORT_SYMBOL(icnss_socinfo_get_serial_number); EXPORT_SYMBOL(icnss_socinfo_get_serial_number);
int icnss_set_wlan_mac_address(struct device *dev,
const u8 *in, uint32_t len)
{
struct icnss_priv *priv = dev_get_drvdata(dev);
uint32_t no_of_mac_addr;
struct icnss_wlan_mac_addr *addr = NULL;
int iter;
u8 *temp = NULL;
if (priv->magic != ICNSS_MAGIC) {
icnss_pr_err("Invalid drvdata: dev %p, data %p, magic 0x%x\n",
dev, priv, priv->magic);
return -EINVAL;
}
if (priv->is_wlan_mac_set) {
icnss_pr_dbg("WLAN MAC address is already set\n");
return 0;
}
if (len == 0 || (len % ETH_ALEN) != 0) {
icnss_pr_err("Invalid length %d\n", len);
return -EINVAL;
}
no_of_mac_addr = len / ETH_ALEN;
if (no_of_mac_addr > MAX_NO_OF_MAC_ADDR) {
icnss_pr_err("Exceed maxinum supported MAC address %u %u\n",
MAX_NO_OF_MAC_ADDR, no_of_mac_addr);
return -EINVAL;
}
priv->is_wlan_mac_set = true;
addr = &priv->wlan_mac_addr;
addr->no_of_mac_addr_set = no_of_mac_addr;
temp = &addr->mac_addr[0][0];
for (iter = 0; iter < no_of_mac_addr;
++iter, temp += ETH_ALEN, in += ETH_ALEN) {
ether_addr_copy(temp, in);
icnss_pr_dbg("MAC_ADDR:%02x:%02x:%02x:%02x:%02x:%02x\n",
temp[0], temp[1], temp[2],
temp[3], temp[4], temp[5]);
}
return 0;
}
EXPORT_SYMBOL(icnss_set_wlan_mac_address);
u8 *icnss_get_wlan_mac_address(struct device *dev, uint32_t *num)
{
struct icnss_priv *priv = dev_get_drvdata(dev);
struct icnss_wlan_mac_addr *addr = NULL;
if (priv->magic != ICNSS_MAGIC) {
icnss_pr_err("Invalid drvdata: dev %p, data %p, magic 0x%x\n",
dev, priv, priv->magic);
goto out;
}
if (!priv->is_wlan_mac_set) {
icnss_pr_dbg("WLAN MAC address is not set\n");
goto out;
}
addr = &priv->wlan_mac_addr;
*num = addr->no_of_mac_addr_set;
return &addr->mac_addr[0][0];
out:
*num = 0;
return NULL;
}
EXPORT_SYMBOL(icnss_get_wlan_mac_address);
static int icnss_smmu_init(struct icnss_priv *priv) static int icnss_smmu_init(struct icnss_priv *priv)
{ {
struct dma_iommu_mapping *mapping; struct dma_iommu_mapping *mapping;

View file

@ -124,5 +124,8 @@ extern int icnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 *ch_count,
extern int icnss_wlan_set_dfs_nol(const void *info, u16 info_len); extern int icnss_wlan_set_dfs_nol(const void *info, u16 info_len);
extern int icnss_wlan_get_dfs_nol(void *info, u16 info_len); extern int icnss_wlan_get_dfs_nol(void *info, u16 info_len);
extern bool icnss_is_qmi_disable(void); extern bool icnss_is_qmi_disable(void);
extern int icnss_set_wlan_mac_address(struct device *dev,
const u8 *in, uint32_t len);
extern u8 *icnss_get_wlan_mac_address(struct device *dev, uint32_t *num);
#endif /* _ICNSS_WLAN_H_ */ #endif /* _ICNSS_WLAN_H_ */