Merge "cnss: Add support to program MAC address thru debugfs"

This commit is contained in:
Linux Build Service Account 2018-02-08 19:03:31 -08:00 committed by Gerrit - the friendly Code Review server
commit 71de2d96a7

View file

@ -13,8 +13,10 @@
#define pr_fmt(fmt) "cnss_utils: " fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/etherdevice.h>
#include <linux/debugfs.h>
#include <net/cnss_utils.h>
#define CNSS_MAX_CH_NUM 45
@ -29,6 +31,7 @@ struct cnss_dfs_nol_info {
};
#define MAX_NO_OF_MAC_ADDR 4
#define MAC_PREFIX_LEN 2
struct cnss_wlan_mac_addr {
u8 mac_addr[MAX_NO_OF_MAC_ADDR][ETH_ALEN];
u32 no_of_mac_addr_set;
@ -50,6 +53,7 @@ static struct cnss_utils_priv {
struct cnss_wlan_mac_addr wlan_mac_addr;
struct cnss_wlan_mac_addr wlan_der_mac_addr;
enum cnss_utils_cc_src cc_source;
struct dentry *root_dentry;
} *cnss_utils_priv;
int cnss_utils_set_wlan_unsafe_channel(struct device *dev,
@ -317,6 +321,137 @@ enum cnss_utils_cc_src cnss_utils_get_cc_source(struct device *dev)
}
EXPORT_SYMBOL(cnss_utils_get_cc_source);
static ssize_t cnss_utils_mac_write(struct file *fp,
const char __user *user_buf,
size_t count, loff_t *off)
{
struct cnss_utils_priv *priv =
((struct seq_file *)fp->private_data)->private;
char buf[128];
char *input, *mac_type, *mac_address;
u8 *dest_mac;
u8 val;
const char *delim = " \n";
size_t len = 0;
char temp[3] = "";
len = min_t(size_t, count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EINVAL;
buf[len] = '\0';
input = buf;
mac_type = strsep(&input, delim);
if (!mac_type)
return -EINVAL;
if (!input)
return -EINVAL;
mac_address = strsep(&input, delim);
if (!mac_address)
return -EINVAL;
if (strncmp("0x", mac_address, MAC_PREFIX_LEN)) {
pr_err("Invalid MAC prefix\n");
return -EINVAL;
}
len = strlen(mac_address);
mac_address += MAC_PREFIX_LEN;
len -= MAC_PREFIX_LEN;
if (len < ETH_ALEN * 2 || len > ETH_ALEN * 2 * MAX_NO_OF_MAC_ADDR ||
len % (ETH_ALEN * 2) != 0) {
pr_err("Invalid MAC address length %zu\n", len);
return -EINVAL;
}
if (!strcmp("provisioned", mac_type)) {
dest_mac = &priv->wlan_mac_addr.mac_addr[0][0];
priv->wlan_mac_addr.no_of_mac_addr_set = len / (ETH_ALEN * 2);
} else if (!strcmp("derived", mac_type)) {
dest_mac = &priv->wlan_der_mac_addr.mac_addr[0][0];
priv->wlan_der_mac_addr.no_of_mac_addr_set =
len / (ETH_ALEN * 2);
} else {
pr_err("Invalid MAC address type %s\n", mac_type);
return -EINVAL;
}
while (len--) {
temp[0] = *mac_address++;
temp[1] = *mac_address++;
if (kstrtou8(temp, 16, &val))
return -EINVAL;
*dest_mac++ = val;
}
return count;
}
static int cnss_utils_mac_show(struct seq_file *s, void *data)
{
u8 mac[6];
int i;
struct cnss_utils_priv *priv = s->private;
struct cnss_wlan_mac_addr *addr = NULL;
addr = &priv->wlan_mac_addr;
if (addr->no_of_mac_addr_set) {
seq_puts(s, "\nProvisioned MAC addresseses\n");
for (i = 0; i < addr->no_of_mac_addr_set; i++) {
ether_addr_copy(mac, addr->mac_addr[i]);
seq_printf(s, "MAC_ADDR:%02x:%02x:%02x:%02x:%02x:%02x\n",
mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
}
}
addr = &priv->wlan_der_mac_addr;
if (addr->no_of_mac_addr_set) {
seq_puts(s, "\nDerived MAC addresseses\n");
for (i = 0; i < addr->no_of_mac_addr_set; i++) {
ether_addr_copy(mac, addr->mac_addr[i]);
seq_printf(s, "MAC_ADDR:%02x:%02x:%02x:%02x:%02x:%02x\n",
mac[0], mac[1], mac[2],
mac[3], mac[4], mac[5]);
}
}
return 0;
}
static int cnss_utils_mac_open(struct inode *inode, struct file *file)
{
return single_open(file, cnss_utils_mac_show, inode->i_private);
}
static const struct file_operations cnss_utils_mac_fops = {
.read = seq_read,
.write = cnss_utils_mac_write,
.release = single_release,
.open = cnss_utils_mac_open,
.owner = THIS_MODULE,
.llseek = seq_lseek,
};
static int cnss_utils_debugfs_create(struct cnss_utils_priv *priv)
{
int ret = 0;
struct dentry *root_dentry;
root_dentry = debugfs_create_dir("cnss_utils", NULL);
if (IS_ERR(root_dentry)) {
ret = PTR_ERR(root_dentry);
pr_err("Unable to create debugfs %d\n", ret);
goto out;
}
priv->root_dentry = root_dentry;
debugfs_create_file("mac_address", 0600, root_dentry, priv,
&cnss_utils_mac_fops);
out:
return ret;
}
static int __init cnss_utils_init(void)
{
struct cnss_utils_priv *priv = NULL;
@ -329,7 +464,7 @@ static int __init cnss_utils_init(void)
mutex_init(&priv->unsafe_channel_list_lock);
spin_lock_init(&priv->dfs_nol_info_lock);
cnss_utils_debugfs_create(priv);
cnss_utils_priv = priv;
return 0;