diff --git a/drivers/net/wireless/cnss_utils/cnss_utils.c b/drivers/net/wireless/cnss_utils/cnss_utils.c index 49551309c42c..77a58c8cb6a4 100644 --- a/drivers/net/wireless/cnss_utils/cnss_utils.c +++ b/drivers/net/wireless/cnss_utils/cnss_utils.c @@ -13,8 +13,10 @@ #define pr_fmt(fmt) "cnss_utils: " fmt #include +#include #include #include +#include #include #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;